/* todont — one continuously scrolling calendar.
   Desktop: 7-column week rows, ~4 weeks in view.
   Narrow:  the same DOM reflows to one full-width day per row.
   No layout branch in the templates; it's all this file. */

:root {
  --bar-h: 3.4rem;
  --weeks-in-view: 4;

  /* Consolas is the ask. The rest of the stack is what Linux and the phone
     actually have, in descending order of how much they look like it. */
  --font: Consolas, "DejaVu Sans Mono", "Liberation Mono", Menlo, monospace;

  /* Dark, built as a ladder of lightness on one neutral slate hue.
     Every surface distinction -- weekend, alternating month, the tile on top
     of the cell -- is a step up or down that ladder, never a change of hue.
     Tinting each state a different colour is what made this hard to read:
     your eye had to decode a colour instead of just seeing a step. */
  --bg: #0d1117;            /* the page, behind and between the cells */
  --cell: #1a212b;          /* a day */
  --cell-alt: #1f2731;      /* ...in the alternating month */
  --cell-weekend: #151b23;  /* ...at the weekend */
  --cell-alt-weekend: #19212a;
  --bg-alt: #232c37;        /* a tile, sitting on top of a cell */
  --line: #3b4756;          /* grid lines: meant to be seen */
  --line-soft: #2a3340;     /* borders inside a cell */
  --ink: #e3e9f0;
  --ink-dim: #a3b1c2;
  --ink-faint: #71808f;
  --accent: #6cb8ff;
  --accent-ink: #0b1016;
  --good: #56d394;
  --warn: #e5b547;
  --bad: #ff8172;
  --pop: #273140;
  --shadow: rgba(0, 0, 0, .5);
  --sun: "\2600";     /* button shows the mode you'd switch *to* */
  --moon: "\263D";
}

/* Light. Declared twice on purpose: once for "the system says so and you
   haven't picked", once for "you picked it". No preprocessor here to share. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg: #e7ebf0;
    --cell: #ffffff;
    --cell-alt: #fafcfe;
    --cell-weekend: #f3f6f9;
    --cell-alt-weekend: #eff3f7;
    --bg-alt: #f1f4f8;
    --line: #c3ccd6;
    --line-soft: #dfe5ec;
    --ink: #16202b;
    --ink-dim: #566475;
    --ink-faint: #8b98a6;
    --accent: #1668c4;
    --accent-ink: #ffffff;
    --good: #1f8a52;
    --warn: #8a5d00;
    --bad: #b23a30;
    --pop: #ffffff;
    --shadow: rgba(23, 36, 51, .18);
  }
}

:root[data-theme="light"] {
  --bg: #e7ebf0;
  --cell: #ffffff;
  --cell-alt: #fafcfe;
  --cell-weekend: #f3f6f9;
  --cell-alt-weekend: #eff3f7;
  --bg-alt: #f1f4f8;
  --line: #c3ccd6;
  --line-soft: #dfe5ec;
  --ink: #16202b;
  --ink-dim: #566475;
  --ink-faint: #8b98a6;
  --accent: #1668c4;
  --accent-ink: #ffffff;
  --good: #1f8a52;
  --warn: #8a5d00;
  --bad: #b23a30;
  --pop: #ffffff;
  --shadow: rgba(23, 36, 51, .18);
}

* { box-sizing: border-box; }

/* Any `display:` further down this file outranks the browser's default rule
   for [hidden], and then an element the JS thinks it has put away is still on
   screen. This is the one place that is worth an !important. */
[hidden] { display: none !important; }

html { scroll-padding-top: var(--bar-h); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 13px/1.4 var(--font);
  -webkit-text-size-adjust: 100%;
}

button, input, textarea, select { font: inherit; color: inherit; }

/* --- top bar ------------------------------------------------------------ */

.bar {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  gap: .9rem;
  padding: 0 1rem;
  /* The notch eats into a fixed height under border-box, so add to it rather
     than paying for the inset out of the bar's own room. */
  padding-top: env(safe-area-inset-top);
  box-sizing: content-box;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.brand { font-size: 1.05rem; font-weight: 700; color: var(--ink); text-decoration: none; }
.month-label { font-size: .95rem; color: var(--ink-dim); font-variant-numeric: tabular-nums; }
.bar-right { margin-left: auto; display: flex; align-items: center; gap: .5rem; }

.ghost {
  background: none;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: .3rem .7rem;
  font-size: .9rem;
  color: var(--ink-dim);
  cursor: pointer;
  text-decoration: none;
}
.ghost:hover { color: var(--ink); border-color: var(--ink-faint); }

#theme-toggle { min-width: 2.5rem; text-align: center; }
#theme-toggle::after { content: var(--moon); }
:root[data-theme="light"] #theme-toggle::after { content: var(--sun); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) #theme-toggle::after { content: var(--sun); }
}

/* --- calendar ----------------------------------------------------------- */

.calendar { padding: 0 0 40vh; }   /* tail room so the last week can reach the top */

.week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  /* The gap is the grid. Showing through in --line rather than something
     barely off the background is what makes the table read as a table. */
  background: var(--line);
  border-bottom: 1px solid var(--line);
  min-height: max(150px, calc((100vh - var(--bar-h)) / var(--weeks-in-view)));
}

.day {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: .35rem .4rem .35rem;
  background: var(--cell);
  min-width: 0;
}
.day.weekend { background: var(--cell-weekend); }
.day.m1 { background: var(--cell-alt); }
.day.m1.weekend { background: var(--cell-alt-weekend); }
.day.today { box-shadow: inset 0 0 0 2px var(--accent); }

/* Lit up while a tile is hovering over this cell mid-drag. */
.day.drop-target { background: color-mix(in srgb, var(--cell) 80%, var(--accent)); }

/* Date on the left, weekday pinned to the right-hand corner. */
.day-head {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  font-variant-numeric: tabular-nums;
}
.dateiso { font-weight: 700; letter-spacing: -.02em; }
.day.today .dateiso { color: var(--accent); }
.dow { margin-left: auto; color: var(--ink-faint); font-size: .78rem; }

/* --- tiles -------------------------------------------------------------- */

.tiles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tile {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: .35rem;
  padding: .2rem .3rem;
  font-size: .82rem;
  line-height: 1.35;
  background: var(--bg-alt);
  border: 1px solid var(--line-soft);
  border-radius: 6px;
  cursor: grab;
  touch-action: pan-y;          /* a plain drag of the page still scrolls */
  user-select: none;
}
.tile:hover { border-color: var(--line); }
.tile:focus-visible, .tile.picked { outline: none; border-color: var(--accent); }
.tile.picked { box-shadow: 0 0 0 1px var(--accent); }

/* The one under your finger. Lifted out of flow and parked on the cursor. */
.tile.dragging {
  position: fixed;
  z-index: 200;
  cursor: grabbing;
  pointer-events: none;
  opacity: .92;
  box-shadow: 0 8px 22px var(--shadow);
  background: var(--pop);
  border-color: var(--accent);
}
/* Holds the gap open in the source list so nothing jumps while you drag. */
.tile.ghost { visibility: hidden; }
/* Where it would land. */
.tile-slot {
  height: 3px;
  margin: -1px 0;
  border-radius: 999px;
  background: var(--accent);
  list-style: none;
}

.box {
  flex: 0 0 auto;
  width: 15px; height: 15px;
  margin-top: 1px;
  border: 1.5px solid var(--ink-faint);
  border-radius: 4px;
  background: none;
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 11px;
  line-height: 1;
  padding: 0;
}
.box:hover { border-color: var(--accent); }
.s-done     .box { background: var(--good); border-color: var(--good); color: var(--accent-ink); }
.s-done     .box::after { content: "\2713"; }
.s-deferred .box { border-color: var(--warn); color: var(--warn); }
.s-deferred .box::after { content: "\203A"; font-weight: 700; }
.s-dropped  .box { border-color: var(--ink-faint); color: var(--ink-faint); }
.s-dropped  .box::after { content: "\2715"; }

/* Checked is a colour change, not a crossing-out: the words stay readable. */
.text { min-width: 0; overflow-wrap: anywhere; }
.s-done .text { color: var(--ink-dim); }
.s-deferred .text { color: var(--ink-dim); font-style: italic; }
.s-dropped .text { color: var(--ink-faint); }

/* How far this has drifted from the day it was written. Right-hand edge,
   always, so a column of them lines up and you can read the drift at a
   glance. The longer it follows you around, the louder it gets. */
.defer {
  flex: 0 0 auto;
  margin-left: auto;
  align-self: flex-start;
  font-size: .66rem;
  font-variant-numeric: tabular-nums;
  padding: 0 .3rem;
  border-radius: 999px;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  white-space: nowrap;
}
.defer.early { color: var(--ink-dim); border-color: var(--line); }
.defer.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.defer.bad  { color: var(--bad);  border-color: color-mix(in srgb, var(--bad) 45%, transparent); font-weight: 700; }

/* Double-click swaps the text for this, with everything selected. */
.tile-edit { flex: 1 1 auto; min-width: 0; }
.tile-edit input.edit {
  width: 100%;
  background: var(--pop);
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 0 .25rem;
  font-size: .82rem;
}
.tile-edit input.edit:focus { outline: none; }

/* --- add + notes -------------------------------------------------------- */

/* Always the last row of the list, so adding is where your eye already is. */
.add-tile { list-style: none; padding-top: .15rem; }
.add input {
  width: 100%;
  background: none;
  border: 1px dashed transparent;
  border-radius: 6px;
  padding: .15rem .3rem;
  font-size: .82rem;
  color: var(--ink);
}
.add input::placeholder { color: var(--ink-faint); }
.add input:hover { border-color: var(--line-soft); }
.add input:focus { outline: none; border-color: var(--line); border-style: solid; background: var(--bg-alt); }

/* Always open, never labelled, never resized by hand: JS sizes it to its
   text and then levels every box in the week row to the tallest one.
   margin-top:auto pins it to the floor of the cell, so a row of notes reads
   as one strip across the week however many tiles sit above them. */
.notes {
  width: 100%;
  margin-top: auto;
  background: var(--bg-alt);
  border: 1px solid var(--line-soft);
  border-radius: 6px;
  padding: .25rem .35rem;
  font-size: .76rem;
  line-height: 1.35;
  resize: none;
  overflow: hidden;
  min-height: 1.9rem;
}
.notes:focus { outline: none; border-color: var(--accent); }

/* --- sentinels ---------------------------------------------------------- */

.sentinel {
  padding: .6rem;
  text-align: center;
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* --- narrow: one day per row, still one continuous scroll --------------- */

@media (max-width: 899px) {
  .week {
    grid-template-columns: 1fr;
    min-height: 0;
    gap: 1px;
    position: relative;
  }
  .week::before {
    content: attr(data-month);
    display: block;
    position: sticky;
    top: var(--bar-h);
    z-index: 10;
    padding: .2rem .75rem;
    font-size: .68rem;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--ink-faint);
    background: var(--bg);
    border-bottom: 1px solid var(--line-soft);
  }
  .day { min-height: 3.1rem; padding: .5rem .75rem; }
  .day-head { font-size: .95rem; }
  .dow { font-size: .85rem; }
  .tile { font-size: .95rem; padding: .3rem .4rem; }
  .box { width: 20px; height: 20px; font-size: 13px; }
  .tile-edit input.edit, .add input { font-size: .92rem; padding: .2rem .3rem; }
  .notes { font-size: .88rem; }
  .month-label { display: none; }
}

/* --- reference pages ---------------------------------------------------- */

.ref { display: flex; gap: 1.5rem; padding: 1.25rem; align-items: flex-start; }
.ref-list { flex: 0 0 220px; position: sticky; top: calc(var(--bar-h) + 1rem); }
.ref-list h2 { font-size: .74rem; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-faint); margin: 0 0 .5rem; }
.ref-list ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .15rem; }
.ref-list a { color: var(--ink-dim); text-decoration: none; padding: .2rem .4rem; border-radius: 6px; display: block; }
.ref-list a:hover, .ref-list a.active { color: var(--ink); background: var(--cell); }

.ref-new input {
  width: 100%;
  margin-top: .6rem;
  background: none;
  border: 1px dashed var(--line);
  border-radius: 6px;
  padding: .25rem .4rem;
  color: var(--ink);
}
.ref-new input::placeholder { color: var(--ink-faint); }
.ref-new input:focus { outline: none; border-style: solid; border-color: var(--accent); }

.ref-main { flex: 1; min-width: 0; max-width: 52rem; }
.ref-body-wrap { width: 100%; }
.ref-body table { border-collapse: collapse; }
.ref-body th, .ref-body td { border: 1px solid var(--line); padding: .3rem .5rem; text-align: left; }
.ref-body pre { background: var(--cell); padding: .6rem; border-radius: 8px; overflow-x: auto; }
.ref-body code { background: var(--cell); padding: .05rem .25rem; border-radius: 4px; }
.ref-body pre code { background: none; padding: 0; }
.ref-body :first-child { margin-top: 0; }
.ref-body { cursor: text; }

.ref-edit { display: flex; flex-direction: column; gap: .5rem; }
.ref-edit textarea {
  width: 100%;
  min-height: 60vh;
  background: var(--cell);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: .6rem .7rem;
  line-height: 1.5;
  resize: vertical;
  tab-size: 2;
}
.ref-edit textarea:focus { outline: none; border-color: var(--accent); }
.ref-edit-actions { display: flex; align-items: center; gap: .5rem; }
.ref-edit-actions button {
  background: var(--bg-alt);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: .25rem .7rem;
  cursor: pointer;
  color: var(--ink-dim);
}
.ref-edit-actions button[type="submit"] { background: var(--accent); border-color: transparent; color: var(--accent-ink); font-weight: 700; }
.ref-edit-actions button:hover { color: var(--ink); }
.ref-edit-actions button[type="submit"]:hover { color: var(--accent-ink); }
.hint { font-size: .72rem; color: var(--ink-faint); }

.empty { color: var(--ink-faint); }

@media (max-width: 899px) { .ref { flex-direction: column; } .ref-list { position: static; flex: none; } }

/* --- oversight ---------------------------------------------------------- */

/* The calendar fakes its gridlines by letting a 1px gap show the container's
   background through. That trick does not survive being borrowed here: this
   grid has padding and an uneven number of cards, so the line colour flooded
   the padding ring and every empty grid area. Cards carry their own borders
   instead, and the container just sits on the page background. */
.oversight {
  padding: 1.25rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1rem;
  background: var(--bg);
}

.card {
  background: var(--cell);
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  padding: .9rem 1rem 1rem;
  min-width: 0;
}
.card.wide { grid-column: 1 / -1; }
.card h2 {
  margin: 0 0 .6rem;
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-faint);
  font-weight: 400;
}
.card .big { margin: 0; font-size: 1.6rem; font-weight: 700; letter-spacing: -.02em; }
.card .note { margin: .3rem 0 0; font-size: .74rem; color: var(--ink-dim); overflow-wrap: anywhere; }
.card .good { color: var(--good); }
.card .warn { color: var(--warn); }
.card .bad  { color: var(--bad); }

/* The backup card earns an edge; it's the only one that can cost you data. */
.card.backup { box-shadow: inset 3px 0 0 var(--good); }
.card.backup.alarm { box-shadow: inset 3px 0 0 var(--bad); }

.pairs {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .15rem .7rem;
  margin: .7rem 0 0;
  font-size: .76rem;
}
.pairs dt { color: var(--ink-faint); }
.pairs dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

.plain { list-style: none; margin: .7rem 0 0; padding: 0; font-size: .76rem; display: flex; flex-direction: column; gap: .2rem; }
.plain .age { font-variant-numeric: tabular-nums; color: var(--ink-faint); margin-right: .3rem; }
.plain .age.warn { color: var(--warn); }
.plain .age.bad { color: var(--bad); }
.plain .where { float: right; color: var(--ink-faint); text-decoration: none; }
.plain .where:hover { color: var(--accent); }

/* Named `meter`, not `bar`. It used to be `.bar`, which is also the sticky
   header -- same specificity, declared later, so the header quietly inherited
   `height: .55rem` and collapsed. Two different things, two names. */
.bars { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .25rem; font-size: .76rem; }
.bars li { display: grid; grid-template-columns: 3.6rem 1fr 2.5rem; align-items: center; gap: .5rem; }
.bar-label { color: var(--ink-dim); }
.meter { background: var(--bg-alt); border-radius: 999px; height: .55rem; overflow: hidden; }
.meter i { display: block; height: 100%; background: var(--accent); }
.bar-value { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-dim); }

/* A subcategory inside a card: the label and its own total on one line, the
   verbs underneath. The totals are what you read across groups; the bars are
   on one shared scale so four note edits look like four of anything else. */
.group + .group { margin-top: .7rem; }
.group h3 {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  margin: 0 0 .3rem;
  font-size: .76rem;
  font-weight: 700;
  color: var(--ink-dim);
}
.group h3 span { margin-left: auto; color: var(--ink); font-variant-numeric: tabular-nums; }

/* Contribution grid: a column per week, read left to right like a calendar. */
.heat { display: flex; gap: 2px; overflow-x: auto; padding-bottom: .2rem; }
.heat-col { display: flex; flex-direction: column; gap: 2px; }
.heat-cell { width: 11px; height: 11px; border-radius: 2px; background: var(--bg-alt); }
.heat-cell.future { background: none; box-shadow: inset 0 0 0 1px var(--line-soft); }
.heat-cell.l1 { background: color-mix(in srgb, var(--accent) 28%, var(--bg-alt)); }
.heat-cell.l2 { background: color-mix(in srgb, var(--accent) 52%, var(--bg-alt)); }
.heat-cell.l3 { background: color-mix(in srgb, var(--accent) 76%, var(--bg-alt)); }
.heat-cell.l4 { background: var(--accent); }

.hours { display: flex; align-items: flex-end; gap: 1px; height: 46px; margin-top: .8rem; }
.hours i { flex: 1; min-height: 1px; background: var(--accent); border-radius: 1px 1px 0 0; opacity: .8; }
.scale { display: flex; justify-content: space-between; font-variant-numeric: tabular-nums; }

@media (max-width: 899px) {
  .oversight { padding: .75rem; gap: .75rem; grid-template-columns: 1fr; }
}

/* --- toast -------------------------------------------------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  transform: translateX(-50%);
  background: var(--pop);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .35rem .85rem;
  font-size: .8rem;
  color: var(--ink-dim);
  box-shadow: 0 6px 20px var(--shadow);
  z-index: 100;
}
.toast[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto !important; }
}
