partirdezero/static/css/app.css

2675 lines
No EOL
65 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Design tokens — 2025 foundation */
/* Dark as default (overridden by light theme stylesheet) */
:root,
[data-theme='dark'] {
/* Palette — Bleu pétrole */
--bg: #0f1f2e;
--fg: #c4d7e0;
--muted: #5e88a0;
--primary: #4e9ed6;
--primary-contrast: #06121b;
--accent: #a79228;
--border: #4f6f8f;
--card: #13293d;
--elev: rgba(15,31,46,0.6);
--nav-bg: rgba(0,8,36,0.65);
/* Semantic text/link aliases */
--text: var(--fg);
--text-muted: var(--muted);
--link: var(--primary);
--link-hover: var(--accent);
/* Functional colors */
--success: #2fa86c;
--success-contrast: #ffffff;
--warning: #f2a93b;
--warning-contrast: #0b0b0b;
--danger: #e35d57;
--danger-contrast: #ffffff;
--info: #5aa7e1;
--info-contrast: #0b0b0b;
/* Neutral scale (tailored for dark UI) */
--neutral-0: #0b1621;
--neutral-100: #0f1f2e; /* = bg */
--neutral-200: #122638;
--neutral-300: #173145;
--neutral-400: #1d3c53;
--neutral-500: #274a62;
--neutral-600: #355c75;
--neutral-700: #4c7590;
--neutral-800: #7da0b6;
--neutral-900: #c4d7e0; /* = fg */
/* Surfaces & borders */
--surface: var(--card);
--surface-raised: var(--elev);
--border-subtle: rgba(79,111,143,0.5);
--border-strong: #6a8cb0;
/* Spacing scale */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 24px;
--space-6: 32px;
/* Radius */
--r-1: 4px;
--r-2: 6px;
--r-3: 10px;
--r-4: 16px;
/* Shadows */
--shadow-1: 0 1px 2px rgba(0,0,0,0.15);
--shadow-2: 0 6px 20px rgba(0,0,0,0.25);
--shadow-3: 0 12px 30px rgba(0,0,0,0.35);
/* Transitions */
--ease-1: cubic-bezier(.2,.8,.2,1);
--ease-2: cubic-bezier(.16,1,.3,1);
--transition-1: 200ms var(--ease-1);
--transition-2: 320ms var(--ease-2);
/* Typography */
--font-sans: "Montserrat", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, "Apple Color Emoji", "Segoe UI Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* Layout */
/* Fluid container and gutters for responsive spacing */
--container-w: clamp(320px, 92vw, 1100px);
--gutter: clamp(14px, 3vw, 24px);
--focus-ring: 0 0 0 3px rgba(78,158,214,0.45);
/* Utility base colors */
--white: #ffffff;
--black: #000000;
/* Code window & syntax tokens (dark default) */
--code-bg: #1e1e2e;
--code-header-bg: #28293d;
--code-filename: #a9a9b3;
--code-text: #cdd6f4;
--code-line-number: #5c5f77;
--code-dot-red: #ff5f56;
--code-dot-yellow: #ffbd2e;
--code-dot-green: #27c93f;
--syn-qn: #cba6f7; /* keywords like def/if/return */
--syn-fn: #89b4fa; /* function names */
--syn-st: #a6e3a1; /* strings */
--syn-kw: #f9e2af; /* booleans/values */
--syn-cm: #6c7086; /* comments */
--syn-ow: #cba6f7; /* operators */
/* Misc */
--border-glass-dark: rgba(0,0,0,0.2);
--border-glass-light: rgba(255,255,255,0.05);
}
/*
Mobile width guardrail
- Cap container width on touch devices to improve readability and avoid edge overflows
*/
@media (hover: none) and (pointer: coarse) {
:root {
/* Keep fluid gutters but prevent overly wide lines on large/mobile landscape */
--container-w: min(92vw, 480px);
}
html, body { overflow-x: hidden; }
}
/* Global box-sizing reset to prevent width overflow on mobile
Ensures padding/border are included in the element's total width/height */
html { box-sizing: border-box; }
*, *::before, *::after { box-sizing: inherit; }
/* Light theme values — applied via colors_light.css inclusion */
/* ==========================
Cours — Sommaire (TOC)
========================== */
.courseToc {
background: var(--surface);
border: 1px solid var(--border-subtle);
border-radius: var(--r-3);
box-shadow: var(--shadow-1);
/* Make the TOC span the full width of its section */
width: 100%;
margin: var(--space-5) 0;
padding: var(--space-5);
max-width: none;
}
.courseToc .tocModules,
.courseToc .tocLessons {
list-style: none;
margin: 0;
padding: 0;
}
.courseToc .tocModule + .tocModule {
margin-top: var(--space-5);
padding-top: var(--space-5);
border-top: 2px dashed var(--border-subtle);
}
.courseToc .tocModuleHeader {
display: flex;
align-items: center;
gap: var(--space-3);
color: var(--text);
font-weight: 600;
letter-spacing: .2px;
margin-bottom: var(--space-3);
}
.courseToc .tocModuleIndex {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 999px;
background: var(--primary);
color: var(--primary-contrast);
font-size: 14px;
font-weight: 700;
box-shadow: 0 0 0 3px rgba(78,158,214,0.15);
}
.courseToc .tocModuleTitle {
font-size: 18px;
}
.courseToc .tocLessons {
display: grid;
grid-template-columns: 1fr;
gap: 6px;
}
.courseToc .tocLesson {
position: relative;
}
.courseToc .tocLink {
display: block;
padding: 10px 12px;
border-radius: var(--r-2);
text-decoration: none;
color: var(--link);
background: rgba(255,255,255,0.02);
border: 1px solid transparent;
transition: all var(--transition-1);
}
.courseToc .tocLink:hover {
color: var(--link-hover);
background: rgba(78,158,214,0.08);
border-color: var(--border-subtle);
}
.courseToc .tocLesson.current .tocLink {
color: var(--success);
background: rgba(47,168,108,0.12);
border-color: rgba(47,168,108,0.35);
font-weight: 700;
}
.courseToc .tocCurrentTag {
color: var(--text-muted);
font-weight: 600;
margin-left: 8px;
font-size: 12px;
}
.content-lesson {
border: 1px solid var(--border);
border-radius: var(--r-2);
background: var(--surface-raised);
color: var(--text);
padding: 20px;
}
.content-lesson .lessonTitle {
font-size: 1.4rem;
padding-bottom: 10px;
font-weight: 600;
color: var(--primary);
}
/* Petit badge "PREMIUM" affiché dans la TOC des cours */
.premium-tag {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 2px 8px;
margin-left: 8px;
border-radius: 2px;
background: var(--accent);
color: var(--text);
font-size: 11px;
font-weight: 800;
letter-spacing: .3px;
line-height: 1.2;
vertical-align: middle;
text-transform: uppercase;
white-space: nowrap;
}
.current-tag {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 2px 8px;
border-radius: 2px;
background: var(--primary);
color: var(--primary-contrast);
font-size: 11px;
font-weight: 800;
letter-spacing: .3px;
line-height: 1.2;
vertical-align: middle;
text-transform: uppercase;
white-space: nowrap;
}
.completed-tag {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 2px 8px;
border-radius: 2px;
background: var(--success);
color: var(--success-contrast);
font-size: 11px;
font-weight: 800;
letter-spacing: .3px;
line-height: 1.2;
vertical-align: middle;
text-transform: uppercase;
white-space: nowrap;
}
.courseToc .tocLink.disabled {
color: var(--text-muted);
background: transparent;
border-color: transparent;
cursor: not-allowed;
opacity: 0.6;
pointer-events: none;
font-weight: 500;
}
/* Progression des cours */
.progress-container {
display: flex;
flex-direction: row;
}
.progress-bar {
display: flex;
border-radius: var(--r-2);
border: 1px solid var(--border);
height: 20px;
background: var(--neutral-900);
}
.progress-text {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
color: var(--text);
font-size: 12px;
margin-left: 10px;
}
.progress-bar-fill {
background: var(--success);
height: 100%;
border-radius: var(--r-2) 0 0 var(--r-2);
}
.course-completed {
display: flex;
flex-direction: row;
border-radius: var(--r-2);
border: 1px solid var(--border);
margin: var(--space-2) 0;
background: var(--success);
}
.course-completed .container {
display: flex;
flex-direction: column;
padding: var(--space-2);
height: 100%;
vertical-align: middle;
}
.course-completed .container .icon {
color: var(--success-contrast);
font-size: 50px;
}
.course-completed .container .title {
color: var(--success-contrast);
font-size: 28px;
font-weight: 600;
}
.course-completed .container .content {
color: var(--success-contrast);
font-size: 14px;
}
[data-theme='light'] {
/* Palette: plus nuancé, moins "blanc" */
--bg: #eef3f7; /* fond légèrement teinté bleu-gris */
--fg: #0f1f2e;
--muted: #385a72; /* un peu plus contrasté pour la lisibilité */
--primary: #2f8bd6; /* bleu plus saturé pour des boutons plus colorés */
--primary-contrast: #ffffff;
--accent: #ff7a1c; /* orange plus vif */
--border: #bfd0dc;
--card: #ffffff;
--elev: rgba(255,255,255,0.7);
--nav-bg: rgba(255,255,255,0.85); /* barre plus lisible et moins fade */
--focus-ring: 0 0 0 3px rgba(47,139,214,0.30);
/* Semantic text/link aliases */
--text: var(--fg);
--text-muted: var(--muted);
--link: var(--primary);
/* Hover liens (light): garder une teinte bleue pour éviter l'orange sur bleu */
--link-hover: color-mix(in oklab, var(--primary) 78%, var(--black) 22%);
/* Visited liens (light): un ton plus profond, toujours dans la gamme bleue */
--link-visited: color-mix(in oklab, var(--primary) 70%, var(--black) 30%);
/* Functional colors */
--success: #1f9d63;
--success-contrast: #ffffff;
--warning: #e6951a;
--warning-contrast: #0b0b0b;
--danger: #d64541;
--danger-contrast: #ffffff;
--info: #318bd0;
--info-contrast: #ffffff;
/* Neutral scale — davantage d'écarts entre 200/300 */
--neutral-0: #ffffff;
--neutral-100: #f3f7fa; /* = proche du bg mais différent */
--neutral-200: #e9f1f6; /* plus marqué qu'avant */
--neutral-300: #dde8f0; /* idem */
--neutral-400: #d0dde8;
--neutral-500: #bfd0dc; /* = border */
--neutral-600: #a0bccd;
--neutral-700: #7ea0b6;
--neutral-800: #5b778a;
--neutral-900: #0f1f2e; /* = fg */
/* Surfaces & borders */
--surface: var(--card);
--surface-raised: var(--elev);
--border-subtle: rgba(12,32,55,0.10);
--border-strong: #8fb0c4;
/* Utility base colors */
--white: #ffffff;
--black: #000000;
/* Code window & syntax tokens (light theme keeps same accent look) */
--code-bg: #1e1e2e;
--code-header-bg: #28293d;
--code-filename: #a9a9b3;
--code-text: #cdd6f4;
--code-line-number: #5c5f77;
--code-dot-red: #ff5f56;
--code-dot-yellow: #ffbd2e;
--code-dot-green: #27c93f;
--syn-qn: #cba6f7;
--syn-fn: #89b4fa;
--syn-st: #a6e3a1;
--syn-kw: #f9e2af;
--syn-cm: #6c7086;
--syn-ow: #cba6f7;
--border-glass-dark: rgba(0,0,0,0.2);
--border-glass-light: rgba(255,255,255,0.05);
}
html {
display: flex;
flex-direction: column;
font-size: 16px;
font-family: var(--font-sans, "Montserrat");
scroll-behavior: smooth;
}
body {
display: flex;
flex-direction: column;
margin: 0;
background: var(--bg);
color: var(--fg);
}
/* Header / Navigation v2 */
.site-nav {
position: sticky;
top: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: space-between;
height: auto;
min-height: 64px;
padding: 0 var(--gutter);
background: var(--nav-bg);
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border);
box-shadow: var(--shadow-1);
}
.navbar {
display: flex;
width: 70%;
justify-content: flex-start;
margin-right: 30px;
}
.navbar ul, .navbar li {
list-style: none;
padding: 0;
margin: 0;
}
.navbar ul {
display: flex;
flex-direction: row;
width: 100%;
}
.navbar li {
position: relative;
margin: auto 10px;
}
.navend {
margin-right: 20px;
display: flex;
width: 100%;
align-items: end;
flex-direction: row-reverse;
}
.navend a {
cursor: pointer;
}
.navbar ul ul {
display: none;
position: absolute;
width: auto;
left: 0;
top: 100%;
flex-direction: column;
transform: translateX(-25%);
background: var(--elev);
backdrop-filter: blur(6px);
border: 1px solid var(--border);
border-radius: var(--r-2);
}
.navbar li:hover ul,
.navbar li ul:hover {
display: flex; /* Changed to flex to support horizontal layout */
}
/* Accessibilité: ouvrir le sous-menu au focus clavier */
.navbar li:focus-within > ul {
display: flex;
}
.navbar ul ul li {
width: auto; /* Adjust width for inline layout */
margin: auto 10px;
padding: 10px;
border-left: 1px solid var(--border);
}
.navbar ul ul li:first-child {
margin-top: 20px;
}
.navbar ul ul a {
display: block;
padding: 0 0 10px 0;
text-decoration: none;
white-space: nowrap; /* Prevents text from wrapping */
}
/* Burger / mobile navigation */
.nav-toggle {
display: none;
align-items: center;
justify-content: center;
gap: 8px;
padding: 8px 12px;
border-radius: var(--r-2);
}
/* Hide burger on large screens explicitly */
@media (min-width: 1025px) {
.nav-toggle { display: none !important; }
}
@media (max-width: 1024px) {
.site-nav {
position: sticky;
top: 0;
flex-wrap: wrap;
padding: var(--space-2) var(--gutter);
}
.brand { display: flex; align-items: center; gap: 12px; }
/* Put the burger to the right of the brand */
.nav-toggle { display: inline-flex; margin-left: auto; position: relative; z-index: 1301; }
/* Off-canvas menu (hidden to the right by default) */
.navbar {
position: fixed;
top: 0;
right: 0;
height: 100vh;
/* Ensure total box never exceeds the viewport width (padding + border included) */
box-sizing: border-box;
width: min(92vw, 380px);
margin: 0;
/* Safe-area aware padding on the right (iOS notch) */
padding: var(--space-5) max(var(--gutter), env(safe-area-inset-right)) var(--space-5) var(--gutter);
display: flex;
flex-direction: column;
gap: var(--space-3);
background: var(--surface);
border-left: 1px solid var(--border);
box-shadow: var(--shadow-3);
z-index: 1200;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
transform: translateX(100%);
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: transform var(--transition-2), opacity var(--transition-2), visibility 0s linear 320ms;
}
.navbar.is-open {
transform: translateX(0);
opacity: 1;
visibility: visible;
pointer-events: auto;
transition: transform var(--transition-2), opacity var(--transition-2), visibility 0s;
}
/* Dim background when menu is open (requires :has support) */
body:has(#navToggle[aria-expanded="true"]) { overflow: hidden; }
.site-nav:has(#navToggle[aria-expanded="true"])::after {
content: "";
position: fixed;
inset: 0;
background: rgba(0,0,0,0.45);
backdrop-filter: blur(2px);
z-index: 1100;
}
.navbar ul { flex-direction: column; width: 100%; align-items: flex-start; }
.navbar li { margin: 0; width: 100%; }
.navbar a { display: block; padding: 12px 14px; border-radius: var(--r-1); }
/* Dropdowns behave as inline lists on mobile */
.navbar ul ul {
position: static;
transform: none;
display: block;
background: transparent;
border: 0;
padding-left: 10px;
}
.navbar ul ul { align-items: flex-start; }
.navbar ul ul li { border: 0; margin: 0; padding: 6px 8px; width: 100%; }
.navbar ul ul a { text-align: left; }
.navend {
width: 100%;
margin-top: auto; /* push to bottom */
display: flex;
flex-direction: column;
align-items: flex-start; /* start-align items on mobile */
justify-content: flex-start;
gap: 6px;
}
.navend ul { width: 100%; align-items: flex-start; }
.navend a { text-align: left; }
}
/* Respect reduced motion preferences */
@media (max-width: 1024px) and (prefers-reduced-motion: reduce) {
.navbar,
.navbar.is-open,
.site-nav:has(#navToggle[aria-expanded="true"])::after {
transition: none !important;
}
}
.brand {
display: flex;
flex-direction: column;
gap: 2px;
font-size: clamp(1.1rem, 2vw, 1.5rem);
font-weight: 600;
letter-spacing: 0.2cm;
font-variant: small-caps;
}
.brand-title {
display: inline-flex;
align-items: center;
gap: 10px;
}
/* Logo inside brand: keep it within navbar height */
.brand .logo {
max-height: 64px;
height: auto;
vertical-align: middle;
display: inline-block;
}
.subtitle {
font-size: 1rem;
letter-spacing: 0.05cm;
margin-top: 2px;
}
a.site-nav-link,
.site-nav a {
color: var(--fg);
padding: 8px 10px;
border-radius: var(--r-2);
}
a {
text-decoration: none;
font-weight: 600;
color: var(--primary);
transition: color var(--transition-1), text-shadow var(--transition-1);
scroll-margin-top: 80px;
}
.site-nav a:hover { color: var(--accent); background-color: var(--surface-raised); }
.site-nav a:focus-visible { background-color: var(--surface-raised); box-shadow: var(--focus-ring); }
.button {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
max-width: 300px;
cursor: pointer;
font-size: 1rem;
border: 1px solid transparent;
border-radius: var(--r-2);
margin: 10px;
background: var(--primary);
color: var(--primary-contrast);
box-shadow: var(--shadow-1);
transition: transform var(--transition-1), box-shadow var(--transition-1), background var(--transition-1), color var(--transition-1);
}
.button:hover { transform: translateY(-1px); box-shadow: var(--shadow-2); }
.button:active { transform: translateY(0); box-shadow: var(--shadow-1); }
.button:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.button-ghost { background: transparent; color: var(--fg); border-color: var(--border); }
.button-ghost:hover { background: var(--surface-raised); }
/* Variantes de boutons */
.button.button-secondary {
background: transparent;
color: var(--primary);
border-color: var(--primary);
}
.button.button-secondary:hover {
background: var(--surface-raised);
}
.button.button-quiet {
background: transparent;
color: var(--muted);
border-color: transparent;
}
.button.button-quiet:hover { color: var(--fg); background: var(--surface-raised); }
.button-grp {
display: flex;
flex-direction: row;
justify-content: center;
width: 100%;
}
main {
flex: 1;
}
section {
display: flex;
flex-direction: column;
padding: var(--space-6) var(--gutter);
width: 100%;
max-width: var(--container-w);
margin: clamp(12px, 3vw, 24px) auto;
}
.courseNav {
display: block;
float: left;
position: sticky;
left: 0;
top: clamp(64px, 12vh, 150px);
max-width: clamp(220px, 22vw, 300px);
border: 1px solid;
}
.edito {
border: 1px solid var(--border);
border-radius: var(--r-2);
background: var(--card);
}
.comment {
font-weight: 500;
}
.test {
border: 1px solid var(--border);
padding: 10px;
}
.ul-arrow li {
list-style: none;
}
.ul-arrow li:before {
content: "→ ";
font-size: 1.5rem;
}
/* --- Headings system (H1H6) --- */
/* Base: consistent rhythm, weight, and accessibility across themes */
:where(h1,h2,h3,h4,h5,h6) {
font-family: var(--font-sans);
font-weight: 700;
line-height: 1.2;
margin: 0 0 var(--space-4);
color: var(--fg);
letter-spacing: -0.01em;
}
h1 {
font-size: clamp(2rem, 4.5vw, 2.75rem);
color: var(--primary);
border-left: 4px solid var(--accent);
padding-left: var(--space-3);
}
h2 {
font-size: clamp(1.5rem, 3.5vw, 2rem);
color: var(--accent);
border-bottom: 1px solid var(--border);
padding-bottom: 6px;
margin-top: var(--space-6);
}
h3 { font-size: clamp(1.25rem, 3vw, 1.5rem); color: var(--fg); }
h4 { font-size: clamp(1.1rem, 2.2vw, 1.25rem); color: var(--fg); }
h5 { font-size: clamp(1rem, 2vw, 1.1rem); color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
h6 { font-size: 0.95rem; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
img {
max-width: 100%;
height: auto;
}
/* ======================================
Blog components
====================================== */
/* Accessibilité: élément visuellement masqué mais accessible aux lecteurs d'écran */
.sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0,0,0,0) !important;
white-space: nowrap !important;
border: 0 !important;
}
/* Blog layout wrappers */
.blog.blog-home .blog-header {
display: grid;
gap: var(--space-3);
margin-bottom: var(--space-6);
}
.blog-title {
margin: 0;
}
.blog-description {
color: var(--text-muted);
font-size: 1.05rem;
}
/* Post list grid */
.post-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: var(--space-5);
}
.post-card {
background: var(--surface);
border: 1px solid var(--border-subtle);
border-radius: var(--r-3);
box-shadow: var(--shadow-1);
padding: var(--space-5);
display: grid;
gap: var(--space-3);
transition: transform var(--transition-1), box-shadow var(--transition-1), border-color var(--transition-1);
}
.post-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-2);
border-color: var(--border-strong);
}
.post-card-title {
margin: 0;
}
.post-card-title a { color: var(--fg); text-decoration: none; }
.post-card-title a:hover { color: var(--link-hover); text-decoration: underline; }
.post-excerpt { color: var(--text); opacity: 0.95; }
.post-actions { margin-top: 2px; }
/* Post meta (date, tags) */
.post-meta { color: var(--text-muted); font-size: 0.95rem; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.post-meta i { color: var(--muted); margin-right: 6px; }
.post-meta .sep { color: var(--muted); }
/* Post detail */
.post-detail .post-header { margin-bottom: var(--space-5); }
.post-detail .post-title { margin-bottom: var(--space-2); }
/* Prose content: typographic rhythm inside articles */
.prose {
line-height: 1.75;
color: var(--text);
}
.prose :where(p, ul, ol, blockquote, pre, table, img) { margin: 0 0 var(--space-4); }
.prose a { color: var(--link); }
.prose a:hover { color: var(--link-hover); text-decoration: underline; }
.prose blockquote {
margin-left: 0;
padding-left: var(--space-4);
border-left: 3px solid var(--border-strong);
color: var(--text-muted);
font-style: italic;
}
.prose code { font-family: var(--font-mono); background: var(--neutral-300); padding: 0 4px; border-radius: var(--r-1); }
.prose pre {
background: var(--code-bg);
color: var(--code-text);
padding: var(--space-4);
border-radius: var(--r-2);
overflow: auto;
}
/* Make embedded media responsive */
iframe, video { max-width: 100%; height: auto; }
/* Responsive tables: wrap in a container if needed */
.table-responsive { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.card-header img.thumbnails {
transition: transform 1s ease
}
.card:hover img.thumbnails {
transform: scale(1.2);
}
.container-inline {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: var(--space-5);
}
.card {
display: flex;
flex-direction: column;
width: 100%;
border-left: 1px solid var(--border);
border-top: 1px solid var(--border);
border-radius: var(--r-2);
overflow: hidden;
margin: 0;
background: var(--card);
box-shadow: var(--shadow-1);
transition: transform var(--transition-1), box-shadow var(--transition-1);
}
.card:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.card-header h2 {
display: flex;
overflow: hidden;
}
.card-header {
display: flex;
width: 100%;
font-size: 1rem;
font-weight: 500;
}
.card-body a {
font-size: 1rem;
font-weight: 600;
}
.card-body a:hover {
text-decoration: underline
}
.card-body {
border-top: 1px solid var(--border);
padding: 5px;
line-height: 90%;
overflow: hidden;
z-index: 3;
}
.def-author {
display: flex;
padding: var(--space-3);
flex-direction: row;
align-items: center;
font-size: 0.8rem;
font-style: italic;
}
/* CODE */
.inline {
display: inline-block;
}
pre {
border-radius: var(--r-2);
/* Ne dépasse pas du parent en largeur et défile si nécessaire */
max-width: clamp(320px, 100%, 800px);
overflow: auto; /* scroll horizontal et vertical si besoin */
max-height: clamp(360px, 70vh, 800px);
}
/* ====== Homepage enhancements ====== */
.hero {
display: block;
width: 100%;
padding: clamp(48px, 10vw, 96px) var(--gutter) clamp(32px, 6vw, 64px);
text-align: center;
background:
radial-gradient(1200px 600px at 50% -10%, rgba(78,158,214,0.20), transparent 60%),
radial-gradient(900px 400px at 80% 0%, rgba(255,122,28,0.12), transparent 60%),
var(--surface-raised);
position: relative;
}
.hero-inner { max-width: var(--container-w); margin: 0 auto; padding: 0 var(--gutter); }
.hero-decor {
position: absolute;
inset: 0;
pointer-events: none;
background:
radial-gradient(80px 80px at 20% 30%, rgba(47,139,214,0.35), transparent 60%),
radial-gradient(120px 120px at 80% 20%, rgba(255,122,28,0.25), transparent 60%);
filter: blur(30px);
opacity: .6;
}
.hero .hero-sub { font-size: clamp(1rem, 2.4vw, 1.125rem); font-weight: 500; margin: var(--space-3) auto 0; max-width: 65ch; }
.badge-row { display: flex; gap: var(--space-3); justify-content: center; margin: var(--space-4) 0 var(--space-2); flex-wrap: wrap; }
.badge { display: inline-flex; align-items: center; gap: var(--space-2); padding: 6px 10px; border: 1px solid var(--border-subtle); border-radius: 999px; background: color-mix(in oklab, var(--card) 80%, transparent); font-size: .9rem; color: var(--text-muted); }
.hero-cta .button { padding: 12px 18px; font-size: 1rem; border-radius: var(--r-2); }
.cta-primary {
/* Make primary CTA more visible */
font-weight: 700;
background: linear-gradient(180deg,
color-mix(in oklab, var(--primary) 92%, var(--white) 8%),
color-mix(in oklab, var(--primary) 82%, var(--black) 18%)
);
border-color: color-mix(in oklab, var(--primary) 70%, var(--black) 30%);
box-shadow:
0 8px 22px color-mix(in oklab, var(--primary) 35%, transparent),
0 0 0 1px color-mix(in oklab, var(--primary) 40%, transparent);
}
.cta-primary:hover {
transform: translateY(-2px);
background: linear-gradient(180deg,
color-mix(in oklab, var(--primary) 96%, var(--white) 4%),
color-mix(in oklab, var(--primary) 88%, var(--black) 12%)
);
box-shadow:
0 12px 28px color-mix(in oklab, var(--primary) 45%, transparent),
0 0 0 1px color-mix(in oklab, var(--primary) 50%, transparent);
}
.cta-primary:focus-visible {
outline: none;
box-shadow:
var(--focus-ring),
0 8px 22px color-mix(in oklab, var(--primary) 40%, transparent),
0 0 0 1px color-mix(in oklab, var(--primary) 55%, transparent);
}
.cta-secondary {
/* Stronger outline for visibility next to the primary CTA */
background: color-mix(in oklab, var(--card) 85%, transparent);
color: var(--primary);
border-color: var(--primary);
border-width: 2px;
}
.cta-secondary:hover {
background: color-mix(in oklab, var(--card) 100%, transparent);
box-shadow: 0 6px 18px color-mix(in oklab, var(--primary) 25%, transparent);
}
.hero-trust {
margin-top: 16px;
display: flex;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
font-size: 0.95rem;
opacity: 0.9;
}
.features {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
width: 90%;
max-width: 1100px;
margin: 10px auto 30px;
}
.feature {
border: 1px solid var(--border);
border-radius: var(--r-3);
padding: 18px;
text-align: center;
box-shadow: var(--shadow-1);
transition: transform var(--transition-1), box-shadow var(--transition-1), border-color var(--transition-1);
}
.feature .feat-ico {
font-size: 1.8rem;
margin-bottom: 8px;
}
.feature:hover {
transform: translateY(-3px);
box-shadow: var(--shadow-2);
border-color: var(--border-strong);
}
.pricing-teaser {
width: 100%;
max-width: 820px;
margin: var(--space-3) auto var(--space-6);
border: 1px solid var(--border);
border-radius: var(--r-3);
padding: var(--space-5);
background: var(--card);
}
/* Carousel (scroll-snap, lightweight) */
.carousel {
width: min(100%, var(--container-w));
margin: 0 auto var(--space-6);
}
.carousel-track {
display: grid;
grid-auto-flow: column;
grid-auto-columns: minmax(260px, 80%);
gap: var(--space-4);
overflow-x: auto;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
padding-bottom: var(--space-3);
}
.carousel-item {
scroll-snap-align: start;
}
.ratio-16x9 { position: relative; width: 100%; padding-top: 56.25%; overflow: hidden; border-radius: var(--r-2); }
.ratio-16x9 > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Hide scrollbar in supported browsers */
.carousel-track { scrollbar-width: none; }
.carousel-track::-webkit-scrollbar { display: none; }
/* Testimonials */
.testimonials {
width: min(100%, var(--container-w));
margin: 0 auto var(--space-6);
display: grid;
gap: var(--space-4);
}
.testimonials-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-4); }
.testimonial {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--r-3);
padding: var(--space-5);
box-shadow: var(--shadow-1);
position: relative;
}
.testimonial .who { font-weight: 600; color: var(--fg); margin-top: var(--space-3); }
.testimonial p { position: relative; padding-left: 26px; }
.testimonial p:before {
content: "\201C";
position: absolute;
left: 0; top: -6px;
font-size: 2rem;
color: var(--muted);
opacity: .5;
line-height: 1;
}
/* Focus styles */
:focus-visible { outline: none; box-shadow: var(--focus-ring); }
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
* { transition: none !important; animation: none !important; }
}
/* ---------------------------------------------
Container Global
--------------------------------------------- */
.lessonComments {
margin-top: var(--space-6);
background: var(--surface); /* Assure-toi que c'est une couleur un peu plus claire que le fond de page */
border: 1px solid var(--border-subtle);
border-radius: var(--r-3);
/* On enlève le padding global pour coller les éléments aux bords si besoin,
ou on le garde pour un effet "carte" */
padding: var(--space-5);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.lessonComments h3 {
font-size: 1.1rem;
font-weight: 700;
color: var(--text);
margin-bottom: var(--space-4);
display: flex;
align-items: center;
gap: 10px;
}
/* ---------------------------------------------
Liste des commentaires
--------------------------------------------- */
.commentsList {
list-style: none;
padding: 0;
margin: 0 0 var(--space-6) 0;
display: flex;
flex-direction: column;
gap: var(--space-4); /* Espace entre les commentaires */
}
.commentItem {
background: var(--neutral-100); /* Un fond très léger pour détacher le commentaire */
border: 1px solid var(--border-subtle);
border-radius: var(--r-2);
padding: var(--space-4);
transition: border-color 0.2s ease;
}
.commentItem:hover {
border-color: var(--border-strong);
}
/* En-tête du commentaire (Auteur + Date) */
.commentHeader {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-3);
padding-bottom: var(--space-3);
border-bottom: 1px solid var(--border-subtle);
}
.commentAuthor {
font-weight: 700;
color: var(--primary); /* Couleur primaire pour l'auteur */
font-size: 0.95rem;
display: flex;
align-items: center;
gap: 8px;
}
/* Petit point décoratif avant le nom */
.commentAuthor::before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
background-color: var(--primary);
border-radius: 50%;
opacity: 0.6;
}
.commentDate {
font-size: 0.8rem;
color: var(--text-muted);
}
/* Contenu du texte */
.commentContent {
color: var(--text);
font-size: 0.95rem;
line-height: 1.6;
}
/* Markdown Styles dans les commentaires */
.commentContent p { margin-bottom: 0.8em; }
.commentContent p:last-child { margin-bottom: 0; }
.commentContent code {
font-family: 'Fira Code', monospace;
background: rgba(124, 58, 237, 0.1); /* Petite teinte violette légère */
color: var(--primary);
padding: 2px 5px;
border-radius: 4px;
font-size: 0.9em;
}
.commentContent pre {
background: #1e1e2e; /* Fond sombre style IDE */
color: #cdd6f4;
padding: 15px;
border-radius: 8px;
overflow-x: auto;
margin: 10px 0;
border: 1px solid rgba(255,255,255,0.05);
}
.commentContent a {
color: var(--primary);
text-decoration: none;
border-bottom: 1px dotted var(--primary);
}
.commentContent a:hover { border-bottom-style: solid; }
/* ---------------------------------------------
Formulaire "Éditeur Riche"
--------------------------------------------- */
.commentFormBlock {
margin-top: var(--space-4);
}
.commentForm {
background: var(--surface);
border: 1px solid var(--border-strong); /* Bordure plus visible */
border-radius: var(--r-2);
overflow: hidden; /* Pour que les enfants ne dépassent pas des coins */
transition: box-shadow 0.2s;
}
.commentForm:focus-within {
box-shadow: 0 0 0 2px var(--primary-focus, rgba(124, 58, 237, 0.3));
border-color: var(--primary);
}
/* La barre d'outils collée au textarea */
.commentToolbar {
background: var(--neutral-200); /* Fond gris clair/sombre pour la barre */
padding: 8px 12px;
border-bottom: 1px solid var(--border-subtle);
display: flex;
gap: 8px;
}
.commentToolbar .btnTool {
background: transparent;
border: none;
color: var(--text-muted);
cursor: pointer;
padding: 6px;
border-radius: 4px;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
}
.commentToolbar .btnTool:hover {
background: rgba(0,0,0,0.05); /* Ou blanc semi-transparent en dark mode */
color: var(--primary);
}
/* Le champ texte */
.commentField {
padding: 0; /* On enlève le padding du container */
}
.commentField textarea {
width: 100%; /* Prend toute la largeur */
border: none; /* Pas de bordure, c'est le container .commentForm qui gère */
background: transparent;
color: var(--text);
padding: 15px;
min-height: 120px;
resize: vertical;
font-family: inherit;
outline: none; /* Le focus est géré par le parent */
display: block; /* Évite les espaces fantômes */
line-height: 1.5;
}
/* Footer du formulaire (Aide + Bouton) */
.formActions {
padding: 10px 15px;
background: var(--neutral-100); /* Pied de formulaire légèrement différent */
border-top: 1px solid var(--border-subtle);
display: flex;
justify-content: space-between; /* Aide à gauche, Bouton à droite */
align-items: center;
}
.commentHelp {
margin: 0;
font-size: 0.75rem;
color: var(--text-muted);
font-style: italic;
}
.lessonComments .btn {
background: var(--primary);
color: #fff;
border: none;
padding: 8px 20px;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
font-size: 0.9rem;
}
.lessonComments .btn:hover {
background: var(--bg, #6d28d9);
transform: translateY(-1px);
}
/* Responsive */
@media (max-width: 1024px) {
section { width: 80%; }
.features { grid-template-columns: repeat(2, 1fr); width: 90%; }
.testimonials-grid { grid-template-columns: repeat(2, 1fr); }
.carousel-track { grid-auto-columns: 88%; }
}
@media (max-width: 640px) {
.site-nav { height: auto; padding: var(--space-2) var(--gutter); }
.navbar { width: 100%; }
section { width: 95%; margin: 16px auto; }
.features { grid-template-columns: 1fr; }
.hero { padding: 56px 16px 40px; }
.hero-cta .button { margin: 10px; }
.testimonials-grid { grid-template-columns: 1fr; }
.carousel-track { grid-auto-columns: 92%; }
}
/* Steps for larger viewports to afficher plus d'éléments dans le carrousel */
@media (min-width: 900px) {
.carousel-track { grid-auto-columns: 48%; }
}
@media (min-width: 1200px) {
.carousel-track { grid-auto-columns: 32%; }
}
code {
font-family: "Courier New", Courier, monospace;
border-radius: 5px;
}
.alert {
border: 1px solid var(--border);
border-radius: var(--r-2);
padding: 20px;
margin: 20px 0;
}
.question {
background: url('../img/question.png') right no-repeat;
}
#hide {
display: none;
}
/* Footer v2 — site-footer */
footer.site-footer {
display: block;
background-color: var(--card);
color: var(--text-muted);
border-top: 1px solid var(--border);
padding: var(--space-6) var(--gutter);
box-shadow: 0 -1px 0 rgba(0,0,0,0.05) inset;
}
.footer-columns {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: var(--space-6);
max-width: var(--container-w);
margin: 0 auto var(--space-5);
}
.footer-columns h5 {
margin: 0 0 var(--space-3) 0;
color: var(--fg);
font-size: 1rem;
}
.footer-columns p,
.footer-columns li,
.footer-columns a {
font-size: 0.95rem;
line-height: 1.6;
}
.footer-columns a { color: var(--link); text-decoration: none; }
.footer-columns a:hover { color: var(--link-hover); }
.footer-link ul {
list-style: none;
margin: 0;
padding: 0;
display: grid;
gap: 8px;
}
.social {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 10px 16px;
}
.social a { display: inline-flex; align-items: center; gap: 8px; }
.footer-legal {
max-width: var(--container-w);
margin: 0 auto;
display: flex;
gap: 12px;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
color: var(--text-muted);
border-top: 1px dashed var(--border-subtle);
padding-top: var(--space-3);
}
/* Legacy footer classes support (can be removed when not used elsewhere) */
.footer { display: flex; flex-direction: row; justify-content: space-between; }
.about { }
.footer-link { width: 30%; }
@media (max-width: 1000px) {
.courseNav {
display: block;
position: relative;
top: 0;
border: 0;
max-width: 100%;
box-shadow: 0 0 transparent;
background-color: transparent;
}
}
@media (max-width: 678px) {
nav {
position: absolute;
height: auto;
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
width: 100%;
}
.navbar {
width: 100%;
}
.navbar ul {
flex-direction: column;
width: 100%;
}
.navbar ul li {
width: 100%;
}
.navbar ul ul {
position: static;
flex-direction: column;
}
.navbar ul ul li {
width: 100%;
margin: 0;
}
.navbar ul ul a {
padding: 10px 20px;
}
/* Initialement, les sous-menus sont cachés */
.navbar ul ul {
display: none;
}
/* Afficher les sous-menus lorsque l'élément parent est focalisé */
.navbar li:focus-within > ul {
display: flex;
}
/* Styles pour les liens parents pour permettre le focus */
.navbar a {
display: block;
padding: 10px;
text-decoration: none;
}
.navbar li > a:focus + ul {
display: flex;
}
section { margin: 32px auto; width: 90%; }
.footer-columns {
grid-template-columns: 1fr;
}
.footer-legal {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.submenu {
display: none;
}
}
/* design.css */
.snowflake {
position: fixed;
top: -10px;
color: var(--fg);
font-size: 1em;
opacity: 0.8;
filter: blur(1px);
z-index: 1000; /* Assurez-vous que les flocons sont au premier plan */
pointer-events: none; /* Empêche les flocons d'interférer avec les clics */
animation: fall linear infinite;
}
@keyframes fall {
to {
transform: translateY(100vh);
}
}
/* design.css */
.light {
animation: blink 1s infinite;
}
.light:nth-child(2) {
animation-delay: 0.2s;
}
.light:nth-child(3) {
animation-delay: 0.4s;
}
.light:nth-child(4) {
animation-delay: 0.6s;
}
.light:nth-child(5) {
animation-delay: 0.8s;
}
.light:nth-child(6) {
animation-delay: 1s;
}
.light:nth-child(7) {
animation-delay: 1.2s;
}
.light:nth-child(8) {
animation-delay: 1.4s;
}
.light:nth-child(9) {
animation-delay: 1.6s;
}
.light:nth-child(10) {
animation-delay: 1.8s;
}
@keyframes blink {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
/* Dark theme stylesheet — relies on design tokens */
html { background: var(--bg); color: var(--fg); }
nav.site-nav { background: var(--nav-bg); }
/* Light-mode link ergonomics — avoid orange on blue, improve affordance */
[data-theme='light'] a:not(.button) {
color: var(--link);
text-decoration: none;
text-underline-offset: 2px;
}
[data-theme='light'] a:not(.button):hover,
[data-theme='light'] a:not(.button):focus-visible {
color: var(--link-hover);
text-decoration: underline;
}
[data-theme='light'] a:not(.button):visited {
color: var(--link-visited);
}
/* Navigation links: keep same bg hover but swap orange for blue in light */
[data-theme='light'] .site-nav a:hover {
color: var(--link-hover);
background-color: var(--surface-raised);
}
.navbar ul ul { background: var(--elev); border-color: var(--border); box-shadow: var(--shadow-1); }
.navbar ul ul a { color: var(--muted); }
.brand { color: var(--fg); }
a { color: var(--primary); }
a:hover { color: var(--accent); text-shadow: none; }
.courseNav { border-color: var(--border); box-shadow: var(--shadow-1); background-color: var(--card); }
.edito { border-color: var(--border); background-color: var(--card); color: var(--muted); }
.test { border-color: var(--border); background-color: var(--surface); color: var(--fg); }
h1 { color: var(--primary); border-left-color: var(--accent); border-bottom-color: var(--accent); }
h2 { color: var(--accent); }
.card { border-color: var(--border); box-shadow: var(--shadow-1); background: var(--card); }
.card-body a { color: var(--primary); }
.card-body a:hover { color: var(--link-hover); }
th { border-color: var(--border); }
tr:nth-child(even) { background-color: var(--neutral-300); color: var(--fg); }
footer { background-color: var(--neutral-0); color: var(--text-muted); }
/* Homepage sections */
.hero { background: var(--surface-raised); }
.features .feature { border-color: var(--border); background-color: var(--card); box-shadow: var(--shadow-1); }
.pricing-teaser { border-color: var(--border); background-color: var(--card); }
/* --- MISE EN PAGE HERO (SPLIT SCREEN) --- */
/* Par défaut (mobile), les éléments s'empilent avec un espace */
.hero-split {
display: flex;
flex-direction: column;
gap: 40px;
}
/* Sur grand écran (Desktop), on passe en 2 colonnes */
@media (min-width: 992px) {
.hero-split {
/* Reste en colonne aussi sur desktop comme demandé */
flex-direction: column;
align-items: stretch;
justify-content: flex-start;
gap: 60px; /* Espace entre le texte et le visuel */
}
.hero-text {
/* En colonne, ne pas forcer l'expansion verticale */
flex: 0 0 auto;
max-width: 100%;
}
.hero-visual {
flex: 0 0 auto;
width: 100%; /* S'assure que le visuel prend la largeur */
max-width: 100%;
perspective: 1000px; /* Pour un petit effet 3D si souhaité plus tard */
}
}
/* --- STYLE DE LA FENÊTRE DE CODE (TECH VISUAL) --- */
.code-window {
/* Fond sombre style éditeur moderne (ex: Dracula/Catppuccin) */
background: var(--code-bg);
border-radius: 12px;
/* Une ombre portée pour donner de la profondeur */
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
overflow: hidden; /* Pour que les coins arrondis fonctionnent */
border: 1px solid var(--border-glass-light);
font-family: 'Fira Code', 'Roboto Mono', 'Courier New', monospace; /* Important: police monospace */
transform: translateY(0);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
/* Petit effet interactif au survol */
.code-window:hover {
transform: translateY(-5px);
box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.6);
}
/* HEADER DE LA FENÊTRE (Style macOS) */
.window-header {
background: var(--code-header-bg); /* Légèrement plus clair que le fond */
padding: 12px 16px;
display: flex;
align-items: center;
position: relative;
border-bottom: 1px solid var(--border-glass-dark);
}
/* Les 3 petits points colorés */
.dots {
display: flex;
gap: 8px;
z-index: 2;
}
.dot { width: 12px; height: 12px; border-radius: 50%; }
.dot.red { background: var(--code-dot-red); }
.dot.yellow { background: var(--code-dot-yellow); }
.dot.green { background: var(--code-dot-green); }
/* Le nom du fichier centré */
.filename {
position: absolute;
left: 0;
right: 0;
text-align: center;
color: var(--code-filename);
font-size: 0.85rem;
font-weight: 500;
user-select: none; /* Empêche de sélectionner le texte du titre */
}
/* CONTENU DU CODE */
.window-content {
padding: 24px;
text-align: left; /* Force l'alignement à gauche même si le parent est centré */
}
.code-block {
margin: 0;
color: var(--code-text); /* Couleur de base du texte */
line-height: 1.7;
font-size: 15px;
white-space: pre; /* Respecte les espaces et sauts de ligne */
overflow-x: auto; /* Scroll si le code est trop long */
}
/* --- COLORATION SYNTAXIQUE MANUELLE (Style Dracula/Catppuccin) --- */
/* Numéros de ligne */
.line {
display: block;
counter-increment: line-counter;
}
.code-block { counter-reset: line-counter; }
.line::before {
content: counter(line-counter);
display: inline-block;
width: 30px;
margin-right: 20px;
color: var(--code-line-number); /* Gris foncé pour les numéros */
text-align: right;
user-select: none;
}
/* Couleurs des mots-clés (Basé sur les classes span ajoutées dans le HTML) */
.qn { color: var(--syn-qn); font-weight: bold; } /* def, if, return (Mauve) */
.fn { color: var(--syn-fn); } /* Noms de fonctions (Bleu) */
.st { color: var(--syn-st); } /* Strings / Textes (Vert) */
.kw { color: var(--syn-kw); } /* Booléens, valeurs clés (Jaune/Orange) */
.cm { color: var(--syn-cm); font-style: italic; } /* Commentaires (Gris) */
.ow { color: var(--syn-ow); } /* Opérateurs and/or (Mauve) */
/* --- SECTION PRICING --- */
.pricing-section {
padding: 80px 20px;
max-width: 1000px;
margin: 0 auto;
}
.pricing-header {
text-align: center;
margin-bottom: 50px;
}
.pricing-header h2 { font-size: 2rem; margin-bottom: 10px; }
.pricing-header p { color: var(--text-muted); }
/* La Grille des cartes */
.pricing-grid {
display: grid;
grid-template-columns: 1fr;
gap: 30px;
}
/* Sur écran large, on met côte à côte */
@media (min-width: 768px) {
.pricing-grid {
grid-template-columns: 1fr 1fr;
align-items: center; /* Pour centrer verticalement si tailles différentes */
}
}
/* --- STYLE DES CARTES --- */
.plan-card {
background: var(--code-bg); /* Fond sombre carte */
border: 1px solid var(--border-glass-light);
border-radius: 16px;
padding: 30px;
position: relative;
transition: transform 0.3s ease;
}
.plan-card:hover {
transform: translateY(-5px);
}
.plan-header {
margin-bottom: 25px;
text-align: center;
border-bottom: 1px solid color-mix(in oklab, var(--white) 10%, transparent);
padding-bottom: 20px;
}
.plan-header h3 { font-size: 1.4rem; margin-bottom: 5px; color: var(--white); }
.plan-header .price { font-size: 2rem; font-weight: bold; color: var(--white); margin: 10px 0; }
.plan-header p { font-size: 0.9rem; color: var(--text-muted); margin: 0; }
/* Liste des features */
.plan-features {
list-style: none;
padding: 0;
margin: 0 0 30px 0;
}
.plan-features li {
margin-bottom: 15px;
color: var(--text);
display: flex;
align-items: flex-start;
gap: 10px;
}
.plan-features i {
color: var(--success); /* Check vert */
margin-top: 4px; /* Alignement visuel */
}
/* Bouton pleine largeur dans les cartes */
.full-width {
width: 100%;
display: block;
text-align: center;
box-sizing: border-box;
}
/* --- SPÉCIFICITÉS CARTE PREMIUM --- */
.plan-card.premium {
background: color-mix(in oklab, var(--code-bg) 92%, var(--white) 8%); /* Un poil plus clair pour ressortir */
border: 1px solid var(--primary); /* Bordure violette (ou ta couleur primaire) */
box-shadow: 0 0 30px color-mix(in oklab, var(--primary) 15%, transparent); /* Glow subtil */
transform: scale(1.02); /* Légèrement plus grande par défaut */
}
/* Le petit badge "Recommandé" */
.badge-popular {
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: var(--primary); /* Ta couleur primaire */
color: var(--white);
padding: 4px 12px;
border-radius: 20px;
font-size: 0.75rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.5px;
}
/* Light mode adjustments for plan cards — align with light DA */
[data-theme='light'] .plan-card {
background: var(--card);
border: 1px solid var(--border);
}
[data-theme='light'] .plan-header {
border-bottom: 1px solid color-mix(in oklab, var(--black) 8%, transparent);
}
[data-theme='light'] .plan-header h3,
[data-theme='light'] .plan-header .price {
color: var(--fg);
}
[data-theme='light'] .plan-card.premium {
background: color-mix(in oklab, var(--card) 94%, var(--primary) 6%);
border: 1px solid color-mix(in oklab, var(--primary) 60%, var(--border) 40%);
box-shadow: 0 0 24px color-mix(in oklab, var(--primary) 18%, transparent);
}
/* Light theme stylesheet — relies on design tokens */
html { background: var(--bg); color: var(--fg); }
nav.site-nav { background: var(--nav-bg); }
/* Links & buttons inherit from design.css using tokens. Only minimal tweaks here. */
.navbar ul ul { background: var(--elev); border-color: var(--border); box-shadow: var(--shadow-1); }
.navbar ul ul a { color: var(--muted); }
.brand { color: var(--fg); }
a { color: var(--primary); }
a:hover { color: var(--accent); text-shadow: none; }
.courseNav { border-color: var(--border); box-shadow: var(--shadow-1); background-color: var(--card); }
.edito { border-color: var(--border); background-color: var(--card); }
.test { border-color: var(--border); background-color: var(--neutral-200); color: var(--fg); }
h1 { color: var(--primary); border-left-color: var(--accent); border-bottom-color: var(--accent); }
h2 { color: var(--accent); }
.card { border-color: var(--border); box-shadow: var(--shadow-1); background: var(--card); }
.card-body a { color: var(--primary); }
.card-body a:hover { color: var(--link-hover); }
th { border-color: var(--border); }
tr:nth-child(even) { background-color: var(--neutral-200); }
footer { background-color: var(--card); color: var(--text-muted); }
/* FORUMULAIRES */
form {
display: flex;
flex-direction: column;
width: 90%;
margin: 20px auto;
}
/* Styles pour la section du formulaire */
.form-section {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
background-color: var(--elev); /* Fond surélevé via token */
border: 1px solid var(--border); /* Bordure légère */
border-radius: 10px; /* Bordure arrondie */
box-shadow: var(--shadow-1); /* Ombre légère */
margin: 20px auto;
width: min(680px, 92%);
}
.login-form {
display: flex;
flex-direction: column;
width: 100%;
align-items: center;
}
.form-group {
display: flex;
flex-direction: column;
margin-bottom: 15px;
}
.form-group label {
margin-bottom: 5px;
font-weight: bold;
}
.login-form input[type="text"],
.login-form input[type="email"],
.login-form input[type="password"],
.login-form textarea {
padding: 10px;
border: 1px solid var(--border); /* Gris clair */
border-radius: 5px; /* Bordure légèrement arrondie */
background-color: var(--surface); /* Fond de surface */
color: var(--text-muted);
margin-bottom: 10px;
font-size: 1rem; /* Taille de police harmonisée */
box-shadow: inset var(--shadow-1); /* Ombre intérieure subtile */
}
.login-form .btn-submit {
/* Aligne le bouton du formulaire sur le système de thème */
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
font: inherit;
font-weight: 600;
line-height: 1.2;
border-radius: var(--r-2);
border: 1px solid var(--primary);
background-color: var(--primary);
color: var(--primary-contrast);
box-shadow: var(--shadow-1);
cursor: pointer;
transition: background-color var(--transition-1), border-color var(--transition-1), transform var(--transition-1), box-shadow var(--transition-1);
}
.login-form .btn-submit:hover {
background-color: var(--link-hover);
}
input[type="text"], input[type="email"], input[type="password"], textarea {
padding: 10px;
border: 1px solid var(--border); /* Gris foncé */
border-radius: 2px;
background-color: var(--surface); /* Gris clair harmonisé */
color: var(--fg);
}
/*
Système de formulaires générique — pour un rendu cohérent avec le site
À appliquer avec class="form" sur <form> (fonctionne aussi avec {{ form.as_p }})
*/
.form {
width: 100%;
}
.form p { /* Django {{ form.as_p }} */
display: flex;
flex-direction: column;
gap: 6px;
margin: 0 0 14px 0;
}
.form label {
font-weight: 600;
color: var(--text);
}
.form input[type="text"],
.form input[type="email"],
.form input[type="password"],
.form input[type="url"],
.form input[type="number"],
.form input[type="file"],
.form input[type="search"],
.form input[type="tel"],
.form select,
.form textarea {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: var(--r-2);
background-color: var(--surface);
color: var(--text);
box-shadow: inset var(--shadow-1);
transition: border-color var(--transition-1), box-shadow var(--transition-1), background-color var(--transition-1);
}
.form input:focus,
.form select:focus,
.form textarea:focus {
outline: none;
box-shadow: var(--focus-ring);
border-color: var(--primary);
}
.form .helptext,
.form small.helptext {
color: var(--text-muted);
font-size: 0.9rem;
}
/* Erreurs Django: ul.errorlist > li */
.form ul.errorlist {
list-style: none;
margin: 0 0 6px 0;
padding: 8px 10px;
border: 1px solid color-mix(in oklab, var(--danger) 60%, var(--border));
background: color-mix(in oklab, var(--danger) 12%, var(--surface));
color: var(--danger);
border-radius: var(--r-2);
}
.form ul.errorlist li { margin: 0; }
.form .actions,
.form .form-actions {
display: flex;
gap: 8px;
justify-content: flex-end;
margin-top: 12px;
}
/*
Système de boutons — harmonisé avec le thème
Utilise les tokens de couleurs et de rayons définis en haut de fichier.
*/
/* Base */
.btn, .button, input[type="submit"], button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 16px;
font: inherit;
font-weight: 600;
line-height: 1.2;
border-radius: var(--r-2);
border: 1px solid var(--border);
background-color: var(--surface);
color: var(--text);
box-shadow: var(--shadow-1);
cursor: pointer;
text-decoration: none;
transition: background-color var(--transition-1), border-color var(--transition-1), transform var(--transition-1), box-shadow var(--transition-1), color var(--transition-1);
}
.btn:hover, .button:hover, input[type="submit"]:hover, button:hover {
background-color: var(--neutral-300);
}
.btn:active, .button:active, input[type="submit"]:active, button:active {
transform: translateY(1px);
box-shadow: var(--shadow-1);
}
.btn:focus-visible, .button:focus-visible, input[type="submit"]:focus-visible, button:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.btn[disabled], .button[disabled], input[type="submit"][disabled], button[disabled] {
opacity: 0.6;
cursor: not-allowed;
}
/* Variantes */
.btn-primary, .button-primary {
background-color: var(--primary);
border-color: var(--primary);
color: var(--primary-contrast);
}
.btn-primary:hover, .button-primary:hover {
background-color: var(--link-hover);
border-color: var(--link-hover);
color: var(--primary-contrast);
}
.btn-secondary, .button-secondary {
background-color: var(--neutral-500);
border-color: var(--neutral-500);
color: var(--success-contrast);
}
.btn-secondary:hover, .button-secondary:hover {
background-color: var(--neutral-600);
border-color: var(--neutral-600);
}
/* Light theme: boutons plus colorés (secondaire = accent) */
[data-theme='light'] .button.button-secondary,
[data-theme='light'] .btn-secondary,
[data-theme='light'] .button-secondary {
background-color: var(--accent);
border-color: var(--accent);
color: var(--white);
}
[data-theme='light'] .button.button-secondary:hover,
[data-theme='light'] .btn-secondary:hover,
[data-theme='light'] .button-secondary:hover {
filter: brightness(0.95);
}
.btn-outline, .button-outline {
background: transparent;
color: var(--text);
border-color: var(--border);
}
.btn-outline:hover, .button-outline:hover {
background: var(--neutral-300);
}
.btn-ghost, .button-ghost {
background: transparent;
border-color: transparent;
color: var(--text);
box-shadow: none;
}
.btn-ghost:hover, .button-ghost:hover {
background: var(--neutral-300);
}
.btn-danger, .button-danger {
background-color: var(--danger);
border-color: var(--danger);
color: var(--danger-contrast);
}
.btn-danger:hover, .button-danger:hover {
filter: brightness(1.05);
}
.btn-warning, .button-warning {
background-color: var(--warning);
border-color: var(--warning);
color: var(--warning-contrast);
}
.btn-warning:hover, .button-warning:hover {
filter: brightness(1.05);
}
/* Tailles */
.btn-sm, .button-sm { padding: 6px 10px; font-size: 0.9rem; }
.btn-lg, .button-lg { padding: 12px 20px; font-size: 1.05rem; }
/* Compat: mappe les anciens sélecteurs spécifiques vers le système */
.login-form .btn-submit { /* déjà défini ci-dessus comme primaire */ }
/* PROFILE */
.profile-section {
max-width: 800px;
margin: 0 auto;
padding: 20px;
border-radius: 8px;
box-shadow: var(--shadow-1);
}
.profile-header {
text-align: center;
margin-bottom: 20px;
}
.profile-header h2 {
font-size: 2em;
margin-bottom: 10px;
}
.profile-picture {
width: 150px;
height: 150px;
border-radius: 50%;
object-fit: cover;
margin-bottom: 20px;
}
.profile-picture-mini {
width: 30px;
height: 30px;
border-radius: 50%;
object-fit: cover;
margin: 10px;
}
.profile-details p {
font-size: 1.1em;
margin: 10px 0;
}
.profile-actions {
text-align: center;
margin-top: 20px;
}
.profile-actions .btn {
margin: 0 10px;
padding: 10px 20px;
font-size: 1em;
border-radius: 5px;
text-decoration: none;
}
.profile-actions .btn-primary {
background-color: var(--primary);
color: var(--primary-contrast);
}
.profile-actions .btn-secondary {
background-color: var(--neutral-700);
color: var(--success-contrast);
}
.profile-nav {
display: flex;
border-bottom: 1px solid var(--border); /* Bordure légère */
margin: 20px auto; /* Centrer la navigation */
}
.profile-nav ul {
list-style: none; /* Supprimer les puces */
display: flex;
flex-direction: row;
padding: 0;
margin: 0;
}
.profile-nav li {
margin-bottom: 10px; /* Espacement entre les éléments */
}
.profile-nav a {
text-decoration: none; /* Supprimer la décoration de texte */
color: var(--link); /* Couleur du texte */
font-weight: bold; /* Texte en gras */
display: block; /* Afficher les liens comme des blocs */
padding: 10px; /* Espacement interne */
border-radius: 5px; /* Bordure arrondie */
transition: background-color 0.3s ease; /* Transition pour le survol */
}
.profile-nav a:hover {
background-color: var(--neutral-300); /* Couleur de fond au survol */
}
/* Redesigned social-style profile */
.profile-cover {
position: relative;
border-radius: 12px;
overflow: hidden;
box-shadow: var(--shadow-1);
margin-bottom: 20px;
}
.profile-cover-bg {
height: 140px;
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
opacity: 0.25;
}
.profile-cover-content {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 16px;
align-items: center;
padding: 12px 16px 16px 16px;
background: var(--surface);
}
.profile-avatar {
width: 96px;
height: 96px;
border-radius: 50%;
object-fit: cover;
border: 3px solid var(--surface);
margin-top: -68px;
box-shadow: var(--shadow-2);
}
.profile-identity {
display: flex;
flex-direction: column;
gap: 6px;
}
.profile-name { margin: 0; font-size: 1.6rem; }
.profile-username { color: var(--text-muted); font-size: 0.95rem; }
.profile-bio { margin: 4px 0 0 0; color: var(--fg); }
.profile-meta {
display: flex;
gap: 16px;
margin: 8px 0 0 0;
padding: 0;
list-style: none;
color: var(--text-muted);
font-size: 0.95rem;
}
.profile-meta i { color: var(--text-muted); margin-right: 6px; }
.profile-actions-rail { display: flex; gap: 8px; }
.profile-tabs {
border-bottom: 1px solid var(--border);
margin-bottom: 16px;
}
.profile-tabs ul {
display: flex;
gap: 12px;
list-style: none;
margin: 0;
padding: 0 4px;
}
.profile-tabs li a {
display: inline-block;
padding: 10px 12px;
border-radius: 8px 8px 0 0;
text-decoration: none;
color: var(--link);
}
.profile-tabs li.active a {
background: var(--surface);
color: var(--fg);
border: 1px solid var(--border);
border-bottom-color: transparent;
}
.profile-content { margin-top: 12px; }
.profile-grid {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 16px;
}
@media (max-width: 900px) {
.profile-cover-content { grid-template-columns: auto 1fr; }
.profile-actions-rail { grid-column: 1 / -1; }
.profile-grid { grid-template-columns: 1fr; }
}
.profile-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 10px;
padding: 16px;
box-shadow: var(--shadow-1);
}
.profile-about-list {
list-style: none;
padding: 0;
margin: 0 0 8px 0;
}
.profile-about-list li { margin: 6px 0; }
.profile-bio-body { margin-top: 8px; line-height: 1.5; }
.profile-courses {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 10px;
list-style: none;
padding: 0;
margin: 0 0 10px 0;
}
.profile-courses li a {
display: flex;
align-items: center;
gap: 10px;
text-decoration: none;
color: var(--fg);
padding: 8px;
border: 1px solid var(--border);
border-radius: 8px;
}
.course-thumb-mini {
width: 40px;
height: 40px;
object-fit: cover;
border-radius: 6px;
}
.muted { color: var(--text-muted); }
.text-right { text-align: right; }
/* TABLEAUX */
table {
width: 80%;
border-collapse: collapse;
}
.table-40 {
width: 40%;
}
.table-50 {
width: 50%;
}
.table-60 {
width: 60%;
}
.table-70 {
width: 70%;
}
th {
border-bottom: 2px solid;
text-align: left;
font-size: 1.1rem;
padding: 5px;
}
td {
padding: 10px;
}
/* UTILS */
span.helptext {
font-size: 0.7em;
color: var(--text-muted);
margin-left: 5px;
font-style: italic;
}
ul.flash_messages {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 10px;
position: fixed;
top: 70px;
right: 10px;
z-index: 1000;
}
ul.flash_message {
background-color: var(--surface);
border: 1px solid var(--border);
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
opacity: 1;
transition: opacity 1s ease-out; /* Transition pour l'opacité */
}
ul.flash_messages li {
list-style: none;
padding: 10px;
margin: 10px;
border-radius: 5px;
color: var(--fg);
}
ul.flash_messages li.error {
background-color: var(--danger);
color: var(--danger-contrast);
}
ul.flash_messages li.success {
background-color: var(--success);
color: var(--success-contrast);
}