app.kluk.fr/app/assets/stylesheets/app.css
Christophe Robillard a484f8ffd9
Some checks are pending
CI / lint (push) Waiting to run
CI / scan_ruby (push) Waiting to run
CI / scan_js (push) Waiting to run
CI / test (push) Waiting to run
put the user's name forward on the public page
- title "Les humeurs de …" (with elision) above both columns
- selected date shown above the mode, in ink instead of grey
- brief fade when another day is selected (public page and dashboard)

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

523 lines
12 KiB
CSS

/*
* Styles propres à l'application, construits sur la charte (charte.css).
* La couleur d'un mode est choisie par l'utilisateur : elle arrive dans la variable
* --humeur, posée en style en ligne. Le reste de l'interface reste neutre
* (porcelaine, encre, chêne) pour que les humeurs soient les seules couleurs.
*
* Sommaire
* 1. Compléments à la charte (boutons, champs, navigation)
* 2. Messages flash
* 3. Carte d'humeur (illustration posée sur la Kluk)
* 4. Légende
* 5. Calendrier des humeurs
* 6. Tableau de bord
* 7. Page publique
* 8. Page d'un jour (journal)
* 9. Impression
*/
/* ---------- 1. Compléments à la charte ---------- */
/* La charte ne prépare les <button class="bouton"> que dans un .formulaire */
button.bouton,
input.bouton {
border: 0;
font: inherit;
font-weight: 700;
cursor: pointer;
}
/* Bouton d'action présenté comme un lien de la charte */
button.lien {
padding: 0;
border: 0;
background: none;
color: var(--encre);
font: inherit;
cursor: pointer;
text-decoration-line: underline;
text-decoration-color: var(--vert);
text-decoration-thickness: 0.12em;
text-underline-offset: 0.2em;
}
button.lien:hover { text-decoration-color: var(--encre); }
/* button_to enveloppe son bouton dans un formulaire : le garder en ligne */
.nav form.button_to { display: inline; }
.formulaire input[type="password"],
.formulaire input[type="text"] {
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 input[type="password"]:focus-visible,
.formulaire input[type="text"]:focus-visible {
outline: 3px solid var(--vert);
outline-offset: 1px;
border-color: var(--encre);
}
.formulaire .formulaire-erreur { margin: 0 0 1.75rem; }
.texte-etroit { max-width: calc(30rem + 2 * var(--gouttiere)); }
.texte-etroit h1 { font-size: clamp(2.1rem, 1.7rem + 2vw, 2.75rem); }
.texte-etroit .formulaire { margin-top: 1.5rem; }
/* ---------- 2. Messages flash ---------- */
.flash {
max-width: calc(var(--colonne) + 2 * var(--gouttiere));
margin: 0 auto;
padding: 0.5rem var(--gouttiere) 0;
}
.flash-message {
margin: 0 0 0.5rem;
padding: 0.75rem 1rem;
border-left: 4px solid var(--vert);
background: var(--surface);
font-size: 1rem;
}
.flash-alerte {
border-left-color: var(--rouge);
background: var(--erreur-fond);
}
/* ---------- 3. Carte d'humeur ---------- */
/* L'illustration du mode, dessinée à l'encre sur papier blanc, posée sur le socle
de la Kluk : une pilule à la couleur de l'humeur, avec son voyant. */
.carte-humeur {
margin: 0;
}
.carte-humeur img {
width: 100%;
aspect-ratio: 1;
object-fit: contain;
background: var(--blanc);
border: 2.5px solid var(--encre);
border-radius: var(--arrondi);
}
.carte-humeur::after {
content: "";
display: block;
height: 1rem;
margin: 0.4rem 6% 0;
border: 2.5px solid var(--encre);
border-radius: var(--arrondi-pilule);
background:
radial-gradient(circle, var(--porcelaine) 0 2.5px, transparent 3px),
var(--humeur, var(--porcelaine-fonce));
}
/* ---------- 4. Légende ---------- */
.pastille {
flex: none;
display: inline-block;
width: 0.85rem;
height: 0.85rem;
border-radius: 3px;
background: var(--humeur);
}
.pastille-supposee {
background: color-mix(in srgb, var(--encre-douce) 35%, var(--porcelaine));
}
.pastille-inconnue {
background: var(--surface);
border: 1.5px dashed var(--bordure-champ);
}
.pastille-journal {
position: relative;
background: var(--porcelaine-fonce);
}
.pastille-journal::after,
.jour-journal::after {
content: "";
position: absolute;
inset: 0;
margin: auto;
width: 5px;
height: 5px;
border-radius: 50%;
background: var(--blanc);
box-shadow: 0 0 0 1px var(--encre);
}
.legende {
margin: 0 0 0.5rem;
font-size: 1rem;
line-height: 1.4;
}
.legende ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.4rem 1.4rem;
}
.legende li {
display: flex;
align-items: center;
gap: 0.5rem;
}
.legende .legende-etats {
margin-top: 0.6rem;
color: var(--encre-douce);
font-size: 0.9375rem;
}
/* ---------- 5. Calendrier des humeurs ---------- */
/* Une colonne par semaine, une ligne par jour (du lundi au dimanche), comme sur GitHub. */
.calendrier-humeurs {
--case: 0.95rem;
--ecart: 3px;
}
@media (max-width: 30rem) {
.calendrier-humeurs { --case: 0.9rem; }
}
.annee-titre {
margin: 2.25rem 0 0.75rem;
font-size: 1.6rem;
}
.annee-mois {
display: flex;
flex-wrap: wrap;
gap: 1.25rem 1rem;
}
.mois-nom {
margin: 0 0 0.3rem;
font-family: var(--sans);
font-size: 0.875rem;
font-weight: 400;
line-height: 1.4rem;
color: var(--encre-douce);
}
.mois-jours,
.semaine-jours {
display: grid;
grid-template-rows: repeat(7, var(--case));
grid-auto-flow: column;
grid-auto-columns: var(--case);
gap: var(--ecart);
}
.semaine-jours {
grid-auto-columns: auto;
padding-top: 1.7rem;
margin-right: 0.15rem;
font-size: 0.75rem;
line-height: var(--case);
color: var(--encre-douce);
}
.jour {
position: relative;
display: block;
width: var(--case);
height: var(--case);
margin: 0;
padding: 0;
border: 0;
border-radius: 3px;
background: transparent;
font: inherit;
}
.jour-filled {
background: var(--humeur);
}
/* Mode supposé : la couleur de la veille, pâlie */
.jour-guessed {
background: color-mix(in srgb, var(--humeur) 35%, var(--porcelaine));
}
.jour-unknown {
background: var(--surface);
border: 1.5px dashed var(--bordure-champ);
}
.jour-empty {
background: var(--porcelaine-fonce);
}
.jour-future {
box-shadow: inset 0 0 0 1px var(--porcelaine-fonce);
}
button.jour { cursor: pointer; }
button.jour[aria-pressed="true"] {
outline: 2.5px solid var(--encre);
outline-offset: 2px;
border-radius: 3px;
}
button.jour:focus-visible {
outline: 3px solid var(--encre);
outline-offset: 2px;
border-radius: 3px;
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
button.jour { transition: transform 0.12s ease; }
button.jour:hover { transform: scale(1.3); z-index: 1; }
}
/* ---------- 6. Tableau de bord ---------- */
.tableau {
max-width: var(--largeur-entete);
margin: 0 auto;
padding: 0.5rem var(--gouttiere) 0;
}
.tableau-titre {
margin: 0.5rem 0 1.25rem;
font-size: clamp(2.1rem, 1.7rem + 2vw, 3rem);
}
.tableau-calendrier { padding-bottom: 3rem; }
.detail-date {
margin: 0;
font-size: 1.35rem;
}
.detail-date::first-letter { text-transform: uppercase; }
.detail-mode {
margin: 0.2rem 0 0;
font-weight: 700;
line-height: 1.35;
}
.detail-statut {
font-weight: 400;
color: var(--encre-douce);
}
.detail-statut:not(:empty)::before { content: "("; }
.detail-statut:not(:empty)::after { content: ")"; }
.detail-journal {
margin: 0.75rem 0 1.25rem;
white-space: pre-line;
overflow-wrap: anywhere;
}
.detail-journal-vide {
color: var(--encre-douce);
font-style: italic;
}
/* Sur mobile, le jour choisi reste en bas de l'écran pendant qu'on parcourt le calendrier */
@media (max-width: 59.99rem) {
.detail {
position: sticky;
bottom: 0;
z-index: 2;
display: grid;
grid-template-columns: 4.75rem minmax(0, 1fr);
gap: 1rem;
align-items: start;
margin: 0 calc(-1 * var(--gouttiere));
padding: 0.9rem var(--gouttiere) 1rem;
background: var(--porcelaine);
border-top: 3px solid var(--encre);
}
.detail .carte-humeur img { border-width: 2px; border-radius: var(--arrondi-petit); }
.detail .carte-humeur::after { height: 0.6rem; margin-top: 0.25rem; border-width: 2px; background: var(--humeur, var(--porcelaine-fonce)); }
.detail-date { font-size: 1.1rem; }
.detail-mode { font-size: 1rem; }
.detail-journal {
margin: 0.35rem 0 0.6rem;
font-size: 1rem;
line-height: 1.45;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
}
@media (min-width: 60rem) {
.tableau {
display: grid;
grid-template-columns: minmax(0, 1fr) 19rem;
gap: 4rem;
align-items: start;
}
.detail {
position: sticky;
top: 1.5rem;
margin-top: 1.25rem;
}
.detail-texte { margin-top: 1.5rem; }
}
/* ---------- 7. Page publique ---------- */
/* Le nom de la personne en titre. Sur ordinateur, tout tient dans le premier écran :
l'illustration à gauche, le jour choisi et les derniers mois à droite. */
.public {
max-width: var(--largeur-entete);
margin: 0 auto;
padding: 0 var(--gouttiere) 4rem;
display: grid;
gap: 1.5rem;
}
.public-nom {
margin: 0;
font-size: clamp(2.6rem, 1.8rem + 3.4vw, 4rem);
line-height: 1.05;
overflow-wrap: anywhere;
}
.carte-humeur-grande {
width: 100%;
max-width: 22rem;
}
.public-date {
margin: 0;
font-size: 1.25rem;
}
.public-date::first-letter { text-transform: uppercase; }
.public-mode {
margin: 0.15rem 0 0.5rem;
font-family: var(--serif);
font-size: clamp(2rem, 1.6rem + 1.6vw, 2.75rem);
line-height: 1.15;
text-wrap: balance;
}
.public-depuis {
margin: 0;
font-size: 1.1rem;
}
.public-autre-jour .detail-statut:not(:empty) { margin-right: 0.75rem; }
.public-historique h2 {
margin: 2rem 0 0.75rem;
font-size: 1.35rem;
}
.public-historique .annee-mois { margin-top: 1rem; }
@media (min-width: 52rem) {
.public {
grid-template-columns: min(19rem, 42vh) minmax(0, 1fr);
column-gap: 3.5rem;
row-gap: 1.25rem;
align-items: start;
}
.public-nom { grid-column: 1 / -1; }
.carte-humeur-grande { max-width: none; margin-top: 0.4rem; }
}
/* Changement de jour : bref fondu du détail */
@media (prefers-reduced-motion: no-preference) {
.apparition { animation: apparition 0.35s ease-out; }
}
@keyframes apparition {
from { opacity: 0.1; }
to { opacity: 1; }
}
/* ---------- 8. Page d'un jour (journal) ---------- */
.page-jour {
max-width: 56rem;
margin: 0 auto;
padding: 0.5rem var(--gouttiere) 5rem;
}
.retour {
margin: 0;
font-size: 1rem;
}
.page-jour-titre {
margin: 0.5rem 0 1.5rem;
font-size: clamp(2rem, 1.6rem + 2vw, 2.75rem);
}
.page-jour .carte-humeur {
max-width: 11rem;
}
.page-jour .formulaire { margin-top: 1.75rem; }
.choix-modes {
list-style: none;
margin: 0.25rem 0 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
}
.choix-modes li { position: relative; }
.choix-modes input {
position: absolute;
opacity: 0;
width: 1px;
height: 1px;
}
.choix-modes label {
display: flex;
align-items: center;
gap: 0.55rem;
padding: 0.5rem 1rem 0.5rem 0.85rem;
border: 2px solid var(--bordure-champ);
border-radius: var(--arrondi-pilule);
background: var(--blanc);
font-size: 1rem;
line-height: 1.3;
cursor: pointer;
}
.choix-modes label:hover { border-color: var(--encre); }
.choix-modes input:checked + label {
border-color: var(--encre);
box-shadow: inset 0 0 0 1.5px var(--encre);
background: var(--surface);
}
.choix-modes input:focus-visible + label {
outline: 3px solid var(--encre);
outline-offset: 3px;
}
.actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1rem 1.75rem;
}
@media (min-width: 48rem) {
.page-jour {
display: grid;
grid-template-columns: 17rem minmax(0, 1fr);
grid-template-areas:
"carte entete"
"carte formulaire";
column-gap: 3.5rem;
align-items: start;
}
.page-jour-entete { grid-area: entete; }
.page-jour .carte-humeur {
grid-area: carte;
max-width: none;
position: sticky;
top: 1.5rem;
margin-top: 1rem;
}
.page-jour .formulaire { grid-area: formulaire; margin-top: 0; }
}
/* ---------- 9. Impression ---------- */
@media print {
.detail { position: static; border: 0; }
.page-jour .formulaire .actions { display: none; }
}