Skip to content
Merged
17 changes: 7 additions & 10 deletions src/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { notFound } from 'next/navigation';
import Link from 'next/link';
import { format } from 'date-fns';
import { ArrowLeft } from 'lucide-react';
import { MDXRemote } from 'next-mdx-remote/rsc';
import { getAllPosts, getPostBySlug } from '@/lib/blog';
import type { Metadata } from 'next';
Expand Down Expand Up @@ -42,22 +41,20 @@ export default async function BlogPostPage({

return (
<div className="container mx-auto max-w-4xl px-4 py-8 sm:px-6 lg:px-8">
<Link
href="/blog"
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-6"
>
<ArrowLeft className="h-4 w-4" />
Back to Blog
</Link>
<nav className="mb-6 font-mono text-[10px] uppercase tracking-[0.08em] text-muted-foreground">
<Link href="/blog" className="hover:text-primary">Blog</Link>
<span className="mx-2">/</span>
<span className="text-foreground">Post</span>
</nav>

<header className="mb-9 border-b border-border pb-7">
<h1 className="article-title">{post.title}</h1>
<p className="mt-4 font-mono text-[10px] uppercase tracking-[0.08em] text-muted-foreground">
{format(new Date(post.date), 'MMMM d, yyyy')}
{format(new Date(post.date), 'dd MMMM yyyy')}
</p>
</header>

<article className="prose prose-slate max-w-none prose-headings:font-display prose-headings:font-medium prose-a:text-primary">
<article className="prose max-w-none prose-headings:font-display prose-headings:font-medium prose-pre:border prose-pre:border-border">
<MDXRemote source={post.content} />
</article>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default function BlogPage() {
{format(new Date(post.date), 'dd MMMM yyyy')}
</time>
<span>
<span className="block font-display text-2xl group-hover:text-primary">{post.title}</span>
<span className="block text-lg font-semibold leading-snug group-hover:text-primary">{post.title}</span>
<span className="mt-2 block text-sm leading-6 text-muted-foreground">{post.description}</span>
</span>
<ArrowRight className="h-5 w-5 self-center text-primary" />
Expand Down
200 changes: 72 additions & 128 deletions src/app/framework/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import {
import { getPolicyFrameworkArtifact } from '@/lib/data-service';
import { parseCalendarDateForDisplay } from '@/lib/format-policy-date';
import Link from 'next/link';
import { ArrowLeft, ExternalLink, FileText, Download } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { ExternalLink, FileText, Download } from 'lucide-react';
import { PageIntro } from '@/components/layout';
import { SourceState } from '@/components/policy-table';

export const revalidate = 3600;

Expand All @@ -21,152 +20,97 @@ export default async function FrameworkPage() {
const artifact = await getPolicyFrameworkArtifact();
if (!artifact) {
return (
<div className="container mx-auto max-w-3xl px-4 py-8 sm:px-6 lg:px-8">
<div className="mb-6">
<Link
href="/policies"
className="inline-flex items-center text-sm text-muted-foreground transition-colors hover:text-foreground"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Policies
</Link>
</div>
<div className="container mx-auto px-4 py-7 sm:px-6 lg:px-8">
<PageIntro title="AI in government framework" />
<Card className="rounded-none border-[var(--caution)]/30 bg-[var(--status-proposed-bg)]/25 shadow-none">
<CardHeader>
<CardTitle>Framework temporarily unavailable</CardTitle>
</CardHeader>
<CardContent className="space-y-4 text-sm text-muted-foreground">
<p>
Policai is withholding this derived visualisation while its
source policy and framework data await fingerprinted editorial
re-verification. This prevents an older interpretation from
being presented as current.
</p>
<p>
See the{' '}
<Link href="/methodology" className="text-primary hover:underline">
methodology and trust model
</Link>{' '}
for how records return to public view.
</p>
</CardContent>
</Card>
<div className="border-l-2 border-[var(--caution)] bg-[var(--status-proposed-bg)]/30 px-4 py-3 text-sm">
<p className="font-medium">Framework temporarily unavailable</p>
<p className="mt-2 text-muted-foreground">
Policai is withholding this derived visualisation while its
source policy and framework data await fingerprinted editorial
re-verification. This prevents an older interpretation from
being presented as current.
</p>
<p className="mt-2 text-muted-foreground">
See the{' '}
<Link href="/methodology" className="text-primary hover:underline">
methodology and trust model
</Link>{' '}
for how records return to public view.
</p>
</div>
</div>
);
}
const frameworkData = artifact as unknown as FrameworkData;

return (
<div className="container mx-auto px-4 py-7 sm:px-6 lg:px-8">
{/* Breadcrumb */}
<div className="mb-6">
<PageIntro title="AI in government framework" />

<div className="mb-8 flex flex-wrap items-center gap-1">
<a
href={frameworkData.sourceUrl}
target="_blank"
rel="noopener noreferrer"
className="inline-flex min-h-11 items-center gap-2 bg-primary px-4 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90"
>
<ExternalLink className="h-4 w-4" />
View official source
</a>
<Link
href="/policies"
className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors"
href={`/policies/${frameworkData.relatedPolicyId}`}
className="inline-flex min-h-11 items-center gap-2 px-3 text-sm font-medium hover:text-primary"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Policies
<FileText className="h-4 w-4" />
Register entry
</Link>
<a
href="https://www.digital.gov.au/sites/default/files/documents/2025-12/Policy%20for%20the%20responsible%20use%20of%20AI%20in%20Government%202.0_0.pdf"
target="_blank"
rel="noopener noreferrer"
className="inline-flex min-h-11 items-center gap-2 px-3 text-sm font-medium hover:text-primary"
>
<Download className="h-4 w-4" />
Download PDF
</a>
</div>

<div className="mb-8 space-y-6">
<PageIntro title="AI in government framework" />

<Card className="rounded-none border-primary/20 bg-primary/5 shadow-none">
<CardContent className="p-6">
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div className="flex-1">
<h2 className="mb-2 text-xl font-semibold">Version 2.0 visual map</h2>
<p className="text-sm text-muted-foreground">
Select a pillar to view its principles and requirements.
</p>
</div>
<div className="flex flex-wrap gap-2">
<Button variant="outline" size="sm" asChild>
<Link href={`/policies/${frameworkData.relatedPolicyId}`}>
<FileText className="mr-2 h-4 w-4" />
Register entry
</Link>
</Button>
<Button variant="outline" size="sm" asChild>
<a
href={frameworkData.sourceUrl}
target="_blank"
rel="noopener noreferrer"
>
<FileText className="mr-2 h-4 w-4" />
View Original
<ExternalLink className="ml-2 h-3 w-3" />
</a>
</Button>
<Button variant="outline" size="sm" asChild>
<a
href="https://www.digital.gov.au/sites/default/files/documents/2025-12/Policy%20for%20the%20responsible%20use%20of%20AI%20in%20Government%202.0_0.pdf"
target="_blank"
rel="noopener noreferrer"
>
<Download className="mr-2 h-4 w-4" />
Download PDF
</a>
</Button>
</div>
</div>
</CardContent>
</Card>
</div>

{/* Framework Visualization */}
<PolicyFrameworkMap data={frameworkData as FrameworkData} />
<PolicyFrameworkMap data={frameworkData} />

<Card className="mt-10 rounded-none border-border bg-card/35 shadow-none">
<CardContent className="p-4">
<div className="flex flex-wrap gap-x-6 gap-y-2 text-xs text-muted-foreground">
<div>
<span className="font-medium">Effective:</span>{' '}
<div className="mt-10 flex flex-wrap gap-x-10 gap-y-4 border-y border-[var(--rule-hair)] py-4">
<div>
<p className="page-eyebrow">Effective</p>
<p className="mt-1 text-sm">
{parseCalendarDateForDisplay(
frameworkData.effectiveDate,
).toLocaleDateString('en-AU', {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</p>
</div>
{frameworkData.lastUpdated && (
<div>
<p className="page-eyebrow">Page updated</p>
<p className="mt-1 text-sm">
{parseCalendarDateForDisplay(
frameworkData.effectiveDate,
frameworkData.lastUpdated,
).toLocaleDateString('en-AU', {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</div>
{frameworkData.lastUpdated && (
<div>
<span className="font-medium">Page Updated:</span>{' '}
{parseCalendarDateForDisplay(
frameworkData.lastUpdated,
).toLocaleDateString('en-AU', {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</div>
)}
<div>
<span className="font-medium">Version:</span> {frameworkData.version}
</div>
<div>
<span className="font-medium">Authority:</span> {frameworkData.authority}
</div>
<div>
<span className="font-medium">Verification:</span>{' '}
{frameworkData.verification.status === 'verified'
? 'Verified'
: 'Needs review'}
</div>
<a
href={frameworkData.sourceUrl}
target="_blank"
rel="noopener noreferrer"
className="font-medium text-primary hover:underline"
>
Official DTA source
</a>
</p>
</div>
</CardContent>
</Card>
)}
<div>
<p className="page-eyebrow">Verification</p>
<p className="mt-1">
<SourceState verification={frameworkData.verification} />
</p>
</div>
</div>
</div>
);
}
32 changes: 32 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,38 @@
}
}

/*
* Typography-plugin prose, wired to our tokens instead of a fixed palette
* modifier (`prose-slate` etc). Every value is already `light-dark()`-aware,
* so one set of `--tw-prose-*` variables covers both themes with no
* `dark:prose-invert` needed.
*
* Deliberately NOT inside `@layer base`: the typography plugin's own
* `.prose` reset lives in a higher-priority layer, so a same-or-lower-layer
* override loses regardless of source order and dark-mode text silently
* falls back to the plugin's fixed (non-theme-aware) values. An unlayered
* rule always wins over a layered one, which is what we need here.
*/
.prose {
--tw-prose-body: var(--foreground);
--tw-prose-headings: var(--foreground);
--tw-prose-lead: var(--muted-foreground);
--tw-prose-links: var(--primary);
--tw-prose-bold: var(--foreground);
--tw-prose-counters: var(--muted-foreground);
--tw-prose-bullets: var(--border);
--tw-prose-hr: var(--rule-hair);
--tw-prose-quotes: var(--foreground);
--tw-prose-quote-borders: var(--rule);
--tw-prose-captions: var(--muted-foreground);
--tw-prose-kbd: var(--foreground);
--tw-prose-code: var(--foreground);
--tw-prose-pre-code: var(--foreground);
--tw-prose-pre-bg: var(--muted);
--tw-prose-th-borders: var(--rule-heavy);
--tw-prose-td-borders: var(--rule-hair);
}

@layer utilities {
.font-display {
font-family: var(--font-display);
Expand Down
2 changes: 1 addition & 1 deletion src/app/methodology/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default async function MethodologyPage() {
<section>
<h2 className="section-title">Trust levels</h2>
<dl className="space-y-4">
<div className="mt-4 border-l-2 border-[var(--trust)] bg-[var(--status-active-bg)]/25 px-4 py-3">
<div className="border-l-2 border-[var(--trust)] bg-[var(--status-active-bg)]/25 px-4 py-3">
<dt className="font-medium">Verified register record</dt>
<dd className="text-muted-foreground">
Title, jurisdiction, issuer, type, status, displayed date, and
Expand Down
Loading
Loading