@layer blocks {
  .task-item {
    --task-item-z-index: 1;
    position: relative;
    z-index: var(--task-item-z-index);
    cursor: pointer;
    min-block-size: var(--grid-cell); /* rows sit on the paper's dot pitch */
    line-height: var(--grid-cell);
    font-size: var(--font-base);
    padding-inline: 2px;
    border-radius: var(--radius-m);
    --repel-gap: 0.875rem; /* spec demo-list / product row gap 14px */
    --repel-vertical-alignment: center;
  }

  /* Shrink-wraps the title and its tags so the struck rule spans the text and
     nothing more. Without it the rule would run the full flex width.

     It becomes a containing block only while struck. Making it positioned
     unconditionally would trap .task-item-link::before, which spans the whole
     row from .task-item and is what makes the entire row clickable. */
  .task-item-text {
    display: inline-block;
  }

  /* Tags read as a quieter aside inside the title, not as separate metadata:
     same line, slightly smaller, pencil weight. */
  .task-item .hashes {
    font-size: 0.9em;
    font-weight: var(--weight-normal);
    color: var(--color-text-faint);
  }

  /* Done: struck with a drawn rule at a slight angle, not text-decoration.
     Shared by the landing demo ([data-state="done"]) and the real list as it
     animates away (.completing), so both read identically. */
  .task-item[data-state="done"] .task-item-text,
  .task-item.completing .task-item-text {
    position: relative;
    opacity: 0.55;
  }

  .task-item[data-state="done"] .task-item-text::after,
  .task-item.completing .task-item-text::after {
    content: "";
    position: absolute;
    inset-inline: -3px -7px;
    inset-block-start: 54%;
    block-size: 2.5px;
    border-radius: 2px;
    background: var(--color-decorative);
    rotate: -1.6deg;
  }

  .task-item[data-state="done"] .badge {
    opacity: 0.55;
  }

  .task-item .checkbox {
    margin-inline-end: 0;
  }

  .task-item-content {
    flex: 1;
    min-width: 0;
  }

  .task-item .title {
    overflow-wrap: anywhere;
    hyphens: auto;
  }

  .task-item-link {
    position: static;
    color: inherit;
    --link-decoration: none;
  }

  .task-item-link::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: var(--task-item-z-index);
  }

  .task-item :where(a, button, input, select, textarea, [tabindex]):not(.task-item-link) {
    position: relative;
    z-index: calc(var(--task-item-z-index) + 1);
  }

  /* Focus handling */
  .task-item:focus-within:has(:focus-visible) {
    outline: 1px solid var(--color-focus-border);
    outline-offset: 1px;
  }

  .task-item:focus {
    outline: 1px solid var(--color-focus-border);
    outline-offset: 1px;
  }

  .task-item:focus-within:not(:has(:focus-visible)):not(:focus) {
    outline: none;
  }

  .task-item-link:focus-visible {
    outline: none;
  }

  /* Completing animation */
  @keyframes task-complete {
    0% {
      opacity: 1;
      transform: translateX(0);
    }
    70% {
      opacity: 0.5;
      transform: translateX(0);
    }
    100% {
      opacity: 0;
      transform: translateX(1rem);
      max-height: 0;
      padding: 0;
      margin: 0;
      overflow: hidden;
    }
  }

  .task-item.completing {
    animation: task-complete 0.4s ease-out forwards;
  }

  .task-item.completing .badge {
    opacity: 0.5;
  }

  .task-item[data-state="ghost"] {
    margin-top: var(--space-3xs);
    cursor: default;
  }

  .task-item[data-state="preview"] {
    cursor: default;
  }

  .task-item[data-state="preview"] > span:first-child {
    flex: none;
  }

  .task-item[data-state="preview"] .title a,
  .task-item[data-state="ghost"] .title a {
    --color-link: var(--color-accent-strong);
    --color-link-hover: var(--color-text);
  }
}
