app.kluk.fr/app/assets/stylesheets/charte.css
Christophe Robillard 7a7fa4c095
Some checks are pending
CI / scan_ruby (push) Waiting to run
CI / scan_js (push) Waiting to run
CI / lint (push) Waiting to run
CI / test (push) Waiting to run
redesign app on top of the kluk.fr charte
- drop Bulma and Font Awesome, plain CSS built on charte.css
- dashboard: GitHub-like calendar grouped by year, selected day panel
  (sticky side column on desktop, bottom bar on mobile), keyboard navigation
- public page: today's mood and last months fit in one screen, journal hidden
- day log page: mode picker as pills, illustration follows the chosen mode
- login, password and invitation screens in French, global flash messages
- add User#current_mode_since

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 07:35:53 +02:00

531 lines
12 KiB
CSS
Raw Permalink 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.

/*
* Kluk — charte graphique, feuille de style réutilisable.
* Extraite de assets/css/style.scss (site kluk.fr), en CSS pur, sans Sass.
* Copie de charte/css/kluk.css : seuls les chemins des polices changent, ils
* pointent vers app/assets/fonts/ (Propshaft les réécrit avec l'empreinte).
* Ne pas modifier ici : les compléments propres à l’application sont dans app.css.
*
* Palette : la porcelaine du matin, l'encre du thé, le chêne de la table,
* et les quatre couleurs des tasses en accent.
*
* Sommaire
* 1. Polices
* 2. Variables (couleurs, typographies, mise en page)
* 3. Base
* 4. Liens, focus, lien d'évitement
* 5. Boutons
* 6. En-tête et navigation
* 7. Colonne de texte et titres
* 8. Illustration « tasses »
* 9. Calendrier d'humeurs
* 10. Photos
* 11. Formulaire
* 12. Pied de page
* 13. Impression
*/
/* ---------- 1. Polices ---------- */
@font-face {
font-family: "Young Serif";
src: url("/young-serif-400.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
/* Fichier variable : couvre toutes les graisses de 200 à 800 */
@font-face {
font-family: "Atkinson Hyperlegible Next";
src: url("/atkinson-hyperlegible-next-400.woff2") format("woff2");
font-weight: 200 800;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Atkinson Hyperlegible Next";
src: url("/atkinson-hyperlegible-next-400-italic.woff2") format("woff2");
font-weight: 400;
font-style: italic;
font-display: swap;
}
/* ---------- 2. Variables ---------- */
:root {
/* Fonds et texte */
--porcelaine: #F5F6F0;
--porcelaine-fonce: #E9ECE2;
--encre: #2E2A26;
--encre-douce: #5A534C;
--chene: #D9BC94;
--chene-fonce: #B48D5F;
/* Humeurs (les quatre tasses) */
--gris: #8D97A8;
--orange: #EDA33D;
--vert: #5F9B59;
--rouge: #D8573F;
--vert-lien: #3F7A3B;
/* Teintes utilitaires (écrites en dur dans le site d'origine) */
--encre-survol: #45403A;
--surface: #FBFCF8;
--bordure-champ: #8A8279;
--erreur-fond: #FBE9E5;
--blanc: #fff;
/* Typographies */
--serif: "Young Serif", Georgia, serif;
--sans: "Atkinson Hyperlegible Next", "Atkinson Hyperlegible", system-ui, sans-serif;
/* Mise en page */
--colonne: 36rem;
--gouttiere: 1.25rem;
--largeur-entete: 64rem;
/* Arrondis */
--arrondi-petit: 0.5rem;
--arrondi: 0.75rem;
--arrondi-pilule: 999px;
}
/* ---------- 3. Base ---------- */
*,
*::before,
*::after { box-sizing: border-box; }
html {
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
body {
margin: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
background: var(--porcelaine);
color: var(--encre);
font-family: var(--sans);
font-size: 1.1875rem;
line-height: 1.65;
font-kerning: normal;
hyphens: manual;
}
main { flex: 1; outline: none; }
img, svg { display: block; max-width: 100%; }
/* ---------- 4. Liens, focus, lien d'évitement ---------- */
a {
color: var(--encre);
text-decoration-line: underline;
text-decoration-color: var(--vert);
text-decoration-thickness: 0.12em;
text-underline-offset: 0.2em;
}
a:hover { text-decoration-color: var(--encre); }
:focus-visible {
outline: 3px solid var(--encre);
outline-offset: 3px;
border-radius: 4px;
}
.evitement {
position: absolute;
left: var(--gouttiere);
top: -4rem;
padding: 0.5rem 1rem;
background: var(--encre);
color: var(--porcelaine);
z-index: 10;
}
.evitement:focus { top: 0.75rem; }
/* ---------- 5. Boutons ---------- */
.bouton {
display: inline-block;
padding: 0.8rem 1.6rem;
border-radius: var(--arrondi-pilule);
background: var(--encre);
color: var(--porcelaine);
font-weight: 700;
line-height: 1.3;
text-decoration: none;
transition: background-color 0.15s ease;
}
.bouton:hover { background: var(--encre-survol); color: var(--porcelaine); }
.bouton:focus-visible { outline-offset: 4px; border-radius: var(--arrondi-pilule); }
.bouton-petit {
padding: 0.45rem 1rem;
font-size: 1rem;
}
/* Un bouton seul dans son paragraphe respire davantage */
p:has(> .bouton:only-child) { margin: 2rem 0; }
/* ---------- 6. En-tête et navigation ---------- */
.entete {
max-width: var(--largeur-entete);
margin: 0 auto;
padding: 1.25rem var(--gouttiere);
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 1rem 2rem;
width: 100%;
}
.logo {
display: inline-block;
padding: 0.05rem 0.55rem 0.15rem;
border: 2.5px solid var(--encre);
border-radius: var(--arrondi-petit);
font-family: var(--sans);
font-weight: 800;
font-size: 1.35rem;
line-height: 1.2;
letter-spacing: 0.01em;
text-decoration: none;
}
.nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.35rem 1.35rem;
font-size: 1rem;
}
.nav a:not(.bouton) {
text-decoration-color: transparent;
}
.nav a:not(.bouton):hover,
.nav a[aria-current="page"]:not(.bouton) {
text-decoration-color: var(--vert);
}
.nav a.bouton[aria-current="page"] {
background: var(--porcelaine);
color: var(--encre);
box-shadow: inset 0 0 0 2px var(--encre);
}
/* ---------- 7. Colonne de texte et titres ---------- */
.texte {
max-width: calc(var(--colonne) + 2 * var(--gouttiere));
margin: 0 auto;
padding: 2rem var(--gouttiere) 5rem;
}
h1, h2, h3 {
font-family: var(--serif);
font-weight: 400;
line-height: 1.15;
letter-spacing: -0.005em;
text-wrap: balance;
}
h1 {
font-size: clamp(2.35rem, 1.6rem + 3.6vw, 3.75rem);
margin: 1.5rem 0 1.5rem;
}
h2 {
font-size: clamp(1.6rem, 1.35rem + 1vw, 2rem);
margin: 4.5rem 0 1.25rem;
}
p { margin: 0 0 1.15rem; }
/* Le chapeau : paragraphe entièrement en italique juste sous le titre */
h1 + p:has(> em:only-child) {
font-size: 1.3rem;
line-height: 1.55;
color: var(--encre-douce);
}
.note {
margin-top: 2.5rem;
color: var(--encre-douce);
font-size: 1.0625rem;
}
.exergue {
margin: 2.25rem 0;
padding-left: 1.25rem;
border-left: 4px solid var(--orange);
font-family: var(--serif);
font-size: 1.45rem;
line-height: 1.4;
}
code {
font-size: 0.9em;
background: var(--porcelaine-fonce);
padding: 0.05em 0.3em;
border-radius: 3px;
}
/* ---------- 8. Illustration « tasses » ---------- */
.tasses {
margin: 1.5rem 0 0;
}
/* L'illustration déborde légèrement de la colonne sur grand écran */
@media (min-width: 48rem) {
.tasses { margin-inline: -4rem; }
}
.tasses svg { width: 100%; height: auto; overflow: visible; }
.table { fill: var(--chene); }
.table-fil,
.tasse-corps,
.tasse-anse,
.kluk-socle,
.vapeur path {
stroke: var(--encre);
stroke-width: 3;
stroke-linecap: round;
stroke-linejoin: round;
}
.tasse-anse { fill: none; stroke-width: 6; }
.tasse-corps { fill: currentColor; }
.tasse-reflet { fill: none; stroke: var(--blanc); stroke-opacity: 0.45; stroke-width: 4; stroke-linecap: round; }
.kluk-socle { fill: var(--chene-fonce); }
.kluk-voyant { fill: var(--porcelaine); }
.vapeur path { fill: none; stroke-width: 2.5; stroke: var(--encre-douce); }
.humeur-gris { color: var(--gris); }
.humeur-orange { color: var(--orange); }
.humeur-rouge { color: var(--rouge); }
.humeur-vert { color: var(--vert); }
@media (prefers-reduced-motion: no-preference) {
.vapeur path {
animation: vapeur 5s ease-in-out infinite;
}
.vapeur path + path { animation-delay: 2.5s; }
}
@keyframes vapeur {
0%, 100% { opacity: 0.25; transform: translateY(6px); }
50% { opacity: 0.9; transform: translateY(-6px); }
}
/* ---------- 9. Calendrier d'humeurs (décoratif) ---------- */
.calendrier {
display: grid;
grid-template-rows: repeat(7, auto);
grid-auto-flow: column;
grid-auto-columns: 1fr;
gap: 4px;
margin: 2.25rem 0 1rem;
padding: 1.25rem;
background: var(--surface);
border-radius: var(--arrondi);
box-shadow: inset 0 0 0 1px var(--porcelaine-fonce);
}
.jour {
aspect-ratio: 1;
border-radius: 2px;
}
.jour-g { background: var(--gris); }
.jour-o { background: var(--orange); }
.jour-v { background: var(--vert); }
.jour-r { background: var(--rouge); }
@media (max-width: 30rem) {
.calendrier { gap: 3px; padding: 0.9rem; }
}
/* ---------- 10. Photos ---------- */
.photo {
margin: 2rem 0;
}
.photo img {
width: 100%;
height: auto;
border-radius: var(--arrondi);
}
.photo figcaption {
margin-top: 0.6rem;
font-size: 0.95rem;
color: var(--encre-douce);
}
.photo-attente {
display: flex;
align-items: center;
gap: 1.25rem;
aspect-ratio: 3 / 2;
padding: 1.5rem;
border: 2px dashed var(--chene-fonce);
border-radius: var(--arrondi);
background: var(--porcelaine-fonce);
color: var(--encre-douce);
font-size: 1rem;
line-height: 1.5;
}
.photo-attente svg {
flex: none;
width: 2.75rem;
fill: none;
stroke: var(--chene-fonce);
stroke-width: 2.5;
stroke-linejoin: round;
stroke-linecap: round;
}
.photo-attente p { margin: 0; }
.photo-attente strong { color: var(--encre); }
/* ---------- 11. Formulaire ---------- */
.formulaire {
margin: 2.5rem 0 1rem;
padding: 1.75rem 1.25rem;
background: var(--surface);
border-radius: var(--arrondi);
box-shadow: inset 0 0 0 1px var(--porcelaine-fonce);
}
@media (min-width: 40rem) {
.formulaire { padding: 2.25rem 2.5rem; }
}
.champ {
margin: 0 0 1.75rem;
padding: 0;
border: 0;
min-width: 0;
}
.champ > label,
.champ > legend {
display: block;
padding: 0;
margin-bottom: 0.5rem;
font-weight: 700;
}
.precision {
font-weight: 400;
color: var(--encre-douce);
}
.formulaire input[type="email"],
.formulaire textarea {
display: block;
width: 100%;
padding: 0.7rem 0.85rem;
border: 2px solid var(--bordure-champ);
border-radius: var(--arrondi-petit);
background: var(--blanc);
color: var(--encre);
font: inherit;
line-height: 1.4;
}
.formulaire textarea { resize: vertical; min-height: 8rem; }
.formulaire input[type="email"]:focus-visible,
.formulaire textarea:focus-visible {
outline: 3px solid var(--vert);
outline-offset: 1px;
border-color: var(--encre);
}
.choix {
list-style: none;
margin: 0;
padding: 0;
}
.choix li {
display: flex;
align-items: flex-start;
gap: 0.75rem;
padding: 0.35rem 0;
}
.choix input {
flex: none;
width: 1.35rem;
height: 1.35rem;
margin: 0.2rem 0 0;
accent-color: var(--vert-lien);
cursor: pointer;
}
.choix label { cursor: pointer; }
/* Champ piège anti-robots, invisible */
.piege {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.formulaire-erreur {
padding: 0.75rem 1rem;
border-left: 4px solid var(--rouge);
background: var(--erreur-fond);
font-size: 1rem;
}
.formulaire .bouton {
border: 0;
font: inherit;
font-weight: 700;
cursor: pointer;
}
.formulaire .bouton:disabled { opacity: 0.6; cursor: progress; }
.formulaire-secours {
margin: 1rem 0 0;
font-size: 1rem;
color: var(--encre-douce);
}
/* ---------- 12. Pied de page : la table en bois ---------- */
.pied {
background: var(--chene);
border-top: 3px solid var(--encre);
font-size: 1rem;
}
.pied-interieur {
max-width: calc(var(--colonne) + 2 * var(--gouttiere));
margin: 0 auto;
padding: 2rem var(--gouttiere) 2.5rem;
}
.pied-phrase {
font-family: var(--serif);
font-size: 1.15rem;
margin: 0 0 1rem;
}
.pied-liens {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.5rem 2rem;
}
.pied a { text-decoration-color: var(--encre); text-decoration-thickness: 1px; }
.pied a:hover { text-decoration-thickness: 2px; }
/* ---------- 13. Impression ---------- */
@media print {
.entete .nav, .pied, .tasses, .calendrier { display: none; }
body { background: var(--blanc); }
}