/* ---------------------------------------------------------------------------
   tasks.css — AREA: TASKS  (owns js/ui/tasks.js, css/tasks.css)

   The task list, the task editor, the projects grid and the tags manager.
   Declares NO custom property: every value comes from tokens.css. The one
   thing set from outside is --dot, written inline by tasks.js and carrying a
   project's or a tag's own colour — user data that must survive a theme
   change, exactly like --bar-progress or --ring-progress elsewhere. Every
   rule here reads it with a fallback, so an element without one still paints.

   Naming: .tasks-<block>[__<element>][--<modifier>], plus .task-… for the
   editor and .project-… / .tag-… for the two managers.

   Motion: base.css already flattens every transition under reduced motion, so
   the gestures keep working and only the easing goes. The two places where
   the still version needs a different *design* rather than a shorter one are
   at the foot of this file.
--------------------------------------------------------------------------- */

/* =========================================================================
   THE COLOURED PROJECT MARK
   Shared by the row, the grid, the detail hero and the archived list.
   ========================================================================= */
.tasks-mark {
  flex: none;
  width: 44px; height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--dot, var(--c-accent)) 15%, var(--c-surface));
  color: var(--dot, var(--c-accent));
  border: var(--bw) solid color-mix(in srgb, var(--dot, var(--c-accent)) 24%, transparent);
  transition: transform var(--d-2) var(--e-spring);
}
.tasks-mark--sm { width: 32px; height: 32px; }
.tasks-mark--lg { width: 56px; height: 56px; }

/* A mid-tone hex on a near-black surface loses too much contrast, so the ink
   is lifted and the wash deepened rather than left to chance. */
:root[data-mode="dark"] .tasks-mark {
  background: color-mix(in srgb, var(--dot, var(--c-accent)) 24%, var(--c-surface));
  color: color-mix(in srgb, var(--dot, var(--c-accent)) 68%, #ffffff);
}

/* =========================================================================
   TOOLBAR — search, tabs, filter chips
   Sticky at the top of the scrolling screen. Genuinely opaque, because the
   rows pass underneath it — a blurred 92% wash bought nothing visible and made
   the phone re-read the strip beneath the bar on every scroll frame.
   ========================================================================= */
.tasks-toolbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding-block: var(--sp-2) var(--sp-3);
  background: var(--c-bg);
}

.tasks-search {
  position: relative;
  display: flex;
  align-items: center;
  animation: fx-rise var(--d-2) var(--e-out);
}
.tasks-search__icon {
  position: absolute;
  inset-inline-start: var(--sp-3);
  display: flex;
  color: var(--c-ink-3);
  pointer-events: none;
}
/* The end padding clears the clear button, which is a full --tap wide. */
.tasks-search__input { padding-inline: var(--sp-8) var(--sp-9); }
.tasks-search__clear {
  position: absolute;
  inset-inline-end: 2px;
}

/* The shared segment is 38px; these two are the screen's primary control and
   have to clear the 44px hit area like everything else. */
.tasks-tabs .c-seg__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap);
}
.tasks-tabs__count {
  min-width: 20px;
  padding-inline: 5px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, currentColor 15%, transparent);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
}

.tasks-filters { padding-block: 2px; }
.tasks-filters > .c-chip { flex: none; }

/* =========================================================================
   THE LIST
   ========================================================================= */
.tasks-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.tasks-item {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-card);
  /* Only the FLIP of a displaced neighbour uses this; the row under the
     finger switches it off so it never lags behind the pointer. */
  transition: transform var(--d-2) var(--e-out);
}
.tasks-item.is-dragging {
  transition: none;
  z-index: var(--z-raised);
  overflow: visible;
}
.tasks-item.is-dragging .tasks-card {
  box-shadow: var(--sh-3);
  transform: scale(1.02);
  cursor: grabbing;
  /* The hint belongs to the one row being moved, not to all of them. */
  will-change: transform;
}

/* ---- the swipe hint layer ------------------------------------------------ */
.tasks-swipe {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: space-between;
  border-radius: inherit;
  overflow: hidden;
}
.tasks-swipe__side {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding-inline: var(--sp-4);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  opacity: 0;
  transform: scale(0.9);
  transition: opacity var(--d-2) var(--e-out), transform var(--d-2) var(--e-spring);
}
.tasks-swipe__side--start {
  background: var(--c-accent-soft);
  color: var(--c-accent-deep);
  flex: 1 1 50%;
}
.tasks-swipe__side--end {
  background: var(--c-ok-soft);
  color: var(--c-ok);
  flex: 1 1 50%;
  justify-content: flex-end;
}
.tasks-item[data-swipe="start"] .tasks-swipe__side--start,
.tasks-item[data-swipe="end"] .tasks-swipe__side--end { opacity: 0.6; }
.tasks-item[data-armed="true"][data-swipe="start"] .tasks-swipe__side--start,
.tasks-item[data-armed="true"][data-swipe="end"] .tasks-swipe__side--end {
  opacity: 1;
  transform: scale(1.04);
}

/* ---- the card ------------------------------------------------------------ */
.tasks-card {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 68px;
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-surface);
  border: var(--card-border);
  border-radius: var(--r-card);
  box-shadow: var(--sh-card);
  touch-action: pan-y;          /* the horizontal axis belongs to the swipe */
}
.tasks-card.is-settling { transition: transform var(--d-3) var(--e-out), box-shadow var(--d-2) var(--e-out); }

/* The leading notch. No project means no --dot, and the fallback makes the
   strip disappear rather than pick a colour that means nothing. */
.tasks-card::before {
  content: "";
  position: absolute;
  inset-block: var(--sp-3);
  inset-inline-start: 0;
  width: 3px;
  border-radius: var(--r-pill);
  background: var(--dot, transparent);
}

.tasks-card__mark {
  position: relative;
  flex: none;
  width: 44px; height: 44px;
  border-radius: var(--r-pill);
}
.tasks-card__tick {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: inherit;
  background: var(--c-accent);
  color: var(--c-accent-ink);
  opacity: 0;
  transform: scale(0.55);
  transition: opacity var(--d-2) var(--e-out), transform var(--d-2) var(--e-spring);
}
.tasks-card__mark:hover .tasks-card__tick,
.tasks-card__mark:focus-visible .tasks-card__tick { opacity: 0.92; transform: scale(1); }
.tasks-card__mark:active .tasks-mark { transform: scale(0.9); }
.tasks-item.is-done .tasks-card__tick {
  opacity: 1;
  transform: scale(1);
  background: var(--c-ok);
  color: var(--c-ink-inv);
}

.tasks-card__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  min-height: 44px;
  padding-block: var(--sp-1);
  text-align: start;
  color: inherit;
  border-radius: var(--r-sm);
}
.tasks-card__title {
  width: 100%;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-tight);
}
.tasks-card__meta {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  font-size: var(--fs-xs);
  color: var(--c-ink-3);
}
.tasks-card__pomo { display: inline-flex; align-items: center; gap: 4px; }
.tasks-card__pomo > svg { width: 13px; height: 13px; }
.tasks-card__when { width: 100%; }

.tasks-card__tags { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.tasks-card__tag {
  padding: 1px 8px;
  border-radius: var(--r-pill);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  background: color-mix(in srgb, var(--dot, var(--c-accent)) 14%, transparent);
  color: color-mix(in srgb, var(--dot, var(--c-accent)) 72%, var(--c-ink));
}

.tasks-card__bar.c-bar {
  width: 100%;
  height: 4px;
  margin-top: 3px;
}

.tasks-card__play.c-btn--icon {
  flex: none;
  background: var(--c-accent-soft);
  color: var(--c-accent-deep);
  border-color: var(--c-accent-line);
}
.tasks-card__play.c-btn--icon:hover:not(:disabled) {
  background: var(--c-accent);
  color: var(--c-accent-ink);
  transform: scale(1.06);
}

/* The finished row keeps its shape and loses its weight. */
.tasks-item.is-done .tasks-card { background: var(--c-surface-2); box-shadow: none; }
.tasks-item.is-done .tasks-card__title { text-decoration: line-through; color: var(--c-ink-3); }
.tasks-item.is-done .tasks-mark { opacity: 0.55; }

/* ---- grouping and the tail ----------------------------------------------- */
.tasks-group {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-1) var(--sp-1);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-ink-3);
}
.tasks-group:first-child { padding-top: 0; }
.tasks-group__dot {
  width: 8px; height: 8px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--c-line-strong);
}
.tasks-group__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tasks-group__count { margin-inline-start: auto; }

.tasks-more { padding-top: var(--sp-2); }

/* The shell's .c-fab is absolute, which inside a scrolling screen parks it at
   the bottom of the CONTENT. Fixed keeps it where a FAB belongs; the offsets
   it already carries are measured from the same viewport. */

/* =========================================================================
   THE EDITOR
   ========================================================================= */
.tasks-editor { gap: var(--sp-5); }
.tasks-counter { align-self: flex-end; font-variant-numeric: tabular-nums; }
.tasks-editor__tagfield { margin-top: var(--sp-1); }
.tasks-editor__stats .c-stat__value { font-size: var(--fs-lg); }
.tasks-editor__delete { margin-top: var(--sp-2); }

/* The "new project" / "new tag" chips read as an invitation, not a state. */
.tasks-chip--add {
  border-style: dashed;
  color: var(--c-ink-3);
}
.tasks-chip--add:hover { color: var(--c-accent); border-color: var(--c-accent-line); }

/* =========================================================================
   MENU SHEETS
   ========================================================================= */
.tasks-menu__row { min-height: var(--tap); }
.tasks-menu__row.is-danger { color: var(--c-danger); }
.tasks-menu__row.is-danger .c-row__meta { color: color-mix(in srgb, var(--c-danger) 70%, var(--c-ink-3)); }

/* =========================================================================
   PROJECTS
   ========================================================================= */
.project-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
}
.project-grid > .c-empty { grid-column: 1 / -1; }

.project-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
  padding: var(--sp-4);
  text-align: start;
  background: var(--c-surface);
  border: var(--card-border);
  border-radius: var(--r-card);
  box-shadow: var(--sh-card);
  transition: transform var(--d-2) var(--e-out), box-shadow var(--d-2) var(--e-out);
}
/* A wash of the project's own colour, top-down, so the grid reads as a set of
   identities rather than a set of boxes. */
.project-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 76px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--dot, var(--c-accent)) 18%, transparent), transparent);
  pointer-events: none;
}
.project-card:hover { transform: translateY(-2px); box-shadow: var(--sh-3); }
.project-card:active { transform: translate(var(--btn-translate), var(--btn-translate)); box-shadow: var(--sh-press); }
.project-card > * { position: relative; }

.project-card__head { display: flex; align-items: center; justify-content: space-between; width: 100%; }
.project-card__pct {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--c-ink-3);
}
.project-card__name {
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
  line-height: var(--lh-snug);
}
.project-card__meta { font-size: var(--fs-xs); color: var(--c-ink-3); }
.project-card__time {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: color-mix(in srgb, var(--dot, var(--c-accent)) 78%, var(--c-ink));
}
.project-card__bar.c-bar { width: 100%; height: 4px; margin-top: auto; }

.project-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-6) var(--sp-4);
  border-radius: var(--r-xl);
  border: var(--card-border);
  background:
    radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--dot, var(--c-accent)) 26%, transparent), transparent 70%),
    var(--c-surface);
  box-shadow: var(--sh-card);
  text-align: center;
}
.project-hero__name {
  font-size: var(--fs-xl);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
}
.project-hero__meta { font-size: var(--fs-sm); color: var(--c-ink-2); }

.project-archived { border-top: var(--bw) solid var(--c-line); padding-top: var(--sp-3); }
.project-archived__head {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--c-ink-2);
  list-style: none;
}
.project-archived__head::-webkit-details-marker { display: none; }
.project-archived[open] .project-archived__head { margin-bottom: var(--sp-2); }

.project-icons {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-2);
}
.project-icons__btn {
  min-height: var(--tap);
  display: grid;
  place-items: center;
  border-radius: var(--r-md);
  border: var(--bw) solid var(--c-line);
  background: var(--c-surface-2);
  color: var(--c-ink-2);
  transition: background var(--d-2) var(--e-out), color var(--d-2) var(--e-out), transform var(--d-1) var(--e-spring);
}
.project-icons__btn:hover { color: var(--c-ink); background: var(--c-surface-sunken); }
.project-icons__btn:active { transform: scale(0.94); }
.project-icons__btn[aria-pressed="true"] {
  background: var(--c-accent-soft);
  border-color: var(--c-accent-line);
  color: var(--c-accent-deep);
}

.project-delete__option {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  min-height: var(--tap);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  border: var(--bw) solid var(--c-line);
  cursor: pointer;
}
.project-delete__option:has(input:checked) {
  border-color: var(--c-accent);
  background: var(--c-accent-softer);
}
.project-delete__option > .c-select { flex: 1 1 100%; }

/* =========================================================================
   THE 14-DAY SPARKLINE
   Fourteen numbers do not need an SVG, and they must stay legible at 150px.
   ========================================================================= */
.tasks-spark {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  width: 100%;
  height: 20px;
}
.tasks-spark__bar {
  flex: 1 1 0;
  min-width: 2px;
  height: max(2px, var(--h, 0%));
  border-radius: 2px;
  background: var(--c-track);
}
.tasks-spark__bar[data-on="true"] {
  background: color-mix(in srgb, var(--dot, var(--c-accent)) 65%, transparent);
}

/* =========================================================================
   TAGS
   ========================================================================= */
.tag-list { gap: var(--sp-2); }

.tag-row__dot {
  width: 16px; height: 16px;
  border-radius: var(--r-pill);
  background: var(--dot, var(--c-accent));
  border: var(--bw) solid color-mix(in srgb, var(--dot, var(--c-accent)) 60%, var(--c-ink));
}
.tag-row__name {
  text-align: start;
  color: inherit;
  min-height: var(--tap);
  justify-content: center;
  border-radius: var(--r-sm);
}
.tag-row__input { min-height: 38px; }

.tag-create {
  display: flex;
  align-items: center;
  flex-wrap: wrap;      /* at 360 the button drops to its own line */
  gap: var(--sp-2);
  padding: var(--sp-3);
  border: var(--bw) dashed var(--c-line-strong);
  border-radius: var(--r-card);
  background: var(--c-surface-2);
}
.tag-create > .c-input { flex: 1 1 9rem; min-width: 0; }
.tag-create > .c-btn { flex: 1 1 auto; }
.tag-create__color {
  flex: none;
  width: var(--tap); height: var(--tap);
  border-radius: var(--r-pill);
  background: var(--dot, var(--c-accent));
  border: var(--bw) solid var(--c-line-strong);
  transition: transform var(--d-1) var(--e-spring), background var(--d-2) var(--e-out);
}
.tag-create__color:hover { transform: scale(1.06); }
.tag-create__color:active { transform: scale(0.94); }

/* =========================================================================
   WIDER THAN A PHONE
   ========================================================================= */
@media (min-width: 600px) {
  .tasks-card { min-height: 74px; padding-inline: var(--sp-4); }
  .project-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Below the design width the grid has to give way before the text does. */
@media (max-width: 359px) {
  .project-grid { grid-template-columns: minmax(0, 1fr); }
  .tasks-card { gap: var(--sp-2); padding-inline: var(--sp-2); }
}

/* =========================================================================
   STILL EQUIVALENTS
   base.css already collapses every duration, so the gestures keep working and
   only the easing goes. These two need a different design rather than a
   shorter one: the swipe hint has to be legible without the scale-up that
   normally announces it, and the drag lift has to be visible without the
   scale that normally carries it.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) .tasks-swipe__side { opacity: 0.85; transform: none; }
  :root:not([data-motion="full"]) .tasks-item.is-dragging .tasks-card {
    transform: none;
    outline: 2px solid var(--c-accent);
    outline-offset: 2px;
  }
}
:root[data-motion="reduced"] .tasks-swipe__side { opacity: 0.85; transform: none; }
:root[data-motion="reduced"] .tasks-item.is-dragging .tasks-card {
  transform: none;
  outline: 2px solid var(--c-accent);
  outline-offset: 2px;
}
