:root {
  --bg: #f7f7f8;
  --fg: #1f2937;
  --line: #d8dbe0;
  --accent: #2563eb;
  --danger: #b91c1c;
  --warn: #92400e;
  --ok: #166534;
  --topbar-h: 3rem;
}

* { box-sizing: border-box; }

/* L'attribut hidden vient de la feuille du NAVIGATEUR : n'importe quelle règle d'auteur
   posant un display l'emporte sur lui, quelle que soit la spécificité. Le front pilote
   presque tout son affichage par `hidden` (bandeau, tiroir, sélecteurs, indices) : sans
   cette ligne, il suffit qu'une règle comme `dialog select { display: block }` existe pour
   qu'un élément marqué caché reste visible. C'est ce qui affichait le sélecteur de
   destination de la capture alors qu'il n'y avait qu'une seule connexion Vikunja. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  font: 16px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--fg);
  background: var(--bg);
}

body {
  display: flex;
  flex-direction: column;
}

/* ---------- barre supérieure ---------- */

.topbar {
  display: flex;
  align-items: center;
  gap: .5rem;
  height: var(--topbar-h);
  padding: 0 .5rem;
  background: var(--fg);
  color: #fff;
  padding-top: env(safe-area-inset-top);
}

.topbar h1 {
  flex: 1;
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
}

.icon-btn {
  background: none;
  border: 0;
  color: inherit;
  font-size: 1.25rem;
  padding: .4rem .6rem;
  cursor: pointer;
  border-radius: .35rem;
}

.icon-btn:hover { background: rgba(255,255,255,.15); }

/* Identité de session. Sur petit écran, seul le nom reste : « Connecté comme » mangerait
   la place du titre sans rien apprendre. */
.whoami {
  margin: 0;
  font-size: .8rem;
  color: rgba(255,255,255,.75);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40vw;
}

.whoami b { color: #fff; font-weight: 600; }

.tasks-btn { position: relative; }

.badge {
  position: absolute;
  top: .1rem;
  right: .15rem;
  min-width: 1.05rem;
  padding: 0 .2rem;
  font-size: .7rem;
  line-height: 1.05rem;
  text-align: center;
  color: #fff;
  background: var(--danger);
  border-radius: .6rem;
}

/* ---------- bandeau d'erreurs partielles ---------- */

.banner {
  padding: .5rem .75rem;
  font-size: .85rem;
  background: #fee2e2;
  color: var(--danger);
  border-bottom: 1px solid #fca5a5;
}

.banner.warn {
  background: #fef3c7;
  color: var(--warn);
  border-bottom-color: #fcd34d;
}

.banner.ok {
  background: #dcfce7;
  color: var(--ok);
  border-bottom-color: #86efac;
}

/* ---------- calendrier ---------- */

main {
  flex: 1;
  min-height: 0;
  padding: .5rem;
  overflow-y: auto;   /* le calendrier est en height:'auto' : c'est ici qu'on défile */
  /* La gouttière est réservée en permanence : sinon FullCalendar mesure la largeur AVANT
     que la barre n'apparaisse, et la dernière colonne (le dimanche) finit dessous, numéro
     du jour et titres rognés. */
  scrollbar-gutter: stable;
}

.fc .fc-toolbar-title { font-size: 1.05rem; }
.fc .fc-button { padding: .3rem .55rem; font-size: .85rem; }

/* Styles par kind (cf. CLAUDE.md § 9). */
.kind-task { font-weight: 600; }
.kind-task .fc-event-title::before { content: "✓ "; }
.is-done { opacity: .55; text-decoration: line-through; }
.is-overdue { background: var(--danger) !important; border-color: var(--danger) !important; }

/* En vue liste, FullCalendar peint le texte des cellules en couleur sombre : sur le rouge
   des retards, le contraste devient illisible. */
.fc-list-event.is-overdue td,
.fc-list-event.is-overdue .fc-list-event-title a { color: #fff !important; }
.fc-list-event.is-overdue:hover td { background: var(--danger) !important; }

/* FullCalendar recolore .fc-event-main en dur (--fc-event-text-color, blanc) : une règle
   posée seulement sur la racine de l'événement est battue par cette règle enfant, et le
   tickler s'affichait en BLANC SUR BLANC. D'où les trois sélecteurs. */
/* La bordure pointillée distingue le marqueur d'un vrai rendez-vous, sans le rendre
   invisible comme le faisait un fond transparent. */
.kind-tickler {
  background: rgba(107, 114, 128, .10) !important;
  border: 1px dashed #9ca3af !important;
}

/* Ruban de survol : les jours entre le réveil et l'échéance. Posé uniquement pendant le
   survol du marqueur, en permanence, il révélerait une échéance que le § 8 masque.
   Le liseré haut et bas fait lire une BANDE continue : une simple teinte de fond se perd
   derrière des cases déjà remplies de pastilles bleues. */
.fc .tickler-span {
  background: rgba(37, 99, 235, .22) !important;
  box-shadow: inset 0 3px 0 var(--accent), inset 0 -3px 0 var(--accent);
}

.kind-tickler,
.kind-tickler .fc-event-main,
.kind-tickler .fc-event-title {
  color: #6b7280 !important;
  font-style: italic;
}

/* ---------- drawer des sources ---------- */

.drawer {
  position: fixed;
  inset: 0 auto 0 0;
  width: min(20rem, 85vw);
  background: #fff;
  border-right: 1px solid var(--line);
  padding: .75rem;
  overflow-y: auto;
  z-index: 20;
}

.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.drawer-head h2 { font-size: 1rem; margin: 0; }
.drawer-head .icon-btn { color: var(--fg); }

.drawer h3 {
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: #6b7280;
  margin: 1rem 0 .35rem;
}

.source-row {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .3rem 0;
  font-size: .9rem;
}

/* Seule cette partie bascule la case : le sélecteur de couleur vit en dehors du label. */
.source-pick {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

.source-pick span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* La pastille EST le sélecteur : un carré de couleur qu'on clique, sans chrome autour. */
.source-color {
  flex: none;
  width: 1.4rem;
  height: 1.4rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: .25rem;
  background: none;
  cursor: pointer;
}

.source-color::-webkit-color-swatch-wrapper { padding: 2px; }
.source-color::-webkit-color-swatch { border: 0; border-radius: .15rem; }
.source-color::-moz-color-swatch { border: 0; border-radius: .15rem; }

.source-reset {
  flex: none;
  padding: 0 .25rem;
  font-size: .9rem;
  line-height: 1.4rem;
  color: #6b7280;
  background: none;
  border: 0;
  cursor: pointer;
}

.source-reset:hover { color: var(--fg); }

.drawer-foot {
  margin-top: 1.5rem;
  font-size: .85rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.drawer-user { color: #6b7280; }
.drawer-user b { color: var(--fg); }

.lang-row {
  display: flex;
  align-items: center;
  gap: .5rem;
  color: #6b7280;
}

.lang-row select {
  flex: 1;
  padding: .3rem .4rem;
  font: inherit;
  font-size: .85rem;
  border: 1px solid var(--line);
  border-radius: .35rem;
  background: #fff;
  color: var(--fg);
}

.scrim {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.35);
  z-index: 10;
}

/* ---------- dialogues ---------- */

dialog {
  border: 0;
  border-radius: .6rem;
  padding: 1rem;
  width: min(28rem, 92vw);
  box-shadow: 0 10px 30px rgba(0,0,0,.2);
}

dialog::backdrop { background: rgba(0,0,0,.35); }

dialog h2 { margin: 0 0 .75rem; font-size: 1.05rem; }

dialog label {
  display: block;
  margin: .6rem 0;
  font-size: .85rem;
  color: #374151;
}

dialog label.inline {
  display: flex;
  align-items: center;
  gap: .4rem;
}

dialog input[type="text"],
dialog input[type="date"],
dialog input[type="datetime-local"],
dialog input[type="password"],
dialog select,
dialog textarea {
  display: block;
  width: 100%;
  margin-top: .2rem;
  padding: .45rem .5rem;
  font: inherit;
  border: 1px solid var(--line);
  border-radius: .35rem;
  background: #fff;
}

.row { display: flex; gap: .5rem; }
.row label { flex: 1; }

dialog menu {
  display: flex;
  justify-content: flex-end;
  gap: .5rem;
  margin: 1rem 0 0;
  padding: 0;
}

dialog button {
  font: inherit;
  padding: .45rem .8rem;
  border-radius: .35rem;
  border: 1px solid var(--line);
  background: #fff;
  cursor: pointer;
}

dialog button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
dialog button.danger { color: var(--danger); border-color: #fca5a5; }
dialog button:disabled { opacity: .5; cursor: not-allowed; }

.form-error { color: var(--danger); font-size: .85rem; margin: .5rem 0 0; }
.hint { color: var(--warn); font-size: .85rem; }
.desc { white-space: pre-wrap; font-size: .9rem; color: #374151; }

/* ---------- modal des tâches ---------- */

dialog.wide { width: min(34rem, 94vw); }

.dlg-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
}

.dlg-head h2 { margin: 0; }
.dlg-head .icon-btn { color: var(--fg); }

/* Capture : une ligne, un bouton. C'est le geste qui doit être court, pas le formulaire. */
.capture {
  display: flex;
  gap: .4rem;
  margin: .75rem 0 .25rem;
}

.capture input[type="text"] { flex: 1; min-width: 0; }
.capture select { flex: 0 1 9rem; }

.capture input[type="text"],
.capture select {
  padding: .45rem .5rem;
  font: inherit;
  border: 1px solid var(--line);
  border-radius: .35rem;
  background: #fff;
}

.capture button {
  font: inherit;
  padding: .45rem .8rem;
  border-radius: .35rem;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
}

.capture button:disabled { opacity: .5; cursor: not-allowed; }

#tasks-list { max-height: min(60vh, 30rem); overflow-y: auto; margin-top: .5rem; }

.task-group h3 {
  margin: .9rem 0 .3rem;
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #6b7280;
}

.task-row { border-top: 1px solid var(--line); }
.task-row:last-child { border-bottom: 1px solid var(--line); }

.task-head {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  width: 100%;
  padding: .5rem .25rem;
  font: inherit;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}

.task-head:hover { background: #f3f4f6; }

.task-mark { flex: 0 0 1rem; color: #6b7280; }
.task-label { flex: 1; min-width: 0; }

.task-when {
  flex: 0 0 auto;
  font-size: .8rem;
  color: #6b7280;
  font-variant-numeric: tabular-nums;
}

.task-row.task-late { border-left: 3px solid var(--danger); }
.task-row.task-late .task-when,
.task-row.task-late .task-mark { color: var(--danger); }
.task-row.task-done .task-label { text-decoration: line-through; color: #6b7280; }

.task-detail {
  padding: .1rem .25rem .7rem 1.75rem;
  font-size: .9rem;
}

.task-detail p { margin: .25rem 0; }
.task-link { display: inline-block; margin-top: .4rem; color: var(--accent); }

/* ---------- page de connexion ---------- */

.login-wrap {
  flex: 1;
  display: grid;
  place-items: center;
  padding: 1rem;
}

.login-card {
  width: min(22rem, 100%);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: .6rem;
  padding: 1.25rem;
}

.login-card h1 { margin: 0 0 1rem; font-size: 1.2rem; }
.login-card label { display: block; margin: .75rem 0; font-size: .85rem; }

.login-card input {
  display: block;
  width: 100%;
  margin-top: .25rem;
  padding: .5rem;
  font: inherit;
  border: 1px solid var(--line);
  border-radius: .35rem;
}

.login-card button {
  width: 100%;
  margin-top: 1rem;
  padding: .55rem;
  font: inherit;
  color: #fff;
  background: var(--accent);
  border: 0;
  border-radius: .35rem;
  cursor: pointer;
}

/* ---------- page de gestion (connexions) ---------- */

.page {
  overflow-y: auto;
  padding: .75rem;
  max-width: 44rem;
  margin: 0 auto;
  width: 100%;
}

.conn-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: .5rem;
  padding: .65rem .8rem;
  margin-bottom: .5rem;
}

.conn-url {
  font-size: .8rem;
  color: #6b7280;
  word-break: break-all;
}

.conn-actions { display: flex; gap: .4rem; flex: none; }

.conn-actions button,
.login-card button.secondary,
.login-card button.danger {
  font: inherit;
  padding: .4rem .7rem;
  border-radius: .35rem;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--fg);
  cursor: pointer;
  width: auto;
  margin-top: 0;
}

.login-card button.secondary { width: 100%; margin-top: .5rem; }
.conn-actions button.danger,
.login-card button.danger { color: var(--danger); border-color: #fca5a5; }

/* ---------- aide contextuelle des connexions ---------- */

.howto {
  background: #f3f4f6;
  border: 1px solid var(--line);
  border-radius: .5rem;
  padding: .7rem .85rem;
  margin: .75rem 0;
  font-size: .85rem;
  line-height: 1.5;
}

.howto h2 {
  margin: 0 0 .5rem;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #6b7280;
}

.howto p { margin: .45rem 0; }
.howto ol { margin: .45rem 0; padding-left: 1.2rem; }
.howto li { margin: .25rem 0; }

.howto code {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: .2rem;
  padding: .05rem .25rem;
  font-size: .82em;
  word-break: break-all;
}

.samples {
  display: flex;
  flex-direction: column;
  gap: .25rem;
}

.samples .ok { color: #166534; }
.samples .ko { color: #991b1b; }

.howto-note {
  font-size: .8rem;
  color: #6b7280;
  margin: .5rem 0;
}

@media (max-width: 720px) {
  main { padding: .25rem; }
  .page { padding: .5rem; }
  .conn-row { flex-direction: column; align-items: stretch; }
  .conn-actions { justify-content: flex-end; }

  /* Les trois groupes de la barre FullCalendar ne tiennent pas sur 390 px : « Aujourd'hui »
     retombe sous les chevrons et chevauche le titre. On donne au titre sa propre ligne,
     au-dessus, et les commandes se répartissent sur la seconde. */
  .fc .fc-toolbar { flex-wrap: wrap; gap: .35rem; }
  .fc .fc-toolbar-chunk:nth-child(2) {
    order: -1;
    flex: 1 0 100%;
    text-align: center;
  }

  /* Le titre de la page et le nom du compte se disputent la barre : on garde le nom,
     qui est l'information, et on laisse tomber la formule qui l'introduit. */
  .whoami-label { display: none; }
  .whoami { max-width: 30vw; }
  .topbar h1 { font-size: 1rem; }

  /* Le modal des tâches prend l'écran plutôt que de flotter dessus : sur un téléphone,
     une carte centrée avec des marges perd deux lignes de liste pour rien. */
  dialog.wide {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border-radius: 0;
    padding: .75rem;
    padding-top: calc(.75rem + env(safe-area-inset-top));
  }

  /* [open] est indispensable : sans lui, le display:flex écraserait le display:none
     que le navigateur applique à un dialog fermé, et le modal serait toujours visible. */
  dialog.wide[open] { display: flex; flex-direction: column; }

  #tasks-list { max-height: none; flex: 1; }

  /* Une seule destination (le cas courant) : champ + bouton tiennent sur une ligne.
     Dès qu'un sélecteur apparaît, le champ prend toute la première ligne, se saisir au
     pouce dans 8 rem est intenable, et sélecteur + bouton passent dessous. */
  .capture { flex-wrap: wrap; }
  .capture input[type="text"] { flex: 1 1 11rem; }
  .capture:has(select:not([hidden])) input[type="text"] { flex: 1 0 100%; }
  .capture select { flex: 1; }
}

/* Sous 380 px (petits Android, iPhone SE), la barre du haut n'a plus la place pour le
   nom du compte : il reste accessible dans le tiroir. */
@media (max-width: 380px) {
  .whoami { display: none; }
}

/* ---------- aide-mémoire GTD ---------- */

.gtd { max-width: 46rem; line-height: 1.6; }
.gtd h2 { font-size: 1.05rem; margin: 2rem 0 .5rem; }
.gtd section:first-of-type h2 { margin-top: .5rem; }
.gtd p { margin: .6rem 0; }
.gtd .lead { font-size: 1.05rem; color: #374151; }
.gtd ul { padding-left: 1.2rem; }
.gtd li { margin: .4rem 0; }

.gtd table {
  width: 100%;
  border-collapse: collapse;
  margin: .8rem 0;
  font-size: .9rem;
}

.gtd th, .gtd td {
  text-align: left;
  padding: .45rem .5rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.gtd th { color: #6b7280; font-weight: 600; }

.gtd kbd {
  font: inherit;
  font-size: .85em;
  padding: 0 .3rem;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: .25rem;
  background: #fff;
}

.gtd .howto-note {
  background: #f3f4f6;
  border-left: 3px solid var(--line);
  padding: .5rem .75rem;
  font-size: .9rem;
  color: #4b5563;
}

.gtd h3 { font-size: .95rem; margin: 1.2rem 0 .4rem; }

/* Le déroulé se lit comme une suite d'étapes : chiffres détachés, respiration entre
   chacune. Une <ol> serrée se lirait comme une liste de courses. */
.gtd .walkthrough { padding-left: 1.4rem; }
.gtd .walkthrough > li { margin: .9rem 0; padding-left: .2rem; }
.gtd .walkthrough > li::marker { color: var(--accent); font-weight: 600; }

.gtd code {
  font-size: .9em;
  padding: 0 .25rem;
  background: #f3f4f6;
  border-radius: .2rem;
}

/* L'inbox pleine est un signal, pas une décoration : elle se voit sans crier. */
.inbox-state {
  margin: .4rem 0 0;
  font-size: .85rem;
}

.inbox-state a {
  color: var(--accent);
  text-decoration: none;
}

.inbox-state a:hover { text-decoration: underline; }

/* Sous-titre de modale : une explication, pas un avertissement. La classe .hint est en
   ambre et servait ici à tort. */
.dlg-sub {
  margin: .1rem 0 .2rem;
  font-size: .85rem;
  color: #6b7280;
}

/* Le rappel de syntaxe est replié : il ne doit pas allonger le geste de capture pour ceux
   qui tapent simplement une ligne. */
.capture-magic { margin-top: .6rem; font-size: .85rem; }
.capture-magic summary { cursor: pointer; color: var(--accent); }
.capture-magic ul { margin: .4rem 0; padding-left: 1.1rem; }
.capture-magic li { margin: .2rem 0; }
.capture-magic code {
  padding: 0 .25rem;
  background: #f3f4f6;
  border-radius: .2rem;
}

/* La zone de capture démarre sur une ligne et grandit : un vidage de tête doit se voir en
   entier sans quitter le champ. */
.capture textarea {
  flex: 1;
  min-width: 0;
  min-height: 2.4rem;
  padding: .45rem .5rem;
  font: inherit;
  line-height: 1.4;
  resize: none;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: .35rem;
  background: #fff;
}

/* ---------- œil de révélation ---------- */

/* L'enveloppe reprend la largeur du champ : le bouton se pose PAR-DESSUS, sans rétrécir
   la zone de saisie ni décaler les formulaires existants. */
.with-reveal {
  position: relative;
  display: block;
}

/* Deux classes, pour passer devant `.login-card button` et `dialog button`, qui sont plus
   spécifiques qu'une classe seule et imposaient au bouton la largeur pleine et le fond
   accentué du bouton de validation. */
.with-reveal .reveal-btn {
  position: absolute;
  top: 50%;
  right: .35rem;
  transform: translateY(-50%);
  padding: .15rem .3rem;
  font-size: 1rem;
  line-height: 1;
  background: none;
  border: 0;
  cursor: pointer;
  opacity: .65;
  width: auto;
  margin: 0;
  color: inherit;
}

.with-reveal .reveal-btn:hover { opacity: 1; background: none; }

/* La place du bouton est réservée dans le champ, sinon un mot de passe long passe
   dessous. */
.with-reveal input { padding-right: 2.1rem; }
