diff --git a/public/css/style.css b/public/css/style.css index 1c62a8c..6bc7af9 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -15,6 +15,11 @@ --radius: 14px; --radius-sm: 8px; --shadow: 0 1px 2px rgba(32, 31, 43, 0.04), 0 4px 16px rgba(32, 31, 43, 0.06); + /* Higher than the dark-mode value below — pale accent tints on a white + surface read as barely-there in light mode, so light needs a stronger mix + to hit the same perceived contrast dark mode gets "for free" against a + dark surface. */ + --cal-marker-mix: 38%; font-family: "Segoe UI", system-ui, -apple-system, Roboto, sans-serif; } @@ -34,6 +39,7 @@ --success: #4fd190; --success-bg: #163828; --shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 8px 24px rgba(0, 0, 0, 0.35); + --cal-marker-mix: 24%; } } @@ -51,6 +57,7 @@ --danger-bg: #3a201f; --success: #4fd190; --success-bg: #163828; + --cal-marker-mix: 24%; } :root[data-theme="light"] { @@ -67,6 +74,7 @@ --danger-bg: #fdecea; --success: #1e8e5a; --success-bg: #e8f7ef; + --cal-marker-mix: 38%; } * { box-sizing: border-box; } @@ -1567,6 +1575,10 @@ button.calendar-filters-close { display: none; } .vote-badge.accept { border-left: 3px solid var(--success); } .vote-badge.reject { border-left: 3px solid var(--danger); } +.vote-badge.rehearsal-status-confirmed { border-left: 3px solid var(--accent); } +.vote-badge.rehearsal-status-suggested { border-left: 3px solid var(--success); } +.vote-badge.rehearsal-status-rejected { border-left: 3px solid var(--danger); } + .rehearsal-voted-section { margin-top: 0.75rem; } .rehearsal-voted-section > summary { @@ -1595,16 +1607,22 @@ button.calendar-filters-close { display: none; } /* Concert/rehearsal markers take priority over the availability heat colors above (same specificity, later in the cascade) — a scheduled date matters - more than who's free that day. */ -.cal-cell.has-rehearsal { background: color-mix(in srgb, var(--accent) 20%, var(--surface)); border-color: var(--accent); } -.cal-cell.rehearsal-confirmed { background: color-mix(in srgb, var(--success) 20%, var(--surface)); border-color: var(--success); } -.cal-cell.rehearsal-suggested { background: color-mix(in srgb, var(--accent) 20%, var(--surface)); border-color: var(--accent); } -.cal-cell.has-concert { background: color-mix(in srgb, var(--accent-2) 20%, var(--surface)); border-color: var(--accent-2); } -.cal-cell.has-rehearsal.has-concert { - background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 20%, var(--surface)), color-mix(in srgb, var(--accent-2) 20%, var(--surface))); -} + more than who's free that day. + Colors: confirmed rehearsals are purple (accent) — the "settled, book it" + state; still-pending suggestions are green — an invitation to vote, not yet + settled; a rejected rehearsal (host said no, or too many refusals) is red. */ +.cal-cell.rehearsal-confirmed { background: color-mix(in srgb, var(--accent) var(--cal-marker-mix), var(--surface)); border-color: var(--accent); } +.cal-cell.rehearsal-suggested { background: color-mix(in srgb, var(--success) var(--cal-marker-mix), var(--surface)); border-color: var(--success); } +.cal-cell.rehearsal-rejected { background: color-mix(in srgb, var(--danger) var(--cal-marker-mix), var(--surface)); border-color: var(--danger); } +.cal-cell.has-concert { background: color-mix(in srgb, var(--accent-2) var(--cal-marker-mix), var(--surface)); border-color: var(--accent-2); } .cal-cell.rehearsal-confirmed.has-concert { - background: linear-gradient(135deg, color-mix(in srgb, var(--success) 20%, var(--surface)), color-mix(in srgb, var(--accent-2) 20%, var(--surface))); + background: linear-gradient(135deg, color-mix(in srgb, var(--accent) var(--cal-marker-mix), var(--surface)), color-mix(in srgb, var(--accent-2) var(--cal-marker-mix), var(--surface))); +} +.cal-cell.rehearsal-suggested.has-concert { + background: linear-gradient(135deg, color-mix(in srgb, var(--success) var(--cal-marker-mix), var(--surface)), color-mix(in srgb, var(--accent-2) var(--cal-marker-mix), var(--surface))); +} +.cal-cell.rehearsal-rejected.has-concert { + background: linear-gradient(135deg, color-mix(in srgb, var(--danger) var(--cal-marker-mix), var(--surface)), color-mix(in srgb, var(--accent-2) var(--cal-marker-mix), var(--surface))); } /* ---------- Concerts: upcoming list + detail actions ---------- */ diff --git a/public/js/calendar.js b/public/js/calendar.js index a6d6537..cc1bb98 100644 --- a/public/js/calendar.js +++ b/public/js/calendar.js @@ -106,6 +106,7 @@ function concertLinksHtml(concert) { function rehearsalStatusLabel(r) { if (r.status === 'confirmed') return 'Répétition confirmée'; + if (r.status === 'rejected') return 'Répétition refusée'; const accepted = r.votes.filter((v) => v.vote === 'accept').length; return `Suggestion de répétition (${accepted}/${r.confirmThreshold} votes)`; } @@ -216,10 +217,14 @@ function renderCalendar() { const rehearsal = rehearsalsByDate.get(isoDate(date)); if (rehearsal) { - const isConfirmed = rehearsal.status === 'confirmed'; - cell.classList.add('has-rehearsal', isConfirmed ? 'rehearsal-confirmed' : 'rehearsal-suggested'); + const statusTitles = { + confirmed: 'Répétition confirmée', + rejected: 'Répétition refusée', + suggested: 'Répétition proposée (en attente de votes)', + }; + cell.classList.add('has-rehearsal', `rehearsal-${rehearsal.status}`); const badge = document.createElement('span'); - badge.title = isConfirmed ? 'Répétition confirmée' : 'Répétition proposée (en attente de votes)'; + badge.title = statusTitles[rehearsal.status] || statusTitles.suggested; badge.textContent = '🎸'; badges.appendChild(badge); } @@ -522,7 +527,7 @@ function rehearsalRowTemplate(r) { return `