init: scaffold IRPF — Institut de Recherche Politique pour la France
Astro 6 SSG, Tailwind, Content Collections (themes/propositions/rapports/acteurs). Fiche pilote : Économie & Finances publiques. Déployé sur france.reverdin.eu. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
07ccb222ae
17 changed files with 5539 additions and 0 deletions
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
||||
# jetbrains setting folder
|
||||
.idea/
|
||||
4
.vscode/extensions.json
vendored
Normal file
4
.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
43
README.md
Normal file
43
README.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Astro Starter Kit: Minimal
|
||||
|
||||
```sh
|
||||
pnpm create astro@latest -- --template minimal
|
||||
```
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```text
|
||||
/
|
||||
├── public/
|
||||
├── src/
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `pnpm install` | Installs dependencies |
|
||||
| `pnpm dev` | Starts local dev server at `localhost:4321` |
|
||||
| `pnpm build` | Build your production site to `./dist/` |
|
||||
| `pnpm preview` | Preview your build locally, before deploying |
|
||||
| `pnpm astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `pnpm astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
17
astro.config.mjs
Normal file
17
astro.config.mjs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// @ts-check
|
||||
import { defineConfig } from 'astro/config';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import mdx from '@astrojs/mdx';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'https://france.reverdin.eu',
|
||||
integrations: [
|
||||
mdx(),
|
||||
sitemap(),
|
||||
],
|
||||
vite: {
|
||||
plugins: [tailwindcss()]
|
||||
}
|
||||
});
|
||||
24
package.json
Normal file
24
package.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "irpf",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.9",
|
||||
"@astrojs/mdx": "^6.0.2",
|
||||
"@astrojs/sitemap": "^3.7.3",
|
||||
"@tailwindcss/vite": "^4.3.0",
|
||||
"astro": "^6.4.4",
|
||||
"pagefind": "^1.5.2",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"typescript": "^6.0.3"
|
||||
}
|
||||
}
|
||||
4688
pnpm-lock.yaml
generated
Normal file
4688
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load diff
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 655 B |
9
public/favicon.svg
Normal file
9
public/favicon.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 749 B |
69
src/content.config.ts
Normal file
69
src/content.config.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import { defineCollection, z } from 'astro:content';
|
||||
import { glob } from 'astro/loaders';
|
||||
|
||||
const themesCollection = defineCollection({
|
||||
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/themes' }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
slug: z.string(),
|
||||
description: z.string(),
|
||||
ordre: z.number(),
|
||||
priorite: z.enum(['critique', 'haute', 'normale']).default('normale'),
|
||||
budget_etat_milliards: z.number().optional(),
|
||||
effectifs_publics: z.number().optional(),
|
||||
tags: z.array(z.string()).default([]),
|
||||
sources_data: z.array(z.string()).default([]),
|
||||
derniere_maj: z.string(),
|
||||
image: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
const propositionsCollection = defineCollection({
|
||||
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/propositions' }),
|
||||
schema: z.object({
|
||||
titre: z.string(),
|
||||
theme: z.string(),
|
||||
source: z.string(),
|
||||
type_source: z.enum(['parti', 'think-tank', 'rapport-officiel', 'programme-presidentiel', 'rapport-parlementaire']),
|
||||
orientation: z.enum(['gauche', 'centre-gauche', 'centre', 'centre-droit', 'droite', 'autre']).optional(),
|
||||
annee: z.number(),
|
||||
horizon: z.enum(['court-terme', 'moyen-terme', 'long-terme']).default('moyen-terme'),
|
||||
impact_budgetaire: z.enum(['positif', 'negatif', 'neutre', 'variable']).optional(),
|
||||
url: z.string().url().optional(),
|
||||
resume: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
const rapportsCollection = defineCollection({
|
||||
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/rapports' }),
|
||||
schema: z.object({
|
||||
titre: z.string(),
|
||||
theme: z.string(),
|
||||
date: z.string(),
|
||||
auteurs: z.array(z.string()).default([]),
|
||||
institution: z.string(),
|
||||
resume: z.string(),
|
||||
url_pdf: z.string().url().optional(),
|
||||
tags: z.array(z.string()).default([]),
|
||||
}),
|
||||
});
|
||||
|
||||
const acteursCollection = defineCollection({
|
||||
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/acteurs' }),
|
||||
schema: z.object({
|
||||
nom: z.string(),
|
||||
type: z.enum(['think-tank', 'institution-publique', 'parti-politique', 'organisation-internationale', 'media']),
|
||||
orientation: z.enum(['gauche', 'centre-gauche', 'centre', 'centre-droit', 'droite', 'neutre']).optional(),
|
||||
specialites: z.array(z.string()).default([]),
|
||||
site: z.string().url().optional(),
|
||||
description: z.string(),
|
||||
fondation: z.number().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = {
|
||||
themes: themesCollection,
|
||||
propositions: propositionsCollection,
|
||||
rapports: rapportsCollection,
|
||||
acteurs: acteursCollection,
|
||||
};
|
||||
87
src/content/themes/economie-finances.mdx
Normal file
87
src/content/themes/economie-finances.mdx
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
title: "Économie & Finances publiques"
|
||||
slug: "economie-finances"
|
||||
description: "Dette, déficit, fiscalité, compétitivité : les enjeux budgétaires structurels de la France et les leviers de redressement."
|
||||
ordre: 1
|
||||
priorite: critique
|
||||
budget_etat_milliards: 492
|
||||
effectifs_publics: 0
|
||||
tags: [dette, deficit, fiscalite, competitivite, budget]
|
||||
sources_data: ["INSEE", "Banque de France", "FMI", "HCFP", "Eurostat", "CAE"]
|
||||
derniere_maj: "2026-06"
|
||||
---
|
||||
|
||||
## Diagnostic
|
||||
|
||||
La France présente en 2025 un déséquilibre budgétaire chronique qui place ses finances publiques sous surveillance des institutions européennes et des marchés. Avec un déficit public de **5,5% du PIB en 2024** — soit le double de la limite maastrichtienne de 3% — et une dette à **113% du PIB**, la trajectoire actuelle est insoutenable à moyen terme sans ajustement significatif.
|
||||
|
||||
### Les chiffres clés
|
||||
|
||||
- **Dette publique** : 3 228 milliards d'euros (113% PIB, fin 2024 · source : INSEE)
|
||||
- **Déficit public** : -5,5% du PIB en 2024 (hors objectif des 3%) · source : INSEE/HCFP
|
||||
- **Charge de la dette** : 54 milliards d'euros en 2024, en hausse rapide avec la remontée des taux
|
||||
- **Dépenses publiques** : 57,3% du PIB — 2e rang de l'UE derrière la Finlande · source : Eurostat
|
||||
- **Prélèvements obligatoires** : 45,4% du PIB — parmi les plus élevés de l'OCDE · source : OCDE
|
||||
- **Croissance 2024** : +1,1% du PIB (consensus économistes) · source : Banque de France
|
||||
|
||||
### Comparaisons internationales
|
||||
|
||||
| Pays | Dette/PIB | Déficit/PIB | Dépenses publiques/PIB |
|
||||
|------|-----------|------------|----------------------|
|
||||
| **France** | **113%** | **-5,5%** | **57,3%** |
|
||||
| Allemagne | 63% | -1,6% | 48,5% |
|
||||
| Italie | 137% | -3,4% | 54,9% |
|
||||
| Espagne | 105% | -3,5% | 46,8% |
|
||||
| Moyenne UE | 82% | -3,5% | 49,8% |
|
||||
|
||||
La France est dans une position particulière : dépenses publiques très élevées, croissance atone, dette en progression rapide depuis 2008.
|
||||
|
||||
## Enjeux structurels
|
||||
|
||||
### 1. La trajectoire de la dette est préoccupante
|
||||
Sans réforme, la dette devrait dépasser **120% du PIB d'ici 2030** selon le FMI. La charge des intérêts double avec la normalisation des taux de la BCE, passant de 35 à 60+ milliards d'euros. Un choc de taux de +1 point coûte 3 milliards d'euros par an à terme.
|
||||
|
||||
### 2. Le modèle fiscal atteint ses limites
|
||||
La France a l'un des taux de prélèvements obligatoires les plus élevés de l'OCDE (45,4% du PIB). Les Français payent plus d'impôts que les Allemands, les Britanniques et les Américains. L'espace pour de nouvelles hausses est très limité — et les études du CAE montrent que des hausses d'impôts excessives réduisent l'activité économique.
|
||||
|
||||
### 3. La structure des dépenses est rigide
|
||||
75% des dépenses publiques françaises sont des dépenses de fonctionnement (salaires, retraites, prestations sociales) très difficiles à réduire rapidement. La "coquille" des dépenses productives (investissement, recherche) est comprimée.
|
||||
|
||||
### 4. La compétitivité productive s'érode
|
||||
Le coût du travail reste élevé malgré les allègements de charges. La France produit moins de brevets que l'Allemagne proportionnellement à sa taille, et ses champions industriels sont trop peu nombreux dans les secteurs stratégiques du XXIe siècle (semi-conducteurs, IA, défense).
|
||||
|
||||
### 5. La décentralisation est un facteur d'inefficience
|
||||
La France cumule communes (36 000), intercommunalités, départements, régions et État central — cinq niveaux de gouvernance avec des compétences qui se chevauchent. Le "millefeuille territorial" coûte selon l'iFRAP entre 15 et 25 milliards d'euros par an en doublons administratifs.
|
||||
|
||||
## Cartographie des propositions
|
||||
|
||||
| Proposition | Source | Orientation | Impact budgétaire | Horizon |
|
||||
|------------|--------|------------|-------------------|---------|
|
||||
| Réduction de 50 Md€ des dépenses publiques en 5 ans | iFRAP | Centre-droit | +50 Md€/an à terme | Long terme |
|
||||
| Fusion communes + intercommunalités | Terra Nova | Centre-gauche | -15 Md€/an | Long terme |
|
||||
| Taxe sur les "super-profits" des entreprises énergie | LFI | Gauche | +5 Md€ ponctuel | Court terme |
|
||||
| Baisse de l'IS à 20% pour PME innovantes | LR | Centre-droit | -3 Md€/an | Moyen terme |
|
||||
| Règle d'or budgétaire constitutionnelle | Fondapol | Centre-droit | Contraignant | Long terme |
|
||||
| Impôt minimum mondial 15% sur les multinationales | OCDE/Gouvernement | Neutre | +1,5 Md€/an | Court terme |
|
||||
| Réforme structurelle de la fiscalité du capital | CAE | Neutre | Variable | Long terme |
|
||||
| Grand emprunt vert pour la transition | PS/EELV | Gauche | +50 Md€ dette | Court terme |
|
||||
|
||||
## Scénarios 2027–2032
|
||||
|
||||
### Scénario Dérive (-5,5% PIB en 2032)
|
||||
Maintien du statu quo politique : hausses d'impôts marginales, pas de réforme structurelle. La dette atteint 125% du PIB. Les agences de notation dégradent la France. La charge de la dette absorbe 4% du budget de l'État. Risque de spirale.
|
||||
|
||||
### Scénario Réforme graduelle (-3% PIB en 2030)
|
||||
Économies de 15 Md€/an sur les dépenses publiques + optimisation fiscale ciblée. Retour aux critères de Maastricht en 2030. Dette stabilisée à 115% du PIB. Croissance portée à +1,5%/an grâce à l'amélioration de la confiance des investisseurs.
|
||||
|
||||
### Scénario Choc républicain (-1,5% PIB en 2032)
|
||||
Réforme ambitieuse : fusion de niveaux de gouvernance (économie 20 Md€), réforme de la fonction publique (10 Md€), simplification fiscale radicale (baisse de la fiscalité du travail compensée par élargissement des bases). Croissance portée à +2%/an.
|
||||
|
||||
## Sources et références
|
||||
|
||||
- [Rapport de la Cour des comptes — Situation des finances publiques 2024](https://www.ccomptes.fr)
|
||||
- [HCFP — Avis sur le projet de loi de finances 2025](https://www.hcfp.fr)
|
||||
- [OCDE — Études économiques : France 2024](https://www.oecd.org/economy/france-economic-snapshot/)
|
||||
- [FMI — Article IV : France 2024](https://www.imf.org)
|
||||
- [INSEE — Comptes nationaux trimestriels](https://www.insee.fr)
|
||||
- [Banque de France — Projections macroéconomiques](https://www.banque-france.fr)
|
||||
117
src/layouts/BaseLayout.astro
Normal file
117
src/layouts/BaseLayout.astro
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
---
|
||||
import '../styles/global.css';
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
og_image?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
title = 'IRPF — Institut de Recherche Politique pour la France',
|
||||
description = 'Analyse indépendante et non-partisane des politiques publiques françaises. Données, diagnostic, propositions.',
|
||||
og_image = '/og-default.png',
|
||||
} = Astro.props;
|
||||
|
||||
const canonical = new URL(Astro.url.pathname, Astro.site);
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="canonical" href={canonical} />
|
||||
|
||||
<!-- OG -->
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content={og_image} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet" />
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||
</head>
|
||||
<body class="min-h-screen flex flex-col">
|
||||
|
||||
<!-- Barre institutionnelle -->
|
||||
<div style="background: #0f172a; color: white; font-size: 0.75rem; padding: 0.375rem 0; text-align: center; letter-spacing: 0.05em;">
|
||||
INSTITUT DE RECHERCHE POLITIQUE POUR LA FRANCE · Analyse indépendante · Données publiques
|
||||
</div>
|
||||
|
||||
<!-- Header -->
|
||||
<header style="background: white; border-bottom: 2px solid #1e3a6e; position: sticky; top: 0; z-index: 50;">
|
||||
<div style="max-width: 1200px; margin: 0 auto; padding: 0 1.5rem; display: flex; align-items: center; justify-content: space-between; height: 4rem;">
|
||||
|
||||
<a href="/" style="display: flex; align-items: center; gap: 0.75rem; text-decoration: none;">
|
||||
<div style="background: #1e3a6e; color: white; font-weight: 700; font-size: 1.125rem; padding: 0.25rem 0.625rem; border-radius: 0.25rem; letter-spacing: 0.05em;">IRPF</div>
|
||||
<span style="font-size: 0.8rem; color: #374151; font-weight: 500; display: none;" class="sm-show">Institut de Recherche Politique pour la France</span>
|
||||
</a>
|
||||
|
||||
<nav style="display: flex; gap: 1.5rem; align-items: center;">
|
||||
<a href="/themes/" style="font-size: 0.875rem; color: #374151; text-decoration: none; font-weight: 500;" class="nav-link">Thèmes</a>
|
||||
<a href="/donnees/" style="font-size: 0.875rem; color: #374151; text-decoration: none; font-weight: 500;" class="nav-link">Données</a>
|
||||
<a href="/propositions/" style="font-size: 0.875rem; color: #374151; text-decoration: none; font-weight: 500;" class="nav-link">Propositions</a>
|
||||
<a href="/scenarios/" style="font-size: 0.875rem; color: #374151; text-decoration: none; font-weight: 500;" class="nav-link">Scénarios</a>
|
||||
<a href="/rapports/" style="font-size: 0.875rem; color: #374151; text-decoration: none; font-weight: 500;" class="nav-link">Rapports</a>
|
||||
<a href="/a-propos/" style="font-size: 0.875rem; color: #6b7280; text-decoration: none;" class="nav-link">À propos</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Contenu -->
|
||||
<main class="flex-1">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer style="background: #0f172a; color: #9ca3af; margin-top: 4rem;">
|
||||
<div style="max-width: 1200px; margin: 0 auto; padding: 3rem 1.5rem; display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 2rem;">
|
||||
<div>
|
||||
<div style="color: white; font-weight: 700; font-size: 1.125rem; margin-bottom: 0.75rem;">IRPF</div>
|
||||
<p style="font-size: 0.875rem; line-height: 1.6;">Institut de Recherche Politique pour la France. Analyse indépendante, non-partisane, fondée sur les données publiques.</p>
|
||||
<p style="font-size: 0.75rem; margin-top: 1rem; color: #6b7280;">Sources : INSEE, OCDE, Eurostat, Banque de France, data.gouv.fr et institutions publiques.</p>
|
||||
</div>
|
||||
<div>
|
||||
<div style="color: white; font-weight: 600; font-size: 0.875rem; margin-bottom: 0.75rem;">Thèmes</div>
|
||||
<ul style="space-y: 0.5rem; font-size: 0.8rem;">
|
||||
<li><a href="/themes/economie-finances/" style="color: #9ca3af; text-decoration: none; hover: white;">Économie</a></li>
|
||||
<li><a href="/themes/sante/" style="color: #9ca3af; text-decoration: none;">Santé</a></li>
|
||||
<li><a href="/themes/education/" style="color: #9ca3af; text-decoration: none;">Éducation</a></li>
|
||||
<li><a href="/themes/" style="color: #6b7280; text-decoration: none;">Voir tous →</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<div style="color: white; font-weight: 600; font-size: 0.875rem; margin-bottom: 0.75rem;">Analyses</div>
|
||||
<ul style="font-size: 0.8rem;">
|
||||
<li><a href="/donnees/" style="color: #9ca3af; text-decoration: none;">Tableau de bord</a></li>
|
||||
<li><a href="/propositions/" style="color: #9ca3af; text-decoration: none;">Propositions</a></li>
|
||||
<li><a href="/scenarios/" style="color: #9ca3af; text-decoration: none;">Scénarios 2032</a></li>
|
||||
<li><a href="/rapports/" style="color: #9ca3af; text-decoration: none;">Publications</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<div style="color: white; font-weight: 600; font-size: 0.875rem; margin-bottom: 0.75rem;">Institut</div>
|
||||
<ul style="font-size: 0.8rem;">
|
||||
<li><a href="/a-propos/" style="color: #9ca3af; text-decoration: none;">Mission</a></li>
|
||||
<li><a href="/acteurs/" style="color: #9ca3af; text-decoration: none;">Cartographie</a></li>
|
||||
<li><a href="/bibliotheque/" style="color: #9ca3af; text-decoration: none;">Bibliothèque</a></li>
|
||||
<li><a href="/veille/" style="color: #9ca3af; text-decoration: none;">Veille</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #1f2937; text-align: center; padding: 1.5rem; font-size: 0.75rem; color: #4b5563;">
|
||||
© {new Date().getFullYear()} Institut de Recherche Politique pour la France · Données publiques · Analyse libre
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
148
src/pages/index.astro
Normal file
148
src/pages/index.astro
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
const themes = (await getCollection('themes')).sort((a, b) => a.data.ordre - b.data.ordre);
|
||||
const rapports = (await getCollection('rapports')).slice(0, 3);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="IRPF — Institut de Recherche Politique pour la France"
|
||||
description="Analyse indépendante des grandes problématiques françaises. Données, diagnostics, propositions pour 2027 et au-delà."
|
||||
>
|
||||
|
||||
<!-- Hero -->
|
||||
<section style="background: linear-gradient(135deg, #0f172a 0%, #1e3a6e 100%); color: white; padding: 5rem 1.5rem 4rem;">
|
||||
<div style="max-width: 900px; margin: 0 auto; text-align: center;">
|
||||
<div style="font-size: 0.8rem; letter-spacing: 0.15em; color: #93c5fd; margin-bottom: 1.5rem; font-weight: 500;">
|
||||
INSTITUT DE RECHERCHE POLITIQUE POUR LA FRANCE
|
||||
</div>
|
||||
<h1 style="font-family: 'Playfair Display', serif; font-size: 3rem; font-weight: 700; line-height: 1.2; margin-bottom: 1.5rem;">
|
||||
Comprendre la France.<br/>
|
||||
<span style="color: #93c5fd;">Proposer des solutions.</span>
|
||||
</h1>
|
||||
<p style="font-size: 1.125rem; color: #cbd5e1; max-width: 680px; margin: 0 auto 2.5rem; line-height: 1.7;">
|
||||
Analyse non-partisane des politiques publiques françaises, fondée sur les données de l'INSEE, de l'OCDE et des institutions internationales. Pour alimenter le débat démocratique en 2027 et au-delà.
|
||||
</p>
|
||||
<div style="display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap;">
|
||||
<a href="/themes/" style="background: white; color: #1e3a6e; padding: 0.75rem 2rem; border-radius: 0.375rem; font-weight: 600; text-decoration: none; font-size: 0.9rem;">
|
||||
Explorer les thèmes →
|
||||
</a>
|
||||
<a href="/donnees/" style="border: 1px solid rgba(255,255,255,0.3); color: white; padding: 0.75rem 2rem; border-radius: 0.375rem; font-weight: 500; text-decoration: none; font-size: 0.9rem;">
|
||||
Tableau de bord France
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- KPIs -->
|
||||
<section style="background: #f8fafc; border-bottom: 1px solid #e5e7eb; padding: 2rem 1.5rem;">
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem;">
|
||||
<div class="kpi-card" style="text-align: center;">
|
||||
<div class="kpi-value">-5,5%</div>
|
||||
<div class="kpi-label">Déficit public / PIB 2024</div>
|
||||
<div class="kpi-source">Source : INSEE</div>
|
||||
</div>
|
||||
<div class="kpi-card" style="text-align: center;">
|
||||
<div class="kpi-value">113%</div>
|
||||
<div class="kpi-label">Dette publique / PIB</div>
|
||||
<div class="kpi-source">Source : Eurostat</div>
|
||||
</div>
|
||||
<div class="kpi-card" style="text-align: center;">
|
||||
<div class="kpi-value">7,3%</div>
|
||||
<div class="kpi-label">Taux de chômage T1 2025</div>
|
||||
<div class="kpi-source">Source : DARES</div>
|
||||
</div>
|
||||
<div class="kpi-card" style="text-align: center;">
|
||||
<div class="kpi-value">28e</div>
|
||||
<div class="kpi-label">Rang PISA 2022 (sciences)</div>
|
||||
<div class="kpi-source">Source : OCDE</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Manifeste -->
|
||||
<section style="padding: 4rem 1.5rem; max-width: 780px; margin: 0 auto;">
|
||||
<div style="font-size: 0.8rem; letter-spacing: 0.1em; color: #1e3a6e; font-weight: 600; margin-bottom: 1rem;">NOTRE DÉMARCHE</div>
|
||||
<h2 style="font-family: 'Playfair Display', serif; font-size: 2rem; color: #0f172a; margin-bottom: 1.5rem;">
|
||||
La France a besoin d'un diagnostic rigoureux avant un programme
|
||||
</h2>
|
||||
<div style="color: #374151; line-height: 1.8; font-size: 1.05rem;">
|
||||
<p style="margin-bottom: 1rem;">Le débat politique français souffre d'un paradoxe : beaucoup de propositions, peu de données ; beaucoup de slogans, peu de diagnostic. L'IRPF fait le chemin inverse.</p>
|
||||
<p style="margin-bottom: 1rem;">Nous partons des faits — ceux de l'INSEE, de l'OCDE, de la Cour des comptes, des rapports parlementaires — pour cartographier chaque grande problématique française, recenser toutes les propositions des acteurs du débat, et proposer des analyses originales.</p>
|
||||
<p>Ni de gauche ni de droite. Exigeant sur les chiffres. Libre sur les idées.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Thèmes -->
|
||||
<section style="background: #f8fafc; padding: 4rem 1.5rem; border-top: 1px solid #e5e7eb;">
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 2rem;">
|
||||
<div>
|
||||
<div style="font-size: 0.8rem; letter-spacing: 0.1em; color: #1e3a6e; font-weight: 600; margin-bottom: 0.5rem;">14 GRANDES THÉMATIQUES</div>
|
||||
<h2 style="font-family: 'Playfair Display', serif; font-size: 1.875rem; color: #0f172a;">Les chantiers de la France</h2>
|
||||
</div>
|
||||
<a href="/themes/" style="color: #1e3a6e; font-weight: 500; text-decoration: none; font-size: 0.9rem;">Voir tout →</a>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;">
|
||||
{themes.slice(0, 6).map((theme) => (
|
||||
<a href={`/themes/${theme.slug}/`} style="background: white; border: 1px solid #e5e7eb; border-radius: 0.5rem; padding: 1.5rem; text-decoration: none; display: block;" class="theme-card">
|
||||
<div style="font-weight: 600; color: #0f172a; margin-bottom: 0.5rem;">{theme.data.title}</div>
|
||||
<p style="font-size: 0.85rem; color: #6b7280; line-height: 1.5; margin-bottom: 1rem;">{theme.data.description}</p>
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||
{theme.data.priorite === 'critique' && (
|
||||
<span style="background: #fee2e2; color: #991b1b; font-size: 0.7rem; font-weight: 600; padding: 0.2rem 0.5rem; border-radius: 0.25rem;">CRITIQUE</span>
|
||||
)}
|
||||
{theme.data.budget_etat_milliards && (
|
||||
<span style="background: #eff6ff; color: #1d4ed8; font-size: 0.7rem; padding: 0.2rem 0.5rem; border-radius: 0.25rem;">{theme.data.budget_etat_milliards} Md€</span>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
{themes.length > 6 && (
|
||||
<div style="text-align: center; margin-top: 2rem;">
|
||||
<a href="/themes/" style="display: inline-block; border: 1px solid #1e3a6e; color: #1e3a6e; padding: 0.625rem 1.5rem; border-radius: 0.375rem; font-weight: 500; text-decoration: none; font-size: 0.9rem;">
|
||||
Voir les {themes.length - 6} autres thèmes
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Scénarios -->
|
||||
<section style="padding: 4rem 1.5rem; max-width: 1200px; margin: 0 auto;">
|
||||
<div style="background: linear-gradient(135deg, #0f172a, #1e3a6e); border-radius: 0.75rem; padding: 3rem; color: white; display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center;">
|
||||
<div>
|
||||
<div style="font-size: 0.8rem; letter-spacing: 0.1em; color: #93c5fd; font-weight: 600; margin-bottom: 1rem;">SCÉNARIOS MACRO 2027–2032</div>
|
||||
<h2 style="font-family: 'Playfair Display', serif; font-size: 1.875rem; margin-bottom: 1rem;">Trois avenirs possibles pour la France</h2>
|
||||
<p style="color: #cbd5e1; line-height: 1.7; margin-bottom: 1.5rem;">De la dérive budgétaire au choc républicain : nous chiffrons les conséquences de chaque trajectoire sur la dette, la croissance et les services publics.</p>
|
||||
<a href="/scenarios/" style="background: white; color: #1e3a6e; padding: 0.625rem 1.5rem; border-radius: 0.375rem; font-weight: 600; text-decoration: none; font-size: 0.9rem;">Lire les scénarios →</a>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 1rem;">
|
||||
<div style="background: rgba(255,255,255,0.07); border-left: 3px solid #ef4444; padding: 1rem 1.25rem; border-radius: 0.25rem;">
|
||||
<div style="font-weight: 600; color: white;">Dérive</div>
|
||||
<div style="font-size: 0.85rem; color: #ef4444; font-weight: 500;">-5,5% PIB en 2032 · +0,8%/an</div>
|
||||
</div>
|
||||
<div style="background: rgba(255,255,255,0.07); border-left: 3px solid #f59e0b; padding: 1rem 1.25rem; border-radius: 0.25rem;">
|
||||
<div style="font-weight: 600; color: white;">Réforme graduelle</div>
|
||||
<div style="font-size: 0.85rem; color: #f59e0b; font-weight: 500;">-3% PIB en 2030 · +1,4%/an</div>
|
||||
</div>
|
||||
<div style="background: rgba(255,255,255,0.07); border-left: 3px solid #22c55e; padding: 1rem 1.25rem; border-radius: 0.25rem;">
|
||||
<div style="font-weight: 600; color: white;">Choc républicain</div>
|
||||
<div style="font-size: 0.85rem; color: #22c55e; font-weight: 500;">-1,5% PIB en 2032 · +2%/an</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
.theme-card:hover {
|
||||
border-color: #1e3a6e !important;
|
||||
box-shadow: 0 2px 8px rgba(30,58,110,0.1);
|
||||
}
|
||||
</style>
|
||||
143
src/pages/themes/[slug].astro
Normal file
143
src/pages/themes/[slug].astro
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getCollection, render } from 'astro:content';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const themes = await getCollection('themes');
|
||||
return themes.map(theme => ({
|
||||
params: { slug: theme.data.slug },
|
||||
props: { theme },
|
||||
}));
|
||||
}
|
||||
|
||||
const { theme } = Astro.props;
|
||||
const { Content } = await render(theme);
|
||||
|
||||
const allPropositions = await getCollection('propositions');
|
||||
const propositions = allPropositions.filter(p => p.data.theme === theme.data.slug);
|
||||
|
||||
function orientationBadge(o?: string) {
|
||||
const map: Record<string, string> = {
|
||||
'gauche': 'background:#fee2e2;color:#991b1b',
|
||||
'centre-gauche': 'background:#fce7f3;color:#9d174d',
|
||||
'centre': 'background:#dbeafe;color:#1e40af',
|
||||
'centre-droit': 'background:#ede9fe;color:#5b21b6',
|
||||
'droite': 'background:#f3e8ff;color:#6b21a8',
|
||||
'neutre': 'background:#f3f4f6;color:#374151',
|
||||
};
|
||||
return map[o ?? 'neutre'] ?? map['neutre'];
|
||||
}
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${theme.data.title} — IRPF`}
|
||||
description={theme.data.description}
|
||||
>
|
||||
|
||||
<!-- Breadcrumb -->
|
||||
<div style="background: #f8fafc; border-bottom: 1px solid #e5e7eb; padding: 0.75rem 1.5rem;">
|
||||
<div style="max-width: 1200px; margin: 0 auto; font-size: 0.8rem; color: #6b7280;">
|
||||
<a href="/" style="color: #6b7280; text-decoration: none;">Accueil</a>
|
||||
<span style="margin: 0 0.5rem;">›</span>
|
||||
<a href="/themes/" style="color: #6b7280; text-decoration: none;">Thèmes</a>
|
||||
<span style="margin: 0 0.5rem;">›</span>
|
||||
<span style="color: #374151;">{theme.data.title}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Header -->
|
||||
<section style="background: linear-gradient(135deg, #0f172a, #1e3a6e); color: white; padding: 3rem 1.5rem;">
|
||||
<div style="max-width: 1200px; margin: 0 auto; display: grid; grid-template-columns: 1fr auto; gap: 2rem; align-items: start;">
|
||||
<div>
|
||||
{theme.data.priorite === 'critique' && (
|
||||
<span style="background: #ef4444; color: white; font-size: 0.7rem; font-weight: 700; padding: 0.2rem 0.625rem; border-radius: 0.25rem; letter-spacing: 0.05em; margin-bottom: 1rem; display: inline-block;">PRIORITÉ CRITIQUE</span>
|
||||
)}
|
||||
<h1 style="font-family: 'Playfair Display', serif; font-size: 2.5rem; margin-bottom: 1rem;">{theme.data.title}</h1>
|
||||
<p style="color: #cbd5e1; font-size: 1.05rem; line-height: 1.7; max-width: 700px;">{theme.data.description}</p>
|
||||
<div style="display: flex; gap: 1rem; margin-top: 1.5rem; flex-wrap: wrap;">
|
||||
{theme.data.budget_etat_milliards && (
|
||||
<div style="background: rgba(255,255,255,0.1); padding: 0.5rem 1rem; border-radius: 0.375rem;">
|
||||
<div style="font-size: 1.25rem; font-weight: 700;">{theme.data.budget_etat_milliards} Md€</div>
|
||||
<div style="font-size: 0.75rem; color: #93c5fd;">Budget État 2025</div>
|
||||
</div>
|
||||
)}
|
||||
<div style="background: rgba(255,255,255,0.1); padding: 0.5rem 1rem; border-radius: 0.375rem;">
|
||||
<div style="font-size: 1.25rem; font-weight: 700;">{propositions.length}</div>
|
||||
<div style="font-size: 0.75rem; color: #93c5fd;">Propositions recensées</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<div style="font-size: 0.75rem; color: #6b7280;">Mis à jour</div>
|
||||
<div style="font-size: 0.875rem; color: #93c5fd;">{theme.data.derniere_maj}</div>
|
||||
<div style="margin-top: 1rem;">
|
||||
<div style="font-size: 0.75rem; color: #6b7280; margin-bottom: 0.5rem;">Sources data</div>
|
||||
{theme.data.sources_data.map(s => (
|
||||
<div style="font-size: 0.75rem; color: #93c5fd;">{s}</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Nav interne -->
|
||||
<nav style="background: white; border-bottom: 1px solid #e5e7eb; padding: 0 1.5rem; position: sticky; top: 64px; z-index: 40;">
|
||||
<div style="max-width: 1200px; margin: 0 auto; display: flex; gap: 2rem; overflow-x: auto;">
|
||||
{['Diagnostic', 'Enjeux', 'Propositions', 'Scénarios', 'Sources'].map(anchor => (
|
||||
<a href={`#${anchor.toLowerCase().replace('é','e').replace('s','s')}`} style="padding: 1rem 0; font-size: 0.875rem; font-weight: 500; color: #374151; text-decoration: none; white-space: nowrap; border-bottom: 2px solid transparent;" class="nav-anchor">
|
||||
{anchor}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Contenu -->
|
||||
<div style="max-width: 1200px; margin: 0 auto; padding: 3rem 1.5rem; display: grid; grid-template-columns: 1fr 280px; gap: 3rem; align-items: start;">
|
||||
|
||||
<article>
|
||||
<div class="prose-irpf">
|
||||
<Content />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<aside style="position: sticky; top: 120px;">
|
||||
{propositions.length > 0 && (
|
||||
<div style="background: #f8fafc; border: 1px solid #e5e7eb; border-radius: 0.5rem; padding: 1.25rem; margin-bottom: 1.5rem;">
|
||||
<div style="font-weight: 600; font-size: 0.875rem; color: #0f172a; margin-bottom: 1rem;">Propositions recensées ({propositions.length})</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 0.75rem;">
|
||||
{propositions.slice(0, 5).map(p => (
|
||||
<div style="background: white; border: 1px solid #e5e7eb; border-radius: 0.375rem; padding: 0.75rem;">
|
||||
<div style="font-size: 0.8rem; font-weight: 500; color: #0f172a; margin-bottom: 0.35rem; line-height: 1.4;">{p.data.titre}</div>
|
||||
<div style="display: flex; gap: 0.35rem; flex-wrap: wrap; align-items: center;">
|
||||
<span style={`font-size: 0.65rem; padding: 0.15rem 0.4rem; border-radius: 0.2rem; font-weight: 500; ${orientationBadge(p.data.orientation)}`}>
|
||||
{p.data.source}
|
||||
</span>
|
||||
<span style="font-size: 0.65rem; color: #9ca3af;">{p.data.annee}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{propositions.length > 5 && (
|
||||
<a href="/propositions/" style="display: block; text-align: center; margin-top: 0.75rem; font-size: 0.8rem; color: #1e3a6e; text-decoration: none;">
|
||||
Voir les {propositions.length - 5} autres →
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style="background: #f8fafc; border: 1px solid #e5e7eb; border-radius: 0.5rem; padding: 1.25rem;">
|
||||
<div style="font-weight: 600; font-size: 0.875rem; color: #0f172a; margin-bottom: 0.75rem;">Mots-clés</div>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 0.4rem;">
|
||||
{theme.data.tags.map(tag => (
|
||||
<span style="background: white; border: 1px solid #e5e7eb; color: #374151; font-size: 0.75rem; padding: 0.25rem 0.625rem; border-radius: 0.25rem;">#{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
.nav-anchor:hover { color: #1e3a6e; border-bottom-color: #1e3a6e !important; }
|
||||
</style>
|
||||
78
src/pages/themes/index.astro
Normal file
78
src/pages/themes/index.astro
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
const themes = (await getCollection('themes')).sort((a, b) => a.data.ordre - b.data.ordre);
|
||||
const critiques = themes.filter(t => t.data.priorite === 'critique');
|
||||
const autres = themes.filter(t => t.data.priorite !== 'critique');
|
||||
---
|
||||
|
||||
<BaseLayout title="Thèmes — IRPF" description="Les 14 grandes thématiques des politiques publiques françaises analysées par l'IRPF.">
|
||||
|
||||
<section style="background: #0f172a; color: white; padding: 3rem 1.5rem;">
|
||||
<div style="max-width: 1200px; margin: 0 auto;">
|
||||
<div style="font-size: 0.75rem; letter-spacing: 0.1em; color: #93c5fd; margin-bottom: 0.75rem;">IRPF</div>
|
||||
<h1 style="font-family: 'Playfair Display', serif; font-size: 2.5rem; margin-bottom: 1rem;">Les 14 thèmes</h1>
|
||||
<p style="color: #cbd5e1; max-width: 600px; line-height: 1.7;">Pour chaque thème : diagnostic sourcé, cartographie des propositions par acteur, scénarios chiffrés, analyse originale.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section style="padding: 3rem 1.5rem; max-width: 1200px; margin: 0 auto;">
|
||||
|
||||
{critiques.length > 0 && (
|
||||
<div style="margin-bottom: 3rem;">
|
||||
<div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.5rem;">
|
||||
<span style="background: #fee2e2; color: #991b1b; font-size: 0.7rem; font-weight: 700; padding: 0.25rem 0.75rem; border-radius: 0.25rem; letter-spacing: 0.05em;">PRIORITÉ CRITIQUE</span>
|
||||
<div style="flex: 1; height: 1px; background: #fca5a5;"></div>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;">
|
||||
{critiques.map(theme => (
|
||||
<a href={`/themes/${theme.slug}/`} style="background: white; border: 2px solid #fca5a5; border-radius: 0.5rem; padding: 1.5rem; text-decoration: none; display: block;" class="theme-card">
|
||||
<div style="font-weight: 700; color: #0f172a; font-size: 1.05rem; margin-bottom: 0.5rem;">{theme.data.title}</div>
|
||||
<p style="font-size: 0.85rem; color: #6b7280; line-height: 1.5; margin-bottom: 1rem;">{theme.data.description}</p>
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center;">
|
||||
{theme.data.budget_etat_milliards && (
|
||||
<span style="background: #eff6ff; color: #1d4ed8; font-size: 0.7rem; padding: 0.2rem 0.5rem; border-radius: 0.25rem; font-weight: 500;">{theme.data.budget_etat_milliards} Md€/an</span>
|
||||
)}
|
||||
{theme.data.tags.slice(0, 2).map(tag => (
|
||||
<span style="background: #f3f4f6; color: #6b7280; font-size: 0.7rem; padding: 0.2rem 0.5rem; border-radius: 0.25rem;">#{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{autres.length > 0 && (
|
||||
<div>
|
||||
<div style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 1.5rem;">
|
||||
<span style="color: #374151; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.05em;">TOUS LES THÈMES</span>
|
||||
<div style="flex: 1; height: 1px; background: #e5e7eb;"></div>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem;">
|
||||
{autres.map(theme => (
|
||||
<a href={`/themes/${theme.slug}/`} style="background: white; border: 1px solid #e5e7eb; border-radius: 0.5rem; padding: 1.5rem; text-decoration: none; display: block;" class="theme-card">
|
||||
<div style="font-weight: 600; color: #0f172a; margin-bottom: 0.5rem;">{theme.data.title}</div>
|
||||
<p style="font-size: 0.85rem; color: #6b7280; line-height: 1.5; margin-bottom: 1rem;">{theme.data.description}</p>
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||
{theme.data.tags.slice(0, 2).map(tag => (
|
||||
<span style="background: #f3f4f6; color: #6b7280; font-size: 0.7rem; padding: 0.2rem 0.5rem; border-radius: 0.25rem;">#{tag}</span>
|
||||
))}
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</section>
|
||||
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
.theme-card:hover {
|
||||
border-color: #1e3a6e !important;
|
||||
box-shadow: 0 2px 8px rgba(30,58,110,0.08);
|
||||
}
|
||||
</style>
|
||||
72
src/styles/global.css
Normal file
72
src/styles/global.css
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
--color-bleu-nuit: #0f172a;
|
||||
--color-bleu-republic: #1e3a6e;
|
||||
--color-bleu-accent: #2563eb;
|
||||
--color-gris-ardoise: #374151;
|
||||
--color-gris-clair: #f8fafc;
|
||||
--color-rouge-republique: #c0392b;
|
||||
|
||||
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-serif: "Playfair Display", ui-serif, Georgia, serif;
|
||||
--font-mono: ui-monospace, monospace;
|
||||
}
|
||||
|
||||
html { scroll-behavior: smooth; }
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
color: #111827;
|
||||
font-family: var(--font-sans);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* Typographie éditoriale */
|
||||
.prose-irpf h2 {
|
||||
font-size: 1.5rem;
|
||||
font-family: var(--font-serif);
|
||||
font-weight: 700;
|
||||
color: var(--color-bleu-nuit);
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
padding-bottom: 0.5rem;
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.prose-irpf h3 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-bleu-republic);
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.prose-irpf p {
|
||||
color: #374151;
|
||||
line-height: 1.75;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.prose-irpf a { color: var(--color-bleu-accent); text-decoration: underline; }
|
||||
.prose-irpf blockquote {
|
||||
border-left: 4px solid var(--color-bleu-accent);
|
||||
padding-left: 1rem;
|
||||
font-style: italic;
|
||||
color: #6b7280;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
.prose-irpf ul { list-style: disc inside; color: #374151; margin-bottom: 1rem; }
|
||||
.prose-irpf strong { font-weight: 600; color: #111827; }
|
||||
|
||||
/* KPI cards */
|
||||
.kpi-card {
|
||||
background: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
|
||||
}
|
||||
.kpi-value { font-size: 1.875rem; font-weight: 700; color: var(--color-bleu-nuit); font-family: var(--font-mono); }
|
||||
.kpi-label { font-size: 0.875rem; color: #6b7280; margin-top: 0.25rem; }
|
||||
.kpi-source { font-size: 0.75rem; color: #9ca3af; margin-top: 0.5rem; }
|
||||
5
tsconfig.json
Normal file
5
tsconfig.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue