/* Layout and spacing for Continuity web.
 *
 * Every colour here is a --ts-* role from the vendored tessera palette. None is
 * a hex value and none is a palette colour name: tessera's contract is that a
 * consumer references `ok` or `accent`, never `leaf` or `sun`, so that changing
 * scheme changes no file but the palette.
 *
 * Typography comes from tessera.type.css since v0.6.4: --ts-body, --ts-mono,
 * --ts-display, the --ts-step-* scale and --ts-measure. The local --c-* tokens
 * that stood in for them are gone.
 *
 * What remains local is spacing and the tap target, which tessera does not
 * cover. Grouped here so they can go the same way if it ever does.
 */

:root {
  --c-space-1: 0.25rem;
  --c-space-2: 0.5rem;
  --c-space-3: 1rem;
  --c-space-4: 1.5rem;
  --c-space-5: 2rem;

  --c-radius: 6px;
  /* 44px: the smallest target a thumb hits reliably. Everything tappable is
     at least this tall, which is most of what makes a page usable on a phone. */
  --c-tap: 44px;

  /* What is legible ON the accent. Borrowed from canopée, which hit the same
     wall: in `paper` the accent and the text are both `lead`, so a pressed
     button labelled with --ts-text is ink on ink. One token, applied
     everywhere something sits on the accent, rather than a workaround per
     control -- the first version of the picker leaned on font-weight instead
     and only half worked. */
  --on-accent: var(--ts-outline);
}

:root[data-scheme="paper"] {
  --on-accent: var(--ts-bg);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  /* 16px side gutters, and nothing wider than the viewport: a horizontal
     scrollbar on a phone is the classic symptom of a desktop-first layout. */
  padding: var(--c-space-3);
  overflow-x: hidden;

  font-family: var(--ts-body);
  font-size: var(--ts-step-0);
  line-height: 1.5;

  background: var(--ts-bg);
  color: var(--ts-text);
}

main {
  /* tessera's measure, 64ch: the line length it considers readable, rather
     than a round number of rem that happens to look right at one font size. */
  max-width: var(--ts-measure);
  margin: 0 auto;
}

h1 {
  font-family: var(--ts-display);
  /* Fraunces is variable, and these are the axes tessera picked for it. */
  font-variation-settings: var(--ts-display-axes);
  font-size: var(--ts-step-2);
  font-weight: 400;
  margin: 0;
}

a {
  color: var(--ts-link);
}

.card {
  background: var(--ts-surface);
  border: 1px solid var(--ts-outline);
  border-radius: var(--c-radius);
  padding: var(--c-space-3);
  margin-bottom: var(--c-space-3);
}

.muted {
  color: var(--ts-text-muted);
}

.mono {
  font-family: var(--ts-mono);
  font-feature-settings: "liga" 0;
  font-size: var(--ts-step--1);
}

/* State, by role. These are the only places the app names a colour, so the
   mapping between a Continuity concept and a tessera role lives in one list. */
.ok      { color: var(--ts-ok); }
.warn    { color: var(--ts-warn); }
.error   { color: var(--ts-error); }
.info    { color: var(--ts-info); }

button {
  min-height: var(--c-tap);
  padding: 0 var(--c-space-3);

  font: inherit;
  color: var(--ts-text);
  background: var(--ts-bg);

  border: 1px solid var(--ts-outline);
  border-radius: var(--c-radius);
  cursor: pointer;
}

button:hover {
  border-color: var(--ts-accent);
}

/* Never `outline: none`. The focus ring is how the keyboard path is visible,
   and this app is meant to be usable without a pointer. */
:focus-visible {
  outline: 2px solid var(--ts-accent);
  outline-offset: 2px;
}

/* --- Header ------------------------------------------------------------ */

header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--c-space-3);
  flex-wrap: wrap;
}

button.link {
  min-height: auto;
  padding: var(--c-space-1) 0;
  border: none;
  background: none;
  color: var(--ts-link);
  text-decoration: underline;
}

/* --- Login ------------------------------------------------------------- */

form.card {
  display: flex;
  flex-direction: column;
  gap: var(--c-space-2);
}

label {
  font-size: var(--ts-step--1);
  color: var(--ts-text-muted);
}

input {
  min-height: var(--c-tap);
  padding: 0 var(--c-space-2);

  /* --ts-step-0 is 17px, which clears the 16px floor below which mobile Safari
     zooms the page on focus and leaves the layout scrolled sideways with no way
     back. Worth checking again if tessera ever rescales. */
  font: inherit;
  font-size: var(--ts-step-0);

  color: var(--ts-text);
  background: var(--ts-bg);
  border: 1px solid var(--ts-outline);
  border-radius: var(--c-radius);
}

/* --- Today ------------------------------------------------------------- */

ul.tasks {
  list-style: none;
  margin: 0;
  padding: 0;
}

li.row {
  display: flex;
  align-items: center;
  gap: var(--c-space-2);
  /* The row wraps so a blocker list can sit under it at full width, rather
     than squeezing into the last column on a phone. */
  flex-wrap: wrap;

  padding: var(--c-space-2) 0;
  border-bottom: 1px solid var(--ts-outline);
}

button.done {
  /* Square, and a full tap target: this is the one control pressed all day. */
  width: var(--c-tap);
  min-width: var(--c-tap);
  padding: 0;
  color: var(--ts-ok);
}

.time {
  min-width: 3.5em;
}

.dur {
  margin-left: auto;
  white-space: nowrap;
}

.struck {
  text-decoration: line-through;
  color: var(--ts-text-muted);
}

/* The 409 answer, in place. Indented under the row it explains, because it is
   a continuation of that row and not a separate notice. */
.blockers {
  flex-basis: 100%;
  margin-left: calc(var(--c-tap) + var(--c-space-2));
  padding: var(--c-space-2) 0 0;
}

.blockers ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.blockers .row {
  border-bottom: none;
  padding: var(--c-space-1) 0;
}

/* --- Icônes ------------------------------------------------------------- */

/* The SVGs are drawn with stroke="currentColor", so an icon takes the colour
   of whatever contains it and follows the scheme without a rule per theme. */
.icon {
  display: inline-flex;
  width: 1.25em;
  height: 1.25em;
}

.icon svg {
  width: 100%;
  height: 100%;
}

/* --- Menu et sélecteur de lumière ---------------------------------------
 *
 * Un <details> natif, comme canopée : le navigateur gère l'ouverture et la
 * fermeture, donc il n'y a pas de gestionnaire de clic-à-côté à rater, et le
 * menu fonctionne avant même que le wasm ait démarré.
 */

.menu { position: relative; }

.menu summary {
  list-style: none;
  cursor: pointer;
  min-height: var(--c-tap);
  min-width: var(--c-tap);
  display: flex;
  align-items: center;
  justify-content: center;

  /* Opaque, sans exception : un fond transparent laisserait le « ··· » se
     fondre dans ce qui passe derrière. */
  background: var(--ts-bg);
  border: 1px solid var(--ts-outline);
  border-radius: var(--c-radius);
}

.menu summary::-webkit-details-marker { display: none; }

.menu[open] summary {
  background: var(--ts-accent);
  color: var(--on-accent);
}

.menu .sheet {
  position: absolute;
  right: 0;
  top: calc(100% + var(--c-space-1));
  z-index: 5;

  display: grid;
  gap: var(--c-space-2);
  min-width: 16rem;
  padding: var(--c-space-3);

  background: var(--ts-bg);
  border: 1px solid var(--ts-outline);
  border-radius: var(--c-radius);
}

.menu .sheet > button {
  min-height: var(--c-tap);
  padding: var(--c-space-2);
  font-size: var(--ts-step--1);
  text-align: left;
}

.menu .sheet label {
  display: block;
  margin-bottom: var(--c-space-1);
  font-size: var(--ts-step--1);
  color: var(--ts-text-muted);
}

/* Cinq segments, « Auto » sur sa propre ligne. Ce n'est pas une lumière parmi
   quatre : c'est le refus d'en choisir une, et l'aligner avec les autres la
   ferait lire comme un cinquième schéma. Une grille plutôt qu'un flex, parce
   que cinq cellules dans 16rem débordent sur « Crépuscule ». */
.schemes {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--ts-outline);
  border-radius: var(--c-radius);
  overflow: hidden;
}

.schemes button:first-child {
  grid-column: 1 / -1;
  border-bottom: 1px solid var(--ts-outline);
}

.schemes button {
  min-height: var(--c-tap);
  padding: var(--c-space-1) var(--c-space-1);
  font-size: var(--ts-step--1);
  color: var(--ts-text-muted);
  background: var(--ts-bg);
  border: 0;
  border-radius: 0;
}

/* Pas le deuxième : il ouvre la seconde ligne, où une bordure gauche viendrait
   se coller au cadre. */
.schemes button:nth-child(n+3) {
  border-left: 1px solid var(--ts-outline);
}

.schemes button[aria-pressed="true"] {
  background: var(--ts-accent);
  color: var(--on-accent);
  font-weight: 700;
}

/* --- Projets : l'arbre ---------------------------------------------------
 *
 * Une liste indentée, pas un canevas de nœuds et d'arêtes. Sur 375 px un
 * graphe dessiné est illisible et impossible à parcourir au clavier ; le fait
 * qu'une tâche ait plusieurs parents se dit dans une puce et dans les lignes
 * de référence, pas dans la géométrie.
 */

ul.tree {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Indentation par niveau. Faible à dessein : trois niveaux tiennent alors
   dans la largeur d'un téléphone, et au-delà c'est le zoom qui prend le
   relais. */
ul.tree ul.tree {
  margin-left: var(--c-space-3);
  border-left: 1px solid var(--ts-outline);
  padding-left: var(--c-space-2);
}

ul.tree .folded {
  display: none;
}

li.node > .row {
  display: flex;
  align-items: center;
  gap: var(--c-space-1);
  flex-wrap: wrap;
  padding: var(--c-space-1) 0;
}

button.twisty {
  width: 1.75rem;
  min-width: 1.75rem;
  min-height: 1.75rem;
  padding: 0;
  border: none;
  background: none;
  color: var(--ts-text-muted);
}

/* Le nom est un bouton parce qu'il zoome : ce qui agit doit être annoncé
   comme agissant, et un div cliquable ne l'est pas. Il garde l'apparence du
   texte, la cible tactile venant de la hauteur de ligne. */
button.name {
  flex: 1 1 12rem;
  min-height: auto;
  padding: var(--c-space-1) 0;
  text-align: left;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
}

/* Actionnable : rien d'ouvert ne la bloque. C'est l'information que l'arbre
   existe pour donner, donc elle est portée par la coche elle-même plutôt que
   par une pastille de plus. */
.row .done { color: var(--ts-text-muted); }
.row.ready .done { color: var(--ts-ok); }

.tier {
  font-size: var(--ts-step--1);
  color: var(--ts-text-muted);
}

.chip {
  padding: 0 var(--c-space-1);
  font-size: var(--ts-step--1);
  border: 1px solid currentColor;
  border-radius: var(--c-radius);
}

.chip.info { color: var(--ts-info); }

/* Une référence pointe vers l'endroit où la tâche est réellement rendue.
   Volontairement discrète : c'est un lien, pas du contenu, et la confondre
   avec une vraie ligne ferait croire que la tâche existe en double. */
li.reference {
  padding: var(--c-space-1) 0;
  font-size: var(--ts-step--1);
}

li.more {
  padding: var(--c-space-1) 0;
  font-size: var(--ts-step--1);
}

nav.crumb, p.crumb {
  margin: 0 0 var(--c-space-3);
  font-size: var(--ts-step--1);
}

nav.crumb .sep { color: var(--ts-text-muted); }

/* --- Création ------------------------------------------------------------ */

.toolbar {
  margin-bottom: var(--c-space-3);
}

form.create .fields {
  display: grid;
  /* Deux colonnes dès qu'il y a la place, une seule sur un téléphone : quatre
     champs courts côte à côte deviennent illisibles sous 30rem. */
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--c-space-2);
}

form.create .fields > div {
  display: flex;
  flex-direction: column;
  gap: var(--c-space-1);
}

textarea, select {
  padding: var(--c-space-1) var(--c-space-2);
  font: inherit;
  font-size: var(--ts-step-0);
  color: var(--ts-text);
  background: var(--ts-bg);
  border: 1px solid var(--ts-outline);
  border-radius: var(--c-radius);
}

textarea {
  resize: vertical;
  font-family: var(--ts-body);
}

select[size] {
  /* La liste de parents est longue : une hauteur fixe vaut mieux qu'une liste
     qui repousse le bouton hors de l'écran. */
  min-height: 7rem;
}

/* Le sens de chaque relation, écrit sous son champ plutôt que caché dans une
   infobulle : « bloque » et « est bloquée par » sont les deux directions de la
   même arête, et se lisent de travers une fois sur deux. */
p.hint {
  margin: 0;
  font-size: var(--ts-step--1);
}

p.chosen {
  margin: var(--c-space-1) 0 0;
  font-size: var(--ts-step--1);
}

/* --- Page de détail ------------------------------------------------------ */

.detail h2 {
  font-family: var(--ts-display);
  font-variation-settings: var(--ts-display-axes);
  font-size: var(--ts-step-1);
  font-weight: 400;
  margin: 0 0 var(--c-space-2);
}

.detail .desc {
  margin: 0 0 var(--c-space-3);
  white-space: pre-wrap;
}

/* Une grille de faits plutôt qu'un paragraphe : on vient y chercher une date
   précise, pas lire une phrase. */
dl.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: var(--c-space-2);
  margin: 0 0 var(--c-space-3);
}

dl.facts dt {
  font-size: var(--ts-step--1);
  color: var(--ts-text-muted);
}

dl.facts dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}

button.primary {
  background: var(--ts-accent);
  color: var(--on-accent);
  border-color: var(--ts-outline);
}

button.primary:disabled {
  background: var(--ts-bg);
  color: var(--ts-text-muted);
  cursor: not-allowed;
}

.relations {
  margin-top: var(--c-space-4);
}

.relations h3 {
  font-size: var(--ts-step-0);
  margin: 0;
}

/* L'écran courant est marqué, pas retiré : un menu dont les entrées
   apparaissent et disparaissent est un menu qu'il faut relire à chaque fois.
   Marqué par la bordure et la graisse, pas par la couleur seule. */
.menu .sheet > button[aria-current="page"] {
  border-color: var(--ts-accent);
  font-weight: 700;
}

/* La version, en bas du menu : discrète, mais présente sans avoir à ouvrir
   la console. */
.menu .sheet .version {
  margin: 0;
  font-size: var(--ts-step--1);
  text-align: right;
}
