diff --git a/app/(marketing)/about/AboutPageContent.tsx b/app/(marketing)/about/AboutPageContent.tsx index 57741e662..f1f60d48d 100644 --- a/app/(marketing)/about/AboutPageContent.tsx +++ b/app/(marketing)/about/AboutPageContent.tsx @@ -239,7 +239,7 @@ export default function AboutPageContent() {
- {/* Timeline section removed 2026-05-28 — the previous milestone + {/* Timeline section removed 2026-05-28, the previous milestone array claimed customer deployments and framework launches that hadn't actually shipped. Pulled the whole section rather than fabricate a four-year history. /about flows hero diff --git a/app/(marketing)/author/[slug]/page.tsx b/app/(marketing)/author/[slug]/page.tsx index fe37d7b55..c6b2c4e26 100644 --- a/app/(marketing)/author/[slug]/page.tsx +++ b/app/(marketing)/author/[slug]/page.tsx @@ -24,7 +24,7 @@ export async function generateMetadata({ if (!author) { return { title: 'Author not found | FormaOS' }; } - const title = `${author.name} — ${author.role} | FormaOS`; + const title = `${author.name}, ${author.role} | FormaOS`; const description = author.bio.slice(0, 155); return { title, @@ -77,7 +77,7 @@ export default async function AuthorPage({ ]), ] : [ - // Collective bylines emit Organization rather than Person — + // Collective bylines emit Organization rather than Person , // honest signal to crawlers about what the byline represents. { '@context': 'https://schema.org', diff --git a/app/(marketing)/blog/blogData.ts b/app/(marketing)/blog/blogData.ts index 40be89c98..2e2acd98a 100644 --- a/app/(marketing)/blog/blogData.ts +++ b/app/(marketing)/blog/blogData.ts @@ -29,7 +29,7 @@ export type BlogPost = { /** * Last-revised date for the article. Audit row #59 wants * regulatory-content readers to see how current the guidance is, - * not just when it was first published. Optional — falls back to + * not just when it was first published. Optional, falls back to * `date` (the publish date) when a post has not been revised. */ dateModified?: string; @@ -357,7 +357,7 @@ export const blogPosts: BlogPost[] = [ 'Start with the controls that generate the most recurring evidence. Build momentum before expanding across the full control library.', ], steps: [ - 'Select 3–5 high-volume controls that generate repeatable evidence.', + 'Select 3-5 high-volume controls that generate repeatable evidence.', 'Define evidence templates with required fields and owners.', 'Connect workflow systems to capture events automatically.', 'Set quality checks for completeness and data drift.', @@ -528,7 +528,7 @@ export const blogPosts: BlogPost[] = [ 'Monitoring works best when it is embedded in compliance automation and routed to the people who can act quickly.', ], steps: [ - 'Identify the 10–15 most audit-critical controls.', + 'Identify the 10-15 most audit-critical controls.', 'Define signal thresholds and owners for each control.', 'Automate alerts into the tools teams already use.', 'Review signal trends in a weekly compliance stand-up.', @@ -1867,7 +1867,7 @@ export const blogPosts: BlogPost[] = [ title: 'Australian Compliance Frameworks 2026: A Side-by-Side Reference for Multi-Framework Operators', excerpt: - 'How the seven major Australian compliance frameworks compare on structure, regulator, reporting timeframes, and audit cycle — a reference for compliance leaders running multiple obligations in parallel.', + 'How the seven major Australian compliance frameworks compare on structure, regulator, reporting timeframes, and audit cycle, a reference for compliance leaders running multiple obligations in parallel.', author: 'Compliance Strategy', date: 'May 23, 2026', dateModified: 'May 23, 2026', @@ -1878,9 +1878,9 @@ export const blogPosts: BlogPost[] = [ { heading: 'Why this reference exists', paragraphs: [ - 'Most regulated Australian organisations are accountable to more than one framework. A healthcare provider is bound by NSQHS Standards, AHPRA registration requirements for each clinician, and — if it touches federal funding — often the NDIS Practice Standards as well. A fintech operates under an AFS licence (Corporations Act s912A general obligations), reports to AUSTRAC for AML/CTF, and may be APRA-regulated if it deals with bank-adjacent products. A construction principal in NSW carries harmonised WHS obligations under the WHS Act and contractual safety obligations from every Tier 1 client.', - 'Each framework describes similar work — controls, evidence, incidents, training, audits — in different language. The compliance leader running two or three of them in parallel is left translating between vocabularies just to know where they stand.', - 'This is a side-by-side reference of the seven frameworks we see most often in buyer conversations. It is not exhaustive (state-specific layers like SafeWork NSW vs SafeWork Vic add detail), and it is not a substitute for reading the source instruments — it is the orienting picture a compliance program manager can hold in their head while reading the legislation underneath.', + 'Most regulated Australian organisations are accountable to more than one framework. A healthcare provider is bound by NSQHS Standards, AHPRA registration requirements for each clinician, and, if it touches federal funding, often the NDIS Practice Standards as well. A fintech operates under an AFS licence (Corporations Act s912A general obligations), reports to AUSTRAC for AML/CTF, and may be APRA-regulated if it deals with bank-adjacent products. A construction principal in NSW carries harmonised WHS obligations under the WHS Act and contractual safety obligations from every Tier 1 client.', + 'Each framework describes similar work, controls, evidence, incidents, training, audits, in different language. The compliance leader running two or three of them in parallel is left translating between vocabularies just to know where they stand.', + 'This is a side-by-side reference of the seven frameworks we see most often in buyer conversations. It is not exhaustive (state-specific layers like SafeWork NSW vs SafeWork Vic add detail), and it is not a substitute for reading the source instruments, it is the orienting picture a compliance program manager can hold in their head while reading the legislation underneath.', ], }, { @@ -1891,7 +1891,7 @@ export const blogPosts: BlogPost[] = [ ], bullets: [ 'Audit cycle: registered providers are audited against applicable modules on a 3-year accreditation cycle, with mid-cycle surveillance and the option of unannounced visits', - 'Key reporting: SIRS (Serious Incident Reporting Scheme) — Priority incidents within 24 hours, Standard incidents within 5 business days', + 'Key reporting: SIRS (Serious Incident Reporting Scheme), Priority incidents within 24 hours, Standard incidents within 5 business days', 'Worker controls: NDIS Worker Screening Check status tracked per worker (jurisdiction-specific screening units issue clearances)', 'Common audit gaps: incomplete behaviour-support evidence, inconsistent SIRS notification timing, gaps in worker screening renewal tracking', ], @@ -1913,10 +1913,10 @@ export const blogPosts: BlogPost[] = [ heading: 'AHPRA registration (continuing requirements)', paragraphs: [ 'Regulator: AHPRA (Australian Health Practitioner Regulation Agency) administers registration for 16 regulated health professions through profession-specific National Boards (Medical, Nursing and Midwifery, Psychology, Physiotherapy, etc.). Source instrument: Health Practitioner Regulation National Law (the National Law) as enacted in each state.', - 'AHPRA is not a "framework" in the sense the others are — it is a registration regime. But for any healthcare provider, AHPRA continuing professional development (CPD), professional indemnity insurance (PII), recency-of-practice, and English language requirements show up as ongoing compliance obligations that must be tracked per practitioner.', + 'AHPRA is not a "framework" in the sense the others are, it is a registration regime. But for any healthcare provider, AHPRA continuing professional development (CPD), professional indemnity insurance (PII), recency-of-practice, and English language requirements show up as ongoing compliance obligations that must be tracked per practitioner.', ], bullets: [ - 'Registration cycle: annual renewal (typically May–September depending on profession) with audit selection of declared CPD', + 'Registration cycle: annual renewal (typically May-September depending on profession) with audit selection of declared CPD', 'Key reporting: notifications to AHPRA under the National Law (s140 mandatory notifications for impaired practitioners, sexual misconduct, intoxication while practising, significant departure from accepted standards)', 'CPD: profession-specific hour minimums; Medical Board requires 50 hours per year across categories; Nursing and Midwifery Board requires 20 hours per year', 'Common audit gaps: CPD evidence gaps when audited (declarations often outpace documentation), expired PII, expired First Aid certifications for relevant cohorts', @@ -1938,12 +1938,12 @@ export const blogPosts: BlogPost[] = [ { heading: 'Harmonised WHS (Work Health and Safety)', paragraphs: [ - 'Regulator: the WHS regulator in each jurisdiction — SafeWork NSW, WorkSafe Victoria, WorkSafe Queensland, etc. Victoria has not adopted the harmonised WHS Act and remains under the Occupational Health and Safety Act 2004 (Vic) and OHS Regulations 2017 (Vic) — the obligations are similar but not identical. Source instrument (harmonised jurisdictions): Work Health and Safety Act 2011 (Commonwealth) plus the model Work Health and Safety Regulations 2011, enacted by each jurisdiction.', - 'WHS is not a "modular framework" like NDIS or NSQHS — it is a principal duty plus regulatory specifics. The principal duty (s19 WHS Act) is to ensure, so far as is reasonably practicable, the health and safety of workers and others affected by the business. The Regulations specify how that obligation is discharged for specific hazards (high-risk work, hazardous chemicals, construction work, working at heights).', + 'Regulator: the WHS regulator in each jurisdiction, SafeWork NSW, WorkSafe Victoria, WorkSafe Queensland, etc. Victoria has not adopted the harmonised WHS Act and remains under the Occupational Health and Safety Act 2004 (Vic) and OHS Regulations 2017 (Vic), the obligations are similar but not identical. Source instrument (harmonised jurisdictions): Work Health and Safety Act 2011 (Commonwealth) plus the model Work Health and Safety Regulations 2011, enacted by each jurisdiction.', + 'WHS is not a "modular framework" like NDIS or NSQHS, it is a principal duty plus regulatory specifics. The principal duty (s19 WHS Act) is to ensure, so far as is reasonably practicable, the health and safety of workers and others affected by the business. The Regulations specify how that obligation is discharged for specific hazards (high-risk work, hazardous chemicals, construction work, working at heights).', ], bullets: [ 'Audit cycle: triggered by incident notification, complaint, or proactive regulator program (no fixed cycle)', - 'Key reporting: notifiable incidents under WHS Act s35-38 (death of a person, serious injury or illness, dangerous incident) — notifiable to the regulator immediately', + 'Key reporting: notifiable incidents under WHS Act s35-38 (death of a person, serious injury or illness, dangerous incident), notifiable to the regulator immediately', 'Workforce controls: high-risk work licences (HRWL), inductions per Construction Work Code of Practice, SWMS for high-risk construction work', 'Common audit gaps: SWMS document control (versions, acknowledgements), contractor compliance evidence, notifiable-incident timing', ], @@ -1952,11 +1952,11 @@ export const blogPosts: BlogPost[] = [ heading: 'AFS licence (Australian Financial Services licence)', paragraphs: [ 'Regulator: ASIC (Australian Securities and Investments Commission). Source instrument: Corporations Act 2001, with the AFS licence general obligations set out in s912A.', - 'There is no "module" structure. Section 912A imposes 11 ongoing obligations that an AFS licensee must comply with at all times — providing financial services efficiently, honestly and fairly; complying with conditions on the licence; complying with financial services laws; having adequate arrangements to manage conflicts of interest; complying with the dispute resolution requirements; maintaining competence; ensuring representatives are adequately trained; having adequate risk management systems; maintaining adequate financial resources; having a written policy on training. The Reportable Situations regime (formerly breach reporting) is a discrete obligation under Part 7.6 Division 3.', + 'There is no "module" structure. Section 912A imposes 11 ongoing obligations that an AFS licensee must comply with at all times, providing financial services efficiently, honestly and fairly; complying with conditions on the licence; complying with financial services laws; having adequate arrangements to manage conflicts of interest; complying with the dispute resolution requirements; maintaining competence; ensuring representatives are adequately trained; having adequate risk management systems; maintaining adequate financial resources; having a written policy on training. The Reportable Situations regime (formerly breach reporting) is a discrete obligation under Part 7.6 Division 3.', ], bullets: [ 'Audit cycle: ASIC has continuous surveillance powers; financial statements lodged annually with audit', - 'Key reporting: Reportable Situations regime — material breaches lodged with ASIC within 30 days of becoming aware (significantly tighter than the pre-2021 7-business-day regime for some classes)', + 'Key reporting: Reportable Situations regime, material breaches lodged with ASIC within 30 days of becoming aware (significantly tighter than the pre-2021 7-business-day regime for some classes)', 'Workforce controls: representative training to RG 146 (or RG 105 for credit), continuing competence tracked', 'Common audit gaps: training records that lag licensing changes, conflict-of-interest declarations, dispute resolution timing against AFCA targets', ], @@ -1965,7 +1965,7 @@ export const blogPosts: BlogPost[] = [ heading: 'AUSTRAC AML/CTF program', paragraphs: [ 'Regulator: AUSTRAC (Australian Transaction Reports and Analysis Centre). Source instrument: Anti-Money Laundering and Counter-Terrorism Financing Act 2006 and AML/CTF Rules.', - 'A reporting entity must have a written AML/CTF Program — Part A (general program covering ML/TF risk assessment and management) and Part B (customer identification procedures) — and must comply with reporting obligations including Threshold Transaction Reports (TTRs), International Funds Transfer Instructions (IFTIs), and Suspicious Matter Reports (SMRs). The Tranche 2 amendments (commenced 31 March 2026) extend AML/CTF obligations to additional gatekeeper professions — lawyers, accountants, real estate agents, dealers in precious metals and stones — significantly expanding the reporting-entity population.', + 'A reporting entity must have a written AML/CTF Program, Part A (general program covering ML/TF risk assessment and management) and Part B (customer identification procedures), and must comply with reporting obligations including Threshold Transaction Reports (TTRs), International Funds Transfer Instructions (IFTIs), and Suspicious Matter Reports (SMRs). The Tranche 2 amendments (commenced 31 March 2026) extend AML/CTF obligations to additional gatekeeper professions, lawyers, accountants, real estate agents, dealers in precious metals and stones, significantly expanding the reporting-entity population.', ], bullets: [ 'Audit cycle: internal independent reviews of Part A on a schedule appropriate to ML/TF risk; AUSTRAC compliance assessments triggered by reporting or referral', @@ -1980,17 +1980,17 @@ export const blogPosts: BlogPost[] = [ 'For an organisation accountable to multiple frameworks, the operational overlap is larger than the regulatory language implies. Five domains repeat across nearly every framework above:', ], bullets: [ - 'Workforce credentialing — AHPRA registration (NSQHS, healthcare), NDIS Worker Screening (NDIS), Working with Children Check (NQF), HRWL (WHS), RG 146 (AFS), AML/CTF training records (AUSTRAC). One credential graph satisfies five obligations.', - 'Incident reporting — NSQHS sentinel events, NDIS SIRS, NQF s174 incidents, WHS notifiable incidents, AFS Reportable Situations, AUSTRAC SMRs. The intake form differs; the underlying event capture is the same.', - 'Training and competence — every framework requires ongoing training records with audit trail. The hour minimums and content differ; the evidence shape is identical.', - 'Document control — policies, procedures, SWMS, AML/CTF Program documents, IT security policies. Every framework expects version-controlled, acknowledged, currently-valid documents.', - 'Independent assessment — NDIS accreditation auditors, NSQHS accrediting agencies, ACECQA Assessment and Rating, WHS regulator audits, ASIC surveillance, AML/CTF independent reviews. Each is structured differently, but each consumes the same underlying evidence library.', + 'Workforce credentialing, AHPRA registration (NSQHS, healthcare), NDIS Worker Screening (NDIS), Working with Children Check (NQF), HRWL (WHS), RG 146 (AFS), AML/CTF training records (AUSTRAC). One credential graph satisfies five obligations.', + 'Incident reporting, NSQHS sentinel events, NDIS SIRS, NQF s174 incidents, WHS notifiable incidents, AFS Reportable Situations, AUSTRAC SMRs. The intake form differs; the underlying event capture is the same.', + 'Training and competence, every framework requires ongoing training records with audit trail. The hour minimums and content differ; the evidence shape is identical.', + 'Document control, policies, procedures, SWMS, AML/CTF Program documents, IT security policies. Every framework expects version-controlled, acknowledged, currently-valid documents.', + 'Independent assessment, NDIS accreditation auditors, NSQHS accrediting agencies, ACECQA Assessment and Rating, WHS regulator audits, ASIC surveillance, AML/CTF independent reviews. Each is structured differently, but each consumes the same underlying evidence library.', ], }, { heading: 'What this means for the compliance program', paragraphs: [ - 'If your organisation is bound by more than one of these frameworks, the highest-leverage investment is not a per-framework tool — it is an underlying evidence library where each piece of work satisfies the relevant clauses across every framework it touches. A signed policy, a completed training record, an incident closure note, a quarterly access review: each is referenced by one or more frameworks, but the artifact itself is stored once.', + 'If your organisation is bound by more than one of these frameworks, the highest-leverage investment is not a per-framework tool, it is an underlying evidence library where each piece of work satisfies the relevant clauses across every framework it touches. A signed policy, a completed training record, an incident closure note, a quarterly access review: each is referenced by one or more frameworks, but the artifact itself is stored once.', 'That is the operating-system view of compliance: the mapping lives once, the evidence is captured once, and each framework view is a projection over the same graph. Your team stops translating between vocabularies and starts running the work.', ], links: [ @@ -2017,8 +2017,8 @@ export const blogPosts: BlogPost[] = [ { heading: 'Source notes', paragraphs: [ - 'This piece references the source instruments named in each section. Where regulatory thresholds are stated (e.g. SIRS Priority within 24 hours, AFS Reportable Situations within 30 days, AUSTRAC SMRs within 3 business days), the figures are current as of May 2026 and reflect publicly published rules. Where the Tranche 2 AML/CTF expansion is mentioned, the commencement date (31 March 2026) is the date as announced by the Government in the AML/CTF Amendment Act 2024 — readers should verify against the latest AUSTRAC commencement notices for their entity type.', - 'For any operational decision, read the source instrument and your regulator\'s current guidance — not this article.', + 'This piece references the source instruments named in each section. Where regulatory thresholds are stated (e.g. SIRS Priority within 24 hours, AFS Reportable Situations within 30 days, AUSTRAC SMRs within 3 business days), the figures are current as of May 2026 and reflect publicly published rules. Where the Tranche 2 AML/CTF expansion is mentioned, the commencement date (31 March 2026) is the date as announced by the Government in the AML/CTF Amendment Act 2024, readers should verify against the latest AUSTRAC commencement notices for their entity type.', + 'For any operational decision, read the source instrument and your regulator\'s current guidance, not this article.', ], }, ], diff --git a/app/(marketing)/compare/CompareIndexContent.tsx b/app/(marketing)/compare/CompareIndexContent.tsx index c93437d8a..110926d4e 100644 --- a/app/(marketing)/compare/CompareIndexContent.tsx +++ b/app/(marketing)/compare/CompareIndexContent.tsx @@ -132,7 +132,7 @@ export default function CompareIndexContent() {
- {/* What "compliance OS" means vs traditional GRC — SSR'd */} + {/* What "compliance OS" means vs traditional GRC, SSR'd */}
- Operational compliance execution vs clinical governance reporting — + Operational compliance execution vs clinical governance reporting , see why Australian care providers choose FormaOS. diff --git a/app/(marketing)/components/FigmaHomepage.tsx b/app/(marketing)/components/FigmaHomepage.tsx index 447b87da2..fe2e939af 100644 --- a/app/(marketing)/components/FigmaHomepage.tsx +++ b/app/(marketing)/components/FigmaHomepage.tsx @@ -197,7 +197,7 @@ export default function FormaOSHomepage({ , 200, )} - {/* Cryptographic audit-chain proof — pulled to position 3 + {/* Cryptographic audit-chain proof, pulled to position 3 (after hero + framework strip) on 2026-05-28 to surface the most code-grounded section early. Before, this sat below 8 marketing-feature sections; a buyer scrolling diff --git a/app/(marketing)/components/Footer.tsx b/app/(marketing)/components/Footer.tsx index f5fed2e7f..83107027b 100644 --- a/app/(marketing)/components/Footer.tsx +++ b/app/(marketing)/components/Footer.tsx @@ -169,7 +169,7 @@ export function Footer() { {/* Main Footer Content */}
- {/* Brand column — wider */} + {/* Brand column, wider */}
{brand.address.locality}, {brand.address.region}, {brand.address.country}
- {/* /status badge removed 2026-05-13 — was hardcoded + {/* /status badge removed 2026-05-13, was hardcoded "All systems operational" against 0% uptime data. Route will return when a real status provider is wired. */} diff --git a/app/(marketing)/components/HeroStaticShell.tsx b/app/(marketing)/components/HeroStaticShell.tsx index 9a51bcdcc..f752f4796 100644 --- a/app/(marketing)/components/HeroStaticShell.tsx +++ b/app/(marketing)/components/HeroStaticShell.tsx @@ -20,7 +20,7 @@ const heroCopy = DEFAULT_RUNTIME_MARKETING.hero; // 2026-05-23 (SEO sprint): the primary CTA path used to be rewritten // onto `brand.seo.appUrl` (app.formaos.com.au), which sent every hero // click through a wasted 308 hop and exposed the app subdomain as the -// CTA target. /contact is a marketing route — keep it relative so the +// CTA target. /contact is a marketing route, keep it relative so the // click stays on the canonical www host. const primaryExternal = /^https?:\/\//i.test(heroCopy.primaryCtaHref); const secondaryExternal = /^https?:\/\//i.test(heroCopy.secondaryCtaHref); @@ -52,7 +52,7 @@ export function HeroStaticShell() {
- {/* Eyebrow — restrained typographic label flanked by hairlines, + {/* Eyebrow, restrained typographic label flanked by hairlines, no pill / icon / colour. */}
diff --git a/app/(marketing)/components/HomeProofStaticShell.tsx b/app/(marketing)/components/HomeProofStaticShell.tsx index 0b095e587..f1a07e80e 100644 --- a/app/(marketing)/components/HomeProofStaticShell.tsx +++ b/app/(marketing)/components/HomeProofStaticShell.tsx @@ -11,7 +11,7 @@ const signatureEase: [number, number, number, number] = [ ] as [number, number, number, number]; /* ════════════════════════════════════════════════════════════ - Data — three audiences, one evaluation. No per-card colour + Data, three audiences, one evaluation. No per-card colour identity: the palette stays monochrome so the copy carries it. ════════════════════════════════════════════════════════════ */ @@ -20,7 +20,7 @@ const PROOF_BLOCKS = [ icon: FileCheck2, eyebrow: 'For operators', title: 'Controls run as workflows, not as documents', - body: 'Named tasks, approval gates, and evidence chains execute inside daily operations — not in a separate compliance layer.', + body: 'Named tasks, approval gates, and evidence chains execute inside daily operations, not in a separate compliance layer.', href: '/product', cta: 'See how it works', step: '01', @@ -46,7 +46,7 @@ const PROOF_BLOCKS = [ ] as const; /* ════════════════════════════════════════════════════════════ - Card — restrained surface, hairline border, quiet hover lift. + Card, restrained surface, hairline border, quiet hover lift. ════════════════════════════════════════════════════════════ */ function ConvictionCard({ @@ -71,7 +71,7 @@ function ConvictionCard({ }} className="group relative flex h-full flex-col rounded-2xl border border-white/[0.08] bg-white/[0.02] p-7 transition-colors duration-300 hover:border-white/20 sm:p-8" > - {/* Quiet step index — typographic, not a watermark gimmick */} + {/* Quiet step index, typographic, not a watermark gimmick */} {block.step} @@ -117,7 +117,7 @@ export function HomeProofStaticShell() { ref={sectionRef} className="relative z-10 overflow-hidden bg-slate-950 px-6 pt-20 pb-4 sm:px-8 sm:pt-24 sm:pb-6 lg:px-12 lg:pt-28 lg:pb-8" > - {/* Single hairline top seam — no rainbow edge glow */} + {/* Single hairline top seam, no rainbow edge glow */}
diff --git a/app/(marketing)/components/MobileNav.tsx b/app/(marketing)/components/MobileNav.tsx index 95a284de1..e4d30d9a1 100644 --- a/app/(marketing)/components/MobileNav.tsx +++ b/app/(marketing)/components/MobileNav.tsx @@ -216,7 +216,7 @@ export function MobileNav() {
- {/* Pull indicator — native sheet affordance */} + {/* Pull indicator, native sheet affordance */}
diff --git a/app/(marketing)/components/homepage/AuditChainSection.tsx b/app/(marketing)/components/homepage/AuditChainSection.tsx index 15736d073..eb985520e 100644 --- a/app/(marketing)/components/homepage/AuditChainSection.tsx +++ b/app/(marketing)/components/homepage/AuditChainSection.tsx @@ -19,13 +19,13 @@ const PILLARS = [ icon: History, title: 'External anchor at 05:30 UTC', tag: 'Verifiable without trusting us', - body: "Daily, each org's chain top is submitted to Sigstore Rekor as an RFC 6962-style Merkle entry. An auditor can verify the timestamp of any event without trusting us — the proof goes through Linux Foundation infrastructure.", + body: "Daily, each org's chain top is submitted to Sigstore Rekor as an RFC 6962-style Merkle entry. An auditor can verify the timestamp of any event without trusting us, the proof goes through Linux Foundation infrastructure.", }, { icon: ShieldCheck, title: 'Append-only at the database', tag: 'Immutable, even to platform admins', - body: 'A BEFORE UPDATE OR DELETE trigger rejects any mutation of audit rows, backed by restrictive RLS deny policies. Even a platform admin with service-role credentials — which bypasses RLS — is stopped by the trigger. Enforced by Postgres, not application code.', + body: 'A BEFORE UPDATE OR DELETE trigger rejects any mutation of audit rows, backed by restrictive RLS deny policies. Even a platform admin with service-role credentials, which bypasses RLS, is stopped by the trigger. Enforced by Postgres, not application code.', }, ] as const; @@ -81,7 +81,7 @@ function AuditBoard({ children }: { children: ReactNode }) { st.x += (st.target - st.x) * Math.min(1, dt * 6); bot.style.left = `${st.x}%`; - // Eye tracking — pupils ease toward the cursor while hovering. + // Eye tracking, pupils ease toward the cursor while hovering. const rect = board.getBoundingClientRect(); const cx = rect.left + (st.x / 100) * rect.width; const cy = rect.top; @@ -221,7 +221,7 @@ export function AuditChainSection() {
- {/* Header — matches the "Operational mechanics" section */} + {/* Header, matches the "Operational mechanics" section */}

@@ -232,7 +232,7 @@ export function AuditChainSection() {

Every org's audit log is hash-chained, RLS-locked against - mutation, and anchored daily to Sigstore Rekor — the same + mutation, and anchored daily to Sigstore Rekor, the same append-only transparency log the Linux Foundation runs for signed open-source releases.

@@ -273,7 +273,7 @@ export function AuditChainSection() {
- {/* Facts bar — the technical primitives, hairline-divided */} + {/* Facts bar, the technical primitives, hairline-divided */}
{CHAIN_FACTS.map((fact) => ( diff --git a/app/(marketing)/components/homepage/CTASection.tsx b/app/(marketing)/components/homepage/CTASection.tsx index 06af64699..f5612dccb 100644 --- a/app/(marketing)/components/homepage/CTASection.tsx +++ b/app/(marketing)/components/homepage/CTASection.tsx @@ -41,7 +41,7 @@ export function CTASection() {
- {/* Subtle background glow — monochrome, single neutral wash */} + {/* Subtle background glow, monochrome, single neutral wash */}
diff --git a/app/(marketing)/components/homepage/CapabilitiesGrid.tsx b/app/(marketing)/components/homepage/CapabilitiesGrid.tsx index 8e2f50e94..266798cff 100644 --- a/app/(marketing)/components/homepage/CapabilitiesGrid.tsx +++ b/app/(marketing)/components/homepage/CapabilitiesGrid.tsx @@ -31,7 +31,7 @@ const capabilities = [ icon: GitBranch, title: '9 Framework Packs', description: - 'SOC 2, ISO 27001, GDPR, HIPAA, PCI-DSS, NIST CSF, CIS Controls, NDIS Practice Standards, and Essential Eight — pre-built.', + 'SOC 2, ISO 27001, GDPR, HIPAA, PCI-DSS, NIST CSF, CIS Controls, NDIS Practice Standards, and Essential Eight, pre-built.', }, { icon: Shield, @@ -61,7 +61,7 @@ const capabilities = [ icon: Bot, title: 'AI Compliance Assistant', description: - 'Context-aware AI that drafts policies, runs gap analysis, and gives actionable steps — powered by your live org data.', + 'Context-aware AI that drafts policies, runs gap analysis, and gives actionable steps, powered by your live org data.', }, ]; diff --git a/app/(marketing)/components/homepage/ComplianceEngineDemo.tsx b/app/(marketing)/components/homepage/ComplianceEngineDemo.tsx index 347213e94..75f69d2d4 100644 --- a/app/(marketing)/components/homepage/ComplianceEngineDemo.tsx +++ b/app/(marketing)/components/homepage/ComplianceEngineDemo.tsx @@ -84,7 +84,7 @@ export function ComplianceEngineDemo() {

- One connected lifecycle — obligations become controls, controls + One connected lifecycle, obligations become controls, controls generate tasks, tasks produce evidence, and every step stays audit-ready.

diff --git a/app/(marketing)/components/homepage/ComplianceNetworkSection.tsx b/app/(marketing)/components/homepage/ComplianceNetworkSection.tsx index eb856ebe9..93d14e09f 100644 --- a/app/(marketing)/components/homepage/ComplianceNetworkSection.tsx +++ b/app/(marketing)/components/homepage/ComplianceNetworkSection.tsx @@ -37,12 +37,12 @@ export function ComplianceNetworkSection() {
- {/* Editorial header — asymmetric, left-aligned. A labelled rule and a + {/* Editorial header, asymmetric, left-aligned. A labelled rule and a paired description column replace the centred eyebrow-pill template. */}
- {/* Eyebrow as a relationship chain — previews the graph below and + {/* Eyebrow as a relationship chain, previews the graph below and differentiates this header from the labelled-rule used by the sections above it. */}
diff --git a/app/(marketing)/components/homepage/Industries.tsx b/app/(marketing)/components/homepage/Industries.tsx index b694585fd..a37eb9a01 100644 --- a/app/(marketing)/components/homepage/Industries.tsx +++ b/app/(marketing)/components/homepage/Industries.tsx @@ -41,7 +41,7 @@ const signatureEase: [number, number, number, number] = [ ] as [number, number, number, number]; /* ════════════════════════════════════════════════════════════ - Accent system — monochrome. No per-industry colour identity: + Accent system, monochrome. No per-industry colour identity: surfaces stay white/slate so the copy and structure carry it. ════════════════════════════════════════════════════════════ */ @@ -64,7 +64,7 @@ const ACCENT_MAP: Record = { }; /* ════════════════════════════════════════════════════════════ - Data — visual-first: stats, frameworks, short tagline + Data, visual-first: stats, frameworks, short tagline ════════════════════════════════════════════════════════════ */ interface StatItem { @@ -98,7 +98,7 @@ const industrySolutions: IndustrySolution[] = [ title: 'Healthcare', subtitle: 'HIPAA · RACGP · AHPRA · NSQHS', tagline: - 'Patient safety evidence and clinical governance — audit-ready in minutes, not weeks.', + 'Patient safety evidence and clinical governance, audit-ready in minutes, not weeks.', accent: 'rose', frameworks: ['RACGP', 'AHPRA', 'NSQHS', 'HIPAA'], stats: [ @@ -131,7 +131,7 @@ const industrySolutions: IndustrySolution[] = [ title: 'NDIS Providers', subtitle: 'NDIS Practice Standards · Quality & Safeguards Commission', tagline: - 'Safeguarding registers, worker screening, and incident timelines — built for Commission audits.', + 'Safeguarding registers, worker screening, and incident timelines, built for Commission audits.', accent: 'violet', frameworks: ['NDIS Practice Standards', 'Q&S Commission'], stats: [ @@ -164,7 +164,7 @@ const industrySolutions: IndustrySolution[] = [ title: 'Mental Health Services', subtitle: 'National Standards for Mental Health Services (NSMHS)', tagline: - 'Consumer rights, restrictive-practice governance, and reportable incident timelines — evidenced continuously, not reconstructed for review.', + 'Consumer rights, restrictive-practice governance, and reportable incident timelines, evidenced continuously, not reconstructed for review.', accent: 'violet', frameworks: ['NSMHS', 'Restrictive Practices', 'Reportable Incidents'], stats: [ @@ -200,7 +200,7 @@ const industrySolutions: IndustrySolution[] = [ title: 'Financial Services', subtitle: 'SOC 2 · ISO 27001 · ASIC · APRA', tagline: - 'Multi-framework compliance packs with cross-mapping — one evidence item, multiple frameworks.', + 'Multi-framework compliance packs with cross-mapping, one evidence item, multiple frameworks.', accent: 'amber', frameworks: ['SOC 2', 'ISO 27001', 'PCI-DSS', 'APRA CPS 230'], stats: [ @@ -236,7 +236,7 @@ const industrySolutions: IndustrySolution[] = [ title: 'Education & Accreditation', subtitle: 'TEQSA · ASQA · RTO Standards · VRQA', tagline: - 'Academic governance and trainer credentials — evidence organized by standard for instant retrieval.', + 'Academic governance and trainer credentials, evidence organized by standard for instant retrieval.', accent: 'cyan', frameworks: ['TEQSA', 'ASQA', 'RTO Standards', 'VRQA'], stats: [ @@ -269,7 +269,7 @@ const industrySolutions: IndustrySolution[] = [ title: 'Government & Public Sector', subtitle: 'FOI · ISM · PSPF · Essential Eight', tagline: - 'Decision registers, FOI tracking, and Essential Eight maturity — every action documented and defensible.', + 'Decision registers, FOI tracking, and Essential Eight maturity, every action documented and defensible.', accent: 'indigo', frameworks: ['ISM', 'PSPF', 'Essential Eight', 'FOI Act'], stats: [ @@ -303,7 +303,7 @@ const industrySolutions: IndustrySolution[] = [ ]; /* ════════════════════════════════════════════════════════════ - StatCard — big visual metric + StatCard, big visual metric ════════════════════════════════════════════════════════════ */ const StatCard = memo(function StatCard({ @@ -343,7 +343,7 @@ const StatCard = memo(function StatCard({ }); /* ════════════════════════════════════════════════════════════ - CapabilityCard — compact visual card + CapabilityCard, compact visual card ════════════════════════════════════════════════════════════ */ const CapabilityCard = memo(function CapabilityCard({ @@ -490,7 +490,7 @@ const AccordionItem = memo(function AccordionItem({
- {/* Expanded panel — visual-first layout */} + {/* Expanded panel, visual-first layout */} {isExpanded && (
- {/* Row 2: Stats grid — the visual punch */} + {/* Row 2: Stats grid, the visual punch */}
{solution.stats.map((stat, i) => (
- {/* Editorial header — asymmetric, left-aligned. A labelled rule and a + {/* Editorial header, asymmetric, left-aligned. A labelled rule and a paired description column replace the centred eyebrow-pill template. */}
- {/* Editorial header — asymmetric, left-aligned. A labelled rule and a + {/* Editorial header, asymmetric, left-aligned. A labelled rule and a paired description column replace the centred eyebrow-pill template. */}
@@ -101,7 +101,7 @@ export function ObjectionHandlingSection() {

- From evaluation to procurement — no blockers + From evaluation to procurement, no blockers

diff --git a/app/(marketing)/components/homepage/OutcomeProofSection.tsx b/app/(marketing)/components/homepage/OutcomeProofSection.tsx index b260f2900..a04b06ca3 100644 --- a/app/(marketing)/components/homepage/OutcomeProofSection.tsx +++ b/app/(marketing)/components/homepage/OutcomeProofSection.tsx @@ -51,7 +51,7 @@ const outcomeStats = [ type Scenario = (typeof proofScenarios)[number]; -// The cards plus an automation "agent" that travels along a track above them — +// The cards plus an automation "agent" that travels along a track above them , // a literal stand-in for the crons/evaluators working the scenarios below. // It auto-patrols when idle and chases the cursor while the mouse is over the // board (eased, not 1:1). Monochrome + soft glow to stay on-brand; lg-only (the @@ -103,7 +103,7 @@ function ScenarioBoard({ children }: { children: ReactNode }) { const rect = board.getBoundingClientRect(); const pct = ((e.clientX - rect.left) / rect.width) * 100; st.target = Math.max(8, Math.min(92, pct)); - // Any movement over the board counts as hovering — more reliable than + // Any movement over the board counts as hovering, more reliable than // depending on mouseenter firing first. if (!st.hovering) { st.hovering = true; @@ -169,7 +169,7 @@ function ScenarioCard({ scenario }: { scenario: Scenario }) { {/* Before / After toggle */}
- {/* Body — swaps with the toggle; min-height keeps the row from jumping */} + {/* Body, swaps with the toggle; min-height keeps the row from jumping */}

- {/* State line — reflects the active side */} + {/* State line, reflects the active side */}

diff --git a/app/(marketing)/components/homepage/SecuritySection.tsx b/app/(marketing)/components/homepage/SecuritySection.tsx index aaa543b96..97e37fac2 100644 --- a/app/(marketing)/components/homepage/SecuritySection.tsx +++ b/app/(marketing)/components/homepage/SecuritySection.tsx @@ -30,7 +30,7 @@ const signatureEase: [number, number, number, number] = [ ] as [number, number, number, number]; /* ════════════════════════════════════════════════════════════ - Shared — GlassCard with 3D tilt + spotlight + Shared, GlassCard with 3D tilt + spotlight ════════════════════════════════════════════════════════════ */ function GlassCard({ @@ -98,7 +98,7 @@ function AnimatedCounter({ } /* ════════════════════════════════════════════════════════════ - PostureRing — animated SVG security score + PostureRing, animated SVG security score ════════════════════════════════════════════════════════════ */ function PostureRing({ @@ -171,7 +171,7 @@ function PostureRing({ - {/* Center score — number only, nothing else inside the ring */} + {/* Center score, number only, nothing else inside the ring */}

- {/* Illustrative score — caveat sits below the ring, never inside it. */} + {/* Illustrative score, caveat sits below the ring, never inside it. */}

Composite posture · illustrative @@ -352,7 +352,7 @@ const PostureCard = memo(function PostureCard({ }); /* ════════════════════════════════════════════════════════════ - EncryptionCard — visual lock + layer status + EncryptionCard, visual lock + layer status ════════════════════════════════════════════════════════════ */ const EncryptionCard = memo(function EncryptionCard({ @@ -403,7 +403,7 @@ const EncryptionCard = memo(function EncryptionCard({ }); /* ════════════════════════════════════════════════════════════ - AccessCard — identity & access control + AccessCard, identity & access control ════════════════════════════════════════════════════════════ */ const AccessCard = memo(function AccessCard({ @@ -458,7 +458,7 @@ const AccessCard = memo(function AccessCard({ }); /* ════════════════════════════════════════════════════════════ - AuditLogCard — audit-trail event types (not a live feed) + AuditLogCard, audit-trail event types (not a live feed) ════════════════════════════════════════════════════════════ */ const AuditLogCard = memo(function AuditLogCard({ @@ -476,7 +476,7 @@ const AuditLogCard = memo(function AuditLogCard({ isInView={isInView} >

- {/* Header — describes what the trail captures, not a live feed */} + {/* Header, describes what the trail captures, not a live feed */}
What the audit trail captures @@ -486,7 +486,7 @@ const AuditLogCard = memo(function AuditLogCard({
- {/* Entries — horizontal grid on desktop */} + {/* Entries, horizontal grid on desktop */}
{AUDIT_LOG_ENTRIES.map((entry, i) => (
- {/* Editorial header — asymmetric, left-aligned. A labelled rule and a + {/* Editorial header, asymmetric, left-aligned. A labelled rule and a paired description column replace the centred eyebrow-pill template. */}

Controls are enforced, not just documented. Encryption, identity - governance, and tamper-evident audit logs are infrastructure — not + governance, and tamper-evident audit logs are infrastructure, not add-ons.

@@ -714,7 +714,7 @@ export const SecuritySection = memo(function SecuritySection() { - {/* Row 3: AuditLog — full width */} + {/* Row 3: AuditLog, full width */}
diff --git a/app/(marketing)/components/homepage/ValueProposition.tsx b/app/(marketing)/components/homepage/ValueProposition.tsx index bb60592b9..363f725d8 100644 --- a/app/(marketing)/components/homepage/ValueProposition.tsx +++ b/app/(marketing)/components/homepage/ValueProposition.tsx @@ -43,7 +43,7 @@ function GlassCard({ className={className} >
- {/* Top accent — brightens on hover */} + {/* Top accent, brightens on hover */}
- {/* Center text — number only, no label crowding the ring */} + {/* Center text, number only, no label crowding the ring */}
- {/* Illustrative posture screen — per-framework rows */} + {/* Illustrative posture screen, per-framework rows */}
{frameworks.map((f, i) => (
- Missing approval — A.9.2 Access Control + Missing approval, A.9.2 Access Control
@@ -289,7 +289,7 @@ function EnforcementCard({ Approved
- Control satisfied — CC6.1 Logical Access + Control satisfied, CC6.1 Logical Access
@@ -311,7 +311,7 @@ function EnforcementCard({ Approved
- Evidence attached — HIPAA §164.312 + Evidence attached, HIPAA §164.312
@@ -324,12 +324,12 @@ function EnforcementCard({ Card 3: Evidence Chain ════════════════════════════════════════════════════════════ */ -// Illustrative timeline — generic role labels, no invented names. +// Illustrative timeline, generic role labels, no invented names. const EVIDENCE_EVENTS = [ { text: 'Control created', time: 'Day 0', color: 'bg-slate-500' }, - { text: 'Evidence uploaded — by named owner', time: 'Day 3', color: 'bg-slate-400' }, - { text: 'Review approved — by control reviewer', time: 'Day 4', color: 'bg-slate-400' }, - { text: 'Hash anchored — Sigstore Rekor entry', time: 'Day 5', color: 'bg-slate-300' }, + { text: 'Evidence uploaded, by named owner', time: 'Day 3', color: 'bg-slate-400' }, + { text: 'Review approved, by control reviewer', time: 'Day 4', color: 'bg-slate-400' }, + { text: 'Hash anchored, Sigstore Rekor entry', time: 'Day 5', color: 'bg-slate-300' }, ] as const; function EvidenceCard({ @@ -406,7 +406,7 @@ function EvidenceCard({ ════════════════════════════════════════════════════════════ */ // Designer feedback 2026-05-27 specifically called out "Priya M." / "Sarah L." -// as stock SaaS personas. Replaced with role-only labels — no invented +// as stock SaaS personas. Replaced with role-only labels, no invented // names, no invented headshots-by-initials. Real customer assignments live // inside the product, never in marketing copy. const OWNERS = [ @@ -504,7 +504,7 @@ function AuditCard({

Audit-Ready

- Export complete audit packets — evidence, ownership, control history — + Export complete audit packets, evidence, ownership, control history , without scrambling.

@@ -571,7 +571,7 @@ export function ValueProposition() {
- {/* Editorial header — asymmetric, left-aligned. A labelled rule and a + {/* Editorial header, asymmetric, left-aligned. A labelled rule and a paired description column replace the centred eyebrow-pill template. */}

Other tools store documents. FormaOS enforces your compliance - program — controls are gated, ownership is structural, and evidence + program, controls are gated, ownership is structural, and evidence is generated as teams operate.

diff --git a/app/(marketing)/components/shared/DeferredSection.tsx b/app/(marketing)/components/shared/DeferredSection.tsx index 90f1dc228..77a80f632 100644 --- a/app/(marketing)/components/shared/DeferredSection.tsx +++ b/app/(marketing)/components/shared/DeferredSection.tsx @@ -5,9 +5,9 @@ interface DeferredSectionProps { className?: string; /** Reserve intrinsic size to keep CLS low while content paints lazily. */ minHeight?: number; - /** Retained for backwards compatibility — no longer used. */ + /** Retained for backwards compatibility, no longer used. */ rootMargin?: string; - /** Retained for backwards compatibility — no longer used. */ + /** Retained for backwards compatibility, no longer used. */ fallback?: ReactNode; } diff --git a/app/(marketing)/components/shared/KeyFacts.tsx b/app/(marketing)/components/shared/KeyFacts.tsx index 64bfe52d5..086352119 100644 --- a/app/(marketing)/components/shared/KeyFacts.tsx +++ b/app/(marketing)/components/shared/KeyFacts.tsx @@ -1,7 +1,7 @@ import { CheckCircle2 } from 'lucide-react'; /** - * KeyFacts — a TLDR / "key facts" block placed near the top of long + * KeyFacts, a TLDR / "key facts" block placed near the top of long * marketing pages. SSR-rendered (no client component) so it always * lands in the initial HTML response. * @@ -21,7 +21,7 @@ export interface KeyFactsProps { title?: string; /** Brief intro sentence under the heading. Keep ≤200 chars. */ summary: string; - /** 4–8 atomic facts. Each label is bold, value is the citable claim. */ + /** 4-8 atomic facts. Each label is bold, value is the citable claim. */ facts: KeyFactsItem[]; } diff --git a/app/(marketing)/contact/ContactPageContentNew.tsx b/app/(marketing)/contact/ContactPageContentNew.tsx index 863ddfa72..ca51924c6 100644 --- a/app/(marketing)/contact/ContactPageContentNew.tsx +++ b/app/(marketing)/contact/ContactPageContentNew.tsx @@ -438,7 +438,7 @@ function ContactForm({ submitAction }: ContactFormProps) { // doesn't linger after the user fixes it. const [fieldErrors, setFieldErrors] = useState>({}); - // Same email shape the server action uses (see actions.ts:10) — + // Same email shape the server action uses (see actions.ts:10) , // mirroring it client-side keeps the two checks aligned. const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/; diff --git a/app/(marketing)/customer-stories/CustomerStoriesContent.tsx b/app/(marketing)/customer-stories/CustomerStoriesContent.tsx index 319eb0180..a9e7201ca 100644 --- a/app/(marketing)/customer-stories/CustomerStoriesContent.tsx +++ b/app/(marketing)/customer-stories/CustomerStoriesContent.tsx @@ -16,7 +16,7 @@ import { PUBLIC_CTA_LABELS, } from '@/lib/marketing/cta'; -// Illustrative use-case scenarios — not anonymised customer histories. +// Illustrative use-case scenarios, not anonymised customer histories. // Each one describes how FormaOS would land in a buyer of this shape, // using product capabilities that are actually shipping. Framework // labels reflect what's in lib/compliance/evaluators/register.ts: only @@ -172,7 +172,7 @@ export default function CustomerStoriesContent() {
- {/* Quote block removed 2026-05-28 — the previous + {/* Quote block removed 2026-05-28, the previous quotes ("- Head of Quality & Compliance", etc.) read as anonymised customer testimonials, but there are no real customer deployments behind them. These diff --git a/app/(marketing)/enterprise/EnterprisePageContent.tsx b/app/(marketing)/enterprise/EnterprisePageContent.tsx index f84b83824..b3a8b6d1e 100644 --- a/app/(marketing)/enterprise/EnterprisePageContent.tsx +++ b/app/(marketing)/enterprise/EnterprisePageContent.tsx @@ -46,7 +46,7 @@ import { demoHref, PUBLIC_CTA_LABELS, salesHref } from '@/lib/marketing/cta'; const EASE_OUT_EXPO: [number, number, number, number] = [0.22, 1, 0.36, 1]; /* ─── Section Headers ───────────────────────────────────────── - Two restrained header treatments — a centred-minimal label and an + Two restrained header treatments, a centred-minimal label and an editorial left-aligned label flanked by a hairline rule. Sections alternate between them so the page does not read as one repeated template. @@ -747,7 +747,7 @@ function SecurityArchitecture() { /* ─── Interactive defense-in-depth flow ─────────────────────── Trace a request through all five gates, or attempt a bypass and watch - it get stopped at the first one — "no bypass path" demonstrated, not + it get stopped at the first one, "no bypass path" demonstrated, not asserted. Reuses the securityLayers data. */ type FlowMode = 'idle' | 'trace' | 'bypass'; diff --git a/app/(marketing)/features/FeaturesPageContent.tsx b/app/(marketing)/features/FeaturesPageContent.tsx index 0a04c7d01..b401c252a 100644 --- a/app/(marketing)/features/FeaturesPageContent.tsx +++ b/app/(marketing)/features/FeaturesPageContent.tsx @@ -102,7 +102,7 @@ function CenteredHeader({ ); } -// Left vertical-bar header — third variant so the centered template +// Left vertical-bar header, third variant so the centered template // never repeats on adjacent sections. function BarHeader({ label, @@ -2171,7 +2171,7 @@ function FeatureSystemMap() { })}

- ↻ the loop closes — AI & Certification feeds back into Compliance Core + ↻ the loop closes, AI & Certification feeds back into Compliance Core

{/* Detail panel */} @@ -2272,7 +2272,7 @@ export default function FeaturesPageContent() { {/* Server-rendered feature catalog (audit #28). Lives outside DeferredSection so every feature title is in the initial SSR - HTML — crawlers index the names, sighted users get a quick + HTML, crawlers index the names, sighted users get a quick skimmable list before the heavy interactive grid mounts. */} diff --git a/app/(marketing)/features/pillars/opengraph-image.tsx b/app/(marketing)/features/pillars/opengraph-image.tsx index 17a3df99e..dd68f7362 100644 --- a/app/(marketing)/features/pillars/opengraph-image.tsx +++ b/app/(marketing)/features/pillars/opengraph-image.tsx @@ -1,15 +1,15 @@ import { renderOg, ogSize, ogContentType } from '../../_og/template'; export const runtime = 'edge'; -export const alt = 'FormaOS - Features — 5 Pillars'; +export const alt = 'FormaOS - Features, 5 Pillars'; export const size = ogSize; export const contentType = ogContentType; export default function Image() { return renderOg({ eyebrow: 'Platform Features', - headline: 'Features — 5 Pillars', - subhead: 'One OS for every obligation you owe. Compliance, evidence, tasks, care operations, and trust — governed end-to-end.', + headline: 'Features, 5 Pillars', + subhead: 'One OS for every obligation you owe. Compliance, evidence, tasks, care operations, and trust, governed end-to-end.', badges: ['25 features', '5 pillars'], accent: 'cyan', }); diff --git a/app/(marketing)/features/pillars/page.tsx b/app/(marketing)/features/pillars/page.tsx index dab969431..a97a86b75 100644 --- a/app/(marketing)/features/pillars/page.tsx +++ b/app/(marketing)/features/pillars/page.tsx @@ -265,7 +265,7 @@ export default function FeaturesPillarsPage() { isOdd ? 'lg:[&>*:first-child]:order-2' : '' }`} > - {/* Left — title + lede */} + {/* Left, title + lede */}
- {/* Right — feature grid */} + {/* Right, feature grid */}
    {pillar.features.map((f) => (
  • - {/* Cross-mapping explainer — SSR'd, no DeferredSection gating */} + {/* Cross-mapping explainer, SSR'd, no DeferredSection gating */}
    • - Contractual necessity — + Contractual necessity , providing the service you signed up for
    • - Legal obligations — + Legal obligations , regulatory record-keeping and audit trails
    • - Legitimate interest — + Legitimate interest , securing the platform, preventing abuse, and improving the product without undue impact on your privacy
    • diff --git a/app/(marketing)/mental-health-compliance/page.tsx b/app/(marketing)/mental-health-compliance/page.tsx index 28b1e00eb..cee6fea8c 100644 --- a/app/(marketing)/mental-health-compliance/page.tsx +++ b/app/(marketing)/mental-health-compliance/page.tsx @@ -15,7 +15,7 @@ const mentalHealthFaqSchema = faqSchema([ question: 'Does FormaOS cover the National Standards for Mental Health Services?', answer: - 'Yes. FormaOS ships the NSMHS as a pre-built framework so your obligations across the ten standards are mapped from day one — no manual setup required.', + 'Yes. FormaOS ships the NSMHS as a pre-built framework so your obligations across the ten standards are mapped from day one, no manual setup required.', }, { question: 'Can FormaOS track restrictive practices?', @@ -25,7 +25,7 @@ const mentalHealthFaqSchema = faqSchema([ { question: 'How does FormaOS handle reportable incidents?', answer: - 'FormaOS tracks reportable incidents through a structured pipeline — report, investigation, notification, and closure — with notification timers and submission status so deadlines are not missed.', + 'FormaOS tracks reportable incidents through a structured pipeline, report, investigation, notification, and closure, with notification timers and submission status so deadlines are not missed.', }, { question: 'Does FormaOS track worker screening for clinical staff?', diff --git a/app/(marketing)/ndis-providers/page.tsx b/app/(marketing)/ndis-providers/page.tsx index a01aeed88..71415baca 100644 --- a/app/(marketing)/ndis-providers/page.tsx +++ b/app/(marketing)/ndis-providers/page.tsx @@ -112,7 +112,7 @@ export default function NDISProvidersPage() { ndisServiceSchema, ndisFaqSchema, ]} /> - {/* AEO key-facts block — renders in initial SSR HTML so AI answer + {/* AEO key-facts block, renders in initial SSR HTML so AI answer engines and procurement scanners hit citable claims first. */} diff --git a/app/(marketing)/pricing/PricingPageContent.tsx b/app/(marketing)/pricing/PricingPageContent.tsx index 25c348709..c47cbbfda 100644 --- a/app/(marketing)/pricing/PricingPageContent.tsx +++ b/app/(marketing)/pricing/PricingPageContent.tsx @@ -19,7 +19,7 @@ import { } from './components'; /** - * Scope explorer — replaces the old three-identical-card "How pricing + * Scope explorer, replaces the old three-identical-card "How pricing * works" grid with an interactive recommender (PlanFinder). Priced by * compliance scope, not feature unlocks: the inputs map to real plan * limits and surface the tier your scope actually requires. @@ -31,7 +31,7 @@ function PlanScopeSection() {
      - {/* Header — centered label flanked by hairlines */} + {/* Header, centered label flanked by hairlines */}
      - {/* Header — left labelled rule */} + {/* Header, left labelled rule */}
      diff --git a/app/(marketing)/pricing/components/FAQSection.tsx b/app/(marketing)/pricing/components/FAQSection.tsx index dd321d5e2..0220252aa 100644 --- a/app/(marketing)/pricing/components/FAQSection.tsx +++ b/app/(marketing)/pricing/components/FAQSection.tsx @@ -18,7 +18,7 @@ export function FAQSection() {
      - {/* Section header — left vertical-bar accent */} + {/* Section header, left vertical-bar accent */}
      - {/* Header — centered label flanked by hairlines */} + {/* Header, centered label flanked by hairlines */} - {/* Clean supporting stats — three facts, plainly set, no terminal HUD. + {/* Clean supporting stats, three facts, plainly set, no terminal HUD. Plain div/grid (not a
      ): the prior
      nested
      before
      plus a stray

      , an invalid definition-list structure that tripped a serious axe `definition-list` (WCAG 1.3.1) violation on /pricing. */} diff --git a/app/(marketing)/pricing/components/PricingTiers.tsx b/app/(marketing)/pricing/components/PricingTiers.tsx index 0947fdd7b..9d9ea7da3 100644 --- a/app/(marketing)/pricing/components/PricingTiers.tsx +++ b/app/(marketing)/pricing/components/PricingTiers.tsx @@ -48,7 +48,7 @@ export function PricingTiers() {

      {/* The `id="pricing-table"` anchor that the hero's "View pricing" - CTA targets lives on a sibling div in PricingPageContent — see + CTA targets lives on a sibling div in PricingPageContent, see the comment there. Putting it on this section directly would not work because this component is rendered behind a deferred IntersectionObserver and the id would not be in SSR HTML. @@ -59,7 +59,7 @@ export function PricingTiers() {
      - {/* Section header — labelled rule + paired descriptor */} + {/* Section header, labelled rule + paired descriptor */}

      Manage how FormaOS uses cookies and analytics in your browser. You - can withdraw your consent or change your choice at any time — the + can withdraw your consent or change your choice at any time, the change takes effect immediately.

      @@ -176,7 +176,7 @@ export default function PrivacySettingsContent() { {/* Audit 2026-05-25 (GDPR): cross-link affordances to the authenticated self-serve surface at /app/privacy. The data selectors below are also probed by tests/compliance/ - gdpr-compliance.js — keep `data-testid="export-data"`, + gdpr-compliance.js, keep `data-testid="export-data"`, `data-testid="delete-account"`, and `data-export` in lockstep with that test. */}
      diff --git a/app/(marketing)/privacy/route.ts b/app/(marketing)/privacy/route.ts index 68461c264..f1f04bd41 100644 --- a/app/(marketing)/privacy/route.ts +++ b/app/(marketing)/privacy/route.ts @@ -4,7 +4,7 @@ import { NextResponse, type NextRequest } from 'next/server'; // GDPR compliance test (page.goto('http://localhost:3000/privacy') was // being 301-ed to www.formaos.com.au and Lighthouse/Playwright would // either time out or fetch the wrong page). Use a same-origin redirect -// — the canonical link tag on /legal/privacy already advertises the +//, the canonical link tag on /legal/privacy already advertises the // production URL for SEO. function redirectToPrivacy(request: NextRequest) { const target = new URL('/legal/privacy', request.nextUrl); diff --git a/app/(marketing)/product/components/ComplianceCoreObject.tsx b/app/(marketing)/product/components/ComplianceCoreObject.tsx index 1ee697e62..559d13824 100644 --- a/app/(marketing)/product/components/ComplianceCoreObject.tsx +++ b/app/(marketing)/product/components/ComplianceCoreObject.tsx @@ -18,11 +18,11 @@ import { useDeviceTier } from '@/lib/device-tier'; * Starts VISIBLE with glass shell + UI fragments inside. * On scroll: rotates → layers separate → morphs into full product UI. * - * Scroll phases (driven by parent via scrollProgress 0–1): - * 0–0.15: Core visible at 1x, slight zoom to 1.12x, glow intensifies - * 0.15–0.45: UI fragments separate in 3D space - * 0.45–0.7: Core dissolves, product interface scales up - * 0.7–1.0: Product UI holds at full size + * Scroll phases (driven by parent via scrollProgress 0-1): + * 0-0.15: Core visible at 1x, slight zoom to 1.12x, glow intensifies + * 0.15-0.45: UI fragments separate in 3D space + * 0.45-0.7: Core dissolves, product interface scales up + * 0.7-1.0: Product UI holds at full size */ interface ComplianceCoreObjectProps { diff --git a/app/(marketing)/product/components/FullControlMapSection.tsx b/app/(marketing)/product/components/FullControlMapSection.tsx index a7b465230..c5b936834 100644 --- a/app/(marketing)/product/components/FullControlMapSection.tsx +++ b/app/(marketing)/product/components/FullControlMapSection.tsx @@ -87,10 +87,10 @@ export function FullControlMapSection() { {/* Canvas container - cinematic 16:9-ish ratio */}
      - {/* Subtle graph substrate — masked dot grid */} + {/* Subtle graph substrate, masked dot grid */}
      - {/* Coverage summary cards (desktop) — static, no telemetry chrome */} + {/* Coverage summary cards (desktop), static, no telemetry chrome */}

      diff --git a/app/(marketing)/product/components/ObligationToExecution.tsx b/app/(marketing)/product/components/ObligationToExecution.tsx index 740489a58..2beaec8ed 100644 --- a/app/(marketing)/product/components/ObligationToExecution.tsx +++ b/app/(marketing)/product/components/ObligationToExecution.tsx @@ -34,7 +34,7 @@ export function ObligationToExecution() { return (

      - {/* Header — left labelled rule + paired descriptor */} + {/* Header, left labelled rule + paired descriptor */} - {/* Truths — plain text, no chips */} + {/* Truths, plain text, no chips */} Framework Status
      - {/* Caption marks this hero visual as illustrative — addresses + {/* Caption marks this hero visual as illustrative, addresses both audit row #21 (demo metrics not labelled as such) and the framework-taxonomy rule against absolute claims ("Certified", "Compliant") in marketing mocks. */} @@ -188,16 +188,16 @@ function ComplianceDashboard() {
      - {/* Status rows — sublabels describe the *customer's* compliance + {/* Status rows, sublabels describe the *customer's* compliance state inside FormaOS, not FormaOS-the-product's certification. Wording avoids "Certified" / "Compliant" / "Accredited" per the framework-status taxonomy (audit row #4). */}
      - + - +
      ); diff --git a/app/(marketing)/product/components/WhatIsFormaOS.tsx b/app/(marketing)/product/components/WhatIsFormaOS.tsx index 61b02a100..dab4a10ca 100644 --- a/app/(marketing)/product/components/WhatIsFormaOS.tsx +++ b/app/(marketing)/product/components/WhatIsFormaOS.tsx @@ -27,7 +27,7 @@ export function WhatIsFormaOS() {
      - {/* Thesis — left vertical-bar accent */} + {/* Thesis, left vertical-bar accent */}
      @@ -59,7 +59,7 @@ export function WhatIsFormaOS() {
      - {/* What it unifies — clean ruled list, no icon tiles */} + {/* What it unifies, clean ruled list, no icon tiles */}

      diff --git a/app/(marketing)/security-review/components/SecurityReviewHeroVisual.tsx b/app/(marketing)/security-review/components/SecurityReviewHeroVisual.tsx index a2da484c5..aaa9d8b09 100644 --- a/app/(marketing)/security-review/components/SecurityReviewHeroVisual.tsx +++ b/app/(marketing)/security-review/components/SecurityReviewHeroVisual.tsx @@ -52,7 +52,7 @@ function CheckIcon() { * SecurityReviewHeroVisual * ──────────────────────── * Review-checklist clipboard ringed by framework badges. Renders the - * settled state directly — no auto-running check-off telemetry, no + * settled state directly, no auto-running check-off telemetry, no * orbiting badges, no cursor-reactive tilt (enterprise-restrained). * Clipboard + badges fade/scale in once on entrance. */ diff --git a/app/(marketing)/security-review/page.tsx b/app/(marketing)/security-review/page.tsx index 7de078154..1f051be2b 100644 --- a/app/(marketing)/security-review/page.tsx +++ b/app/(marketing)/security-review/page.tsx @@ -26,14 +26,14 @@ export const metadata: Metadata = { }; // HowTo schema for the security review walkthrough. Mirrors the -// human-facing 12-step checklist in SecurityReviewContent — AI answer +// human-facing 12-step checklist in SecurityReviewContent, AI answer // engines treat HowTo as an authoritative ordered procedure and cite // individual steps when users ask procedural questions ("how do I run a // security review on FormaOS"). const SECURITY_REVIEW_HOWTO = howToSchema({ name: 'How to run a procurement-ready security review of FormaOS', description: - 'A 12-step security review walkthrough for enterprise buyers and procurement teams evaluating FormaOS — covers architecture, data handling, identity, encryption, audit logging, and operational assurance.', + 'A 12-step security review walkthrough for enterprise buyers and procurement teams evaluating FormaOS, covers architecture, data handling, identity, encryption, audit logging, and operational assurance.', url: `${siteUrl}/security-review`, totalTime: 'PT45M', steps: [ diff --git a/app/(marketing)/security/SecurityContent.tsx b/app/(marketing)/security/SecurityContent.tsx index 608be9403..710cd2f6f 100644 --- a/app/(marketing)/security/SecurityContent.tsx +++ b/app/(marketing)/security/SecurityContent.tsx @@ -118,7 +118,7 @@ function LightSection({ }) { return (

      - {/* Single subtle white radial + top hairline — matches the homepage hand */} + {/* Single subtle white radial + top hairline, matches the homepage hand */}
      {/* Content */} @@ -155,7 +155,7 @@ function LightCard({ ); } -/* ─── Restrained section header — plain centered label, no pill / icon ─── */ +/* ─── Restrained section header, plain centered label, no pill / icon ─── */ function SectionLabelHeader({ label, title, @@ -182,7 +182,7 @@ function SectionLabelHeader({ ); } -/* ─── Editorial header variant — left-aligned hairline + label rule ─── */ +/* ─── Editorial header variant, left-aligned hairline + label rule ─── */ function SectionRuleHeader({ label, title, diff --git a/app/(marketing)/security/components/AuditChainVisualizer.tsx b/app/(marketing)/security/components/AuditChainVisualizer.tsx index 4cd6f10f1..2a0a64515 100644 --- a/app/(marketing)/security/components/AuditChainVisualizer.tsx +++ b/app/(marketing)/security/components/AuditChainVisualizer.tsx @@ -4,7 +4,7 @@ * Interactive, tamper-evident audit-chain visualizer. * * Honesty: hashes are REAL SHA-256 (Web Crypto), and chaining mirrors the - * production design described on /trust — each row's hash is derived from + * production design described on /trust, each row's hash is derived from * the previous row's hash plus its own content, so editing any sealed row * makes its recomputed hash diverge from the stored seal and breaks every * block after it. The Rekor anchor footer is labelled illustrative; diff --git a/app/(marketing)/security/components/SecurityArchitecture.tsx b/app/(marketing)/security/components/SecurityArchitecture.tsx index 57e30ff10..943f0ff78 100644 --- a/app/(marketing)/security/components/SecurityArchitecture.tsx +++ b/app/(marketing)/security/components/SecurityArchitecture.tsx @@ -55,12 +55,12 @@ const securityLayers = [ }, ]; -// "certifications" was the old variable name — the list describes +// "certifications" was the old variable name, the list describes // framework support and security practices, NOT a certification // claim. The first card was previously "SOC 2-aligned" which read // like a status claim; it now reads as a framework reference per // audit row #4 taxonomy ("Framework supported"). No code rename of -// the variable here — that's churn for a future PR if the term is +// the variable here, that's churn for a future PR if the term is // repurposed. const certifications = [ { diff --git a/app/(marketing)/status/page.tsx b/app/(marketing)/status/page.tsx index 9f33ef47c..c60d07053 100644 --- a/app/(marketing)/status/page.tsx +++ b/app/(marketing)/status/page.tsx @@ -2,17 +2,17 @@ import type { Metadata } from 'next'; import StatusPageClient from './StatusPageClient'; import { siteUrl } from '@/lib/seo'; -// Audit 2026-05-27 — public platform status page. +// Audit 2026-05-27, public platform status page. // // Surfaces: -// * /api/health — overall up/degraded/down + per-subsystem -// * /api/health/integrity — audit-chain hash integrity -// * Latest audit_chain_anchor — proof we're publishing chain state +// * /api/health , overall up/degraded/down + per-subsystem +// * /api/health/integrity, audit-chain hash integrity +// * Latest audit_chain_anchor, proof we're publishing chain state // to a public transparency log // // Customer-visible without auth so enterprise prospects + customer // auditors can hit /status to see live posture. No PII, no per-org -// data — only platform-level health. +// data, only platform-level health. export const dynamic = 'force-dynamic'; export const revalidate = 0; diff --git a/app/(marketing)/trust/TrustPageContent.tsx b/app/(marketing)/trust/TrustPageContent.tsx index 7f77581e3..577e31e2a 100644 --- a/app/(marketing)/trust/TrustPageContent.tsx +++ b/app/(marketing)/trust/TrustPageContent.tsx @@ -46,7 +46,7 @@ export default function TrustPageContent({
      {/* SSR-rendered index of trust sub-pages. Sits outside DeferredSection - so it lands in the initial HTML response — crawlers and screen + so it lands in the initial HTML response, crawlers and screen readers reach every Trust Center document without needing to hydrate the dynamic TrustModules visual below. */} diff --git a/app/(marketing)/trust/components/AuditChainProof.tsx b/app/(marketing)/trust/components/AuditChainProof.tsx index 57dbcf974..ae5b03f6f 100644 --- a/app/(marketing)/trust/components/AuditChainProof.tsx +++ b/app/(marketing)/trust/components/AuditChainProof.tsx @@ -1,6 +1,6 @@ import { History, Lock, ShieldCheck } from 'lucide-react'; -// Server-rendered (not client) — the audit-chain proof MUST land in the +// Server-rendered (not client), the audit-chain proof MUST land in the // initial HTML response so crawlers, AI answer engines, and procurement // reviewers can read it without executing JS. The homepage // AuditChainSection links here for the long-form explanation, so the diff --git a/app/(marketing)/trust/components/TrustSubpagesIndex.tsx b/app/(marketing)/trust/components/TrustSubpagesIndex.tsx index 0a8200725..cbab66b39 100644 --- a/app/(marketing)/trust/components/TrustSubpagesIndex.tsx +++ b/app/(marketing)/trust/components/TrustSubpagesIndex.tsx @@ -3,8 +3,8 @@ import Link from 'next/link'; // Static, server-rendered index of every Trust Center sub-page. Each of // these documents existed in the sitemap but was previously only reachable // via JS-rendered cards (TrustModules is dynamic({ ssr: false })). For -// crawlers that don't execute JS — and for the human procurement reviewer -// scanning for a specific document — this gives a guaranteed link. +// crawlers that don't execute JS, and for the human procurement reviewer +// scanning for a specific document, this gives a guaranteed link. const TRUST_SUBPAGES = [ { href: '/trust/data-handling', diff --git a/app/(marketing)/trust/incident-response/page.tsx b/app/(marketing)/trust/incident-response/page.tsx index cbc55ba3e..35be85628 100644 --- a/app/(marketing)/trust/incident-response/page.tsx +++ b/app/(marketing)/trust/incident-response/page.tsx @@ -83,7 +83,7 @@ export default function IncidentResponsePage() { ← Back to Trust Center - {/* Status link removed 2026-05-13 — /status route unshipped + {/* Status link removed 2026-05-13, /status route unshipped until a real status provider is wired. */}
      diff --git a/app/(marketing)/use-cases/components/UseCasePageTemplate.tsx b/app/(marketing)/use-cases/components/UseCasePageTemplate.tsx index 9bf5661a0..35269310e 100644 --- a/app/(marketing)/use-cases/components/UseCasePageTemplate.tsx +++ b/app/(marketing)/use-cases/components/UseCasePageTemplate.tsx @@ -173,7 +173,7 @@ const relatedLinksByIndustry: Record< ], }; -/* Plain editorial section header — replaces the rotating-icon glass pill. +/* Plain editorial section header, replaces the rotating-icon glass pill. `variant="rule"` renders a centred hairline-flanked label; `variant="label"` renders a quiet uppercase eyebrow. Headers are varied across the page so the layout never reads as a repeated template. */ diff --git a/app/(marketing)/verify/page.tsx b/app/(marketing)/verify/page.tsx index 2c61f400b..ce43cd20e 100644 --- a/app/(marketing)/verify/page.tsx +++ b/app/(marketing)/verify/page.tsx @@ -2,7 +2,7 @@ import type { Metadata } from 'next'; import { siteUrl } from '@/lib/seo'; import VerifyClient from './VerifyClient'; -// Audit 2026-05-27 (Tier 2.B) — public audit-export verifier page. +// Audit 2026-05-27 (Tier 2.B), public audit-export verifier page. // // Lets external auditors paste either: // 1. A FormaOS audit-export bundle (Merkle root + per-entry proofs).