/* todo.chhlee.com. Paper and ink, the same language as write.chhlee.com: a serif for the words that
   matter, a small grey sans for everything else, text links instead of buttons, no boxes.
   A sidebar of areas on the left; one area (or all of them) in the pane on the right. */

:root {
  --bg: #fafafa;
  --ink: #1a1a1a;
  --muted: #737373;
  --faint: #dcdcdc;
  --hover: #efefef;
  --ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  /* Display font (wordmark, titles, task names). Was a serif; now the same sans as the UI (2026-09-19). */
  --text: var(--ui);
  --ok: #4f9a5e;      /* ready, done arrows */
  --warn: #c98a5a;    /* blocked */
  --late: #b8473a;    /* overdue */
  --pri-high: #b8473a; --pri-medium: #c98a5a; --pri-low: #a3a3a3;   /* priority marks; low sits quietly */
  --snap: #c93aa0;    /* snapping guides on the flow */
  --ok-tint: color-mix(in srgb, var(--ok) 10%, transparent);
  --warn-tint: color-mix(in srgb, var(--warn) 12%, transparent);
  /* Status chips in the list: a tinted pill per status, text dark enough to read on its own tint
     (every pair clears 4.5:1 in both themes, checked 2026-09-19). */
  --st-queued-bg: #e9e9e9; --st-queued-fg: #5a5a5a;
  --st-doing-bg: #dde7f3; --st-doing-fg: #2c5686;
  --st-done-bg: #dfeade; --st-done-fg: #356c44;
  --st-blocked-bg: #f5e2d3; --st-blocked-fg: #8a4c22;
  /* Box colours: eight tints spaced round the wheel, the same set write.chhlee.com uses for rhymes */
  --c1: #f2b8b8; --c2: #f3cc9f; --c3: #e9dc8a; --c4: #badca6;
  --c5: #a6dccf; --c6: #b0ccf1; --c7: #cdbff3; --c8: #ecb9dc;
  /* Boxes (flow boxes, timeline bars) sit on a slightly darker paper than the page, so they stand out. Text inside
     a box uses the on-fill colours: each passes 4.5:1 on the box and on every one of the eight colours (checked
     2026-09-18), where the page's grey and priority colours fell to 2.3 to 3.6 on the tints. */
  --node-bg: #ececec; --node-border: #cbcbcb;
  --on-fill-meta: #4a4a4a; --on-fill-high: #862519; --on-fill-medium: #6b420c; --on-fill-low: #4a4a4a;
  --ease: cubic-bezier(.2, .7, .2, 1); --fast: .18s; --mid: .32s; --slow: .5s;
  /* Other people, live: one colour each (picked from their account id), the same on everyone's screen. White
     text on every one clears 4.5:1, and each stands out on the light and the dark paper. */
  --live-1: #c2410c; --live-2: #1d4ed8; --live-3: #047857; --live-4: #7e22ce; --live-5: #be123c; --live-6: #0e7490;
  color-scheme: light;
}
/* Light is the default; dark only when chosen with the theme disc (kept in localStorage as todo:theme). */
:root[data-theme="dark"] {
  --bg: #151515; --ink: #e8e8e8; --muted: #8f8f8f; --faint: #333333; --hover: #222222;
  --ok: #6fbf7e; --warn: #c9895f; --late: #e0705f;
  --pri-high: #e0705f; --pri-medium: #d9a15e; --pri-low: #6e6e6e;
  --snap: #ff7ad0;
  --c1: #6e2f2f; --c2: #6d4524; --c3: #5f561c; --c4: #2f5128;
  --c5: #1f4e46; --c6: #264264; --c7: #41326b; --c8: #5e2c52;
  --node-bg: #222222; --node-border: #3d3d3d;
  --on-fill-meta: #d2d2d2; --on-fill-high: #ffc6bd; --on-fill-medium: #f5d49f; --on-fill-low: #d2d2d2;
  --st-queued-bg: #282828; --st-queued-fg: #a6a6a6;
  --st-doing-bg: #21344b; --st-doing-fg: #a2c6ec;
  --st-done-bg: #213527; --st-done-fg: #8aca97;
  --st-blocked-bg: #3b291d; --st-blocked-fg: #e0a473;
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 var(--ui);
  -webkit-font-smoothing: antialiased;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
body, dialog, .row-t, .node, input, textarea, select, #sidebar {
  transition: background-color var(--mid) var(--ease), color var(--mid) var(--ease), border-color var(--mid) var(--ease);
}
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; }
}
[hidden] { display: none !important; }
.phone-only { display: none; }
.muted { color: var(--muted); }
.spacer { flex: 1; }
.plain { list-style: none; margin: 0; padding: 0; }
a { color: inherit; }
h2 { font-family: var(--text); font-weight: 400; font-size: 22px; margin: 0 0 14px; }
p { margin: 0 0 12px; }

/* ---------- text links and toggles ---------- */

button.link, a.link {
  background: none; border: 0; padding: 0; margin: 0;
  color: var(--muted); font: inherit; cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: color var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
button.link:hover, a.link:hover, button.link:focus-visible { color: var(--ink); outline: none; }
button.link:disabled { opacity: .4; cursor: default; }
button.toggle { font-weight: 400; }
button.toggle.on { color: var(--ink); font-weight: 600; }
button.toggle::after { content: attr(data-l); display: block; height: 0; overflow: hidden; visibility: hidden; font-weight: 600; }
.group { display: flex; align-items: baseline; gap: 14px; }

button.theme {
  width: 14px; height: 14px; padding: 0; margin: 0; border-radius: 50%;
  color: var(--muted); border: 1.5px solid currentColor;
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
  cursor: pointer; align-self: center; position: relative; flex-shrink: 0;
  transition: transform var(--mid) var(--ease), color var(--fast) var(--ease);
}
button.theme.dark { transform: rotate(180deg); }
button.theme:hover { color: var(--ink); }

.wordmark { font-family: var(--text); font-weight: 400; font-size: 40px; letter-spacing: -0.02em; margin: 0; }
.wordmark.small { font-size: 20px; }
.tag { font: 11px/1 var(--ui); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-left: 10px; vertical-align: middle; }

/* ---------- icons and tooltips ---------- */

.ic { width: 15px; height: 15px; vertical-align: -3px; flex-shrink: 0; }
button.ib {
  background: none; border: 0; padding: 4px; margin: -4px 0; border-radius: 6px; color: var(--muted); cursor: pointer; line-height: 0;
  transition: color var(--fast) var(--ease), background-color var(--fast) var(--ease);
}
button.ib:hover, button.ib:focus-visible { color: var(--ink); background: var(--hover); outline: none; }
button.ib .ic { width: 16px; height: 16px; vertical-align: 0; }
button.link .ic, a.link .ic { margin-right: 4px; }
#view-seg button .ic { margin-right: 5px; }
#menu-btn .ic { margin-right: 4px; }
.menu-rows .ic { margin-right: 10px; color: var(--muted); }
.search-ic { color: var(--muted); line-height: 0; margin-right: -12px; position: relative; top: 2px; }
.search-ic .ic { width: 13px; height: 13px; }
#search { padding-left: 18px; }
button.help .ic { width: 14px; height: 14px; vertical-align: -3px; }
#tip {
  position: fixed; z-index: 50; max-width: 280px; padding: 6px 10px; border-radius: 6px;
  background: var(--ink); color: var(--bg); font: 12px/1.45 var(--ui); pointer-events: none;
  white-space: normal;
}
#tip kbd { border-color: color-mix(in srgb, var(--bg) 40%, transparent); color: var(--bg); margin-left: 4px; }
@media (hover: none) { #tip { display: none !important; } }

/* ---------- inputs ---------- */

input, select, textarea { font: inherit; color: var(--ink); background: none; }
input[type="text"], input[type="email"], input[type="password"], input[type="search"], input[type="date"], input[type="number"], input[type="tel"], input[type="url"], textarea, select {
  border: 0; border-bottom: 1px solid var(--faint); border-radius: 0; padding: 6px 0; min-width: 0; outline: none;
  transition: border-color var(--fast) var(--ease);
}
input:focus, textarea:focus, select:focus { border-bottom-color: var(--ink); }
input[type="search"] { -webkit-appearance: none; appearance: none; }
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
input::placeholder, textarea::placeholder { color: var(--muted); opacity: .7; }
textarea { width: 100%; min-height: 96px; resize: vertical; line-height: 1.5; }
select { cursor: pointer; }
.row { display: flex; gap: 14px; align-items: baseline; }
.row input { flex: 1; }
.field { display: flex; flex-direction: column; gap: 2px; margin-bottom: 16px; }
.field > span { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.fields-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 24px; }
.fields-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 24px; }
.stack { display: flex; flex-direction: column; gap: 12px; align-items: center; }

/* ---------- gates ---------- */

.gate {
  min-height: 100dvh; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; padding: 40px; text-align: center;
}
.gate > * { animation: rise var(--slow) var(--ease) both; }
.gate > *:nth-child(2) { animation-delay: .12s; }
.gate > *:nth-child(3) { animation-delay: .2s; }
.gate p { max-width: 380px; margin: 0; }
button.signin { font-family: var(--text); font-size: 18px; color: var(--ink); border-bottom: 1px solid var(--faint); padding-bottom: 2px; }
button.signin:hover { border-bottom-color: var(--ink); }

/* ---------- layout: sidebar + pane ---------- */

#app { display: grid; grid-template-columns: 240px minmax(0, 1fr); min-height: 100%; animation: fade var(--mid) var(--ease) both; }
#sidebar {
  display: flex; flex-direction: column; box-shadow: inset -1px 0 var(--faint);
  height: 100vh; position: sticky; top: 0;
}
/* Top of the sidebar: the wordmark, then who's signed in, then the theme disc, shortcuts and menu. */
.sidebar-top { display: flex; flex-direction: column; gap: 12px; padding: 20px 16px 14px 20px; border-bottom: 1px solid var(--faint); }
.sidebar-head { display: flex; align-items: center; gap: 6px; }
.sidebar-head .wordmark { margin-right: auto; }
.sidebar-head .ib { margin: -4px 0; }
/* The account row: an initial in a disc, the name, and the role under it. The whole row opens settings. */
.me-row { display: flex; align-items: center; gap: 10px; padding: 6px 8px; margin: 0 -4px 0 -8px; border-radius: 8px; color: var(--ink); text-align: left; max-width: calc(100% + 12px); transition: background-color var(--fast) var(--ease); }
.me-row:hover, .me-row:focus-visible { background: var(--hover); color: var(--ink); }
.me-row::after { display: none; }
.me-row .avatar { flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; background: var(--ink); color: var(--bg); font: 600 12px/1 var(--ui); }
.me-row .me-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.me-row #me { font-size: 13px; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.me-row #me-role { font-size: 11px; line-height: 1.2; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-acts { display: flex; align-items: center; gap: 14px; font-size: 13px; margin-top: 2px; }
#nav { flex: 1; overflow-y: auto; padding: 12px 8px 18px; }
#nav .nav-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 10px; align-items: baseline;
  width: 100%; text-align: left; padding: 6px 12px; border-radius: 6px; border: 0; background: none; color: var(--ink);
  font: inherit; cursor: pointer; transition: background-color var(--fast) var(--ease);
}
#nav .nav-row:hover, #nav .nav-row.on { background: var(--hover); }
#nav .nav-row .t { font-family: var(--text); font-size: 15.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#nav .nav-row .n { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
#nav .nav-row.all { margin-bottom: 0; }
#nav .nav-row.all .t { font-weight: 500; }
/* Each block after "all" is a section behind a hairline: areas, unsorted, saved for later, new area. */
#nav .nav-sec { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--faint); }
#nav .nav-head { display: flex; align-items: center; gap: 6px; width: 100%; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding: 2px 12px 6px; }
#nav .nav-head .ic, #nav .nav-sep .ic { width: 12px; height: 12px; margin: 0; flex: 0 0 auto; }
#nav .nav-head .n { margin-left: auto; letter-spacing: 0; font-variant-numeric: tabular-nums; }
/* Icons on the "all" and "unsorted" rows, sized to the serif beside them. */
#nav .nav-row .t .ic { width: 14px; height: 14px; margin: 0 8px 0 0; vertical-align: -2px; color: var(--muted); }
#nav .nav-row.on .t .ic, #nav .nav-row:hover .t .ic { color: var(--ink); }
#nav .nav-row.archived .t { color: var(--muted); }
/* The "put back" icon on a saved-for-later row sits over the count and replaces it on hover, so every row is one line tall. */
#nav .nav-row { position: relative; }
#nav .nav-row .act { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); line-height: 0; color: var(--muted); opacity: 0; transition: opacity var(--fast) var(--ease); }
#nav .nav-row .act .ic { width: 14px; height: 14px; margin: 0; }
#nav .nav-row:hover .act { opacity: 1; }
#nav .nav-row.archived:hover .n { opacity: 0; }
#nav .nav-sep { display: flex !important; align-items: center; gap: 6px; width: 100%; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding: 2px 12px 6px; }
#nav .nav-sep .ic { transition: transform var(--fast) var(--ease); }
#nav .nav-sep.open .ic { transform: rotate(90deg); }
#nav .nav-sep .n { margin-left: auto; letter-spacing: 0; }
#nav .nav-sep:hover { color: var(--ink); }
#nav .nav-row.no-area { margin-top: 2px; }
#nav .nav-sec.areas .nav-sep { margin-top: 8px; }
.new-area-slot { display: inline-flex; line-height: 0; }

/* The note undo shows at the bottom of the window. */
#undo-note {
  position: fixed; left: 50%; bottom: 22px; z-index: 60; transform: translate(-50%, 12px); opacity: 0; pointer-events: none;
  padding: 7px 14px; border-radius: 8px; background: var(--ink); color: var(--bg); font: 13px/1.4 var(--ui);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18); transition: opacity var(--mid) var(--ease), transform var(--mid) var(--ease); max-width: calc(100vw - 32px);
}
#undo-note.show { opacity: 1; transform: translate(-50%, 0); }
#nav .nav-empty { padding: 8px 12px; color: var(--muted); font-size: 13px; }

#pane { padding: 22px 40px 120px; max-width: 1400px; width: 100%; min-width: 0; }
#pane.wide { max-width: none; }
#pane.wide.single { padding-bottom: 24px; }
#pane.wide.single .area { margin-bottom: 0; }
#top { display: flex; align-items: baseline; gap: 14px; margin-bottom: 4px; }
#pane-title { font-family: var(--text); font-weight: 400; font-size: 30px; margin: 0; letter-spacing: -0.01em; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#pane-count { font-size: 12px; white-space: nowrap; }
#top #sync { align-self: center; }
#top .ib { align-self: center; }
/* Who else is on the list: overlapping discs with initials, before the share button. */
.here { display: inline-flex; align-items: center; align-self: center; margin-right: 2px; }
.here .av { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; background: var(--ink); color: var(--bg); font: 600 10px/1 var(--ui); border: 2px solid var(--bg); margin-left: -7px; box-sizing: content-box; }
.here .av:first-child { margin-left: 0; }
#pane-title.editable { cursor: pointer; text-decoration: underline; text-underline-offset: 6px; text-decoration-color: transparent; transition: text-decoration-color var(--fast) var(--ease); }
#pane-title.editable:hover { text-decoration-color: var(--faint); }
#tools { display: flex; align-items: center; gap: 16px; font-size: 13px; margin: 12px 0 26px; }
.seg { display: inline-flex; gap: 2px; padding: 3px; border-radius: 8px; background: var(--hover); }
.seg button.toggle { padding: 4px 10px; border-radius: 6px; font-weight: 400; transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease); }
.seg button.toggle::after { display: none; }
.seg button.toggle.on { background: var(--bg); color: var(--ink); font-weight: 500; box-shadow: 0 1px 2px rgba(0, 0, 0, .06); }
.seg button .ic { margin-right: 5px; }
.tools-sep { width: 1px; height: 16px; background: var(--faint); }
#search { width: 180px; font-size: 13px; padding: 4px 0; }
.sort-wrap { display: inline-flex; align-items: baseline; gap: 6px; font-size: 13px; margin-left: auto; }
.sort-wrap .dd-btn.quiet { color: var(--ink); }
#sync { font-size: 12px; }
#foot { margin-top: 60px; font-size: 12px; }
.empty { padding: 12px 0 20px; color: var(--muted); font-family: var(--text); font-size: 16px; }
button.help { line-height: 0; }
button.help .ic { width: 15px; height: 15px; margin: 0; vertical-align: 0; }

/* ---------- up next ---------- */

.eyebrow { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin: 0 0 8px; }

/* ---------- areas ---------- */

.area { margin-bottom: 44px; animation: rise var(--mid) var(--ease) both; }
/* The entrance plays when a page opens, not on every redraw after an edit or a sync. */
#content.settled .area { animation: none; }
.area-head { display: flex; align-items: baseline; gap: 14px; margin-bottom: 4px; }
.area-head h2 { margin: 0; font-size: 24px; flex: 1; min-width: 0; }
.area-head h2 button { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }
.area-head h2 button:hover { text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--faint); }
.area-head .count { font-size: 12px; color: var(--muted); white-space: nowrap; }
.progress { height: 1px; background: var(--faint); margin: 8px 0 14px; position: relative; overflow: hidden; }
.progress > span { position: absolute; left: 0; top: 0; bottom: 0; background: var(--ink); transition: width var(--slow) var(--ease); }
.area-notes { margin: -4px 0 14px; font-size: 13px; }
.area-notes summary { cursor: pointer; color: var(--muted); list-style: none; width: max-content; }
.area-notes summary::-webkit-details-marker { display: none; }
.area-notes summary:hover { color: var(--ink); }
.area-notes[open] summary { margin-bottom: 6px; }
.area-notes .notes-body { white-space: pre-wrap; color: var(--muted); font-family: var(--text); font-size: 15px; padding-left: 18px; border-left: 1px solid var(--faint); }

/* ---------- task rows ---------- */

.phase { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin: 18px 0 4px; }
.phase:first-child { margin-top: 0; }
.row-t {
  display: grid; grid-template-columns: 18px 30px var(--w-task, 380px) var(--w-status, 80px) var(--w-start, 90px) var(--w-target, 100px) minmax(0, 1fr); column-gap: 18px; align-items: baseline;
  padding: 12px 10px; margin: 0 -10px; border-bottom: 1px solid var(--faint);
}
/* The overview adds an area column after the title. */
#content.with-area .row-t { grid-template-columns: 18px 30px var(--w-task, 380px) var(--w-area, 130px) var(--w-status, 80px) var(--w-start, 90px) var(--w-target, 100px) minmax(0, 1fr); }
.t-cell.t-area .t-area-link { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.t-cell.t-area .t-area-link:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--faint); }
/* Column headings sort on click; the active one shows a small chevron. */
.row-t.cols-head .col-sort { background: none; border: 0; padding: 0; font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; display: block; width: 100%; height: 100%; text-align: left; }
.row-t.cols-head .col-sort:disabled { cursor: default; }
.row-t.cols-head .col-sort:not(:disabled):hover, .row-t.cols-head .col.sorted .col-sort { color: var(--ink); }
.sort-mark .ic { width: 11px; height: 11px; margin-left: 3px; vertical-align: -1px; }
.sort-mark.desc .ic { transform: rotate(180deg); }
/* Faint column guides between the cells, so the eye can follow a column down the list. */
.row-t > .t-cell { border-left: 1px solid var(--faint); padding-left: 14px; margin-left: -10px; align-self: stretch; padding-top: 5px; margin-top: -12px; margin-bottom: -12px; padding-bottom: 12px; display: flex; align-items: flex-start; }
.row-t > .t-cell.t-notes { display: block; padding-top: 5px; }
.row-t.cols-head > span:nth-child(n+4) { border-left: 1px solid var(--faint); padding-left: 14px; margin-left: -10px; }
.phase { border-bottom: 1px solid var(--faint); padding-bottom: 4px; }
.row-t.cols-head { font-size: 10px; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); padding: 0 10px 6px; border-bottom: 1px solid var(--muted); border-radius: 0; margin-bottom: 4px; }
.row-t.cols-head:hover { background: none; }
.row-t.cols-head .col { position: relative; }
.col-grip { position: absolute; right: -9px; top: -4px; bottom: -4px; width: 9px; cursor: col-resize; }
.col-grip::after { content: ""; position: absolute; left: 4px; top: 0; bottom: 0; width: 1px; background: var(--faint); opacity: 0; transition: opacity var(--fast) var(--ease); }
.row-t.cols-head:hover .col-grip::after, .col-grip:active::after { opacity: 1; }
.col-grip:hover::after { background: var(--muted); }
.t-cell { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* The status reads as a chip: a tinted pill, one colour per status, in both themes. Editors get the
   same chip with the dropdown behind it, so the column looks the same whoever is looking, and the
   menu it opens, the editor's Status field and the right-click rows draw the same chips. */
.t-cell.t-status > span, .t-cell.t-status .dd-btn.quiet, .dd-st .dd-btn .dd-val, .st-chip {
  display: inline-flex; align-items: center; height: 21px; padding: 0 9px; border-radius: 999px;
  font-size: 11.5px; white-space: nowrap; border-bottom: 0;
  background: var(--st-queued-bg); color: var(--st-queued-fg);
  transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease);
}
.t-cell.t-status.doing > span, .t-cell.t-status.doing .dd-btn.quiet, .dd-st[data-value="doing"] .dd-val, .st-chip.doing { background: var(--st-doing-bg); color: var(--st-doing-fg); }
.t-cell.t-status.done > span, .t-cell.t-status.done .dd-btn.quiet, .dd-st[data-value="done"] .dd-val, .st-chip.done { background: var(--st-done-bg); color: var(--st-done-fg); }
.t-cell.t-status.blocked > span, .t-cell.t-status.blocked .dd-btn.quiet, .dd-st[data-value="blocked"] .dd-val, .st-chip.blocked { background: var(--st-blocked-bg); color: var(--st-blocked-fg); }
/* In a menu the chip carries the colour, so the row itself stays plain and the ticked one reads
   through weight rather than a second colour. */
.dd-menu-chips .item { padding-top: 3px; padding-bottom: 3px; }
.dd-menu-chips .item.on { font-weight: 400; }
.dd-menu-chips .item.on .st-chip { font-weight: 600; box-shadow: inset 0 0 0 1px currentColor; }
/* The ticked row in a right-click menu normally turns ink-coloured, which would undo a chip's own
   colour, so each status is restated here at that weight. */
.ctx .ctx-row button.link.st-chip, .ctx .ctx-row button.link.st-chip.on { padding: 0 9px; background: var(--st-queued-bg); color: var(--st-queued-fg); }
.ctx .ctx-row button.link.st-chip.doing, .ctx .ctx-row button.link.st-chip.doing.on { background: var(--st-doing-bg); color: var(--st-doing-fg); }
.ctx .ctx-row button.link.st-chip.done, .ctx .ctx-row button.link.st-chip.done.on { background: var(--st-done-bg); color: var(--st-done-fg); }
.ctx .ctx-row button.link.st-chip.blocked, .ctx .ctx-row button.link.st-chip.blocked.on { background: var(--st-blocked-bg); color: var(--st-blocked-fg); }
.ctx .ctx-row button.link.st-chip.on { font-weight: 600; box-shadow: inset 0 0 0 1px currentColor; }
/* Hovering a chip deepens its tint instead of underlining it. */
.t-cell.t-status .dd-btn.quiet:hover, .t-cell.t-status .dd-btn.quiet:focus-visible,
.row-t > .t-cell.t-status.clickable:hover .dd-btn.quiet { border-bottom-color: transparent; filter: brightness(.96) saturate(1.1); }
:root[data-theme="dark"] .t-cell.t-status .dd-btn.quiet:hover,
:root[data-theme="dark"] .t-cell.t-status .dd-btn.quiet:focus-visible,
:root[data-theme="dark"] .row-t > .t-cell.t-status.clickable:hover .dd-btn.quiet { filter: brightness(1.2); }
.t-cell.t-priority.high { color: var(--pri-high); }
.t-cell.t-priority.medium { color: var(--pri-medium); }
.t-cell.t-priority.low { color: var(--pri-low); }
.t-cell .dd-btn.quiet { color: inherit; }
.pri.high { color: var(--pri-high); } .pri.medium { color: var(--pri-medium); } .pri.low { color: var(--pri-low); }
.ctx .ctx-row button.link.pri-high.on { color: var(--pri-high); } .ctx .ctx-row button.link.pri-medium.on { color: var(--pri-medium); }
.t-cell.t-date { position: relative; }
.t-cell.t-date.late { color: var(--late); }
.t-date-text.none { opacity: 0; }
.row-t:hover .t-date-text.none { opacity: .7; }
input.ghost-date { position: absolute; inset: 0; width: 100%; opacity: 0; cursor: pointer; border: 0; padding: 0; margin: 0; }
.t-cell.t-notes { font-size: 12px; }
select.quiet, input.quiet {
  border: 0; padding: 0; margin: 0; background: none; font: inherit; color: inherit; cursor: pointer; width: 100%;
  -webkit-appearance: none; appearance: none; border-bottom: 1px solid transparent; border-radius: 0;
}
select.quiet:hover, input.quiet:hover { border-bottom-color: var(--faint); }
select.quiet:focus, input.quiet:focus { border-bottom-color: var(--ink); outline: none; }
input.quiet::-webkit-calendar-picker-indicator { opacity: 0; }
input.quiet::-webkit-datetime-edit { padding: 0; }
.row-t.done .t-cell { color: var(--muted); }
.row-t:hover { background: var(--hover); }
.dot {
  width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--muted); background: transparent;
  padding: 0; margin: 0; cursor: default; align-self: center; position: relative; top: -1px;
  transition: background-color var(--fast) var(--ease), border-color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.row-t.ready .dot { border-color: var(--ok); background: var(--ok); }
.row-t.doing .dot { border-color: var(--ink); background: linear-gradient(90deg, var(--ink) 50%, transparent 50%); }
.row-t.waiting .dot { border-color: var(--faint); border-style: dashed; }
.row-t.blocked .dot { border-color: var(--warn); background: var(--warn); }
.row-t.done .dot { border-color: var(--faint); background: var(--faint); }

/* The tick box: a small rounded square in front of every task. Its outline says where the task stands;
   a click marks it done (filled, with a tick). The tick previews faintly on hover. */
/* The tick box. The button is the target and is as tall as the row or box it sits in, plus 8px either side;
   the square you see (.cb) sits inside it, so hovering or pressing never moves the target. */
.check {
  flex-shrink: 0; padding: 0; margin: 0; border: 0; background: none; align-self: stretch; position: relative; z-index: 1;
  display: grid; align-content: center; justify-content: center; color: transparent; cursor: pointer;
}
.check::before { content: ""; position: absolute; inset: 0 -8px; }
.check .cb {
  width: 16px; height: 16px; display: inline-grid; place-items: center; border-radius: 4px; border: 1.5px solid var(--muted); background: var(--bg); color: inherit;
  transition: background-color var(--fast) var(--ease), border-color var(--fast) var(--ease), color var(--fast) var(--ease), transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.check .ic { width: 12px; height: 12px; stroke-width: 2; }
.check.ready .cb { border-color: var(--ok); }
.check.doing .cb { border-color: var(--ink); background: linear-gradient(90deg, color-mix(in srgb, var(--ink) 22%, var(--bg)) 50%, var(--bg) 50%); }
.check.waiting .cb { border-color: var(--muted); border-style: dashed; }
.check.blocked .cb { border-color: var(--warn); background: var(--warn-tint); }
.check:not(:disabled):hover { color: var(--muted); }
.check:not(:disabled):hover .cb { transform: scale(1.2); box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 14%, transparent); }
.check.ready:not(:disabled):hover { color: var(--ok); }
.check.done .cb { background: var(--ok); border-color: var(--ok); }
.check.done { color: var(--bg); }
.check.done:not(:disabled):hover { color: var(--bg); }
.check.done:not(:disabled):hover .cb { background: color-mix(in srgb, var(--ok) 70%, var(--bg)); box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 22%, transparent); }
.check:disabled { cursor: default; }
.check:focus-visible { outline: none; }
.check:focus-visible .cb { outline: 2px solid var(--ink); outline-offset: 2px; }
/* List: the target is the whole row height; the square sits on the title's first line. */
.row-t .check { align-content: start; margin-top: -12px; margin-bottom: -12px; padding-top: 17px; }
.t-main { min-width: 0; }
.t-title {
  display: block; width: 100%; text-align: left; background: none; border: 0; padding: 0; margin: 0;
  font-family: var(--text); font-size: 17px; line-height: 1.35; color: var(--ink); cursor: pointer;
}
.t-title:hover { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--faint); }
.peek-head h3 .swatch, .tl-title .swatch, .t-title .swatch { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 7px; vertical-align: 1px; }
.row-t.done .t-title { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--muted); }
.row-t.waiting .t-title { color: var(--muted); }
.t-sub { font-size: 12px; color: var(--muted); margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-sub .area-name { margin-right: 8px; }
.t-side { font-size: 12px; color: var(--muted); white-space: nowrap; text-align: right; }
.t-side.late { color: var(--late); }
.t-side.high { color: var(--ink); }
.fold { margin: 10px 0 0; font-size: 12px; }
.quick { margin-top: 10px; padding-left: 30px; }
.quick button.link { font-size: 13px; }
.quick input { width: 100%; font-family: var(--text); font-size: 17px; padding: 2px 0; }

/* ---------- drag to reorder ---------- */

.drag-shift { transition: transform var(--mid) var(--ease); }
.drag-lift { position: relative; z-index: 5; box-shadow: 0 10px 28px rgba(0, 0, 0, .16), 0 2px 6px rgba(0, 0, 0, .08); background: var(--bg); transition: box-shadow var(--fast) var(--ease); }
.row-t.drag-lift { border-radius: 6px; border-bottom-color: transparent; }
.tl-label.drag-lift { box-shadow: 0 10px 28px rgba(0, 0, 0, .16); }
.drag-settle { transition: transform var(--fast) var(--ease), box-shadow var(--fast) var(--ease); box-shadow: none; }
body.row-dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }
body.row-dragging * { cursor: grabbing !important; }
.can-edit .row-t:not(.cols-head) { cursor: grab; }
.can-edit .tl-label[data-id] { cursor: grab; }
:root[data-theme="dark"] .drag-lift { box-shadow: 0 10px 28px rgba(0, 0, 0, .6); }

/* ---------- flow: toolbar, canvas, boxes ---------- */

.flowbar { display: flex; align-items: center; gap: 10px; font-size: 12px; margin: 0 0 10px; flex-wrap: wrap; }
.flowbar .sep { width: 1px; height: 14px; background: var(--faint); }
/* Direction button: the arrow turns from down to right. */
.flowbar .dir-btn .ic { transition: transform var(--mid) var(--ease); }
.flowbar .dir-btn.h .ic { transform: rotate(-90deg); }
/* Arrangement: three icons with one highlight that slides between them. */
.seg-icons { position: relative; }
.seg-icons button.toggle { position: relative; z-index: 1; padding: 4px 8px; line-height: 0; background: transparent; box-shadow: none; }
.seg-icons button.toggle.on { background: transparent; box-shadow: none; color: var(--ink); }
.seg-icons button.toggle .ic { width: 15px; height: 15px; margin: 0; }
.seg-thumb { position: absolute; top: 3px; bottom: 3px; left: 3px; width: 0; border-radius: 6px; background: var(--bg); box-shadow: 0 1px 2px rgba(0, 0, 0, .06); transition: left var(--mid) var(--ease), width var(--mid) var(--ease); }
.seg-thumb.no-anim { transition: none; }
.swatches { display: flex; gap: 6px; align-items: center; }
.swatches button {
  width: 14px; height: 14px; border-radius: 50%; border: 1px solid color-mix(in srgb, var(--ink) 15%, transparent);
  padding: 0; cursor: pointer; transition: transform var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.swatches button:hover { transform: scale(1.25); }
.swatches button.none { background: none; border-style: dashed; border-color: var(--muted); }
.swatches button.on { box-shadow: 0 0 0 1.5px var(--ink); }
.swatches.dim button { opacity: .35; cursor: default; }
.swatches.dim button:hover { transform: none; }
.swatches button[data-c="1"] { background: var(--c1); } .swatches button[data-c="2"] { background: var(--c2); }
.swatches button[data-c="3"] { background: var(--c3); } .swatches button[data-c="4"] { background: var(--c4); }
.swatches button[data-c="5"] { background: var(--c5); } .swatches button[data-c="6"] { background: var(--c6); }
.swatches button[data-c="7"] { background: var(--c7); } .swatches button[data-c="8"] { background: var(--c8); }
.sw-1 { background: var(--c1); } .sw-2 { background: var(--c2); } .sw-3 { background: var(--c3); } .sw-4 { background: var(--c4); }
.sw-5 { background: var(--c5); } .sw-6 { background: var(--c6); } .sw-7 { background: var(--c7); } .sw-8 { background: var(--c8); }

.canvas {
  position: relative; overflow: hidden; border-radius: 8px; border: 1px solid var(--faint);
  background-color: var(--bg);
  background-image: radial-gradient(color-mix(in srgb, var(--muted) 28%, transparent) 1px, transparent 1px);
  background-size: 22px 22px;
  touch-action: none; user-select: none; -webkit-user-select: none;
}
.canvas svg { display: block; width: 100%; height: 100%; cursor: grab; }
/* A box is drawn inside a foreignObject, which clips to its own edges by default. At an in-between zoom the
   edges fall between pixels and the clip shaves off the border; the selection ring and the drag shadow sit
   outside the box and were clipped entirely. */
.canvas foreignObject { overflow: visible; }
.node.enter { animation: fade var(--mid) var(--ease); }
.canvas svg.dragging { cursor: grabbing; }
.canvas path.edge { fill: none; stroke: var(--faint); stroke-width: 1.5; }
/* Snapping guides while a box is dragged: hairlines in one colour, with a short tick at each end. */
.canvas .guides line { stroke: var(--snap); stroke-width: 1; vector-effect: non-scaling-stroke; pointer-events: none; opacity: .45; }
.canvas .guides line.guide-end { stroke-width: 1.5; opacity: .6; }
.canvas path.edge.met { stroke: var(--ok); }
.canvas path.edge.open { stroke-dasharray: 4 4; stroke: color-mix(in srgb, var(--muted) 60%, transparent); }
.canvas .arrow { fill: color-mix(in srgb, var(--muted) 60%, transparent); }
.canvas .arrow.met { fill: var(--ok); }
.node {
  box-sizing: border-box; height: 100%; padding: 10px 15px; border-radius: 7px;
  border: 1px solid var(--node-border); background: var(--node-bg); cursor: grab; position: relative;
  display: flex; flex-direction: column; justify-content: center; gap: 1px; line-height: 1.3;
  transition: border-color var(--fast) var(--ease), background-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.node:hover { border-color: var(--muted); }
.node { flex-direction: row; align-items: center; justify-content: flex-start; gap: 11px; padding-left: 13px; }
.node .n-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.node .check .cb { width: 20px; height: 20px; border-radius: 5px; }
.node .check .ic { width: 15px; height: 15px; }
.node .n-title { font-family: var(--text); font-size: 17px; line-height: 1.25; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.node .n-meta { font-size: 13px; color: var(--on-fill-meta); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.node.done { color: var(--muted); border-style: dotted; }
.node.done .n-title { text-decoration: line-through; }
/* Ready: a small green dot in the corner rather than a green border. */
.node.ready::after { content: ""; position: absolute; top: 9px; right: 9px; width: 7px; height: 7px; border-radius: 50%; background: var(--ok); }
.node .pri.high { color: var(--on-fill-high); } .node .pri.medium { color: var(--on-fill-medium); } .node .pri.low { color: var(--on-fill-low); }
.node.waiting .n-title, .node.done .n-title { color: var(--on-fill-meta); }
.node.doing { border-color: var(--ink); }
.node.waiting { color: var(--muted); border-style: dashed; }
.node.blocked { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 16%, var(--node-bg)); }
/* A coloured box keeps its status border and takes the tint as its fill. */
/* The accent: a stripe down the left of the box, instead of colouring the whole box. */
.node::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; border-radius: 7px 0 0 7px; background: var(--tc, transparent); }
.node.done::before { opacity: .45; }
.node { --lift: 0 10px 28px rgba(0, 0, 0, .16), 0 2px 6px rgba(0, 0, 0, .08); transition: border-color var(--mid) var(--ease), background-color var(--fast) var(--ease), box-shadow var(--mid) var(--ease), transform var(--mid) var(--ease); }
/* Selected boxes lift, like selected timeline bars (tracker 10.14). The status border keeps its colour. */
.node.selected { box-shadow: 0 8px 22px rgba(0, 0, 0, .16), 0 2px 5px rgba(0, 0, 0, .08); }
:root[data-theme="dark"] .node.selected { box-shadow: 0 8px 22px rgba(0, 0, 0, .55), 0 2px 5px rgba(0, 0, 0, .35); }
:root[data-theme="dark"] .node { --lift: 0 10px 28px rgba(0, 0, 0, .55), 0 2px 6px rgba(0, 0, 0, .35); }
.node.moving { box-shadow: var(--lift); }
.node.drop { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); }
.canvas path.edge-hit { fill: none; stroke: transparent; stroke-width: 14; cursor: pointer; pointer-events: stroke; }
.canvas .edge-g:hover path.edge { stroke: var(--muted); }
.canvas .edge-g.selected path.edge { stroke: var(--ink); stroke-width: 2.5; stroke-dasharray: none; filter: drop-shadow(0 0 3px color-mix(in srgb, var(--ink) 55%, transparent)) drop-shadow(0 4px 8px rgba(0, 0, 0, .18)); transition: stroke-width var(--mid) var(--ease), filter var(--mid) var(--ease); }
.canvas .edge-g.selected .arrow { fill: var(--ink); }
.canvas .edge-g.selected .edge-end { fill: var(--ink); stroke: var(--ink); }
.canvas path.edge { transition: stroke var(--mid) var(--ease), stroke-width var(--mid) var(--ease), filter var(--mid) var(--ease); }
.canvas .edge-g.rewiring path.edge, .canvas .edge-g.rewiring .edge-end { opacity: .25; }
.edge-end { fill: var(--bg); stroke: var(--muted); stroke-width: 1.5; cursor: grab; opacity: 0; transition: opacity var(--fast) var(--ease); pointer-events: all; }
.edge-g:hover .edge-end, .edge-g.selected .edge-end, .tl-edge:hover .edge-end, .tl-edge.selected .edge-end { opacity: 1; }
.edge-end:hover { fill: var(--ink); stroke: var(--ink); }
@media (hover: none) { .edge-end { opacity: .8; } }
.canvas path.edge.ghost { stroke: var(--ink); stroke-dasharray: 5 4; pointer-events: none; }
.canvas circle.handle { fill: var(--bg); stroke: var(--muted); stroke-width: 1.5; cursor: grab; opacity: .5; transition: opacity var(--fast) var(--ease); }
.canvas circle.handle:hover { fill: var(--ink); stroke: var(--ink); opacity: 1; }
.canvas svg.dragging circle.handle { cursor: grabbing; }
.canvas svg.dragging foreignObject { pointer-events: none; }
.canvas svg.dragging .node { cursor: grabbing; }
@media (hover: none) { .canvas circle.handle { opacity: 1; } }
.legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--muted); margin: 6px 0 0; }
.legend.page-legend { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--faint); }
.legend .l-hint { line-height: 1.5; }
.legend .l-hint { flex-basis: 100%; }
.legend .l-hint::before { display: none; }
.legend span::before { content: ""; display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; border: 1.5px solid var(--muted); }
.legend .l-ready::before { border-color: var(--ok); background: var(--ok); }
.legend .l-doing::before { border-color: var(--ink); background: linear-gradient(90deg, var(--ink) 50%, transparent 50%); }
.legend .l-waiting::before { border-color: var(--faint); border-style: dashed; }
.legend .l-blocked::before { border-color: var(--warn); background: var(--warn); }
.legend .l-done::before { border-color: var(--faint); background: var(--faint); }

/* ---------- timeline ---------- */

.tl-scroll { touch-action: pan-x pan-y; overflow: auto; border: 1px solid var(--faint); border-radius: 8px; max-height: calc(100vh - 200px); position: relative; background: var(--bg); }
.tl-grid { position: relative; }
.tl-head { position: sticky; top: 0; z-index: 3; height: 54px; display: grid; grid-template-columns: 240px 1fr; grid-template-rows: 22px 32px; background: var(--bg); border-bottom: 1px solid var(--faint); }
.tl-corner { position: sticky; left: 0; z-index: 4; background: var(--bg); box-shadow: inset -1px 0 var(--faint); grid-row: 1 / 3; }
.tl-months { position: relative; height: 22px; grid-column: 2; }
.tl-days { position: relative; height: 32px; grid-column: 2; }
.tl-month { position: absolute; top: 4px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding-left: 6px; border-left: 1px solid var(--faint); line-height: 16px; white-space: nowrap; }
.tl-day { position: absolute; top: 1px; font-size: 11px; color: var(--muted); text-align: center; line-height: 15px; }
.tl-day .wd { display: block; font-size: 9px; letter-spacing: .06em; opacity: .75; line-height: 12px; }
.tl-week { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--faint); }
.tl-days .tl-week { top: 4px; bottom: 0; }
.tl-day.weekend { color: color-mix(in srgb, var(--muted) 50%, transparent); }
.tl-day.today { color: var(--late); font-weight: 600; }
.tl-body { position: relative; display: grid; grid-template-columns: 240px 1fr; }
.tl-labels { position: sticky; left: 0; z-index: 2; background: var(--bg); box-shadow: inset -1px 0 var(--faint); width: 240px; }
.tl-label { position: absolute; left: 0; right: 0; height: var(--tl-row, 34px); display: flex; align-items: center; gap: 10px; padding: 0 12px 0 14px; font-size: 13px; }
.tl-label .check { align-content: center; }
.tl-label.ready .dot { border-color: var(--ok); background: var(--ok); }
.tl-label.doing .dot { border-color: var(--ink); background: linear-gradient(90deg, var(--ink) 50%, transparent 50%); }
.tl-label.waiting .dot { border-color: var(--faint); border-style: dashed; }
.tl-label.blocked .dot { border-color: var(--warn); background: var(--warn); }
.tl-label.done .dot { border-color: var(--faint); background: var(--faint); }
.tl-title { background: none; border: 0; padding: 0; font: 14px var(--text); color: var(--ink); cursor: pointer; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tl-title .swatch { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 6px; vertical-align: 1px; }
.tl-title.selected { text-decoration: underline; text-underline-offset: 3px; }
.tl-label.done .tl-title { color: var(--muted); text-decoration: line-through; }
.tl-label.area { font-family: var(--text); font-size: 15px; }
.tl-area { background: none; border: 0; padding: 0; font: inherit; color: var(--ink); cursor: pointer; }
.tl-area:hover { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--faint); }
.tl-lanes { position: relative; grid-column: 2; overflow: hidden; }
/* A hairline under every row, across the names and the chart, like the list. They stop at the last row. */
.tl-labels, .tl-lanes {
  background-image: repeating-linear-gradient(to bottom, transparent 0, transparent calc(var(--tl-row, 34px) - 1px), var(--faint) calc(var(--tl-row, 34px) - 1px), var(--faint) var(--tl-row, 34px));
  background-size: 100% var(--tl-rows-h, 0px); background-repeat: no-repeat;
}
.tl-weekend { position: absolute; top: 0; bottom: 0; background: color-mix(in srgb, var(--muted) 7%, transparent); }
.tl-stripe { position: absolute; left: 0; right: 0; height: var(--tl-row, 34px); background: color-mix(in srgb, var(--muted) 5%, transparent); }
.tl-today { position: absolute; top: 0; bottom: 0; width: 1.5px; margin-left: -.25px; background: var(--late); opacity: .85; z-index: 1; }
.tl-bar {
  position: absolute; height: var(--tl-bar, 22px); border-radius: 5px; border: 1px solid var(--node-border); background: var(--node-bg);
  display: flex; align-items: center; cursor: grab; z-index: 1; overflow: hidden; touch-action: none; user-select: none;
  transition: box-shadow var(--mid) var(--ease), border-color var(--mid) var(--ease), filter var(--mid) var(--ease);
}
.tl-bar-text { font: 12px/1 var(--ui); color: var(--ink); padding: 0 9px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none; }
.tl.rows-thick .tl-bar-text { font-size: 13px; }
.tl.rows-thin .tl-label { font-size: 12px; } .tl.rows-thin .tl-title { font-size: 13px; }
.flowbar .ib.off { opacity: .35; pointer-events: none; }
.flowbar .ib.on { color: var(--ink); background: var(--hover); }
.tl-bar.done .tl-bar-text { color: var(--muted); text-decoration: line-through; }
.tl-when { position: absolute; left: calc(100% + 12px); top: 50%; transform: translateY(-50%); font-size: 11px; color: var(--muted); white-space: nowrap; pointer-events: none; }
.tl-bar.late .tl-when { color: var(--late); }
.tl-bar.done .tl-when { color: var(--ok); }
.tl-bar.single .tl-bar-text { display: none; }
/* A deadline with no start: the line is the target day's right edge; the trail fades out leftwards. */
.tl-bar.single { border: 0; border-radius: 0; border-right: 2px solid var(--muted); background: linear-gradient(to left, color-mix(in srgb, var(--muted) 28%, transparent), transparent); }
.tl-bar.single.ready::before { content: ""; position: absolute; right: 5px; top: 50%; width: 6px; height: 6px; margin-top: -3px; border-radius: 50%; background: var(--ok); }
.tl-bar.single.doing { border-right-color: var(--ink); background: linear-gradient(to left, color-mix(in srgb, var(--ink) 25%, transparent), transparent); }
.tl-bar.single.waiting { border-right-style: dashed; }
.tl-bar.single.blocked { border-right-color: var(--warn); background: linear-gradient(to left, color-mix(in srgb, var(--warn) 35%, transparent), transparent); }
.tl-bar.single.late { border-right-color: var(--late); background: linear-gradient(to left, color-mix(in srgb, var(--late) 30%, transparent), transparent); }
.tl-bar.single.done { border-right-style: dotted; }
.tl-bar.single { background: linear-gradient(to left, color-mix(in srgb, var(--tc, var(--muted)) 30%, transparent), transparent); }
.tl-bar.single.selected { box-shadow: none; border-right-width: 3px; filter: drop-shadow(0 6px 10px rgba(0, 0, 0, .18)); }
.tl-bar.single .tl-grip.r { display: none; }
.tl-bar.single .tl-sock { right: -5px; }
.tl-bar.ready:not(.single)::before { content: ""; position: absolute; left: 7px; top: 50%; width: 6px; height: 6px; margin-top: -3px; border-radius: 50%; background: var(--ok); }
.tl-bar.ready:not(.single) .tl-bar-text { padding-left: 18px; }
.tl-bar.doing { border-color: var(--ink); }
.tl-bar.waiting { border-style: dashed; }
.tl-bar.blocked { border-color: var(--warn); background: var(--warn-tint); }
.tl-bar.done { border-style: dotted; opacity: .6; }
.tl-bar.late { border-color: var(--late); }
/* The same accent on a timeline bar: a thicker left edge on a range, the marker line on a single day. */
.tl-bar:not(.single) { border-left: 3px solid var(--tc, var(--node-border)); }
.tl-bar.single { border-right-color: var(--tc, var(--muted)); }
.tl-bar.selected { box-shadow: 0 8px 22px rgba(0, 0, 0, .16), 0 2px 5px rgba(0, 0, 0, .08); border-color: var(--muted); z-index: 2; }
:root[data-theme="dark"] .tl-bar.selected { box-shadow: 0 8px 22px rgba(0, 0, 0, .55); }
.tl-bar.moving { box-shadow: 0 6px 18px rgba(0, 0, 0, .14); cursor: grabbing; z-index: 2; }
.tl-bar.moving .tl-when { color: var(--ink); }
.tl-grip { position: absolute; top: 0; bottom: 0; width: 8px; cursor: ew-resize; }
.tl-grip.l { left: 0; } .tl-grip.r { right: 0; }
body:not(.can-edit) .tl-bar, body:not(.can-edit) .tl-grip { cursor: default; }
.tl-arrows { position: absolute; pointer-events: none; overflow: visible; }
.tl-arrow-hit { fill: none; stroke: transparent; stroke-width: 12; pointer-events: stroke; cursor: pointer; }
.tl-edge:hover .tl-arrow { stroke: var(--muted); }
.tl-edge.selected .tl-arrow { stroke: var(--ink); stroke-width: 2.5; stroke-dasharray: none; filter: drop-shadow(0 0 3px color-mix(in srgb, var(--ink) 55%, transparent)) drop-shadow(0 4px 8px rgba(0, 0, 0, .18)); }
.tl-edge.selected .edge-end { fill: var(--ink); stroke: var(--ink); }
.tl-arrow { transition: stroke var(--mid) var(--ease), stroke-width var(--mid) var(--ease), filter var(--mid) var(--ease); }
.tl-edge.rewiring .tl-arrow, .tl-edge.rewiring .edge-end { opacity: .25; }
.tl-arrow.ghost { stroke: var(--ink); stroke-dasharray: 5 4; }
.tl-sock { position: absolute; right: -6px; top: 50%; width: 9px; height: 9px; margin-top: -4.5px; border-radius: 50%; background: var(--bg); border: 1.5px solid var(--muted); opacity: .5; cursor: crosshair; transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease); }
.tl-bar:hover .tl-sock, .tl-bar.selected .tl-sock { opacity: 1; }
.tl-sock:hover { background: var(--ink); border-color: var(--ink); transform: scale(1.25); }
.tl-bar { overflow: visible; }
.tl-bar-text { overflow: hidden; min-width: 0; max-width: 100%; }
.tl-drop { position: absolute; left: 0; right: 0; height: var(--tl-row, 34px); background: color-mix(in srgb, var(--ink) 6%, transparent); box-shadow: inset 0 0 0 1px var(--ink); pointer-events: none; z-index: 3; }
@media (hover: none) { .tl-sock { opacity: 1; } }
.tl-arrow { fill: none; stroke-width: 1.5; stroke: color-mix(in srgb, var(--muted) 60%, transparent); stroke-dasharray: 4 4; }
.tl-arrow.met { stroke: var(--ok); stroke-dasharray: none; }
.tl-arrow.broken { stroke: var(--late); stroke-dasharray: none; }
.tl-arrows .arrow { fill: color-mix(in srgb, var(--muted) 60%, transparent); }
.tl-arrows .arrow.met { fill: var(--ok); }
.tl-label.phase-row { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; line-height: var(--tl-row, 34px); }
.tl-stripe.phase { background: none; }
.tl-label.undated .tl-title { color: var(--muted); }
.tl-empty { position: absolute; left: 0; right: 0; height: var(--tl-row, 34px); cursor: copy; }
.tl-empty:hover { background: color-mix(in srgb, var(--ok) 6%, transparent); }
@media (max-width: 760px) {
  .tl-scroll { max-height: 70vh; }
}

/* ---------- dropdowns ---------- */

.dd { display: inline-block; min-width: 0; max-width: 100%; }
.dd-btn {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; background: none; border: 0; border-bottom: 1px solid var(--faint);
  padding: 6px 0; margin: 0; font: inherit; color: var(--ink); cursor: pointer; text-align: left; transition: border-color var(--fast) var(--ease);
}
.dd-btn:hover, .dd-btn:focus-visible { border-bottom-color: var(--ink); outline: none; }
.dd-btn:disabled { cursor: default; color: var(--muted); }
.dd-btn:disabled:hover { border-bottom-color: var(--faint); }
.dd-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-caret { color: var(--muted); line-height: 0; }
.dd-ic { width: 12px; height: 12px; }
.dd-btn.quiet { border-bottom-color: transparent; padding: 0; font-size: 12px; color: inherit; }
.dd-btn.quiet:hover { border-bottom-color: var(--faint); }
.field .dd { display: block; }
.field .dd-btn { width: 100%; justify-content: space-between; }
.dd-menu { padding: 4px 0; max-height: 60vh; overflow: auto; }
.dd-menu .item.on { color: var(--ink); font-weight: 600; }
.dd-menu .item:focus-visible { background: var(--hover); outline: none; }
.dd-pri .dd-val { color: inherit; }

/* ---------- right-click menu ---------- */

/* Timeline details card: opens beside a clicked bar or task name. */
.peek {
  position: fixed; z-index: 19; width: 360px; max-width: calc(100vw - 16px); padding: 14px 16px 10px;
  background: var(--bg); color: var(--ink); border: 1px solid var(--faint); border-radius: 10px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, .16), 0 2px 6px rgba(0, 0, 0, .06); font-size: 13px; line-height: 1.45;
}
:root[data-theme="dark"] .peek { box-shadow: 0 14px 40px rgba(0, 0, 0, .6); }
.peek-head { display: flex; align-items: flex-start; gap: 10px; }
.peek-head .check { align-content: start; padding-top: 4px; }
.peek-head h3 { flex: 1; margin: 0; font: 18px/1.3 var(--text); font-weight: normal; overflow-wrap: anywhere; }
.peek-head h3 .swatch { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 7px; vertical-align: 2px; }
.peek-head .ib { margin: -2px -6px 0 0; }
.peek-where { margin: 2px 0 8px 26px; font-size: 12px; color: var(--muted); }
.peek-line, .peek-rel { margin-left: 26px; padding: 5px 0; border-top: 1px solid var(--faint); }
.peek-rel { display: grid; grid-template-columns: 40px 1fr; gap: 8px; }
.peek-links { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.peek .k { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-right: 4px; }
.peek-rel .k { margin: 3px 0 0; }
.peek .sep { color: var(--faint); margin: 0 7px; }
.peek .st.doing { font-weight: 600; } .peek .st.blocked { color: var(--warn); } .peek .st.done { color: var(--ok); }
.peek .pri.high { color: var(--pri-high); } .peek .pri.medium { color: var(--pri-medium); } .peek .pri.low { color: var(--pri-low); }
.peek .late { color: var(--late); } .peek .ok { color: var(--ok); } .peek .soon { color: var(--pri-medium); font-weight: 600; }
.peek button.peek-link { text-align: left; padding: 0; font-size: 13px; white-space: normal; max-width: 100%; overflow-wrap: anywhere; line-height: 1.4; }
.peek button.peek-link.done { color: var(--muted); text-decoration: line-through; }
.peek-notes { margin-left: 26px; padding: 8px 0 4px; border-top: 1px solid var(--faint); white-space: pre-wrap; overflow-wrap: anywhere; max-height: 220px; overflow: auto; font: 14px/1.5 var(--text); }
.peek-notes.none { font: 12px var(--ui); color: var(--muted); }
.peek-foot { display: flex; justify-content: flex-end; margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--faint); }
.peek-foot .link { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; }

/* The confirmation card: opens by the pointer instead of the browser's box in the middle of the screen. */
.ask {
  position: fixed; z-index: 70; width: 290px; max-width: calc(100vw - 16px); padding: 12px 14px 8px;
  background: var(--bg); color: var(--ink); border: 1px solid var(--faint); border-radius: 10px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, .18), 0 2px 6px rgba(0, 0, 0, .06); font: 13px/1.45 var(--ui);
}
:root[data-theme="dark"] .ask { box-shadow: 0 14px 40px rgba(0, 0, 0, .6); }
.ask p { margin: 0 0 10px; overflow-wrap: anywhere; }
.ask-foot { display: flex; justify-content: flex-end; gap: 18px; padding-top: 6px; border-top: 1px solid var(--faint); }
.ask-foot .link { font-size: 13px; }
.ask-foot .link.danger { color: var(--late); }
.ask-foot .link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 3px; }

.ctx {
  position: fixed; z-index: 20; min-width: 168px; padding: 4px 0;
  background: var(--bg); color: var(--ink); border: 1px solid var(--faint); border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .14); font-size: 13px;
}
.ctx .ctx-head { padding: 4px 12px 2px; font-family: var(--text); font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 240px; }
.ctx button.item { display: block; width: 100%; text-align: left; padding: 4px 12px; border: 0; background: none; color: var(--ink); font: 13px var(--ui); cursor: pointer; }
.ctx button.item:hover { background: var(--hover); }
.ctx button.item.danger { color: var(--late); }
.ctx button.item kbd { float: right; color: var(--muted); font: 11px var(--ui); border: 0; padding: 0; }
.ctx .ctx-row { display: flex; gap: 10px; padding: 4px 12px; align-items: center; }
.ctx .ctx-row.swatch-row { padding: 6px 12px 5px; }
.ctx .ctx-row .swatches { gap: 5px; }
.ctx .ctx-row button.link { font-size: 12px; padding: 2px 0; }
.ctx .ctx-row button.link.on { color: var(--ink); font-weight: 600; }
.ctx .ctx-sep { height: 1px; background: var(--faint); margin: 3px 0; }

/* ---------- dialogs ---------- */

dialog {
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--faint); border-radius: 8px;
  padding: 24px 28px; width: min(560px, 92vw); max-height: calc(100dvh - 32px); font-size: 14px;
}
dialog.wide { width: min(880px, 94vw); }
dialog::backdrop { background: rgba(0, 0, 0, .25); }
dialog form { margin: 0; }
.dialog-foot { display: flex; gap: 18px; justify-content: flex-end; margin-top: 22px; font-size: 13px; }
.dialog-foot .left { margin-right: auto; display: flex; gap: 18px; }
.dialog-foot .danger { color: var(--late); }
.dialog-foot button.link.primary { color: var(--ink); font-weight: 600; }
.menu-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid var(--faint); }
.menu-rows { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; font-size: 15px; }
.share-actions { display: flex; gap: 18px; margin-top: 14px; font-size: 13px; }
#activity-list { font-size: 13px; }
#activity-list li { padding: 6px 0; border-top: 1px solid var(--faint); }
#activity-list li .muted { margin-right: 8px; }
.deps { max-height: 200px; overflow: auto; padding: 2px 0; }
.deps .dep-phase { font-size: 11px; color: var(--muted); letter-spacing: .06em; text-transform: uppercase; margin: 8px 0 2px; }
.deps label { display: flex; gap: 10px; align-items: baseline; padding: 2px 0; cursor: pointer; font-family: var(--text); font-size: 15px; }
.deps label.done { color: var(--muted); text-decoration: line-through; }
.deps input { accent-color: var(--ink); }
.hint { font-size: 12px; color: var(--muted); }
.error { color: var(--late); font-size: 13px; margin-top: 8px; }
#editor input[name="title"] { font-family: var(--text); font-size: 22px; padding: 4px 0; }
#editor details summary { cursor: pointer; color: var(--muted); font-size: 12px; list-style: none; }
#editor details summary::-webkit-details-marker { display: none; }
#editor .swatches { padding: 4px 0; }
.keys { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 28px; }
.keys h3 { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 500; margin: 0 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--faint); }
.keys dl + h3 { margin-top: 18px; }
.keys dl { margin: 0 0 4px; display: grid; grid-template-columns: minmax(96px, auto) 1fr; gap: 0 12px; font-size: 13px; }
.keys dt { color: var(--muted); white-space: nowrap; padding: 4px 0; border-bottom: 1px solid color-mix(in srgb, var(--faint) 60%, transparent); }
.keys dd { margin: 0; padding: 4px 0; border-bottom: 1px solid color-mix(in srgb, var(--faint) 60%, transparent); }
kbd { display: inline-block; min-width: 18px; text-align: center; font: 11px/1 var(--ui); padding: 3px 5px; border: 1px solid var(--faint); border-bottom-width: 2px; border-radius: 4px; color: var(--ink); background: var(--bg); }

/* ---------- phone ---------- */

@media (max-width: 760px) {
  .phone-only { display: inline; }
  .row-t, #content.with-area .row-t { grid-template-columns: 18px 24px minmax(0, 1fr) auto; grid-template-areas: "dot pri main date" ". . meta meta" ". . area area" ". . notes notes"; row-gap: 2px; }
  .row-t .t-priority { grid-area: pri; }
  .row-t .t-area { grid-area: area; }
  .sort-wrap { margin-left: 0; }
  .row-t .check { grid-area: dot; }
  .row-t .t-main { grid-area: main; }
  .row-t .t-date { grid-area: date; }
  .row-t .t-status { grid-area: meta; justify-self: start; }
  .row-t .t-notes { grid-area: notes; white-space: normal; }
  .row-t .t-side { grid-area: date; }
  .row-t.cols-head { display: none; }
  .row-t > .t-cell { border-left: 0; padding-left: 0; margin-left: 0; }
  #app { grid-template-columns: minmax(0, 1fr); }
  #sidebar {
    position: fixed; inset: 0; background: var(--bg); z-index: 6; height: 100dvh; box-shadow: none;
    transform: translateX(-100%); transition: transform var(--mid) var(--ease);
  }
  #app.show-sidebar #sidebar { transform: none; }
  .sidebar-top { padding-top: calc(20px + env(safe-area-inset-top)); }
  #nav .nav-row { padding: 11px 14px; }
  #nav .nav-row .act { opacity: 1; }
  #pane { padding: calc(16px + env(safe-area-inset-top)) max(18px, env(safe-area-inset-right)) 90px max(18px, env(safe-area-inset-left)); }
  #top { flex-wrap: wrap; gap: 8px 14px; }
  #open-sidebar { flex-basis: 100%; font-size: 13px; }
  #pane-title { font-size: 26px; white-space: normal; }
  #tools { margin: 10px 0 24px; flex-wrap: wrap; }
  #search { width: 140px; }
  #sync { display: none; }
  .area-head h2 { font-size: 22px; }
  .t-title { font-size: 16px; }
  .fields-2, .fields-3 { grid-template-columns: 1fr; }
  .keys { grid-template-columns: 1fr; }
  #tools { flex-wrap: wrap; gap: 10px 14px; }
  .tools-sep { display: none; }
  .seg { width: 100%; justify-content: stretch; }
  .seg button.toggle { flex: 1; text-align: center; }
  dialog { padding: 20px; }
  button.help { bottom: calc(14px + env(safe-area-inset-bottom)); }
}
@media (pointer: coarse) {
  button.link { padding: 10px 0; margin: -10px 0; }
  .row-t { padding-top: 11px; padding-bottom: 11px; }
  .dot::after { content: ""; position: absolute; inset: -14px; }
  button.theme::after { content: ""; position: absolute; inset: -15px; }
  .swatches button { width: 18px; height: 18px; }
  .ctx button.item { padding: 10px 14px; }
}

/* ---------- custom cursor (cursor.js; mouse and trackpad only) ---------- */

html.custom-cursor:not(.cursor-native), html.custom-cursor:not(.cursor-native) * { cursor: none !important; }
.cursor-dot, .cursor-ring {
  position: fixed; left: 0; top: 0; z-index: 2147483647; pointer-events: none;
  border-radius: 50%; will-change: transform; transform: translate3d(-100px, -100px, 0);
  transition: opacity var(--fast) var(--ease);
}
.cursor-dot { width: 4.5px; height: 4.5px; background: var(--ink); }
.cursor-ring {
  width: 19.5px; height: 19.5px; border: 1px solid var(--ink); opacity: 1;
  transition: opacity var(--fast) var(--ease), background-color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.cursor-ring.active { border-color: var(--muted); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.cursor-ring.pressed { background: color-mix(in srgb, var(--ink) 14%, transparent); }
html.cursor-native .cursor-dot, html.cursor-native .cursor-ring { opacity: 0 !important; }

/* ---------- task colours ----------
   Every task shows one colour, the same in all three views: its own if one was picked, otherwise its area's
   (taskColor() in app.js). Fills are the palette softened toward the box colour, so they stay quiet. */
:root {
  --t1: color-mix(in srgb, var(--c1) 55%, var(--node-bg)); --t2: color-mix(in srgb, var(--c2) 55%, var(--node-bg));
  --t3: color-mix(in srgb, var(--c3) 55%, var(--node-bg)); --t4: color-mix(in srgb, var(--c4) 55%, var(--node-bg));
  --t5: color-mix(in srgb, var(--c5) 55%, var(--node-bg)); --t6: color-mix(in srgb, var(--c6) 55%, var(--node-bg));
  --t7: color-mix(in srgb, var(--c7) 55%, var(--node-bg)); --t8: color-mix(in srgb, var(--c8) 55%, var(--node-bg));
}
/* The list: a thin stripe down the row's left edge. */
.row-t.tc { box-shadow: inset 3px 0 0 var(--tc); }
.row-t.tc:hover { background: color-mix(in srgb, var(--tc) 14%, var(--hover)); }

/* Timeline: arrows hide while zooming (they're redrawn when it stops); the empty chart can be dragged. */
.tl.zooming .tl-arrows { opacity: 0; }
.tl-lanes, .tl-head { cursor: grab; }
.tl.panning, .tl.panning * { cursor: grabbing !important; user-select: none; }

.row-t.cols-head .col { cursor: pointer; }

/* ---------- motion ----------
   Things that pop in also ease out; everything short (0.12 to 0.3s) on the same curve, and off entirely with
   reduced motion (the rule near the top). Exits use display transitions, so an element given [hidden] fades
   before it goes; browsers without that support just hide it at once. */
#tip, .peek, .ctx, .ask {
  transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease), display var(--fast) allow-discrete;
}
#tip[hidden], .peek[hidden], .ctx[hidden], .ask[hidden] { opacity: 0; transform: translateY(4px); }
@starting-style { #tip, .peek, .ctx, .ask { opacity: 0; transform: translateY(6px); } }
dialog {
  transition: opacity var(--mid) var(--ease), transform var(--mid) var(--ease), overlay var(--mid) allow-discrete, display var(--mid) allow-discrete,
    background-color var(--mid) var(--ease), color var(--mid) var(--ease), border-color var(--mid) var(--ease);
}
dialog[open] { opacity: 1; transform: none; }
dialog:not([open]) { opacity: 0; transform: translateY(6px); }
@starting-style { dialog[open] { opacity: 0; transform: translateY(6px); } }
dialog::backdrop { transition: background-color var(--mid) var(--ease), overlay var(--mid) allow-discrete, display var(--mid) allow-discrete; }
dialog:not([open])::backdrop { background-color: transparent; }
@starting-style { dialog[open]::backdrop { background-color: transparent; } }
/* Switching views or areas: the timeline eases in like the list and the flow do. */
.tl { animation: rise var(--mid) var(--ease) both; }
#content.settled .tl { animation: none; }
/* Small things that changed state without a transition. */
#nav .nav-row { transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease); }
.sort-mark .ic { transition: transform var(--mid) var(--ease); }
.check:not(:disabled):active .cb { transform: scale(.88); }
@keyframes pop { 0% { transform: scale(.7); } 60% { transform: scale(1.14); } 100% { transform: none; } }
.check.pop .cb { animation: pop .32s var(--ease) both; }
.quick form { animation: rise var(--fast) var(--ease) both; }
/* Light and dark: a short cross-fade while the theme switches. */
html.theme-shift *, html.theme-shift *::before, html.theme-shift *::after {
  transition: background-color .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease), fill .35s var(--ease), stroke .35s var(--ease), box-shadow .35s var(--ease) !important;
}

/* The colour key under each view, and the kind on the details card. */
.legend .l-kind::before { background: var(--kc); border-color: color-mix(in srgb, var(--kc) 70%, var(--ink) 30%); border-width: 1px; border-radius: 3px; }
.legend .l-break { flex-basis: 100%; height: 0; }
.legend .l-break::before { display: none; }

/* The 1 / 2 / 3 shortcut beside each view button: faint until hovered. */
.seg .key-hint { margin-left: 6px; font-size: 10px; color: var(--muted); opacity: .55; font-variant-numeric: tabular-nums; transition: opacity var(--fast) var(--ease); }
.seg button:hover .key-hint, .seg button.on .key-hint { opacity: .9; }
@media (pointer: coarse) { .seg .key-hint { display: none; } }

/* Priority as a mark, in its own narrow column at the front of the row. */
.row-t > .t-cell.t-priority { border-left: 0; padding-left: 0; margin-left: 0; justify-content: center; }
.pri-mark { background: none; border: 0; padding: 0; font-size: 9px; line-height: 1; color: inherit; cursor: pointer; }
.t-priority.high .pri-mark { color: var(--pri-high); }
.t-priority.medium .pri-mark { color: var(--pri-medium); }
.t-priority.low .pri-mark { color: var(--pri-low); }
.row-t.cols-head .col[data-col="priority"] { text-align: center; }
.row-t.cols-head .col[data-col="priority"] .col-sort { text-align: center; }
.row-t.cols-head .pri-mark { color: var(--muted); cursor: inherit; }
.node .n-meta .pri { line-height: 0; }

/* ---------- list: spacing and alignment (2026-09-18) ----------
   The mark at the front carries the priority, so the row no longer also wears a coloured stripe. Dates line up
   on the right with even-width digits; the other columns sit on the title's first line. */
.row-t.tc { box-shadow: none; }
.row-t.tc:hover { background: var(--hover); }
.row-t > .t-cell.t-date { justify-content: flex-end; text-align: right; font-variant-numeric: tabular-nums; }
.row-t.cols-head .col[data-col="target"], .row-t.cols-head .col[data-col="target"] .col-sort { text-align: right; }
.row-t > .t-cell.t-priority { padding-top: 12px; align-items: flex-start; justify-content: center; }
/* The three marks are drawn at one size; only the shape and colour differ. */
.t-priority .pri-mark { display: flex; align-items: center; justify-content: center; height: 23px; margin: 0; line-height: 1; }
.pri-ic { width: 13px; height: 13px; display: block; }
.node .n-meta .pri .pri-ic { width: 12px; height: 12px; display: inline-block; vertical-align: -2px; }
.pri-head { font-size: 13px; font-weight: 700; letter-spacing: 0; }
.t-cell, .t-notes { line-height: 1.5; }
.phase { margin: 26px 0 6px; }
.area-head { margin-bottom: 8px; }
@media (max-width: 760px) {
  .row-t, #content.with-area .row-t { column-gap: 10px; padding: 12px 0; margin: 0; }
  .row-t > .t-cell.t-priority { padding-top: 12px; }
}

/* Ready to start (nothing waiting on an arrow): the title carries a little more weight. */
.row-t.ready .t-title, .row-t.doing .t-title { font-weight: 600; }
.node.ready .n-title, .node.doing .n-title { font-weight: 600; }
.tl-bar.ready + .tl-when, .tl-title.ready { font-weight: 600; }

/* ---------- signing in, joining, resetting ---------- */
.gate-form { display: flex; flex-direction: column; gap: 10px; width: min(320px, 100%); margin: 6px 0 2px; }
.gate-form input { font-size: 15px; padding: 8px 0; }
.gate-form input:focus, .gate-form input:focus-visible { outline: none; border-bottom-color: var(--ink); }
.gate-form button { align-self: flex-start; margin-top: 4px; }
.gate .or { margin: 10px 0 2px; font-size: 12px; }
.gate .fine { font-size: 12px; max-width: 320px; line-height: 1.5; }
.err { color: var(--late); font-size: 13px; margin: 4px 0 0; }
.ws-switch { font-size: 13px; margin: -2px 0 2px; }
.ws-switch .dd-btn { color: var(--ink); }
#account-dialog .row, #admin-dialog .row { display: flex; align-items: center; gap: 10px; margin: 10px 0; }
#account-dialog .stack { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
#admin-dialog li { display: flex; align-items: baseline; gap: 8px; padding: 4px 0; font-size: 13px; flex-wrap: wrap; }
#admin-dialog code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; overflow-wrap: anywhere; }
#admin-dialog h3 { font-size: 15px; margin: 16px 0 4px; }

/* Tokens in the account panel. */
#account-dialog h3 { font-size: 15px; margin: 18px 0 4px; }
#account-dialog .fine { font-size: 12px; line-height: 1.5; margin: 0 0 8px; }
#token-list li { display: flex; align-items: baseline; gap: 10px; padding: 4px 0; font-size: 13px; }
#token-list li span:first-child { min-width: 140px; }
#token-list li .muted { flex: 1; }
.token-new { font-size: 13px; margin: 8px 0; }
.token-new code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; overflow-wrap: anywhere; background: var(--hover); padding: 2px 5px; border-radius: 4px; }

/* The account row at the top of the sidebar: a gear and who is signed in; the whole row opens the menu. */
/* The @ is set in the same type as the name, so the row reads as one word: @username. */

/* ---------- list cells: whole-cell clicks, and text on the title's first line ----------
   Every cell's text sits on the same line as the first line of the task's title (a 23px line, 12px down,
   the row's own padding), so the columns read straight across. */
.row-t > .t-cell { padding-top: 12px; line-height: 23px; align-items: flex-start; }
.row-t > .t-cell.t-notes { padding-top: 12px; line-height: 23px; }
.row-t > .t-cell .dd-btn.quiet { line-height: 23px; }
.row-t > .t-cell.t-date .t-date-text { line-height: 23px; }
.row-t > .t-cell.clickable { cursor: pointer; }
.row-t > .t-cell.clickable:hover { color: var(--ink); }
.row-t > .t-cell.t-priority.clickable:hover .pri-mark { transform: scale(1.15); }
.t-priority .pri-mark { transition: transform var(--fast) var(--ease); }
/* The due date's picker already covers its whole cell. */
.row-t > .t-cell.t-date { cursor: pointer; }

/* The account row: the @ and the name in one type, with room below before the icons. */

/* Typing a date into a start or due cell. */
.row-t > .t-cell.t-date { position: relative; gap: 4px; }
.row-t > .t-cell.t-start { justify-content: flex-end; text-align: right; font-variant-numeric: tabular-nums; }
.row-t.cols-head .col[data-col="start"], .row-t.cols-head .col[data-col="start"] .col-sort { text-align: right; }
input.date-type { width: 100%; min-width: 0; font: inherit; font-size: 12px; color: var(--ink); line-height: 22px; padding: 0 0 0 2px; border: 0; border-bottom: 1px solid var(--ink); background: none; text-align: right; }
input.date-type:focus { outline: none; }
button.date-cal { background: none; border: 0; padding: 0; color: var(--muted); cursor: pointer; line-height: 0; align-self: center; }
button.date-cal:hover { color: var(--ink); }
button.date-cal .ic { width: 13px; height: 13px; margin: 0; }
input.date-pick-hidden { position: absolute; right: 0; bottom: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; border: 0; padding: 0; }
@media (max-width: 760px) { .row-t .t-start { display: none; } }

/* ---------- settings (one modal: account, appearance, this list, site, shortcuts) ---------- */

dialog.settings { padding: 0; width: min(560px, 94vw); }
.settings-head { display: flex; align-items: baseline; gap: 12px; padding: 20px 26px 14px; border-bottom: 1px solid var(--faint); position: sticky; top: 0; background: var(--bg); z-index: 1; }
.settings-head h2 { margin: 0; }
.settings-head .link { font-size: 13px; align-self: center; }
.settings-body { padding: 4px 26px 24px; max-height: min(78vh, 760px); overflow: auto; }
.set-sec { padding: 16px 0; border-bottom: 1px solid var(--faint); }
.set-sec:last-child { border-bottom: 0; }
.set-sec > h3, .set-sec-head h3 { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); font-weight: 500; margin: 0 0 12px; }
.set-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.set-sec-head h3 { margin: 0; }
.set-sec-head #m-role { font-size: 12px; }
.set-sec #acct-who { margin: 0; }
/* Who is signed in, and the way out, on one line. Sign out is the one red thing in Settings. */
.acct-who-row { margin-bottom: 12px; }
.set-sec .set-signout { color: var(--late); }
.set-sec .set-signout:hover, .set-sec .set-signout:focus-visible { color: var(--late); }
.set-sec .link { display: block; padding: 8px 0; font-size: 14px; }
.set-row { display: flex; align-items: center; gap: 14px; padding: 7px 0; font-size: 14px; }
.set-row > span:first-child { flex: 1; }
.set-row .fine { font-size: 12px; }
.set-row .toggle { flex: 0 0 auto; }
.theme-seg { padding: 3px; }
.theme-seg button.toggle { padding: 4px 16px; border-radius: 6px; font-weight: 400; transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease); }
.theme-seg button.toggle::after { display: none; }
.theme-seg button.toggle.on { background: var(--bg); color: var(--ink); font-weight: 500; box-shadow: 0 1px 2px rgba(0, 0, 0, .06); }

/* A feature whose backend is ready but the UI isn't: shown, greyed out, with a solid WIP chip, never clickable. */

.set-shortcuts > summary { cursor: pointer; color: var(--muted); font-size: 11px; letter-spacing: .09em; text-transform: uppercase; list-style: none; width: max-content; }
.set-shortcuts > summary::-webkit-details-marker { display: none; }
.set-shortcuts > summary::before { content: "\25B8"; margin-right: 6px; display: inline-block; transition: transform var(--fast) var(--ease); }
.set-shortcuts[open] > summary::before { transform: rotate(90deg); }
.set-shortcuts[open] > summary { margin-bottom: 14px; }
.settings .keys { grid-template-columns: 1fr; gap: 0; }
.settings .keys h4 { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 500; margin: 16px 0 6px; padding-bottom: 5px; border-bottom: 1px solid var(--faint); }
.settings .key-group:first-child h4:first-child { margin-top: 0; }
@media (max-width: 760px) { .settings-head, .settings-body { padding-left: 20px; padding-right: 20px; } }

/* Password change in Settings: collapsed by default, left-aligned when open. */
.acct-pw { margin-top: 8px; }
.acct-pw > summary { cursor: pointer; color: var(--muted); list-style: none; width: max-content; }
.acct-pw > summary::-webkit-details-marker { display: none; }
.acct-pw > summary::before { content: "\25B8"; margin-right: 6px; display: inline-block; transition: transform var(--fast) var(--ease); }
.acct-pw[open] > summary::before { transform: rotate(90deg); }
.acct-pw > summary:hover { color: var(--ink); }
.acct-pw[open] > summary { margin-bottom: 10px; }
.acct-pw .stack { align-items: flex-start; }
.acct-pw .stack input { width: 100%; }

/* The account row's arrow: slides toward the name on hover and stays there until the pointer leaves. */
/* 1px down puts the arrow on the middle of the lowercase letters, not the middle of the line box. */

/* ---------- flow toolbar: the consolidated "arrange" dropdown ---------- */
.flowbar .bar-menu { width: auto; gap: 5px; padding: 4px 8px; line-height: 1; font-size: 12px; }
.flowbar .bar-menu .ic { vertical-align: -3px; }
.flowbar .bar-menu .ib-label { color: inherit; }
.flowbar .bar-menu .bar-caret { display: inline-flex; margin-left: -1px; }
.flowbar .bar-menu .bar-caret .ic { width: 11px; height: 11px; }
/* The current choice in a right-click / dropdown menu, marked without an icon. */
.ctx button.item.on { font-weight: 600; color: var(--ink); }

/* ---------- settings: readability + one consistent row rhythm (2026-09-19) ----------
   Every row across every section shares the same height, centre alignment and spacing (the account rows had
   been taller and baseline-aligned, so the section read looser than the rest). The account identity is the
   section's primary line, in ink rather than small grey. */
.settings-body { padding: 6px 26px 26px; }
.settings .set-sec { padding: 20px 0; }
.settings .set-sec > h3, .settings .set-sec-head h3 { margin: 0 0 14px; }
.settings .set-row,
.settings .set-sec > .row { display: flex; align-items: center; gap: 14px; min-height: 36px; margin: 0; padding: 2px 0; font-size: 14px; }
.settings .set-sec > .row > .link { padding: 0; }
.settings .set-sec > .link { display: block; padding: 10px 0; font-size: 14px; }
.settings #acct-who { font-size: 14px; color: var(--ink); margin: 0; }
.settings #acct-google { font-size: 13.5px; }
.settings .acct-who-row, .settings .acct-pw { margin: 0; }
.settings .acct-pw > summary { display: inline-block; padding: 10px 0; font-size: 14px; color: var(--ink); }
.settings .acct-pw[open] > summary { padding-bottom: 6px; }
.settings .acct-pw[open] { margin-bottom: 8px; }
.settings .set-sec .fine { line-height: 1.55; }

/* ---------- ready dot: brighter, with a soft glow (2026-09-19) ---------- */
.node.ready::after,
.tl-bar.ready:not(.single)::before,
.tl-bar.single.ready::before {
  background: color-mix(in srgb, var(--ok) 50%, #ffffff);
  box-shadow: 0 0 10px 2px color-mix(in srgb, var(--ok) 78%, transparent), 0 0 4px 1px color-mix(in srgb, var(--ok) 96%, transparent);
}
/* Met (green) arrows lifted to match: a touch brighter with a soft green glow. */
.canvas path.edge.met { stroke: color-mix(in srgb, var(--ok) 85%, #ffffff); filter: drop-shadow(0 0 2px color-mix(in srgb, var(--ok) 50%, transparent)); }
.canvas .arrow.met { fill: color-mix(in srgb, var(--ok) 85%, #ffffff); }
/* The decluttered arrange button: no leading icon, just the label and caret. */
.flowbar .bar-menu { padding: 4px 9px; }

/* No accent stripe on flow boxes (2026-09-19): the priority mark and status border carry enough. */
.node::before { display: none; }

/* ---------- flow nodes: done vs not-ready (2026-09-19) ----------
   Done boxes are cross-hatched and greyed rather than struck through. Waiting (not-ready) boxes are greyed
   out so the ready and in-progress ones stand out. */
.node.done .n-title { text-decoration: none; }
.node.done { background: color-mix(in srgb, var(--muted) 10%, var(--node-bg)); border-color: var(--faint); }
.node.done .n-title, .node.done .n-meta { color: var(--muted); }
.node.done::after {
  content: ""; position: absolute; inset: 0; border-radius: 7px; pointer-events: none;
  background-image: repeating-linear-gradient(45deg, transparent 0 6px, color-mix(in srgb, var(--muted) 28%, transparent) 6px 7.5px);
}
.node.waiting { opacity: .55; }

/* Green "ready" dot removed from flow and timeline (2026-09-19); readiness reads from the tick box and weight. */
.node.ready::after,
.tl-bar.ready:not(.single)::before,
.tl-bar.single.ready::before { content: none; display: none; }
.tl-bar.ready:not(.single) .tl-bar-text { padding-left: 9px; }

/* Solid arrows in the flow (open dependencies were dashed; met ones stay green). */
.canvas path.edge.open { stroke-dasharray: none; }

/* ---------- flow nodes: greyer done boxes + hover-revealed tick (2026-09-19) ---------- */
/* Done boxes: wider hatch and more greyed out. */
.node.done { opacity: .55; }
.node.done::after { background-image: repeating-linear-gradient(45deg, transparent 0 11px, color-mix(in srgb, var(--muted) 36%, transparent) 11px 12.5px); }
/* The tick box on a flow node stays hidden until you hover the node (or select it), then slides and fades in.
   Touch devices have no hover, so it stays visible there. */
.node .check { width: 0; min-width: 0; margin-right: -11px; transition: width var(--fast) var(--ease), margin-right var(--fast) var(--ease); }
.node .check::before { inset: -14px -6px -14px -13px; }
.node .check .cb { opacity: 0; transform: scale(.6); transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease), background-color var(--fast) var(--ease), border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease); }
.node:hover .check, .node.selected .check { width: 20px; margin-right: 0; }
.node:hover .check .cb, .node.selected .check .cb { opacity: 1; transform: none; }
.node .check:not(:disabled):hover .cb { transform: scale(1.15); }
@media (hover: none) { .node .check { width: 20px; margin-right: 0; } .node .check .cb { opacity: 1; transform: none; } }

/* ---------- document links on areas and tasks (2026-09-20) ---------- */
.field-docs { gap: 8px; }
.links-edit { display: flex; flex-direction: column; gap: 10px; }
/* Attached documents as chips: a doc icon, the name, and (in an editor) a small cross. Same on the area's page. */
.doc-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.doc-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: 999px; max-width: 100%;
  background: var(--st-doing-bg); color: var(--st-doing-fg); font: 500 12.5px/1 var(--ui); text-decoration: none; white-space: nowrap;
  transition: filter var(--fast) var(--ease);
}
.doc-chip .ic { width: 14px; height: 14px; flex: 0 0 auto; }
.doc-chip .doc-label { overflow: hidden; text-overflow: ellipsis; }
.doc-chip:hover { filter: brightness(.96) saturate(1.1); }
:root[data-theme="dark"] .doc-chip:hover { filter: brightness(1.2); }
.doc-chip .doc-rename { font: inherit; color: inherit; background: none; border: 0; border-bottom: 1px solid currentColor; padding: 0; min-width: 60px; }
.doc-chip .doc-rm { display: inline-grid; place-items: center; width: 16px; height: 16px; margin: 0 -4px 0 2px; padding: 0; border: 0; border-radius: 50%; background: none; color: inherit; opacity: .6; cursor: pointer; }
.doc-chip .doc-rm .ic { width: 11px; height: 11px; }
.doc-chip .doc-rm:hover { opacity: 1; background: color-mix(in srgb, currentColor 14%, transparent); }
/* Under the chips: new Google Doc (an outlined pill) and "add existing", which reveals the paste line. */
.link-tools { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.link-tools > button.link { font-size: 13px; }
.link-add { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.link-add .link-url { flex: 1 1 200px; min-width: 0; }
.link-add > button.link { font-size: 13px; }
.doc-new {
  display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 11px 0 8px; border: 1px dashed var(--st-doing-fg); border-radius: 999px;
  background: none; color: var(--st-doing-fg); font: 500 12.5px/1 var(--ui); cursor: pointer; white-space: nowrap;
  transition: background-color var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.doc-new .ic { width: 14px; height: 14px; }
.doc-new:hover, .doc-new:focus-visible { background: var(--st-doing-bg); outline: none; }
.doc-new:disabled { opacity: .55; cursor: default; background: none; }

/* The area dialog: each block is its own section behind a hairline, so name, notes, documents and the actions read apart. */
dialog.area-dlg h2 { margin-bottom: 20px; }
dialog.area-dlg .field { margin-bottom: 0; padding: 18px 0; border-top: 1px solid var(--faint); }
dialog.area-dlg .field > span { margin-bottom: 4px; }
dialog.area-dlg .field:first-of-type { border-top: 0; padding-top: 0; }
dialog.area-dlg .dlg-note { margin: 0; padding: 16px 0 0; border-top: 1px solid var(--faint); line-height: 1.5; }
dialog.area-dlg .dialog-foot { margin-top: 18px; }
.area-docs { margin: 0 0 14px; }

/* ---------- sharing ---------- */
/* One panel for a whole list or one area: people, then the read-only link. Hairlines, no boxes. */
dialog.sharing { width: min(600px, 94vw); }
dialog.sharing h2 { margin-bottom: 6px; }
dialog.sharing .lede { margin: 0 0 20px; line-height: 1.5; }
.sh-sec { padding: 16px 0 18px; border-top: 1px solid var(--faint); }
.sh-sec h3 { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); font-weight: 500; margin: 0 0 10px; }
.sh-sec > p.muted { margin: 0 0 10px; line-height: 1.5; font-size: 13px; }
.sh-people li { display: flex; gap: 14px; align-items: center; min-height: 34px; padding: 4px 0; }
.sh-people li + li:not(.sh-invite) { border-top: 1px solid var(--faint); }
.sh-people .who { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sh-people .who .nm { color: var(--ink); }
.sh-people .fine { font-size: 12px; }
.sh-people li > .link { font-size: 12px; }
.sh-people .sh-role-dd .dd-btn { font-size: 13px; }
.sh-invite { display: block !important; padding: 0 0 10px !important; font-size: 13px; }
.sh-invite .row { display: flex; gap: 12px; align-items: center; margin-top: 6px; }
.sh-invite input { flex: 1; min-width: 0; font-size: 12px; }
.sh-add { display: flex; gap: 14px; align-items: center; margin-top: 10px; }
.sh-add input { flex: 1; min-width: 0; }
.sh-areas li { display: flex; gap: 14px; align-items: baseline; padding: 6px 0; }
.sh-areas li + li { border-top: 1px solid var(--faint); }
.sh-areas li .muted { margin-left: auto; font-size: 12px; }
dialog.sharing .share-actions { margin-top: 10px; }
dialog.sharing .row input { flex: 1; min-width: 0; }

/* Areas shared with me: the owner's first name, quietly, after the area's. */
#nav .nav-row .t .by { margin-left: 8px; font-family: var(--ui); font-size: 11px; color: var(--muted); }

/* ---------- other people, live ---------- */
/* Pointers on the flow canvas: an arrow and a first name, in the person's colour, over the boxes. */
.live-layer { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 2; }
.live-cur { position: absolute; left: 0; top: 0; will-change: transform; }
.live-cur svg { display: block; width: 18px; height: 18px; fill: var(--who); stroke: var(--bg); stroke-width: 1.2; stroke-linejoin: round; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .2)); }
.live-cur span { position: absolute; left: 14px; top: 16px; padding: 2px 7px; border-radius: 4px; background: var(--who); color: #fff; font: 600 11px/1.4 var(--ui); white-space: nowrap; }
/* A task someone has open: their initial on it, top right. */
.row-t { position: relative; }
.live-on { position: absolute; top: 4px; right: 4px; width: 17px; height: 17px; border-radius: 50%; display: grid; place-items: center; background: var(--who); color: #fff; font: 600 9px/1 var(--ui); pointer-events: auto; z-index: 1; }
.node .live-on { top: -7px; right: -7px; box-shadow: 0 0 0 2px var(--bg); }
/* Boxes someone else is dragging right now. */
.node.remote-moving { box-shadow: 0 0 0 2px var(--who), 0 8px 22px rgba(0, 0, 0, .12); }
/* Two people in the same task's editor. */
.live-note { margin: 0 0 14px; padding: 6px 0 6px 10px; border-left: 3px solid var(--who); font-size: 13px; color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .live-cur { transition: none; } }
