Skip to content

fix: preserve card styling in heading hierarchy repair - #23

Merged
nish3451 merged 3 commits into
mainfrom
fix/drishti-support-privacy-heading-hierarchy
Aug 9, 2026
Merged

fix: preserve card styling in heading hierarchy repair#23
nish3451 merged 3 commits into
mainfrom
fix/drishti-support-privacy-heading-hierarchy

Conversation

@nish3451

@nish3451 nish3451 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Promote Drishti support and Privacy Choices card headings from H3 to H2.
  • Preserve the former card-title scale and margin while removing the global H2 width cap inside cards.
  • Extend the deterministic heading regression to cover both pages and the CSS pairing.

Validation

tinystudio-growth-brain@0.1.0 test
node scripts/test-service-engine.mjs && node scripts/test-sales-intake-contract.mjs && node scripts/test-active-offer-projection.mjs && node scripts/test-active-operator-surfaces.mjs && node scripts/test-direction-proof-gate.mjs && node scripts/test-client-readiness-contract.mjs && node scripts/test-validated-service-client.mjs && node scripts/test-client-acceptance-gates.mjs && node scripts/check-product-truth.mjs && node scripts/check-human-service-kit.mjs && node scripts/test-design-system-proving-lab.mjs && node scripts/check-retention-automation.mjs && node scripts/test-retention-automation.mjs && node scripts/check-agency-defaults.mjs && node scripts/check-outbound-claim-safety.mjs && node scripts/check-outbound-send-readiness.mjs && node scripts/test-outbound-send-readiness.mjs && node scripts/test-public-conversion-signal.mjs && node scripts/test-public-structured-data.mjs && node scripts/test-public-heading-hierarchy.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check

{
"status": "passed",
"checks": 38
}
Sales and external-intake contract checks passed.
Active offer projection checks passed.
Active operator surface checks passed.
Direction proof gate checks passed.
Client readiness contract checks passed.
Validated service-client checks passed.
Client acceptance gate checks passed.
{
"status": "passed",
"surfaces": [
"README.md",
"MEMORY.md",
"PRODUCT.md",
"growth-brain/offer.md",
"growth-brain/sales/managed-it-one-page-offer.md",
"growth-brain/sales/one-page-offer.md",
"growth-brain/sales/proposal-template.md",
"growth-brain/sales/buyer-room-template.md",
"growth-brain/sales/sales-call-script.md",
"growth-brain/sales/follow-up-sequences.md",
"growth-brain/sprint-checklist.md",
"growth-brain/delivery-template.md",
"growth-brain/workflows/client-sprint-workflow.md",
"growth-brain/quality/sprint-acceptance-checklist.md",
"growth-brain/positioning/message-house.md",
"growth-brain/delivery/implementation-handoff-template.md",
"growth-brain/README.md",
"growth-brain/sales/pricing-rules.md",
"growth-brain/loom-audit-script.md",
"growth-brain/workflows/loom-audit-workflow.md",
"growth-brain/prospecting/warm-network-scripts.md",
"growth-brain/agency-operating-model.md",
"growth-brain/build-roadmap.md",
"growth-brain/sales/managed-it-one-page-offer.html"
],
"checked": [
"buyer",
"product",
"first-3 price",
"scope",
"fault map",
"rewrite or redesign",
"implementation pass or dev-ready handoff",
"search-trust basics",
"before/after proof",
"Loom",
"measurement plan",
"one revision",
"14-day implementation tracking",
"Day 0 prerequisites",
"client-delay pause",
"no revenue guarantee",
"no ranking guarantee",
"no ROAS guarantee",
"no conversion guarantee",
"no booked-call guarantee",
"no sales-volume guarantee",
"fit review gate",
"claims review gate",
"client-facing review gate",
"delivery/acceptance review gate",
"renewal review gate",
"automation preparation",
"no autonomous send",
"no autonomous publish",
"no autonomous spend",
"no autonomous approval",
"no autonomous acceptance",
"no autonomous renewal",
"SaaS graduation: 10 paid sprints",
"SaaS graduation: same problem",
"SaaS graduation: repeatability",
"SaaS graduation: usefulness",
"SaaS graduation: approval",
"SaaS graduation: recurring need",
"SaaS graduation: deposits"
],
"activeGeneratedOutputs": [
"growth-brain/ops/11-10-proof-run.md",
"growth-brain/ops/proof-library.md",
"growth-brain/ops/live-metrics.md",
"growth-brain/ops/market-parity-readiness.md",
"growth-brain/ops/sender-setup-guide.md",
"growth-brain/ops/sender-setup-guide.html",
"growth-brain/ops/competitive-proof-matrix.md",
"growth-brain/ops/competitive-proof-matrix.html",
"docs/strategy/market-parity-benchmark-2026.md"
],
"excluded": [
"public/",
"historical research"
]
}
{
"status": "passed",
"contract": "human-reviewed-service-kit",
"checkedFiles": 38,
"allowedCommands": 9,
"preservedGates": [
"client readiness",
"product truth",
"claims",
"send readiness",
"retention",
"agency defaults"
]
}
{
"status": "pass",
"checks": 16,
"labStatus": "blocked-before-fresh-mobbin-reference-packets"
}
{
"status": "pass",
"automationId": "tinystudio-retention-checkups",
"path": "/home/nish/.codex/automations/tinystudio-retention-checkups/automation.toml",
"weeklyCadence": "Friday retention prep",
"repo": "/home/nish/workspaces/products/tinystudio-in-autonomous-service",
"failures": [],
"warnings": []
}
Retention automation applicability checks passed.
{
"status": "passed",
"scanned": 110,
"requiredStringKeys": [
"founderName",
"offerName",
"buyer",
"founderSprintPrice",
"scope",
"dayZeroRule",
"automationBoundary",
"optOutLine",
"meetingPlaceholder",
"paymentPlaceholder"
],
"bannedValues": 0
}
{
"status": "pass",
"filesScanned": 7
}
{
"status": "pass",
"filesScanned": 0,
"findings": [],
"warnings": []
}
Outbound send readiness fixture checks passed.
test-public-conversion-signal: public conversion signal (The Website Correction application route)
A. signal definitions
ok registry names are unique
ok registry names are stable lowercase slugs
B. docs contract
ok docs/measurement/public-conversion-signal.md exists
ok docs document signal source homepage-hero
ok docs document signal source homepage-service
ok docs document signal source homepage-footer
ok docs name the offer truthfully as The Website Correction
ok docs never name the offer as a generic reviewed service
ok docs state the prefilled application subject is the operator-visible signal
ok docs pin the operator-visible subject format with the exact product name
ok docs pin the full propagated subject format
ok docs name the signal owner
ok docs state retention
ok docs state the privacy boundary
ok docs explain where the privacy disclosure lives
ok docs contain a falsifiable decision rule
ok docs are honest that tags are not application proof
ok docs count only received human messages as completion evidence
C. homepage Website Correction CTA source tags
ok every Website Correction CTA carries data-measure-source
ok source tag homepage-hero is a registered stable name
ok CTA homepage-hero routes to the application endpoint with source context
ok every Website Correction CTA carries data-measure-source
ok source tag homepage-service is a registered stable name
ok CTA homepage-service routes to the application endpoint with source context
D. contact endpoint source propagation
ok contact page has a Website Correction application mailto route
ok contact page default subject is exactly The Website Correction application
ok contact page application route names the offer as Website Correction
ok contact page names the offer truthfully as The Website Correction
ok contact page never names the offer as a generic reviewed service
ok contact page states the signal is for internal measurement only
ok contact page states nothing is sent automatically
ok contact page states the marker can be removed before sending
ok contact page reads the ?source= parameter
ok contact page allowlists every registered source name
ok contact page propagates the exact The Website Correction application — from (internal measurement marker) subject
ok contact page rejects unregistered source values
ok contact page has no auto-send/auto-submit mechanism (<form)
ok contact page has no auto-send/auto-submit mechanism (<input)
ok contact page has no auto-send/auto-submit mechanism (<textarea)
ok contact page has no auto-send/auto-submit mechanism (location.href)
ok contact page has no auto-send/auto-submit mechanism (location.assign)
ok contact page has no auto-send/auto-submit mechanism (location.replace)
ok contact page has no auto-send/auto-submit mechanism (window.open)
ok contact page has no auto-send/auto-submit mechanism (.submit()
ok contact page has no auto-send/auto-submit mechanism (sendBeacon()
ok contact page has no auto-send/auto-submit mechanism (fetch()
E. no analytics provider, cookies, fingerprinting, or message-content collection
ok public/index.html has no document.cookie
ok public/index.html has no localStorage
ok public/index.html has no sessionStorage
ok public/index.html has no navigator.sendBeacon
ok public/index.html has no sendBeacon(
ok public/index.html has no fetch(
ok public/index.html has no XMLHttpRequest
ok public/index.html has no googletagmanager
ok public/index.html has no google-analytics
ok public/index.html has no gtag(
ok public/index.html has no plausible.io
ok public/index.html has no fathom.js
ok public/index.html has no posthog
ok public/index.html has no mixpanel
ok public/index.html has no amplitude
ok public/index.html has no window.analytics
ok public/index.html has no hotjar
ok public/index.html has no clarity.ms
ok public/index.html has no fbq(
ok public/index.html has no connect.facebook.net
ok public/index.html has no toDataURL
ok public/index.html has no hardwareConcurrency
ok public/index.html has no deviceMemory
ok public/index.html has no navigator.plugins
ok public/index.html has no FingerprintJS
ok public/index.html has no window.fingerprint
ok public/contact/index.html has no document.cookie
ok public/contact/index.html has no localStorage
ok public/contact/index.html has no sessionStorage
ok public/contact/index.html has no navigator.sendBeacon
ok public/contact/index.html has no sendBeacon(
ok public/contact/index.html has no fetch(
ok public/contact/index.html has no XMLHttpRequest
ok public/contact/index.html has no googletagmanager
ok public/contact/index.html has no google-analytics
ok public/contact/index.html has no gtag(
ok public/contact/index.html has no plausible.io
ok public/contact/index.html has no fathom.js
ok public/contact/index.html has no posthog
ok public/contact/index.html has no mixpanel
ok public/contact/index.html has no amplitude
ok public/contact/index.html has no window.analytics
ok public/contact/index.html has no hotjar
ok public/contact/index.html has no clarity.ms
ok public/contact/index.html has no fbq(
ok public/contact/index.html has no connect.facebook.net
ok public/contact/index.html has no toDataURL
ok public/contact/index.html has no hardwareConcurrency
ok public/contact/index.html has no deviceMemory
ok public/contact/index.html has no navigator.plugins
ok public/contact/index.html has no FingerprintJS
ok public/contact/index.html has no window.fingerprint
ok public/privacy-choices/index.html has no document.cookie
ok public/privacy-choices/index.html has no localStorage
ok public/privacy-choices/index.html has no sessionStorage
ok public/privacy-choices/index.html has no navigator.sendBeacon
ok public/privacy-choices/index.html has no sendBeacon(
ok public/privacy-choices/index.html has no fetch(
ok public/privacy-choices/index.html has no XMLHttpRequest
ok public/privacy-choices/index.html has no googletagmanager
ok public/privacy-choices/index.html has no google-analytics
ok public/privacy-choices/index.html has no gtag(
ok public/privacy-choices/index.html has no plausible.io
ok public/privacy-choices/index.html has no fathom.js
ok public/privacy-choices/index.html has no posthog
ok public/privacy-choices/index.html has no mixpanel
ok public/privacy-choices/index.html has no amplitude
ok public/privacy-choices/index.html has no window.analytics
ok public/privacy-choices/index.html has no hotjar
ok public/privacy-choices/index.html has no clarity.ms
ok public/privacy-choices/index.html has no fbq(
ok public/privacy-choices/index.html has no connect.facebook.net
ok public/privacy-choices/index.html has no toDataURL
ok public/privacy-choices/index.html has no hardwareConcurrency
ok public/privacy-choices/index.html has no deviceMemory
ok public/privacy-choices/index.html has no navigator.plugins
ok public/privacy-choices/index.html has no FingerprintJS
ok public/privacy-choices/index.html has no window.fingerprint
F. npm test/ci wiring
ok npm test runs the public conversion signal test
ok npm run ci runs the public conversion signal test

126 checks, 0 failures
test-public-structured-data: JSON-LD structured data on public pages
A. public/contact/index.html
ok contact page has exactly one application/ld+json block
ok contact page JSON-LD block parses as valid JSON
ok contact page uses the schema.org context
ok contact page JSON-LD uses an @graph array
ok contact page page declares a canonical URL
ok contact page page declares a title
ok contact page page declares a description
ok contact page JSON-LD carries the stable Tiny Studio organization reference
ok contact page JSON-LD declares the page as ContactPage
ok contact page JSON-LD url matches the page canonical URL
ok contact page JSON-LD name matches the page title
ok contact page JSON-LD description matches the meta description
ok contact page JSON-LD page is part of the Tiny Studio website
ok contact page JSON-LD page is about the Tiny Studio organization
A. public/promptly/privacy/index.html
ok Promptly privacy policy page has exactly one application/ld+json block
ok Promptly privacy policy page JSON-LD block parses as valid JSON
ok Promptly privacy policy page uses the schema.org context
ok Promptly privacy policy page JSON-LD uses an @graph array
ok Promptly privacy policy page page declares a canonical URL
ok Promptly privacy policy page page declares a title
ok Promptly privacy policy page page declares a description
ok Promptly privacy policy page JSON-LD carries the stable Tiny Studio organization reference
ok Promptly privacy policy page JSON-LD declares the page as WebPage
ok Promptly privacy policy page JSON-LD url matches the page canonical URL
ok Promptly privacy policy page JSON-LD name matches the page title
ok Promptly privacy policy page JSON-LD description matches the meta description
ok Promptly privacy policy page JSON-LD page is part of the Tiny Studio website
ok Promptly privacy policy page JSON-LD page is about the Tiny Studio organization
B. npm test/ci wiring
ok npm test runs the public structured data test
ok npm run check delegates to npm test
ok npm run ci runs the public structured data test

31 checks, 0 failures
test-public-heading-hierarchy: card headings are semantic H2s with the former card scale
A. public/contact/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/promptly/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/promptly/privacy/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/drishti/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/drishti/support/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/privacy-choices/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
B. card-heading CSS pairing
ok styles.css defines .info-card :is(h2, h3) {
ok card rule keeps margin-top: 12px
ok card rule keeps font-size: clamp(1.65rem, 2vw, 2.35rem)
ok card rule keeps max-width: none
ok global h2 styling (12ch cap) is untouched
ok the old .info-card h3-only rule is replaced by the shared :is(h2, h3) rule
C. npm test/ci wiring
ok npm test runs the public heading hierarchy test
ok npm run ci runs the public heading hierarchy test

44 checks, 0 failures passed: 38 checks plus all downstream suites, including 44 heading checks.

tinystudio-growth-brain@0.1.0 ci
node scripts/test-service-engine.mjs && node scripts/test-sales-intake-contract.mjs && node scripts/test-active-offer-projection.mjs && node scripts/test-active-operator-surfaces.mjs && node scripts/test-direction-proof-gate.mjs && node scripts/test-client-readiness-contract.mjs && node scripts/test-validated-service-client.mjs && node scripts/test-client-acceptance-gates.mjs && node scripts/check-product-truth.mjs && node scripts/check-human-service-kit.mjs && node scripts/test-design-system-proving-lab.mjs && node scripts/check-retention-automation.mjs && node scripts/test-retention-automation.mjs && node scripts/check-agency-defaults.mjs && node scripts/check-outbound-claim-safety.mjs && node scripts/check-outbound-send-readiness.mjs && node scripts/test-outbound-send-readiness.mjs && node scripts/test-public-conversion-signal.mjs && node scripts/test-public-structured-data.mjs && node scripts/test-public-heading-hierarchy.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check

{
"status": "passed",
"checks": 38
}
Sales and external-intake contract checks passed.
Active offer projection checks passed.
Active operator surface checks passed.
Direction proof gate checks passed.
Client readiness contract checks passed.
Validated service-client checks passed.
Client acceptance gate checks passed.
{
"status": "passed",
"surfaces": [
"README.md",
"MEMORY.md",
"PRODUCT.md",
"growth-brain/offer.md",
"growth-brain/sales/managed-it-one-page-offer.md",
"growth-brain/sales/one-page-offer.md",
"growth-brain/sales/proposal-template.md",
"growth-brain/sales/buyer-room-template.md",
"growth-brain/sales/sales-call-script.md",
"growth-brain/sales/follow-up-sequences.md",
"growth-brain/sprint-checklist.md",
"growth-brain/delivery-template.md",
"growth-brain/workflows/client-sprint-workflow.md",
"growth-brain/quality/sprint-acceptance-checklist.md",
"growth-brain/positioning/message-house.md",
"growth-brain/delivery/implementation-handoff-template.md",
"growth-brain/README.md",
"growth-brain/sales/pricing-rules.md",
"growth-brain/loom-audit-script.md",
"growth-brain/workflows/loom-audit-workflow.md",
"growth-brain/prospecting/warm-network-scripts.md",
"growth-brain/agency-operating-model.md",
"growth-brain/build-roadmap.md",
"growth-brain/sales/managed-it-one-page-offer.html"
],
"checked": [
"buyer",
"product",
"first-3 price",
"scope",
"fault map",
"rewrite or redesign",
"implementation pass or dev-ready handoff",
"search-trust basics",
"before/after proof",
"Loom",
"measurement plan",
"one revision",
"14-day implementation tracking",
"Day 0 prerequisites",
"client-delay pause",
"no revenue guarantee",
"no ranking guarantee",
"no ROAS guarantee",
"no conversion guarantee",
"no booked-call guarantee",
"no sales-volume guarantee",
"fit review gate",
"claims review gate",
"client-facing review gate",
"delivery/acceptance review gate",
"renewal review gate",
"automation preparation",
"no autonomous send",
"no autonomous publish",
"no autonomous spend",
"no autonomous approval",
"no autonomous acceptance",
"no autonomous renewal",
"SaaS graduation: 10 paid sprints",
"SaaS graduation: same problem",
"SaaS graduation: repeatability",
"SaaS graduation: usefulness",
"SaaS graduation: approval",
"SaaS graduation: recurring need",
"SaaS graduation: deposits"
],
"activeGeneratedOutputs": [
"growth-brain/ops/11-10-proof-run.md",
"growth-brain/ops/proof-library.md",
"growth-brain/ops/live-metrics.md",
"growth-brain/ops/market-parity-readiness.md",
"growth-brain/ops/sender-setup-guide.md",
"growth-brain/ops/sender-setup-guide.html",
"growth-brain/ops/competitive-proof-matrix.md",
"growth-brain/ops/competitive-proof-matrix.html",
"docs/strategy/market-parity-benchmark-2026.md"
],
"excluded": [
"public/",
"historical research"
]
}
{
"status": "passed",
"contract": "human-reviewed-service-kit",
"checkedFiles": 38,
"allowedCommands": 9,
"preservedGates": [
"client readiness",
"product truth",
"claims",
"send readiness",
"retention",
"agency defaults"
]
}
{
"status": "pass",
"checks": 16,
"labStatus": "blocked-before-fresh-mobbin-reference-packets"
}
{
"status": "pass",
"automationId": "tinystudio-retention-checkups",
"path": "/home/nish/.codex/automations/tinystudio-retention-checkups/automation.toml",
"weeklyCadence": "Friday retention prep",
"repo": "/home/nish/workspaces/products/tinystudio-in-autonomous-service",
"failures": [],
"warnings": []
}
Retention automation applicability checks passed.
{
"status": "passed",
"scanned": 110,
"requiredStringKeys": [
"founderName",
"offerName",
"buyer",
"founderSprintPrice",
"scope",
"dayZeroRule",
"automationBoundary",
"optOutLine",
"meetingPlaceholder",
"paymentPlaceholder"
],
"bannedValues": 0
}
{
"status": "pass",
"filesScanned": 7
}
{
"status": "pass",
"filesScanned": 0,
"findings": [],
"warnings": []
}
Outbound send readiness fixture checks passed.
test-public-conversion-signal: public conversion signal (The Website Correction application route)
A. signal definitions
ok registry names are unique
ok registry names are stable lowercase slugs
B. docs contract
ok docs/measurement/public-conversion-signal.md exists
ok docs document signal source homepage-hero
ok docs document signal source homepage-service
ok docs document signal source homepage-footer
ok docs name the offer truthfully as The Website Correction
ok docs never name the offer as a generic reviewed service
ok docs state the prefilled application subject is the operator-visible signal
ok docs pin the operator-visible subject format with the exact product name
ok docs pin the full propagated subject format
ok docs name the signal owner
ok docs state retention
ok docs state the privacy boundary
ok docs explain where the privacy disclosure lives
ok docs contain a falsifiable decision rule
ok docs are honest that tags are not application proof
ok docs count only received human messages as completion evidence
C. homepage Website Correction CTA source tags
ok every Website Correction CTA carries data-measure-source
ok source tag homepage-hero is a registered stable name
ok CTA homepage-hero routes to the application endpoint with source context
ok every Website Correction CTA carries data-measure-source
ok source tag homepage-service is a registered stable name
ok CTA homepage-service routes to the application endpoint with source context
D. contact endpoint source propagation
ok contact page has a Website Correction application mailto route
ok contact page default subject is exactly The Website Correction application
ok contact page application route names the offer as Website Correction
ok contact page names the offer truthfully as The Website Correction
ok contact page never names the offer as a generic reviewed service
ok contact page states the signal is for internal measurement only
ok contact page states nothing is sent automatically
ok contact page states the marker can be removed before sending
ok contact page reads the ?source= parameter
ok contact page allowlists every registered source name
ok contact page propagates the exact The Website Correction application — from (internal measurement marker) subject
ok contact page rejects unregistered source values
ok contact page has no auto-send/auto-submit mechanism (<form)
ok contact page has no auto-send/auto-submit mechanism (<input)
ok contact page has no auto-send/auto-submit mechanism (<textarea)
ok contact page has no auto-send/auto-submit mechanism (location.href)
ok contact page has no auto-send/auto-submit mechanism (location.assign)
ok contact page has no auto-send/auto-submit mechanism (location.replace)
ok contact page has no auto-send/auto-submit mechanism (window.open)
ok contact page has no auto-send/auto-submit mechanism (.submit()
ok contact page has no auto-send/auto-submit mechanism (sendBeacon()
ok contact page has no auto-send/auto-submit mechanism (fetch()
E. no analytics provider, cookies, fingerprinting, or message-content collection
ok public/index.html has no document.cookie
ok public/index.html has no localStorage
ok public/index.html has no sessionStorage
ok public/index.html has no navigator.sendBeacon
ok public/index.html has no sendBeacon(
ok public/index.html has no fetch(
ok public/index.html has no XMLHttpRequest
ok public/index.html has no googletagmanager
ok public/index.html has no google-analytics
ok public/index.html has no gtag(
ok public/index.html has no plausible.io
ok public/index.html has no fathom.js
ok public/index.html has no posthog
ok public/index.html has no mixpanel
ok public/index.html has no amplitude
ok public/index.html has no window.analytics
ok public/index.html has no hotjar
ok public/index.html has no clarity.ms
ok public/index.html has no fbq(
ok public/index.html has no connect.facebook.net
ok public/index.html has no toDataURL
ok public/index.html has no hardwareConcurrency
ok public/index.html has no deviceMemory
ok public/index.html has no navigator.plugins
ok public/index.html has no FingerprintJS
ok public/index.html has no window.fingerprint
ok public/contact/index.html has no document.cookie
ok public/contact/index.html has no localStorage
ok public/contact/index.html has no sessionStorage
ok public/contact/index.html has no navigator.sendBeacon
ok public/contact/index.html has no sendBeacon(
ok public/contact/index.html has no fetch(
ok public/contact/index.html has no XMLHttpRequest
ok public/contact/index.html has no googletagmanager
ok public/contact/index.html has no google-analytics
ok public/contact/index.html has no gtag(
ok public/contact/index.html has no plausible.io
ok public/contact/index.html has no fathom.js
ok public/contact/index.html has no posthog
ok public/contact/index.html has no mixpanel
ok public/contact/index.html has no amplitude
ok public/contact/index.html has no window.analytics
ok public/contact/index.html has no hotjar
ok public/contact/index.html has no clarity.ms
ok public/contact/index.html has no fbq(
ok public/contact/index.html has no connect.facebook.net
ok public/contact/index.html has no toDataURL
ok public/contact/index.html has no hardwareConcurrency
ok public/contact/index.html has no deviceMemory
ok public/contact/index.html has no navigator.plugins
ok public/contact/index.html has no FingerprintJS
ok public/contact/index.html has no window.fingerprint
ok public/privacy-choices/index.html has no document.cookie
ok public/privacy-choices/index.html has no localStorage
ok public/privacy-choices/index.html has no sessionStorage
ok public/privacy-choices/index.html has no navigator.sendBeacon
ok public/privacy-choices/index.html has no sendBeacon(
ok public/privacy-choices/index.html has no fetch(
ok public/privacy-choices/index.html has no XMLHttpRequest
ok public/privacy-choices/index.html has no googletagmanager
ok public/privacy-choices/index.html has no google-analytics
ok public/privacy-choices/index.html has no gtag(
ok public/privacy-choices/index.html has no plausible.io
ok public/privacy-choices/index.html has no fathom.js
ok public/privacy-choices/index.html has no posthog
ok public/privacy-choices/index.html has no mixpanel
ok public/privacy-choices/index.html has no amplitude
ok public/privacy-choices/index.html has no window.analytics
ok public/privacy-choices/index.html has no hotjar
ok public/privacy-choices/index.html has no clarity.ms
ok public/privacy-choices/index.html has no fbq(
ok public/privacy-choices/index.html has no connect.facebook.net
ok public/privacy-choices/index.html has no toDataURL
ok public/privacy-choices/index.html has no hardwareConcurrency
ok public/privacy-choices/index.html has no deviceMemory
ok public/privacy-choices/index.html has no navigator.plugins
ok public/privacy-choices/index.html has no FingerprintJS
ok public/privacy-choices/index.html has no window.fingerprint
F. npm test/ci wiring
ok npm test runs the public conversion signal test
ok npm run ci runs the public conversion signal test

126 checks, 0 failures
test-public-structured-data: JSON-LD structured data on public pages
A. public/contact/index.html
ok contact page has exactly one application/ld+json block
ok contact page JSON-LD block parses as valid JSON
ok contact page uses the schema.org context
ok contact page JSON-LD uses an @graph array
ok contact page page declares a canonical URL
ok contact page page declares a title
ok contact page page declares a description
ok contact page JSON-LD carries the stable Tiny Studio organization reference
ok contact page JSON-LD declares the page as ContactPage
ok contact page JSON-LD url matches the page canonical URL
ok contact page JSON-LD name matches the page title
ok contact page JSON-LD description matches the meta description
ok contact page JSON-LD page is part of the Tiny Studio website
ok contact page JSON-LD page is about the Tiny Studio organization
A. public/promptly/privacy/index.html
ok Promptly privacy policy page has exactly one application/ld+json block
ok Promptly privacy policy page JSON-LD block parses as valid JSON
ok Promptly privacy policy page uses the schema.org context
ok Promptly privacy policy page JSON-LD uses an @graph array
ok Promptly privacy policy page page declares a canonical URL
ok Promptly privacy policy page page declares a title
ok Promptly privacy policy page page declares a description
ok Promptly privacy policy page JSON-LD carries the stable Tiny Studio organization reference
ok Promptly privacy policy page JSON-LD declares the page as WebPage
ok Promptly privacy policy page JSON-LD url matches the page canonical URL
ok Promptly privacy policy page JSON-LD name matches the page title
ok Promptly privacy policy page JSON-LD description matches the meta description
ok Promptly privacy policy page JSON-LD page is part of the Tiny Studio website
ok Promptly privacy policy page JSON-LD page is about the Tiny Studio organization
B. npm test/ci wiring
ok npm test runs the public structured data test
ok npm run check delegates to npm test
ok npm run ci runs the public structured data test

31 checks, 0 failures
test-public-heading-hierarchy: card headings are semantic H2s with the former card scale
A. public/contact/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/promptly/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/promptly/privacy/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/drishti/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/drishti/support/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
A. public/privacy-choices/index.html
ok page contains at least one heading
ok page has exactly one H1
ok the H1 is the first heading in the outline
ok the three card headings are H2s inside .info-card articles
ok card H2s plus the footer H2 keep a flat H2 band before the footer H3s
ok no heading-level jump greater than one (no H1 -> H3 skip)
B. card-heading CSS pairing
ok styles.css defines .info-card :is(h2, h3) {
ok card rule keeps margin-top: 12px
ok card rule keeps font-size: clamp(1.65rem, 2vw, 2.35rem)
ok card rule keeps max-width: none
ok global h2 styling (12ch cap) is untouched
ok the old .info-card h3-only rule is replaced by the shared :is(h2, h3) rule
C. npm test/ci wiring
ok npm test runs the public heading hierarchy test
ok npm run ci runs the public heading hierarchy test

44 checks, 0 failures passed: 38 checks plus all downstream suites, including 44 heading checks.

  • passed.
  • No new security findings. reported only pre-existing warnings, including missing-integrity on untouched shared markup lines; no new changed-line findings.

Proof boundary

  • Independent Grok review: ship.
  • Repository and PR proof only; live deploy and browser paint proof remain unverified.
  • No deployment, merge, or external send performed.

Summary by CodeRabbit

  • Accessibility
    • Improved heading hierarchy across Support and Privacy Choices pages by promoting informational card headings to level-two headings.
  • Style
    • Preserved card heading appearance and spacing while ensuring headings display consistently.
  • Tests
    • Expanded public-page checks to verify heading structure and related styling across supported pages.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@nish3451, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 2 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2be9aeb1-c0bc-431a-a828-2fdd3a6b89cb

📥 Commits

Reviewing files that changed from the base of the PR and between c5393a3 and b293c04.

📒 Files selected for processing (1)
  • public/drishti/support/index.html
📝 Walkthrough

Walkthrough

The PR promotes six public info-card headings from H3 to H2, updates shared card-heading styles, and expands heading hierarchy tests across six public pages.

Changes

Public heading hierarchy

Layer / File(s) Summary
Promote card headings to H2
public/drishti/support/index.html, public/privacy-choices/index.html
The six info-card headings now use H2 elements.
Preserve card heading styles
public/styles.css
The shared rule targets H2 and H3 card headings. The global H2 width cap remains unchanged.
Extend hierarchy validation
scripts/test-public-heading-hierarchy.mjs
Tests now validate six pages, three card H2 headings per page, heading order, and the shared CSS rule.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the heading hierarchy repair and preservation of card styling, which are the main changes in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/drishti-support-privacy-heading-hierarchy

Comment @coderabbitai help to get the list of available commands.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5393a3885

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

console.log("test-public-heading-hierarchy: rendered heading outline on the four finding pages")
// Count <h2> used as .info-card card titles (inside <article class="info-card">).
const infoCardTitleCount = (html) =>
(html.match(/<article class="info-card[^"]*"[^>]*>[\s\S]*?<h2\b/gi) || []).length

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the H2 match inside each article

This regex can continue past the matching </article> until it finds any later H2, so it does not establish the containment asserted by the test. For example, moving the third card title immediately after its closing article still produces a count of three, retains four total H2s and creates no level jump, causing every new hierarchy check to pass even though that card has no H2. Limit each match to the article body or inspect each article independently.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/test-public-heading-hierarchy.mjs`:
- Around line 33-35: Update infoCardTitleCount to bound each match from an
`<article class="info-card">` opening tag through its corresponding closing
`</article>`, then count only article bodies containing exactly one H2 heading.
Ensure H2 elements outside the matched article, including later cards or the
footer, cannot satisfy the count.
- Around line 78-79: Update the globalH2 extraction in the heading hierarchy
test to match only a standalone global h2 selector at a CSS rule boundary,
rather than any substring ending in “h2 {”. Preserve the existing max-width
assertion while preventing matches from more specific selectors or comments.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b0f5f283-9233-418a-ad8d-7842a939af31

📥 Commits

Reviewing files that changed from the base of the PR and between b0f5f06 and c5393a3.

📒 Files selected for processing (4)
  • public/drishti/support/index.html
  • public/privacy-choices/index.html
  • public/styles.css
  • scripts/test-public-heading-hierarchy.mjs

Comment on lines +33 to +35
// Count <h2> used as .info-card card titles (inside <article class="info-card">).
const infoCardTitleCount = (html) =>
(html.match(/<article class="info-card[^"]*"[^>]*>[\s\S]*?<h2\b/gi) || []).length

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Scope each card match to its closing </article>.

The current pattern is not bounded by an article end tag. If a card regresses to H3, the match can consume the next card’s or footer’s H2 and still count that card. The test can therefore pass with fewer than three card H2 headings.

Match each article body separately and count articles that contain exactly one H2.

Proposed fix
 const infoCardTitleCount = (html) =>
-  (html.match(/<article class="info-card[^"]*"[^>]*>[\s\S]*?<h2\b/gi) || []).length
+  [...html.matchAll(
+    /<article\b[^>]*class="[^"]*\binfo-card\b[^"]*"[^>]*>([\s\S]*?)<\/article>/gi
+  )].filter(([, body]) => (body.match(/<h2\b/gi) || []).length === 1).length

Also applies to: 55-55

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test-public-heading-hierarchy.mjs` around lines 33 - 35, Update
infoCardTitleCount to bound each match from an `<article class="info-card">`
opening tag through its corresponding closing `</article>`, then count only
article bodies containing exactly one H2 heading. Ensure H2 elements outside the
matched article, including later cards or the footer, cannot satisfy the count.

Comment on lines +78 to +79
const globalH2 = css.match(/h2\s*{[^}]*}/)?.[0] ?? ""
ok(globalH2.includes("max-width: 12ch"), "global h2 styling (12ch cap) is untouched")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Anchor the global H2 assertion to the global selector.

css.match(/h2\s*{[^}]*}/) searches for the substring h2 {. It can match a more specific rule such as .info-card h2 { or a comment. The assertion can pass even when the standalone global H2 rule is missing.

Anchor the match to a rule boundary or parse the selector list.

Proposed fix
-const globalH2 = css.match(/h2\s*{[^}]*}/)?.[0] ?? ""
+const globalH2 =
+  css.match(/(?:^|[}\n])\s*h2\s*{[^}]*}/)?.[0] ?? ""
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const globalH2 = css.match(/h2\s*{[^}]*}/)?.[0] ?? ""
ok(globalH2.includes("max-width: 12ch"), "global h2 styling (12ch cap) is untouched")
const globalH2 =
css.match(/(?:^|[}\n])\s*h2\s*{[^}]*}/)?.[0] ?? ""
ok(globalH2.includes("max-width: 12ch"), "global h2 styling (12ch cap) is untouched")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test-public-heading-hierarchy.mjs` around lines 78 - 79, Update the
globalH2 extraction in the heading hierarchy test to match only a standalone
global h2 selector at a CSS rule boundary, rather than any substring ending in
“h2 {”. Preserve the existing max-width assertion while preventing matches from
more specific selectors or comments.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@nish3451
nish3451 merged commit 9165305 into main Aug 9, 2026
3 checks passed
nish3451 added a commit that referenced this pull request Aug 11, 2026
The skipped-heading-level finding (Drishti support and Privacy Choices
pages) was repaired in source by PR #23 (H1 -> H2 cards, no outline
jumps), and the local suite (test-public-heading-hierarchy.mjs) guards
the worktree HTML. But the live site still serves the June-20 bundle:
both pages jump H1 -> H3 and the deployed stylesheet keeps the old
.info-card h3-only rule, so the finding silently re-opens against
tinystudio.in.

Add scripts/test-public-live-heading-hierarchy.mjs, wired into npm test
and npm run ci: it fetches the deployed pages and stylesheet and
re-asserts the repaired outline (single H1 first, H2 card titles inside
.info-card, flat H2 band before footer H3s, no jumps greater than one)
and the shared .info-card :is(h2, h3) rule. Network-tolerant: skips when
the site is unreachable, fails loudly when it serves stale pages.

verify: node scripts/test-public-live-heading-hierarchy.mjs fails loudly
on the current deployment (19 checks, 11 failures, all stale-deployment
detections), node scripts/test-public-heading-hierarchy.mjs 44 checks 0
failures, npm test otherwise clean, find scripts -name '*.mjs' node
--check clean, git diff --check clean
nish3451 added a commit that referenced this pull request Aug 14, 2026
…23, live blocked on missing Cloudflare token (#166)

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
nish3451 added a commit that referenced this pull request Aug 21, 2026
…nd now verified live (2026-08-21) (#229)

The heading-hierarchy repair for the Drishti support and Privacy Choices
pages is merged on main (PR #23, 9165305) and guarded live (793f162).
With CLOUDFLARE_API_TOKEN provisioned on 2026-08-20, the deploy lane now
runs green and the live site passes all 17 live-guard checks. No source
change needed; this reverify report closes the item.

Co-authored-by: minimax-vps <minimax-vps@MiniMax.local>
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
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