/* =========================================================
   Projects — what is its own, over the suite's web kit
   (/suite/tokens.css and /suite/kit.css, linked before this file):
   the frame, sign-in, Settings, notices and the brand's colours and
   fonts are the kit's. What is here is the sidebar's projects, the
   views (Next, a project as a list, a Gantt or a dashboard, every
   project at once), the task and Projects' own dialogs.
   No preprocessor and no build: native CSS variables and nothing else.
   ========================================================= */

/*
 * Projects' tokens, mapped to the kit's: the accent is the Projects magenta
 * from tokens.css (#B0308E on light, #E67FCB with ink on dark), the greys have
 * its hue, and yolk marks "now" (the today line) and nothing else. Both themes
 * come from the kit, which follows <html data-theme>.
 */
:root {
  --accent: var(--kit-accent);
  --accent-soft: var(--kit-accent-soft);
  --accent-text: var(--kit-on-accent);

  /* The brand's yolk marks "now" and nothing else: the today line. */
  --now: var(--kit-now);

  /* A task's state colours. They are the same in the list and in the Gantt:
     the colour means the same thing wherever you look at it. */
  --state-done: #8a9099;
  --state-overdue: #d13438;
  --state-at-risk: #e8a33d;
  --state-blocked: #7b61c9;
  --state-in-progress: var(--accent);
  --state-upcoming: #b9c0c8;
  --state-undated: #b9c0c8;
  /* The critical path, in blue: the pink it had before was mistaken for the
     magenta accent, and red already means "overdue". */
  --critical: #1f5fbf;

  --bg: var(--kit-bg);
  --bg-panel: var(--kit-panel);
  --bg-hover: var(--kit-hover);
  --text: var(--kit-text);
  --text-muted: var(--kit-muted);
  --border: var(--kit-border);
  --shadow: var(--kit-shadow);

  --radius: 10px;

  --safe-top: var(--kit-safe-top);
  --safe-bottom: var(--kit-safe-bottom);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/* The dark palette is the kit's, which hangs from data-theme like this one
   (theme.js resolves it before the first paint). Only what is Projects' own
   changes here. */
:root { color-scheme: light; }

:root[data-theme="dark"] {
  color-scheme: dark;
  --critical: #6ea2f0;
  --state-upcoming: #51474f;
  --state-undated: #51474f;
}

* { box-sizing: border-box; }

/* In dark mode the browser's default blue can barely be told apart from the
   background, so selecting text seemed to do nothing. It is set by hand. */
::selection { background: var(--accent); color: var(--accent-text); }

/**
 * The hidden attribute wins over any display further down.
 *
 * `hidden` only hides through the browser stylesheet's `[hidden] { display: none }`
 * rule, and any rule of our own that declares display beats it. When the
 * sign-in screen and the app both declared theirs, marking one hidden from
 * JavaScript did absolutely nothing: the sign-in screen stayed on top of the
 * app, covering it entirely, and only the first tap worked.
 */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;              /* only the central area scrolls */
  overscroll-behavior: none;
}

body {
  font: var(--look-body, 15px)/1.45 var(--kit-font);
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* Installed on an iPhone that only draws part of the screen (main.js, markCroppedCanvas): the
   strip it leaves below already keeps the home indicator clear, so no room is kept for it
   inside as well. The strip shows the body's background, the same as the add bar's. */
:root[data-canvas="cropped"] { --kit-safe-bottom: 0px; }

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

/* --------------------------------- fields -------------------------------- */

/* Projects' own forms (the task, its dialogs); the kit's screens bring theirs. */
/* One column that may shrink: an input's own width (an email field's is ~235 px) never pushes
   its dialog wider than it is. */
.field { display: grid; grid-template-columns: minmax(0, 1fr); gap: 5px; }
.field > span, .field > label { font-size: var(--look-footnote, 13px); color: var(--text-muted); }
.field > label { justify-self: start; cursor: pointer; }
.field input, .field select, .field textarea {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* -------------------------------- buttons -------------------------------- */

.button {
  padding: 10px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-panel);
  cursor: pointer;
  transition: background .12s ease;
}
.button:hover { background: var(--bg-hover); }
.button--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
  font-weight: 600;
}
.button--primary:hover { filter: brightness(1.08); background: var(--accent); }
.button[disabled] { opacity: .55; cursor: default; }

.icon-button {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  font-size: var(--look-body, 18px);
}
.icon-button:hover { background: var(--bg-hover); }
.icon-button--small { width: 28px; height: 28px; font-size: var(--look-body, 18px); }

/* --------------------------------- frame --------------------------------- */

/*
 * The kit's frame (shell.js) with Projects in it (frame.js). From 960 px the
 * task opens as a column on the right of the view, and the view takes the
 * whole width while none is open: the Gantt needs it. Below, the kit's two
 * screens.
 *
 * The sidebar's width is the kit's variable, not a number of Projects' own: in
 * a host (Cronum Work) the kit makes it wider, for the rail of modules beside
 * it. On its own the variable isn't set and it is 260 px, as always.
 */
@container kit-app (min-width: 960px) {
  .kit-app.projects-frame[data-layout="side"][data-panes="split"] .kit-shell {
    grid-template-columns: var(--kit-side-width, 260px) minmax(0, 1fr);
    grid-template-areas: "side banners" "side list";
  }
  .kit-app.projects-frame[data-layout="side"][data-panes="split"][data-task] .kit-shell {
    grid-template-columns: var(--kit-side-width, 260px) minmax(0, 1fr) minmax(340px, 400px);
    grid-template-areas: "side banners banners" "side list detail";
  }
  .kit-app.projects-frame:not([data-task]) .kit-pane--detail { display: none; }
}

/*
 * The sidebar folded away (the kit's): the view and the task, when one is
 * open, take the whole width under the bar.
 */
@container kit-app (min-width: 960px) {
  .kit-app.projects-frame[data-folded][data-layout="side"][data-panes="split"] .kit-shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas: "bar" "banners" "list";
  }
  .kit-app.projects-frame[data-folded][data-layout="side"][data-panes="split"][data-task] .kit-shell {
    grid-template-columns: minmax(0, 1fr) minmax(340px, 400px);
    grid-template-areas: "bar bar" "banners banners" "list detail";
  }
}

/* The view and the task fill their pane, and scroll inside it themselves. */
.kit-app .kit-pane.projects-pane { overflow: hidden; }
.kit-app .kit-pane.projects-pane:not([hidden]) { flex-direction: column; }
.kit-app[data-screen="list"] .kit-pane--list.projects-pane,
.kit-app[data-screen="detail"] .kit-pane--detail.projects-pane { display: flex; }
@container kit-app (min-width: 960px) {
  .kit-app.projects-frame .kit-pane--list.projects-pane { display: flex; }
  .kit-app.projects-frame[data-task] .kit-pane--detail.projects-pane { display: flex; }
}

.main {
  /* What sticks inside it (the chart's dates, the add bar) goes as far as this to sit flush
     against the edges: a sticky box stops at the padding, and the chart showed through the gap. */
  --main-pad: var(--look-gutter, 16px);
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  padding: var(--main-pad);
  padding-bottom: calc(var(--main-pad) + var(--safe-bottom));
}

/* The safety net against a blank screen (main.js): centred over everything. */
.boot-failed { position: fixed; inset: 0; display: grid; place-items: center; padding: 24px; background: var(--kit-bg); }

/* ----------------------------- empty states ------------------------------ */

.empty {
  max-width: 460px;
  margin: 12vh auto 0;
  text-align: center;
  color: var(--text-muted);
}
.empty h2 { color: var(--text); font-size: var(--look-title3, 19px); margin: 0 0 8px; }
.empty p { margin: 0 0 18px; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ----------------------------- state colours ----------------------------- */

.state-done { --state-color: var(--state-done); }
.state-overdue { --state-color: var(--state-overdue); }
.state-at_risk { --state-color: var(--state-at-risk); }
.state-blocked { --state-color: var(--state-blocked); }
.state-in_progress { --state-color: var(--state-in-progress); }
.state-upcoming { --state-color: var(--state-upcoming); }
.state-undated { --state-color: var(--state-undated); }

/* -------------------------------- sidebar -------------------------------- */

.projects-nav__list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1px; }
.projects-nav__title { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.projects-nav__title .kit-nav__section { flex: 1; }
.projects-nav__add { width: 32px; height: 32px; }
.projects-nav__empty { margin: 4px 10px; font-size: var(--look-subhead, 14px); color: var(--text-muted); }
/* A project: its emoji, its name over a thin bar of its progress, and how many are overdue. */
.projects-nav__project { height: auto; min-height: 44px; padding-block: var(--look-item-y, 7px); }
.projects-nav__icon { font-size: var(--look-body, 17px); flex: 0 0 auto; width: 22px; text-align: center; }
.projects-nav__body { flex: 1; min-width: 0; display: grid; gap: 5px; }
.projects-nav__body .kit-nav__label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.projects-nav__overdue { background: var(--state-overdue); color: #fff; border-radius: 999px; padding: 0 7px; font-weight: 600; }
/* A place in someone else's project offered and not answered yet: above the projects, to answer it. */
.offer {
  margin: 4px 6px 8px; padding: 10px; display: grid; gap: 6px;
  border: 1px solid var(--border); border-inline-start: 3px solid var(--project-color, var(--accent));
  border-radius: var(--radius, 8px); background: var(--bg-panel);
}
.offer__from { display: flex; align-items: center; gap: 6px; font-size: var(--look-footnote, 13px); color: var(--text-muted); min-width: 0; }
.offer__from .avatar { flex: 0 0 auto; }
.offer__project { font-size: var(--look-subhead, 14.5px); overflow-wrap: anywhere; }
.offer__role { font-size: var(--look-caption, 12px); color: var(--text-muted); }
.offer__buttons { display: flex; gap: 6px; }
.offer__buttons .button { flex: 1 1 0; }
.members__offer .members__name { color: var(--text-muted); }

/* ----------------------------- progress bar ------------------------------ */

.progress {
  display: block;
  height: 5px;
  border-radius: var(--look-r-xs, 3px);
  background: var(--bg-hover);
  overflow: hidden;
}
/* The fill takes the project's colour when it has one; otherwise, the app's.
   That is what makes them tell apart at a glance in the sidebar list. */
.progress__fill { display: block; height: 100%; background: var(--bar-color, var(--accent)); }
.progress--thin { width: 46px; flex: 0 0 auto; }

/* -------------------------------- avatars --------------------------------- */

.avatar {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  font-size: var(--look-caption, 12px);
  font-weight: 600;
}

/* -------------------------------- "Next" --------------------------------- */

.filter-bar { display: flex; gap: 8px; margin-bottom: 12px; }

/* View on the left, scale on the right, and apart: they are two different
   things and together they read as a single row of identical buttons. */
.view-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 12px;
}
.view-bar__scale { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.gantt__settings { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.pill {
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-panel);
  cursor: pointer;
  font-size: var(--look-subhead, 14px);
}
.pill.is-active { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }

.group {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: var(--look-section, 22px) 0 8px;
  font-size: var(--look-footnote, 13px);
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.group:first-child { margin-top: 0; }
.group--overdue { color: var(--state-overdue); }
.group--blocked { color: var(--state-blocked); }
.group__count {
  padding: 0 7px;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
  font-size: var(--look-caption, 12px);
}

/* ------------------------------- task list -------------------------------- */

.tasks { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }

.task {
  display: flex;
  align-items: center;
  gap: var(--look-row-gap, 10px);
  padding: var(--look-row-y, 9px) 12px var(--look-row-y, 9px) 10px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--state-color, var(--border));
  border-radius: var(--radius);
  background: var(--bg-panel);
  cursor: pointer;
}
.task:hover { background: var(--bg-hover); }
.task.is-open { outline: 2px solid var(--accent); outline-offset: -1px; }
.task.is-done .task__title { text-decoration: line-through; color: var(--text-muted); }
.tasks--tree .task { margin-left: var(--indent, 0); }

.checkbox {
  position: relative;
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border: 2px solid var(--border);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  color: var(--accent-text);
  font-size: var(--look-footnote, 13px);
  line-height: 1;
}
/**
 * The circle is 22 px, which a finger misses. And missing it is not harmless:
 * the tap lands on the row and opens the detail, exactly the opposite of what
 * you meant to do. This takes the touch area to 36 px without changing the drawing.
 */
.checkbox::after {
  content: '';
  position: absolute;
  inset: -7px;
  border-radius: 50%;
}
.checkbox:hover:not([disabled]) { border-color: var(--accent); }
.checkbox.is-checked { background: var(--accent); border-color: var(--accent); }
.checkbox[disabled] { opacity: .45; cursor: default; }

.task__body { flex: 1; min-width: 0; display: grid; gap: 3px; }
.task__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.task__milestone { color: var(--accent); }

.task__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: var(--look-footnote, 12.5px);
  color: var(--text-muted);
}
.task__state { color: var(--state-color); font-weight: 600; }

.project-tag { display: inline-flex; align-items: center; gap: 4px; }
.project-tag::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--project-color, var(--text-muted));
}
.blocked-tag {
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--state-blocked) 16%, transparent);
  color: var(--state-blocked);
}

.priority { padding: 1px 7px; border-radius: 999px; font-weight: 600; }
.priority--urgent { background: var(--state-overdue); color: #fff; }
.priority--high { background: color-mix(in srgb, var(--state-overdue) 16%, transparent); color: var(--state-overdue); }
.priority--medium { background: color-mix(in srgb, var(--state-at-risk) 20%, transparent); color: var(--state-at-risk); }
.priority--low { background: var(--bg-hover); }

.loading { color: var(--text-muted); padding: 24px; text-align: center; }

/* ----------------------------- project header ----------------------------- */

.project {
  padding: 4px 0 var(--look-head-y, 16px);
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
  display: grid;
  gap: 12px;
}
.project__icon {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: var(--look-r-lg, 12px);
  background: color-mix(in srgb, var(--project-color, var(--accent)) 18%, transparent);
  font-size: var(--look-title1, 26px);
  line-height: 1;
}
/* In the view's head (the kit's), beside the project's name: the line's height. */
.kit-head .project__icon { width: 36px; height: 36px; border-radius: var(--look-r-md, 10px); font-size: var(--look-title3, 20px); }
.project__description { margin: 0; color: var(--text-muted); font-size: var(--look-callout, 14px); }

.project__metrics { display: flex; flex-wrap: wrap; gap: 22px; }
.metric { display: grid; gap: 3px; min-width: 84px; }
.metric__label { font-size: var(--look-footnote, 12px); color: var(--text-muted); }
.metric__value { font-size: var(--look-headline, 17px); font-weight: 600; }
.metric__note { font-size: var(--look-footnote, 12px); }
.metric.is-alert .metric__value, .is-alert { color: var(--state-overdue); }
.metric.is-warning .metric__value { color: var(--state-at-risk); }

.team { display: flex; gap: 6px; }

/* -------------------------------- add bar --------------------------------- */

.add-task {
  position: sticky;
  bottom: 0;
  /* Above the chart it slides over: its bars, arrows and names stay inside it (.gantt). */
  z-index: 2;
  display: flex;
  gap: 8px;
  margin-top: 16px;
  /* Down to the view's very edge (below), keeping the home indicator's room inside. */
  padding: var(--look-bar-y, 12px) 0 calc(var(--look-bar-y, 10px) + var(--safe-bottom));
  background: linear-gradient(to top, var(--bg) 70%, transparent);
}
/* The view ends with the bar flush against its foot. With the view's padding below it, the bar
   floated that much above the bottom and the chart's rows showed through the gap. */
.main:has(> .add-task:last-child) { padding-bottom: 0; }
.add-task input {
  flex: 1;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-panel);
}

/* --------------------------------- detail --------------------------------- */

.detail {
  flex: 1;
  min-height: 0;
  background: var(--bg-panel);
  overflow-y: auto;
  padding: 12px var(--look-gutter, 16px) calc(24px + var(--safe-bottom));
  display: grid;
  /* One column that never grows past the panel. A plain grid column is as wide
     as its widest content, and a dropdown is as wide as its longest option: a
     long task title in the dependencies, or "Duration only (let the app place
     it)", stretched everything to 600 px and the panel scrolled
     sideways. minmax(0, …) lets the columns shrink; the controls follow. */
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: 12px;
}
.detail select, .detail input, .detail textarea { min-width: 0; max-width: 100%; }

.detail__breadcrumb { color: var(--text-muted); font-size: var(--look-footnote, 13px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The task's head is the kit's: where it is a screen of its own, ← closes it and × would say it twice. */
@container kit-app (max-width: 959px) {
  .detail__close { display: none; }
}

.detail__title {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 10px;
  background: var(--bg);
  font-size: var(--look-title2, 17px);
  font-weight: 600;
  resize: vertical;
}
.detail__title:hover:not([disabled]) { border-color: var(--text-muted); }
.detail__title[disabled] { background: transparent; border-color: transparent; }

.detail__body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.detail__state { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.detail__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.detail__note { color: var(--text-muted); font-size: var(--look-footnote, 12px); font-weight: 400; }
.detail__pct { font-weight: 600; }
.detail__notes { resize: vertical; }
.detail__footer { margin: 0; color: var(--text-muted); font-size: var(--look-footnote, 12.5px); }

.chip {
  padding: 2px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--state-color, var(--text-muted)) 16%, transparent);
  color: var(--state-color, var(--text-muted));
  font-size: var(--look-caption, 12.5px);
  font-weight: 600;
}

.notice {
  margin: 0;
  padding: 9px 12px;
  border-radius: var(--radius);
  font-size: var(--look-footnote, 13.5px);
}
.notice--blocked {
  background: color-mix(in srgb, var(--state-blocked) 14%, transparent);
  color: var(--state-blocked);
}
.notice--conflict {
  background: color-mix(in srgb, var(--state-overdue) 14%, transparent);
  color: var(--state-overdue);
}

/* ------------------------------ dependencies ------------------------------ */

.time__duration { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.time__number {
  width: 76px;
  padding: 7px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.time__duration select {
  padding: 7px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.notice--floating {
  background: color-mix(in srgb, var(--state-at-risk) 16%, transparent);
  color: var(--state-at-risk);
  margin-top: 10px;
}

.placement__order { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.placement__order .field__note { flex: 1; }

.dependencies__section { margin-bottom: 12px; }
.dependencies__section h4 {
  margin: 0 0 6px;
  font-size: var(--look-footnote, 12px);
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--text-muted);
}
/* Two rows: each dropdown full width, and below them the wait and the button. */
.dependencies__add {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
}
.dependencies__add select {
  grid-column: 1 / -1;
  min-width: 0;
  width: 100%;
  padding: 7px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.dependencies__wait { display: flex; align-items: center; gap: 6px; }
.dependencies__lag {
  width: 58px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.button--small { padding: 4px 10px; font-size: var(--look-footnote, 13px); }

/* ---------------------------- reschedule dates ---------------------------- */

.reschedule { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.reschedule li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: var(--look-row-y, 7px) 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: var(--look-subhead, 14px);
}
.reschedule__title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reschedule__from { color: var(--text-muted); text-decoration: line-through; }
.reschedule__arrow { color: var(--text-muted); }
.reschedule__to { font-weight: 600; }
.reschedule__days {
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--state-at-risk) 20%, transparent);
  color: var(--state-at-risk);
  font-size: var(--look-caption, 12.5px);
  font-weight: 600;
}

.detail__block h3 { margin: 0 0 8px; font-size: var(--look-headline, 14px); }
.breakdown { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 4px; }
.breakdown li { display: flex; align-items: center; gap: 8px; font-size: var(--look-body, 14px); }
.breakdown li.is-done .breakdown__title { text-decoration: line-through; color: var(--text-muted); }
.breakdown__title {
  flex: 1;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  padding: 2px 0;
}
.breakdown__title:hover { text-decoration: underline; }
/* Only the field for adding a part. This rule used to be `.detail__breakdown
   input`, and since the dependencies block reused that same class, it forced
   a 100 % width on its days field: it ate the whole row and left the two
   dropdowns at eighteen pixels, that is, a tiny arrow. */
.breakdown__new {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

/* ------------------------------- task files -------------------------------- */

.files__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}
.file {
  position: relative;
  aspect-ratio: 1;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg);
}
.file__open {
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: pointer;
}
.file--photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.file__pdf { font-size: var(--look-footnote, 13px); font-weight: 700; color: var(--state-overdue); }
.file__name {
  max-width: 100%;
  padding: 0 6px;
  font-size: var(--look-caption2, 11px);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file__remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font-size: var(--look-caption2, 11px);
  line-height: 22px;
  cursor: pointer;
}
.file__remove:hover { background: rgba(0, 0, 0, .75); }
.task__files { color: var(--text-muted); font-size: var(--look-footnote, 12.5px); white-space: nowrap; }

/* The photo full screen: a tap or Esc closes it. */
.viewer {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 16px 16px 56px;
  background: rgba(0, 0, 0, .88);
  cursor: zoom-out;
}
.viewer img { max-width: 100%; max-height: calc(100vh - 88px); object-fit: contain; border-radius: var(--look-r-xs, 4px); }
.viewer__footer {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: calc(14px + var(--safe-bottom));
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: #fff;
  font-size: var(--look-subhead, 14px);
}
.viewer__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.viewer__footer a { color: #fff; font-weight: 600; flex: none; }

/* --------------------------------- notices --------------------------------- */

.button--danger { color: var(--state-overdue); border-color: var(--state-overdue); background: transparent; }
.button--danger:hover { background: color-mix(in srgb, var(--state-overdue) 12%, transparent); }

/* On narrow screens the task's fields go one under the other. */
@media (max-width: 900px) {
  .detail__grid { grid-template-columns: minmax(0, 1fr); }
}

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

.dialog {
  width: min(92vw, 460px);
  padding: 0;
  border: 0;
  border-radius: var(--look-r-xl, 14px);
  background: var(--bg-panel);
  color: var(--text);
  box-shadow: var(--shadow);
}
.dialog::backdrop { background: rgba(0, 0, 0, .45); }
/* The keyboard is up (the kit's keyboard.js sets the dialog on it, no taller than
   the room it leaves): the body shrinks and scrolls, so the header and the
   buttons stay in reach instead of going under the dialog's edge. */
:root[data-kit-keyboard] .dialog[open] { display: flex; flex-direction: column; }
:root[data-kit-keyboard] .dialog__header, :root[data-kit-keyboard] .dialog__actions { flex: none; }
:root[data-kit-keyboard] .dialog__body { flex: 0 1 auto; min-height: 0; max-height: none; }

.dialog__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 14px 12px 10px 20px;
  border-bottom: 1px solid var(--border);
}
.dialog__header h2 { margin: 0; font-size: var(--look-title2, 17px); }
.dialog__body { padding: 16px 20px; max-height: 70vh; overflow-y: auto; }
.dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 20px calc(16px + var(--safe-bottom));
  border-top: 1px solid var(--border);
}

.form { display: grid; gap: 14px; }
.form h3 { margin: 6px 0 0; font-size: var(--look-headline, 14px); }
.form__row { display: flex; gap: 10px; align-items: flex-end; }
.form__row .field { flex: 1; min-width: 0; }
/* A row that goes down a line when it doesn't fit (a phone): the team's "add" — email, role, button. */
.form__row--wrap { flex-wrap: wrap; }
.form__row--wrap .field:first-child { flex: 1 1 200px; }
.form__row--wrap .field { flex: 1 1 120px; }
.form__row--wrap > .button { flex: none; }
.field--icon { width: 66px; text-align: center; font-size: var(--look-title3, 20px); }
.field__note { color: var(--text-muted); font-size: var(--look-footnote, 12.5px); }

.icons { display: flex; flex-wrap: wrap; gap: 5px; margin-top: -6px; }
.icons__item {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--bg);
  cursor: pointer;
  font-size: var(--look-body, 18px);
  line-height: 1;
}
.icons__item:hover { background: var(--bg-hover); }
.icons__item.is-selected { border-color: var(--accent); background: var(--accent-soft); }

.palette { display: flex; flex-wrap: wrap; gap: 8px; }
.swatch {
  width: 28px;
  height: 28px;
  border: 2px solid transparent;
  border-radius: 50%;
  cursor: pointer;
}
.swatch.is-selected { border-color: var(--text); }

.members { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.members li { display: flex; align-items: center; gap: var(--look-row-gap, 10px); }
.members__name { flex: 1; min-width: 0; }

/* =============================== DASHBOARD ================================ */

.dashboard {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: start;
}

.card {
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-panel);
}
.card h3 { margin: 0 0 12px; font-size: var(--look-headline, 14px); }
.card__note { margin: 10px 0 0; color: var(--text-muted); font-size: var(--look-footnote, 12.5px); }

/* The summary takes the full width: it is the first thing people look at. */
.card--summary {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 28px;
  flex-wrap: wrap;
}
.dashboard__figures { display: flex; gap: 28px; flex-wrap: wrap; }

.chart { display: block; max-width: 100%; overflow: visible; }
/* Full width keeping the viewBox's proportion: if only the width is
   stretched, the text inside gets distorted. */
.chart--bars, .chart--burndown { width: 100%; height: auto; }
/* A cap so that on a wide screen it doesn't grow until it looks silly. */
.chart--burndown { max-width: 620px; }
.card--wide { grid-column: 1 / -1; }
.chart__figure { font-size: var(--look-title1, 26px); font-weight: 700; fill: var(--text); }
.chart__caption { font-size: var(--look-caption2, 10.5px); fill: var(--text-muted); }
.chart__label { font-size: var(--look-footnote, 12.5px); fill: var(--text-muted); }
.chart__bar-figure { font-size: var(--look-footnote, 12.5px); font-weight: 600; fill: var(--text); }
.chart__axis { font-size: var(--look-caption2, 11px); fill: var(--text-muted); }
.chart__grid { stroke: var(--border); stroke-width: 1; }

.chart__actual { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linejoin: round; }
.chart__ideal {
  fill: none;
  stroke: var(--text-muted);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
  opacity: .7;
}
.chart__point { fill: var(--accent); }

.legend {
  display: inline-block;
  width: 14px;
  height: 3px;
  margin-right: 5px;
  vertical-align: middle;
  border-radius: var(--look-r-xs, 2px);
}
.legend--actual { background: var(--accent); }
.legend--ideal { background: var(--text-muted); opacity: .7; }

.milestones { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.milestones li { display: flex; align-items: center; gap: var(--look-row-gap, 9px); font-size: var(--look-body, 14px); }
.milestones__diamond { color: var(--state-color, var(--accent)); }
.milestones__title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.milestones__date { color: var(--text-muted); font-size: var(--look-footnote, 13px); }

/* ================================= GANTT ================================== */

.zoom { display: flex; gap: 6px; }

.gantt {
  --gantt-header: 44px;
  --gantt-list: 220px;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-panel);
  /* Clip, not hidden: hidden makes the chart a box that scrolls, and the dates would stick to
     it, which never moves, instead of to the page. Where clip isn't known, hidden stays. */
  overflow: hidden;
  overflow: clip;
  /* Its bars, arrows and today line keep their order among themselves and no longer go over
     what is outside the chart, such as the add bar sliding over it at the bottom. */
  isolation: isolate;
}

/* --- the dates, on top while the page goes down (ganttFrame) --- */

.gantt__top {
  position: sticky;
  top: calc(-1 * var(--main-pad, 16px));
  z-index: 1;
  display: flex;
  background: var(--bg-panel);
}
.gantt__dates {
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
.gantt__dates::-webkit-scrollbar { display: none; }

/* Below them, the names and the canvas. Its own layer, so that a bar being dragged doesn't
   go over the dates. */
.gantt__main { display: flex; isolation: isolate; }

/* --- fixed column on the left --- */

.gantt__list {
  /* The width goes on its own and not inside the `flex` shorthand: with var()
     inside the shorthand, changing the variable in a media query doesn't
     recompute flex-basis. */
  flex: 0 0 auto;
  width: var(--gantt-list);
  border-right: 1px solid var(--border);
  background: var(--bg-panel);
  z-index: 2;
}
.gantt__spacer {
  flex: 0 0 auto;
  width: var(--gantt-list);
  height: var(--gantt-header);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.gantt__rows { list-style: none; margin: 0; padding: 0; }

.gantt__row {
  display: flex;
  align-items: center;
  padding-left: calc(10px + var(--indent, 0px));
  padding-right: 8px;
  font-size: var(--look-footnote, 13px);
  cursor: pointer;
}
/* Must match the canvas striping, which shades the odd rows. */
.gantt__row:nth-child(even of .gantt__row) { background: var(--bg); }
.gantt__row:hover { background: var(--bg-hover); }
.gantt__row.is-open { background: var(--accent-soft); font-weight: 600; }
.gantt__row.is-done .gantt__row-text { text-decoration: line-through; color: var(--text-muted); }
.gantt__row-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --- canvas --- */

.gantt__canvas { flex: 1; min-width: 0; overflow-x: auto; overflow-y: hidden; }

/* Two fingers on the chart don't zoom the page, nor does a double tap: the chart has its own scale
   (Days, Weeks, Months), and a page zoomed in left the frame and its bars off screen. One finger
   still scrolls every way. */
.gantt, .gantt * { touch-action: pan-x pan-y; }

/* --- the sideways scrollbar, at the foot of the view (ganttFrame) --- */

/* Only with a mouse: a finger swipes the chart itself, and there the strip would be an empty band.
   With it, the canvas's own scrollbar, at the very end of a long chart, goes. */
.gantt__foot { display: none; }
@media (pointer: fine) {
  .gantt__foot {
    position: sticky;
    /* Just above the add bar, which sticks to the same foot (--gantt-foot, measured). */
    bottom: var(--gantt-foot, 0px);
    z-index: 1;
    display: flex;
    border-top: 1px solid var(--border);
    background: var(--bg-panel);
  }
  .gantt__canvas { scrollbar-width: none; }
  .gantt__canvas::-webkit-scrollbar { display: none; }
}
.gantt__foot-spacer { flex: 0 0 auto; width: var(--gantt-list); border-right: 1px solid var(--border); }
/* A floor of height, for the scrollbars drawn over the content (macOS): in a box one pixel high
   they would never show. */
.gantt__scroll { flex: 1; min-width: 0; min-height: 12px; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
.gantt__track { height: 1px; }

/* With a mouse, an empty spot of the chart is held and dragged to look around (connectPan). */
@media (pointer: fine) {
  .gantt__body { cursor: grab; }
  .gantt__canvas.is-panning, .gantt__canvas.is-panning * { cursor: grabbing; }
}

.gantt__header {
  height: var(--gantt-header);
  border-bottom: 1px solid var(--border);
  background: var(--bg-panel);
}
.gantt__band { position: relative; height: 21px; }
.gantt__band--top { border-bottom: 1px solid var(--border); }
.gantt__cell {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: 1px solid var(--border);
  font-size: var(--look-caption2, 11px);
  color: var(--text-muted);
  overflow: hidden;
  white-space: nowrap;
}
.gantt__band--top .gantt__cell {
  justify-content: flex-start;
  padding-left: 7px;
  font-weight: 600;
  /* Clip, not hidden: hidden would make the cell the box its label sticks to. */
  overflow: clip;
}
/* The month's name stays at the strip's left edge while its month is in view, and the next one
   pushes it out: a month that began off screen still says which it is (gantt.js, dateHeader). */
.gantt__band--top .gantt__label { position: sticky; left: 7px; }
.gantt__cell.is-weekend { opacity: .55; }

.gantt__body { position: relative; }

/* Stronger than before: at 5 % it could barely be seen and you had to look for it. */
.gantt__weekend {
  position: absolute;
  top: 0;
  bottom: 0;
  background: color-mix(in srgb, var(--text) 11%, transparent);
}
.gantt__vline { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--border); opacity: .55; }
.gantt__row-band { position: absolute; left: 0; right: 0; background: var(--bg); }

.gantt__today {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--now);
  z-index: 4;
  pointer-events: none;
}

.gantt__arrows { position: absolute; top: 0; left: 0; pointer-events: none; z-index: 3; }
.gantt__arrow { fill: none; stroke: var(--text-muted); stroke-width: 1.4; opacity: .85; }
.gantt__arrow.is-critical { stroke: var(--critical); stroke-width: 2; opacity: 1; }
.gantt__arrowhead { fill: var(--text-muted); }
.gantt__arrowhead.is-critical { fill: var(--critical); }

/* --- bars --- */

.gantt__bar {
  position: absolute;
  z-index: 5;
  border-radius: var(--look-r-xs, 5px);
  /* The whole bar is the time span; the solid part, what is already done. */
  background: color-mix(in srgb, var(--state-color) 30%, transparent);
  border: 1px solid var(--state-color);
  cursor: grab;
  /* No touch-action: none. It made every swipe that began on a bar move it; now a finger scrolls
     over the bars and picks one up only by holding it (gantt.js, afterHold). */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.gantt__bar:hover { filter: brightness(1.15); }
.gantt__bar.is-static { cursor: pointer; }
.gantt__bar.is-dragging { cursor: grabbing; opacity: .8; z-index: 6; }
.gantt__bar[data-zone="move"] { cursor: grab; }
.gantt__bar[data-zone="start"], .gantt__bar[data-zone="end"] { cursor: ew-resize; }

.gantt__progress {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  background: var(--state-color);
  border-radius: var(--look-r-xs, 4px) 0 0 var(--look-r-xs, 4px);
}

/* --- handles for linking --- */

.gantt__handle {
  position: absolute;
  top: 50%;
  width: 11px;
  height: 11px;
  margin-top: -5.5px;
  border: 2px solid var(--bg-panel);
  border-radius: 50%;
  background: var(--state-color);
  cursor: crosshair;
  opacity: 0;
  transition: opacity .12s ease;
  z-index: 7;
}
.gantt__handle--start { left: -6px; }
.gantt__handle--end { right: -6px; }

/* They show up when you get close to the bar. On a touch screen there is no
   "getting close", so there they always stay visible: better a bit of noise than
   an invisible feature, which has already happened twice in this project. */
.gantt__bar:hover .gantt__handle { opacity: 1; }
.gantt__handle:hover { opacity: 1; transform: scale(1.25); }

@media (hover: none) {
  .gantt__handle { opacity: .75; }
}

/* With a finger, the handles sit just outside the bar, with a wider invisible ring to hold: on its
   edges they covered the stretch of bar that changes its length, and every try drew a link. */
@media (hover: none) and (pointer: coarse) {
  .gantt__handle--start { left: -22px; }
  .gantt__handle--end { right: -22px; }
  .gantt__handle::after { content: ''; position: absolute; inset: -9px; }
}

.gantt__body.is-linking { cursor: crosshair; }
.gantt__rubber-band {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 5 4;
  pointer-events: none;
}

.gantt__bar--phase {
  border-radius: var(--look-r-xs, 2px);
  background: var(--text-muted);
  border-color: var(--text-muted);
}
.gantt__bar--phase .gantt__progress { background: var(--text); border-radius: var(--look-r-xs, 2px) 0 0 var(--look-r-xs, 2px); }

.gantt__bar--milestone {
  border-radius: 2px;
  background: var(--state-color);
  transform: rotate(45deg);
}

/* The critical path is marked with an outline, not by changing the fill colour:
   the colour already means the task's state and cannot mean two things. */
.gantt__bar.is-critical { box-shadow: 0 0 0 2px var(--critical); }
.gantt__bar.is-conflict { border-style: dashed; border-width: 2px; }

.gantt__arrow.is-conflict { stroke: var(--state-overdue); stroke-dasharray: 4 3; opacity: 1; }

@media (max-width: 780px) {
  .gantt { --gantt-list: 140px; }
  .gantt__row { font-size: var(--look-footnote, 12.5px); }
}

/* -------------------------- all projects at once -------------------------- */

.gantt--overview { --gantt-list: 250px; }

.gantt__row--project {
  gap: 4px;
  padding-left: 4px;
  font-weight: 600;
  border-left: 3px solid var(--project-color, var(--accent));
}
.gantt__row--nested { padding-left: calc(10px + var(--indent, 0px)); font-size: var(--look-footnote, 12.5px); }

.overview__toggle {
  flex: 0 0 auto;
  width: 22px;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--text-muted);
  font-size: var(--look-caption, 12px);
}
.overview__name {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: transparent;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  padding: 0;
}
.overview__name:hover { text-decoration: underline; }

.gantt__bar--project {
  border-radius: var(--look-r-xs, 6px);
  background: color-mix(in srgb, var(--project-color) 30%, transparent);
  border: 1px solid var(--project-color);
  cursor: pointer;
}
.gantt__bar--project .gantt__progress { background: var(--project-color); border-radius: var(--look-r-xs, 5px) 0 0 var(--look-r-xs, 5px); }
.gantt__bar--project.is-alert { box-shadow: 0 0 0 2px var(--state-overdue); }

.overview__label {
  position: absolute;
  left: 8px;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--look-caption, 12px);
  font-weight: 600;
  color: var(--text);
  pointer-events: none;
}

@media (max-width: 780px) {
  .gantt--overview { --gantt-list: 160px; }
}

/* ============================== ROW DRAGGING ============================== */
/* The pointer, the card that says where it lands, the dashed gap and the row
   lit up for "inside" are the kit's (drag.js, kit.css). */

/* Dragging a task's name doesn't select its text. */
.kit-draggable > [data-id] {
  user-select: none;
  -webkit-user-select: none;
}

/* The label that follows the pointer. It is the one that really says where it
   will land: two pixels of difference decide between "after" and "inside",
   and that must be readable before dropping, not discovered afterwards. */
.drag-notice {
  position: fixed;
  z-index: 60;
  max-width: min(320px, 70vw);
  padding: 6px 10px;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-text);
  box-shadow: var(--shadow);
  font-size: var(--look-footnote, 12.5px);
  line-height: 1.35;
  pointer-events: none;
}
.drag-notice__what { display: block; }
.drag-notice__where { display: block; opacity: .85; font-size: var(--look-caption, 11.5px); }
.drag-notice.is-rejected { background: var(--state-overdue); color: #fff; }
.drag-notice.is-unchanged { background: var(--text-muted); color: #fff; }

/* ================================= CLEAN ================================== */
/* The Clean look (<html data-look="clean">): the sizes above are the kit's --look-* variables,
   and this is what only Clean changes besides. The view's large title is the kit's head. Bigger
   text must not push a phone's view sideways: the dashboard's cards, the add bar's field and the
   view's pills give way at 320 px. */
:root[data-look="clean"] { --radius: var(--look-r-md, 10px); }
:root[data-look="clean"] .button:not(.button--small) { font-size: var(--look-subhead, 15px); }
:root[data-look="clean"] .card { border-radius: var(--look-r-lg, 10px); }
:root[data-look="clean"] :is(.group, .dependencies__section h4) { font-weight: 600; letter-spacing: .02em; }
:root[data-look="clean"] .dependencies__lag { width: 66px; }
:root[data-look="clean"] .add-task input { min-width: 0; }
:root[data-look="clean"] .zoom { flex-wrap: wrap; }
:root[data-look="clean"] .dashboard { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
/* A quiet sidebar, the same in every module: 16px entries, the open one in its colour without going bold. */
:root[data-look="clean"] .kit-nav__item { min-height: 40px; padding-block: 8px; font-size: var(--look-callout, 15px); }
:root[data-look="clean"] .kit-nav__item[aria-current="page"] { font-weight: 500; }
