@layer components {
  /* Projects (D-16)

     The same row rhythm as a task list, one rail shorter: a project has a name,
     how much is left in it, and a date. No reference — a project is called by
     its name in a way a task never is. */

  .project-list { list-style: none; margin: 0; padding: 0; }

  .project {
    position: relative;
    display: grid;
    grid-template-columns:
      var(--rail-status) minmax(0, 1fr) var(--rail-when) var(--rail-who) var(--rail-pull);
    align-items: center;
    column-gap: var(--space-2);
    min-height: var(--row-h);
    padding: var(--space) var(--space-2);
    margin-inline: calc(var(--space-2) * -1);
    border-radius: var(--radius);
    transition: background var(--transition);
  }

  /* The project row has no pull of its own; the trailing rail is there so a
     project and a task line up on the same right-hand edge. So when the task
     list stops keeping that rail (task-list.css, the same breakpoint), this
     stops keeping it too — otherwise the two lists agree everywhere except
     where they are read together. */
  @media (width >= 80rem) {
    .project {
      grid-template-columns:
        var(--rail-status) minmax(0, 1fr) var(--rail-when) var(--rail-who);
    }
  }

  .project__lead { width: var(--rail-status); }

  .project:hover { background: var(--surface-hover); }
  .project:has(.project__name:focus-visible) { background: var(--surface-hover); }

  .project__name {
    font-size: var(--text-md);
    letter-spacing: var(--tracking-tight);
    color: var(--ink);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .project__name::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
  .project__name:hover { text-decoration: underline; text-decoration-thickness: 1.5px; }

  .project__remaining {
    display: flex;
    justify-content: flex-end;
    font-size: var(--text-sm);
    color: var(--ink-muted);
    white-space: nowrap;
  }

  .project__due { display: flex; justify-content: flex-end; }

  /* Starting one is naming it, so the field is the form — and the field and its
     button stay on one line. .input carries width: 100%, which as a flex basis
     is wide enough to push the button onto a row of its own; min-width: 0 lets
     it shrink back to what is actually there. */
  .project-start { flex-wrap: nowrap; align-items: stretch; }
  .project-start__input { flex: 1 1 auto; width: auto; min-width: 0; }

  /* Finished business, present but folded away. */
  .archive { margin-top: var(--space-2); }

  .archive__summary {
    font-size: var(--text-sm);
    color: var(--ink-faint);
    cursor: pointer;
    padding: var(--space) 0;
    list-style-position: inside;
  }

  .archive__summary { transition: color var(--transition), var(--responds); }
  .archive__summary:hover { color: var(--ink-muted); }

  /* Finished business, unfolding

     ::details-content is the only handle a browser offers on the part of a
     <details> that is not its summary, and it is what makes this animatable
     without JavaScript holding the element open through its own close.

     Behind @supports on calc-size(), which is the piece that lets a height of
     zero interpolate to a height nobody has measured, and which shipped
     alongside ::details-content. Where either is missing the archive opens
     exactly as it always did — a degradation nobody can see, which is the only
     kind worth writing. */
  @supports (block-size: calc-size(auto, size)) {
    .archive::details-content {
      block-size: 0;
      overflow: hidden;
      opacity: 0;
      transition: block-size var(--transition-exit),
                  opacity var(--transition-exit),
                  content-visibility var(--transition-exit) allow-discrete;
    }

    .archive[open]::details-content {
      block-size: calc-size(auto, size);
      opacity: 1;
      transition: block-size var(--transition-enter),
                  opacity var(--transition-enter),
                  content-visibility var(--transition-enter) allow-discrete;
    }
  }

  .project-list--archived .project__name { color: var(--ink-muted); }

  /* A property that is read rather than set still has to sit on the same line
     as the ones that are. */
  .property__control--static {
    display: flex;
    align-items: center;
    color: var(--ink-muted);
  }
}
