-
-
-
+
+
+
Compare Statutory Releases
+
View word-level additions and deletions between any two federal law releases.
+
+
+
+
+
+
+
+
{#if diffLines.length > 0}
-
-
-
{formatTagName(compareFrom)} → {formatTagName(compareTo)}
-
{diffLines.filter(l => l.type === 'add').length} additions, {diffLines.filter(l => l.type === 'del').length} deletions
+
+
+
+
+
+
+
+
+
+
+
+
+ {formatTagName(compareFrom)} → {formatTagName(compareTo)}
+
+ +{diffMetrics.additions} lines
+
+
+ -{diffMetrics.deletions} lines
+
+
-
{#each diffLines as line}
+ {#each redlineRows as row}
+ {#if row.type === "paired" && row.tokens}
+
+ {#each row.tokens as token}
+ {#if token.type === "del"}
+ {token.text}
+ {:else if token.type === "add"}
+ {token.text}
+ {:else}
+ {token.text}
+ {/if}
+ {/each}
+
+ {:else if row.type === "del"}
+
+ {row.content}
+
+ {:else if row.type === "add"}
+
+ {row.content}
+
+ {:else}
+ {row.content}
+ {/if}
+ {/each}
+
+
+
+ {:else if diffMode === "split"}
+
+
+
+ Previous: {formatTagName(compareFrom)}
+
+
+ Revised: {formatTagName(compareTo)}
+
+
+
+ {#each diffLines as line}
+
+
+
+ {line.type === 'del' || line.type === 'context' ? line.content : ''}
+
+
+
+ {line.type === 'add' || line.type === 'context' ? line.content : ''}
+
+
+ {/each}
+
+
+
+
+ {:else}
+
{#each diffLines as line}{line.content}{/each}
+ : 'text-gray-600 dark:text-gray-400'} block">{line.type === 'add' ? '+ ' : line.type === 'del' ? '- ' : ' '}{line.content}{/each}
+ {/if}
{:else if hasCompared && !diffLoading && compareFrom && compareTo && compareFrom !== compareTo}
-
No changes between {formatTagName(compareFrom)} and {formatTagName(compareTo)} for this section.
+
+
No textual changes detected
+
The statutory text of this section remained identical between {formatTagName(compareFrom)} and {formatTagName(compareTo)}.
+
{/if}
{/if}
-
-
Change History
- {#if commits.length === 0}
-
-
No amendments tracked yet for this section.
-
Change history will appear here automatically when the pipeline detects modifications between US Code release points.
-
- {:else}
- {#if tags.length === 0}
-
Version timeline available when release point tags are published.
- {:else if !commits.some(c => isLegislativeChange(c.message))}
-
No legislative changes tracked yet. Future updates will appear here as diffs.
- {/if}
- {@const visibleCommits = showAllHistory ? commits : commits.slice(0, HISTORY_PREVIEW_COUNT)}
-
- {#each visibleCommits as commit (commit.sha)}
- -
- {formatCommitMessage(commit.message)}
- {commitDisplayDate(commit.message, commit.date)}
-
- {/each}
-
- {#if commits.length > HISTORY_PREVIEW_COUNT}
-
+
+
+
Pipeline Commit Audit
+ {#if commits.length === 0}
+
+
No amendments tracked yet for this section.
+
Commit history will populate automatically as new Public Law releases are published by OLRC.
+
+ {:else}
+ {#if tags.length === 0}
+
Version timeline available when release point tags are published.
+ {:else if !commits.some(c => isLegislativeChange(c.message))}
+
No legislative changes tracked yet. Future updates will appear here as diffs.
+ {/if}
+ {@const visibleCommits = showAllHistory ? commits : commits.slice(0, HISTORY_PREVIEW_COUNT)}
+
+ {#each visibleCommits as commit (commit.sha)}
+ -
+ {formatCommitMessage(commit.message)}
+ {commitDisplayDate(commit.message, commit.date)}
+
+ {/each}
+
+ {#if commits.length > HISTORY_PREVIEW_COUNT}
+
+ {/if}
{/if}
- {/if}
+
{/if}
diff --git a/apps/web/src/components/ReadingToolbar.svelte b/apps/web/src/components/ReadingToolbar.svelte
new file mode 100644
index 0000000..80f7969
--- /dev/null
+++ b/apps/web/src/components/ReadingToolbar.svelte
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web/src/components/SummaryBox.astro b/apps/web/src/components/SummaryBox.astro
new file mode 100644
index 0000000..e43b31a
--- /dev/null
+++ b/apps/web/src/components/SummaryBox.astro
@@ -0,0 +1,141 @@
+---
+// USWDS-aligned Statutory Summary Box (usa-summary-box)
+interface Props {
+ classification: string;
+ uscTitle: number;
+ uscSection: string;
+ chapter: number;
+ currentThrough: string;
+ status?: string;
+ readingTimeMin?: number;
+ lastUpdated?: string;
+ olrcUrl: string;
+}
+
+const {
+ classification,
+ uscTitle,
+ uscSection,
+ chapter,
+ currentThrough,
+ status = 'active',
+ readingTimeMin,
+ lastUpdated,
+ olrcUrl,
+} = Astro.props;
+
+const isRepealed = status === 'repealed';
+const isTransferred = status === 'transferred';
+const isOmitted = status === 'omitted';
+const isReserved = status === 'reserved';
+
+const borderAccent = isRepealed
+ ? 'border-crimson bg-crimson-light/20 dark:border-red-500 dark:bg-red-950/20'
+ : isTransferred || isOmitted || isReserved
+ ? 'border-amber bg-amber-light/20 dark:border-amber-500 dark:bg-amber-950/20'
+ : 'border-teal bg-teal-light/20 dark:border-teal dark:bg-teal/10';
+
+const statusBadge = isRepealed
+ ? { label: 'Repealed', class: 'bg-crimson/15 text-crimson dark:bg-red-900/40 dark:text-red-300' }
+ : isTransferred
+ ? { label: 'Transferred', class: 'bg-amber/15 text-amber dark:bg-amber-900/40 dark:text-amber' }
+ : isOmitted
+ ? { label: 'Omitted', class: 'bg-gray-200 text-slate dark:bg-gray-800 dark:text-gray-300' }
+ : isReserved
+ ? { label: 'Reserved', class: 'bg-gray-200 text-slate dark:bg-gray-800 dark:text-gray-300' }
+ : { label: 'In Force', class: 'bg-teal/15 text-teal dark:bg-teal/30 dark:text-teal-bright' };
+---
+
+
+
+
+
+ {classification}
+
+
+ {statusBadge.label}
+
+
+
+
+
+
+ OLRC
+ →
+
+
+
+
+
+
+
+
+ Title {uscTitle}
+
+
+ Chapter {chapter}
+
+
+ Current through {currentThrough}
+
+ {readingTimeMin && (
+
+ ~{readingTimeMin} min read
+
+ )}
+ {lastUpdated && (
+
+ Last updated: {lastUpdated}
+
+ )}
+
+
+
+
diff --git a/apps/web/src/content.config.ts b/apps/web/src/content.config.ts
index 08be8f4..b9a92e3 100644
--- a/apps/web/src/content.config.ts
+++ b/apps/web/src/content.config.ts
@@ -1,4 +1,5 @@
-import { defineCollection, z } from 'astro:content';
+import { defineCollection } from 'astro:content';
+import { z } from 'astro/zod';
import { glob } from 'astro/loaders';
const statutes = defineCollection({
diff --git a/apps/web/src/layouts/BaseLayout.astro b/apps/web/src/layouts/BaseLayout.astro
index 0c1e996..8cdad07 100644
--- a/apps/web/src/layouts/BaseLayout.astro
+++ b/apps/web/src/layouts/BaseLayout.astro
@@ -3,6 +3,7 @@ import '../styles/global.css';
import '@fontsource/public-sans/400.css';
import '@fontsource/public-sans/500.css';
import '@fontsource/public-sans/600.css';
+import CivicBanner from '../components/CivicBanner.astro';
import ThemeToggle from '../components/ThemeToggle.svelte';
import SearchBar from '../components/SearchBar.svelte';
import BackToTop from '../components/BackToTop.svelte';
@@ -65,31 +66,39 @@ const titleEntries = Object.entries(TITLE_NAMES)
})();
-
+
Skip to content
-
-
-