/* css/task.css
 *
 * A task row wherever it appears: day groups, part-of-day labels, badges,
 * checklists, the add bar and the empty states.
 */

/* ---- day groups & tasks ------------------------------------------------
 * Rows sit in one grouped container with hairline separators, the way a
 * native list does — not as separate floating cards. Chrome recedes, the
 * titles carry the page.
 * --------------------------------------------------------------------- */
.day-group { margin-top: 22px; }
.day-group:first-child { margin-top: 2px; }
.day-label {
  display: flex; align-items: baseline; gap: 8px; margin: 0 0 7px 3px;
}
.day-label .d-title { font-size: 0.9286em; font-weight: 590; color: var(--text-2); }
.day-label .d-date {
  font-size: 0.8214em; color: var(--text-3); font-variant-numeric: tabular-nums;
}
.day-label.is-today .d-title { color: var(--accent); }
.day-label .d-count {
  margin-left: auto; font-size: 0.8214em; color: var(--text-3);
  font-variant-numeric: tabular-nums;
}

/* Part-of-day heading. Sits between the day label and its list, so it has to
   read as subordinate to the day — smaller, tertiary, and tighter to the
   rows it introduces than to the block above it. */
.tod-label {
  font-size: 0.7857em; font-weight: 590; color: var(--text-3);
  text-transform: uppercase; letter-spacing: .05em;
  margin: 14px 0 5px 3px;
}
/* The first label in a day hugs the day header; only labels that FOLLOW a
   list need the gap. `:first-of-type` cannot express this — the first label
   in the DOM is often the second part of the day (the unlabelled block emits
   no heading), and the sibling rule below outranks it anyway. */
.day-label + .tod-label { margin-top: 0; }

ul.tasks {
  list-style: none; margin: 0; padding: 0;
  background: var(--canvas); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden;
}
ul.tasks + .tod-label { margin-top: 14px; }
li.task {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 11px 12px 11px 14px;
  position: relative;
  /* Own stacking/clip context so the highlight bar is cut by this row's box
     rather than escaping past the list's rounded corners. */
  overflow: hidden;
  transition: opacity .2s, transform .2s, background .12s;
}
li.task + li.task { border-top: .5px solid var(--sep-soft); }
li.task:hover { background: var(--fill); }
li.task .hl-bar {
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: transparent;
}
li.task .check {
  flex: 0 0 auto; width: 21px; height: 21px; border-radius: 50%;
  border: 1.5px solid var(--sep); background: transparent; cursor: pointer;
  display: grid; place-items: center; margin-top: 1px;
  transition: background .14s, border-color .14s;
}
li.task .check:hover { border-color: var(--accent); }
li.task .check:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
li.task.done .check { background: var(--accent); border-color: var(--accent); }
li.task .check svg {
  width: 12px; height: 12px; opacity: 0; transform: scale(.6);
  transition: opacity .14s, transform .14s;
}
li.task.done .check svg { opacity: 1; transform: scale(1); }
li.task .body { flex: 1 1 auto; min-width: 0; }
li.task .title { font-size: 1.0357em; word-break: break-word; line-height: 1.35; }
li.task.done .title { color: var(--text-3); text-decoration: line-through; }
li.task .meta {
  font-size: 0.8214em; color: var(--text-3); margin-top: 1px;
  display: flex; gap: 10px; flex-wrap: wrap;
}
li.task .meta .time { color: var(--text-2); font-variant-numeric: tabular-nums; }
li.task .del {
  flex: 0 0 auto; background: none; color: var(--text-3); padding: 2px 7px;
  font-size: 1.3571em; line-height: 1; border-radius: 6px; box-shadow: none;
  opacity: 0; transition: opacity .12s, color .12s, background .12s;
}
li.task:hover .del, li.task .del:focus-visible { opacity: 1; }
li.task .del:hover:not(:disabled) {
  color: var(--danger); background: var(--fill); filter: none;
}
/* Skipped: dimmed but NOT struck through — the phone distinguishes "passed
   over" from "finished", and reusing the done styling would erase that. The
   word carries the meaning; the dimming alone would be colour-only. */
li.task.skipped .title { color: var(--text-2); }
.tag-skipped {
  font-size: 0.75em; font-weight: 590; letter-spacing: .03em;
  text-transform: uppercase; color: var(--text-3);
}
/* A habit repeats — the phone marks that with a dashed ring instead of a
   solid one, so the two read apart at a glance rather than by badge alone. */
li.task .check.habit {
  border-style: dashed; border-width: 1.5px;
}
li.task.done .check.habit { border-style: solid; }

/* Markers (holidays, namedays, folk observances) are facts about the day, not
   work. No checkbox, no delete — tapping either would mean nothing. */
li.task .lead {
  flex: 0 0 auto; width: 21px; height: 21px; display: grid; place-items: center;
  margin-top: 1px; font-size: 1.0em; line-height: 1;
}
li.task.is-marker .title { color: var(--text-2); }

/* Badges. Small, quiet, and after the title — they qualify the task, they are
   not the task. Kept on one line with the title so a row stays one line. */
.badges { display: inline-flex; gap: 5px; align-items: baseline; vertical-align: baseline; }
.bdg {
  font-size: 0.75em; line-height: 1.5; white-space: nowrap;
  font-variant-numeric: tabular-nums; color: var(--text-3);
}
.bdg.bday { color: #d1699a; }
.bdg.list {
  padding: 0 5px; border-radius: 5px; background: var(--fill);
  font-weight: 590; font-size: 0.7143em;
}
.bdg.list.all { color: var(--ok); }
.bdg.habit.multi {
  padding: 0 5px; border-radius: 5px; background: var(--fill); font-weight: 590;
}
li.task.done .bdg, li.task.skipped .bdg { color: var(--text-3); }

/* Notes preview: one clamped line. The phone shows the note in the detail
   sheet; here it earns its place only as a hint of what the task is about. */
li.task .meta .note {
  color: var(--text-3); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 100%; flex: 1 1 auto; min-width: 0;
}

/* Checklist items, expanded inline as on the phone. Read-only: there is no
   per-item push on the web, and a checkbox that silently does nothing is
   worse than no checkbox at all. */
ul.subitems { list-style: none; margin: 6px 0 1px; padding: 0; display: flex; flex-direction: column; gap: 3px; }
ul.subitems li {
  display: flex; align-items: center; gap: 7px;
  font-size: 0.8929em; color: var(--text-2);
}
ul.subitems li .box {
  flex: 0 0 auto; width: 12px; height: 12px; border-radius: 3.5px;
  border: 1.5px solid var(--sep); position: relative;
}
ul.subitems li.on .box { background: var(--ok); border-color: var(--ok); }
ul.subitems li.on .box::after {
  content: ""; position: absolute; left: 3px; top: .5px;
  width: 3px; height: 6.5px; border: solid #fff; border-width: 0 1.6px 1.6px 0;
  transform: rotate(42deg);
}
ul.subitems li.on { color: var(--text-3); text-decoration: line-through; }

li.task.pending { opacity: .5; }
li.task.leaving { opacity: 0; transform: translateX(12px); }
/* Touch has no hover, so a permanently invisible delete button would be
   unreachable there. */
@media (hover: none) { li.task .del { opacity: 1; } }

.empty {
  text-align: center; color: var(--text-2); padding: 48px 24px; font-size: 1.0em;
  background: var(--canvas); border-radius: var(--radius); box-shadow: var(--shadow);
}
.empty .big { font-size: 2.1429em; margin-bottom: 10px; }
/* The habits-but-no-tasks line. Deliberately quieter than a full empty day:
   the rings above already carry the day, so this is a caption confirming
   there is nothing further, not a card competing with them. */
.empty.soft {
  background: none; box-shadow: none; padding: 22px 16px;
  color: var(--text-3); font-size: 0.95em; text-align: left;
}
/* The 48px above is scaled for the day view's full pane. In a 460px sheet it
   is most of the dialog, so an empty day reads as a large void with a bird. */
.daysheet .empty { padding: 26px 20px; }
.daysheet .empty .big { font-size: 1.7em; margin-bottom: 6px; }

/* ---- add bar -----------------------------------------------------------
 * Pinned to the foot of the MAIN COLUMN, not the viewport: in a three-pane
 * window a viewport-fixed bar would run under the sidebar and the digest.
 * -------------------------------------------------------------------- */
.addbar {
  flex: 0 0 auto; z-index: 5;
  background: color-mix(in srgb, var(--chrome) 85%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  border-top: .5px solid var(--sep);
  padding: 10px 20px calc(10px + env(safe-area-inset-bottom));
}
/* Matches whatever the surface above it is: the day's 720px reading measure,
   centred on the column it adds to; the full pane on a grid, where the
   content is not capped either. */
.addbar .inner { display: flex; gap: 9px; margin-inline: auto; }
body.view-day .addbar .inner,
body.view-list .addbar .inner { max-width: 720px; }
.addbar input { flex: 1 1 auto; min-width: 0; font-size: 1.0em; padding: 8px 11px; }
.addbar button { flex: 0 0 auto; }
/* The parser's live crumb ("→ пт, 5 сент · 15:00"). Inside the row, between
   box and button, so the eye meets it on the way to Add — a floating hint
   above the bar read as a tooltip for something else. */
.addbar .addhint {
  flex: 0 0 auto; align-self: center; white-space: nowrap;
  font-size: 0.82em; font-weight: 550; color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  padding: 4px 9px; border-radius: 7px;
  font-variant-numeric: tabular-nums;
}
.addbar .addhint.hidden { display: none; }

/* ---- misc -------------------------------------------------------------- */
.spin {
  display: inline-block; width: 13px; height: 13px; vertical-align: -2px;
  border: 2px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-top-color: var(--accent); border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* Clamping duration alone is not enough: an `infinite` animation at .01ms is
   ~100k iterations a second, which turns the sync spinner into a strobe —
   worse for the people this query exists to protect than the motion it
   replaced. Pinning the iteration count is what actually stops it. */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  /* The spinner conveys "still working", so it cannot just stop dead — a
     static ring reads as a frozen app. Slowed right down instead. */
  .spin { animation: spin 2.4s linear infinite !important; }
}
.hidden { display: none !important; }
.banner {
  margin: 0 0 14px; padding: 10px 13px; border-radius: var(--radius-sm);
  font-size: 0.9286em; display: flex; align-items: center; gap: 9px;
}
.banner.warn {
  background: color-mix(in srgb, var(--danger) 12%, var(--canvas));
  color: var(--danger);
  box-shadow: 0 0 0 .5px color-mix(in srgb, var(--danger) 30%, transparent);
}
.banner.info {
  background: var(--canvas); color: var(--text-2); box-shadow: var(--shadow);
}

/* ======================================================================
 * Calendar views — List / Month / Week
 * ==================================================================== */

/* ---- view switcher (segmented control) --------------------------------- */
.segmented {
  display: flex; padding: 2px; gap: 2px; flex: none;
  background: var(--fill); border-radius: 7px;
}
.segmented button {
  font: inherit; font-size: 0.8929em; font-weight: 500; padding: 3px 12px;
  border-radius: 5px; border: 0; cursor: pointer; white-space: nowrap;
  background: transparent; color: var(--text-2); box-shadow: none;
}
.segmented button[aria-pressed="true"] {
  background: var(--canvas); color: var(--text); box-shadow: var(--shadow);
}
.segmented button:hover:not([aria-pressed="true"]) { color: var(--text); filter: none; }

/* Period stepper: ‹ › Today, at the head of the toolbar. */
.periodnav { display: flex; align-items: center; gap: 4px; flex: none; }
.periodnav .step {
  width: 26px; height: 24px; border-radius: 6px; border: 0; cursor: pointer;
  background: transparent; color: var(--text-2); box-shadow: none;
  display: grid; place-items: center; padding: 0;
}
.periodnav .step:hover:not(:disabled) { background: var(--fill); color: var(--text); filter: none; }
.periodnav .step svg { width: 13px; height: 13px; }
.periodnav .todaybtn {
  font: inherit; font-size: 0.8929em; font-weight: 500; padding: 3px 10px;
  border-radius: 6px; cursor: pointer; color: var(--text);
  background: var(--canvas); border: .5px solid var(--sep); box-shadow: none;
  white-space: nowrap;
}
.periodnav .todaybtn:hover { filter: none; background: var(--fill); }

.searchbox {
  display: flex; align-items: center; gap: 7px;
  background: var(--fill); border-radius: 8px; padding: 0 10px;
  height: 30px; color: var(--text-3);
  /* `min-width` here forced the bar wider than the viewport on a phone: once
     it wrapped, `margin-left: auto` still pushed it right and 150px of it hung
     off the edge, taking the whole page into horizontal scroll. A basis with
     shrink allowed keeps it inside. */
  flex: 0 1 168px; min-width: 0; max-width: 100%;
}
.searchbox svg { width: 13px; height: 13px; flex: 0 0 auto; }
.searchbox input {
  font: inherit; font-size: 0.9286em; border: 0; outline: 0; background: transparent;
  color: var(--text); width: 100%; padding: 0; min-width: 0; box-shadow: none;
}
.searchbox input::placeholder { color: var(--text-3); }
/* Safari paints its own clear button and magnifier inside type=search. */
.searchbox input::-webkit-search-decoration,
.searchbox input::-webkit-search-cancel-button { -webkit-appearance: none; }
.searchbox:focus-within { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }

/* ---- day view ----------------------------------------------------------
 * The day column bleeds to the edges of the main scroller (negative margins
 * cancel its padding) so the day header's hairline runs the full width, the
 * way it does in the mockup — while the rows inside keep the padding.
 * -------------------------------------------------------------------- */
/* The day's own masthead. It is the largest type in the app on purpose: with
   no titlebar this is where you look to know what day you are on. */
