Compare commits
5 Commits
8714d3a30d
...
288a9b4992
| Author | SHA1 | Date | |
|---|---|---|---|
| 288a9b4992 | |||
| 37d8511da7 | |||
| cd2179f7a0 | |||
| 21a8c95a2b | |||
| 1711c2d16b |
@@ -1,22 +1,22 @@
|
|||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
|
|
||||||
export function AuthorBio() {
|
export function AuthorBio() {
|
||||||
return (
|
return (
|
||||||
<Card className="mt-12 bg-muted/50">
|
<Card className="bg-muted/50 mt-12">
|
||||||
<CardContent className="flex items-center gap-4 p-6">
|
<CardContent className="flex items-center gap-4 p-6">
|
||||||
<Avatar className="h-16 w-16 border-2 border-background">
|
<Avatar className="border-background h-16 w-16 border-2">
|
||||||
<AvatarImage src="/images/author-profile.jpg" alt="Author" />
|
<AvatarImage src="/images/author-profile.jpg" alt="Author" />
|
||||||
<AvatarFallback>IF</AvatarFallback>
|
<AvatarFallback>IF</AvatarFallback>
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-semibold">Written by The InvestingFIRE Team</p>
|
<p className="text-sm font-semibold">Written by The InvestingFIRE Team</p>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-muted-foreground text-sm">
|
||||||
We are a group of financial data enthusiasts and early retirees dedicated to building the most accurate FIRE tools on the web. Our goal is to replace guesswork with math.
|
We are a group of financial data enthusiasts and early retirees dedicated to building the
|
||||||
|
most accurate FIRE tools on the web. Our goal is to replace guesswork with math.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ export default function FireCalculatorForm() {
|
|||||||
baristaIncome: 0,
|
baristaIncome: 0,
|
||||||
simulationMode: 'deterministic',
|
simulationMode: 'deterministic',
|
||||||
volatility: 15,
|
volatility: 15,
|
||||||
|
withdrawalStrategy: 'fixed',
|
||||||
|
withdrawalPercentage: 4,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from '@/components/ui/card';
|
||||||
import {
|
import {
|
||||||
ChartContainer,
|
ChartContainer,
|
||||||
ChartLegend,
|
ChartLegend,
|
||||||
@@ -45,6 +52,9 @@ const generateData = () => {
|
|||||||
const data = generateData();
|
const data = generateData();
|
||||||
|
|
||||||
const chartConfig = {
|
const chartConfig = {
|
||||||
|
age: {
|
||||||
|
label: 'Age',
|
||||||
|
},
|
||||||
Standard: {
|
Standard: {
|
||||||
label: 'Standard Path',
|
label: 'Standard Path',
|
||||||
color: 'var(--chart-4)',
|
color: 'var(--chart-4)',
|
||||||
@@ -75,16 +85,22 @@ export function CoastFireChart() {
|
|||||||
tickLine={false}
|
tickLine={false}
|
||||||
axisLine={false}
|
axisLine={false}
|
||||||
tickMargin={8}
|
tickMargin={8}
|
||||||
tickFormatter={(value: number) => `$${String(value / 1000)}k`}
|
tickFormatter={(value: number) => {
|
||||||
|
if (value < 1000) {
|
||||||
|
return `$${String(value)}`;
|
||||||
|
}
|
||||||
|
if (value < 1000000) {
|
||||||
|
return `$${String(value / 1000)}k`;
|
||||||
|
}
|
||||||
|
if (value < 1000000000) {
|
||||||
|
return `$${String(value / 1000000)}M`;
|
||||||
|
}
|
||||||
|
return `$${String(value / 1000000000)}B`;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<ChartTooltip
|
<ChartTooltip
|
||||||
cursor={false}
|
cursor={false}
|
||||||
content={
|
content={<ChartTooltipContent indicator="line" labelKey="age" />}
|
||||||
<ChartTooltipContent
|
|
||||||
labelFormatter={(value) => `Age ${String(value)}`}
|
|
||||||
indicator="line"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Line
|
<Line
|
||||||
dataKey="Standard"
|
dataKey="Standard"
|
||||||
@@ -103,6 +119,12 @@ export function CoastFireChart() {
|
|||||||
<ChartLegend content={<ChartLegendContent />} />
|
<ChartLegend content={<ChartLegendContent />} />
|
||||||
</LineChart>
|
</LineChart>
|
||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
|
<CardFooter>
|
||||||
|
<p className="text-muted-foreground text-sm">
|
||||||
|
Simulation assumes 7% returns. Standard: Save $10k/yr (age 25-65). Coast: Save $30k/yr (age
|
||||||
|
25-35), then $0.
|
||||||
|
</p>
|
||||||
|
</CardFooter>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from '@/components/ui/card';
|
||||||
import {
|
import {
|
||||||
ChartContainer,
|
ChartContainer,
|
||||||
ChartLegend,
|
ChartLegend,
|
||||||
@@ -96,6 +103,15 @@ export function FourPercentRuleChart() {
|
|||||||
</AreaChart>
|
</AreaChart>
|
||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<div>
|
||||||
|
<p className="font-medium">4% balances safety and spending power</p>
|
||||||
|
<p className="text-muted-foreground leading-none">
|
||||||
|
A 5% withdrawal rate risks depleting your portfolio within 30 years, while 3% leaves a large
|
||||||
|
surplus. The 4% rule is widely considered the safe "sweet spot."
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default function CoastVsLeanPage() {
|
|||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
<div className="max-w-none">
|
||||||
<h2>The Quick Summary</h2>
|
<h2>The Quick Summary</h2>
|
||||||
<p>Not sure which one fits you? Here is the high-level breakdown:</p>
|
<p>Not sure which one fits you? Here is the high-level breakdown:</p>
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ export default function CoastVsLeanPage() {
|
|||||||
discipline.
|
discipline.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Separator className="my-12" />
|
<Separator className="my-16" />
|
||||||
|
|
||||||
<h2>Run The Numbers</h2>
|
<h2>Run The Numbers</h2>
|
||||||
<p>The best way to decide is to see the math. Use our calculator to simulate both scenarios:</p>
|
<p>The best way to decide is to see the math. Use our calculator to simulate both scenarios:</p>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default function LearnHubPage() {
|
|||||||
<BlurThing />
|
<BlurThing />
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<span className="rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800 dark:bg-green-900 dark:text-green-300">
|
<span className="rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800">
|
||||||
Beginner
|
Beginner
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,7 +51,7 @@ export default function LearnHubPage() {
|
|||||||
<Card className="hover:border-primary/50 h-full cursor-pointer border-2">
|
<Card className="hover:border-primary/50 h-full cursor-pointer border-2">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<span className="rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-300">
|
<span className="rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800">
|
||||||
Strategy
|
Strategy
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,7 +75,7 @@ export default function LearnHubPage() {
|
|||||||
<Card className="hover:border-primary/50 h-full cursor-pointer border-2">
|
<Card className="hover:border-primary/50 h-full cursor-pointer border-2">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<span className="rounded-full bg-purple-100 px-2.5 py-0.5 text-xs font-medium text-purple-800 dark:bg-purple-900 dark:text-purple-300">
|
<span className="rounded-full bg-purple-100 px-2.5 py-0.5 text-xs font-medium text-purple-800">
|
||||||
Comparison
|
Comparison
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export default function SafeWithdrawalPage() {
|
|||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
<div className="max-w-none">
|
||||||
<h2>What is the 4% Rule?</h2>
|
<h2>What is the 4% Rule?</h2>
|
||||||
<p>
|
<p>
|
||||||
The rule comes from the <strong>Trinity Study</strong> (1998), which looked at historical
|
The rule comes from the <strong>Trinity Study</strong> (1998), which looked at historical
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Separator } from '@/components/ui/separator';
|
|
||||||
import { FireFlowchart } from '@/app/components/charts/FireFlowchart';
|
import { FireFlowchart } from '@/app/components/charts/FireFlowchart';
|
||||||
import { AuthorBio } from '@/app/components/AuthorBio';
|
import { AuthorBio } from '@/app/components/AuthorBio';
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ export default function WhatIsFirePage() {
|
|||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="prose prose-lg dark:prose-invert max-w-none">
|
<div className="max-w-none">
|
||||||
<p>
|
<p>
|
||||||
Imagine waking up on a Monday morning without an alarm clock. You don't have to rush to a
|
Imagine waking up on a Monday morning without an alarm clock. You don't have to rush to a
|
||||||
commute, sit in traffic, or answer to a boss. Instead, you have the ultimate luxury:{' '}
|
commute, sit in traffic, or answer to a boss. Instead, you have the ultimate luxury:{' '}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { BASE_URL } from "@/lib/constants";
|
import { BASE_URL } from '@/lib/constants';
|
||||||
import { type MetadataRoute } from "next";
|
import { type MetadataRoute } from 'next';
|
||||||
|
|
||||||
export default function sitemap(): MetadataRoute.Sitemap {
|
export default function sitemap(): MetadataRoute.Sitemap {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
url: BASE_URL,
|
url: BASE_URL,
|
||||||
lastModified: new Date(),
|
lastModified: new Date(),
|
||||||
changeFrequency: "yearly",
|
changeFrequency: 'yearly',
|
||||||
priority: 1,
|
priority: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -5,18 +5,18 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
|||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg border border-transparent text-sm font-semibold transition-[transform,colors,shadow] shadow-[0_10px_30px_-18px_rgba(0,0,0,0.45)] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
"z-30 inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-semibold transition-[transform,colors,shadow] shadow-[0_10px_30px_-18px_rgba(0,0,0,0.45)] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 aria-invalid:ring-destructive/20 aria-invalid:border-destructive",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default:
|
||||||
'border-primary/20 bg-gradient-to-r from-primary to-secondary text-primary-foreground shadow-lg shadow-primary/30 hover:from-primary/90 hover:to-secondary/90',
|
'bg-gradient-to-r from-primary to-secondary text-primary-foreground shadow-lg shadow-primary/30 hover:from-primary/90 hover:to-secondary/90',
|
||||||
destructive:
|
destructive:
|
||||||
'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20',
|
||||||
outline:
|
outline:
|
||||||
'border border-primary/25 bg-background/80 shadow-sm hover:bg-primary/10 hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
'border border-primary/25 bg-background/80 shadow-sm hover:bg-primary/10 hover:text-foreground',
|
||||||
secondary: 'bg-secondary/90 text-secondary-foreground shadow-md hover:bg-secondary',
|
secondary: 'bg-secondary/90 text-secondary-foreground shadow-md hover:bg-secondary',
|
||||||
ghost: 'text-foreground/80 hover:bg-primary/10 hover:text-foreground dark:hover:bg-accent/50',
|
ghost: 'text-foreground/80 hover:bg-primary/10 hover:text-foreground',
|
||||||
link: 'text-primary underline-offset-4 hover:underline',
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import * as RechartsPrimitive from 'recharts';
|
|||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
// Format: { THEME_NAME: CSS_SELECTOR }
|
// Format: { THEME_NAME: CSS_SELECTOR }
|
||||||
const THEMES = { light: '', dark: '.dark' } as const;
|
const THEMES = { light: '' } as const;
|
||||||
|
|
||||||
export type ChartConfig = Record<
|
export type ChartConfig = Record<
|
||||||
string,
|
string,
|
||||||
@@ -209,7 +209,7 @@ function ChartTooltipContent({
|
|||||||
<span className="text-muted-foreground">{itemConfig?.label ?? item.name}</span>
|
<span className="text-muted-foreground">{itemConfig?.label ?? item.name}</span>
|
||||||
</div>
|
</div>
|
||||||
{item.value && (
|
{item.value && (
|
||||||
<span className="text-foreground font-mono font-medium tabular-nums">
|
<span className="text-foreground pl-2 font-mono font-medium tabular-nums">
|
||||||
{item.value.toLocaleString()}
|
{item.value.toLocaleString()}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ function DropdownMenuItem({
|
|||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
data-variant={variant}
|
data-variant={variant}
|
||||||
className={cn(
|
className={cn(
|
||||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
|
|||||||
type={type}
|
type={type}
|
||||||
data-slot="input"
|
data-slot="input"
|
||||||
className={cn(
|
className={cn(
|
||||||
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input bg-background flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input bg-background z-30 flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||||
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
||||||
'aria-invalid:ring-destructive/20 aria-invalid:border-destructive',
|
'aria-invalid:ring-destructive/20 aria-invalid:border-destructive',
|
||||||
className,
|
className,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function SelectTrigger({
|
|||||||
data-slot="select-trigger"
|
data-slot="select-trigger"
|
||||||
data-size={size}
|
data-size={size}
|
||||||
className={cn(
|
className={cn(
|
||||||
"border-input data-placeholder:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 aria-invalid:border-destructive bg-background flex w-fit items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
"border-input data-placeholder:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 aria-invalid:border-destructive bg-background z-30 flex w-fit items-center justify-between gap-2 rounded-md border px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
@import "tailwindcss";
|
@import 'tailwindcss';
|
||||||
@import "tw-animate-css";
|
@import 'tw-animate-css';
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--font-sans:
|
--font-sans:
|
||||||
var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif,
|
var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
@@ -60,9 +60,7 @@
|
|||||||
--secondary: oklch(0.49 0.1326 259.29); /* denim */
|
--secondary: oklch(0.49 0.1326 259.29); /* denim */
|
||||||
--secondary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
--secondary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||||
--muted: oklch(0.67 0.0763 198.81 / 20%); /* verdigris with opacity */
|
--muted: oklch(0.67 0.0763 198.81 / 20%); /* verdigris with opacity */
|
||||||
--muted-foreground: oklch(
|
--muted-foreground: oklch(0.39 0.0215 96.47 / 80%); /* black olive with opacity */
|
||||||
0.39 0.0215 96.47 / 80%
|
|
||||||
); /* black olive with opacity */
|
|
||||||
--accent: oklch(0.49 0.1326 259.29); /* denim */
|
--accent: oklch(0.49 0.1326 259.29); /* denim */
|
||||||
--accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
--accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||||
--destructive: oklch(0.33 0.1316 336.24); /* palatinate */
|
--destructive: oklch(0.33 0.1316 336.24); /* palatinate */
|
||||||
@@ -80,9 +78,7 @@
|
|||||||
--sidebar-primary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
--sidebar-primary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||||
--sidebar-accent: oklch(0.49 0.1326 259.29); /* denim */
|
--sidebar-accent: oklch(0.49 0.1326 259.29); /* denim */
|
||||||
--sidebar-accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
--sidebar-accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||||
--sidebar-border: oklch(
|
--sidebar-border: oklch(0.67 0.0763 198.81 / 20%); /* verdigris with opacity */
|
||||||
0.67 0.0763 198.81 / 20%
|
|
||||||
); /* verdigris with opacity */
|
|
||||||
--sidebar-ring: oklch(0.67 0.0763 198.81); /* verdigris */
|
--sidebar-ring: oklch(0.67 0.0763 198.81); /* verdigris */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,9 +112,7 @@
|
|||||||
--sidebar-primary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
--sidebar-primary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||||
--sidebar-accent: oklch(0.49 0.1326 259.29); /* denim */
|
--sidebar-accent: oklch(0.49 0.1326 259.29); /* denim */
|
||||||
--sidebar-accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
--sidebar-accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||||
--sidebar-border: oklch(
|
--sidebar-border: oklch(0.97 0.0228 95.96 / 10%); /* cosmic latte with opacity */
|
||||||
0.97 0.0228 95.96 / 10%
|
|
||||||
); /* cosmic latte with opacity */
|
|
||||||
--sidebar-ring: oklch(0.67 0.0763 198.81); /* verdigris */
|
--sidebar-ring: oklch(0.67 0.0763 198.81); /* verdigris */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +136,7 @@
|
|||||||
@apply scroll-m-20 text-xl font-semibold tracking-tight;
|
@apply scroll-m-20 text-xl font-semibold tracking-tight;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
@apply leading-7 [&:not(:first-child)]:mt-6;
|
@apply mb-2 leading-7 [&:not(:first-child)]:mt-6;
|
||||||
}
|
}
|
||||||
blockquote {
|
blockquote {
|
||||||
@apply mt-6 border-l-2 pl-6 italic;
|
@apply mt-6 border-l-2 pl-6 italic;
|
||||||
@@ -151,6 +145,6 @@
|
|||||||
@apply my-6 ml-6 list-disc [&>li]:mt-2;
|
@apply my-6 ml-6 list-disc [&>li]:mt-2;
|
||||||
}
|
}
|
||||||
code {
|
code {
|
||||||
@apply bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold
|
@apply bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user