@layer components {
  /* ——— The dock ———
     A project's tools as a grid of cards that show what is inside them, not an
     icon (docs/planning/basecamp-pm-study.md). BC's grammar for the card
     itself (user, 2026-08-09): the title stands above the frame and is the
     rename affordance, the framed preview is the door, and every other verb —
     quick add, the trash, an empty tool's invitation — waits for the pointer. */
  .dock__tools {
    /* One head height both sides agree on — the tallest thing in a title row
       is the compact quick button, and the add square's top margin has to
       equal the row the real tiles carry or their frames misalign. */
    --dock-head-size: 1.75rem;

    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    gap: var(--block-space);
    align-items: stretch;
  }

  .dock-tool {
    display: flex;
    flex-direction: column;
    gap: var(--block-space-half);
  }

  .dock-tool__head {
    display: flex;
    align-items: center;
    gap: var(--inline-space);
    block-size: var(--dock-head-size);
  }

  /* An inline-rename (inline-rename.css) in the dock's voice: title metrics
     rather than an h1's, and shu, not ink — BC paints its dock titles in the
     accent, and the user ruled the same here (2026-08-09; recorded in HANSHI's
     Deviations). One line always: a long name ellipsizes rather than wrapping
     under its neighbour. */
  .dock-tool__title {
    --inline-rename-size: var(--text-medium);

    flex: 1;
    min-inline-size: 0;
    color: var(--color-accent);
  }

  /* The framed part is the door. It IS a .bucket-card — the anatomy, the wash, the
     hairline and the radius all come from cards.css, and a variant retunes
     rather than restating (AGENTS.md): the dock's is taller, fills its tile,
     and carries the stretched link, so those are the three things said here.
     `position: relative` is what keeps the overlay's box on this element, and
     cards.css positions every control inside it. */
  .dock-tool__card {
    --card-min-height: 15rem;

    position: relative;
    flex: 1;
  }

  /* The door has no text of its own, so the anchor can *be* the overlay
     rather than stretching a ::after over one — which also gives it a real
     box for the focus ring, and for anything that asks whether it is
     visible. */
  .dock-tool__open {
    position: absolute;
    inset: 0;
    border-radius: var(--border-radius);
  }

  /* The trash is compact: quiet enough for its corner, tight enough that
     the card keeps the room (user, 2026-08-09). */
  .dock-tool__card .dock-tool__remove {
    --btn-padding: calc(var(--block-space-half) / 2) var(--inline-space);

    flex-shrink: 0;
    font-size: var(--text-small);
  }

  /* The trash in the corner: a faint glyph until the pointer reaches it, then
     the label unclips and the ink turns negative — same specificity as the
     positioning rule above, so order decides, deliberately. */
  .dock-tool__card .dock-tool__remove {
    --btn-background: transparent;
    --btn-color: var(--color-ink-faint);
    --btn-background-hover: var(--color-canvas);
    --btn-color-hover: var(--color-negative-ink);
    --btn-padding: calc(var(--block-space-half) / 2);

    position: absolute;
    inset-block-end: var(--block-space-half);
    inset-inline-end: var(--block-space-half);
  }

  /* The label is the button's only accessible name, so it is clipped rather
     than `display: none`, and it comes back on hover. Both halves stay here
     instead of joining .for-screen-reader: the reversal has to sit in the same
     cascade layer as the hiding, and a components rule cannot argue with a
     utilities one. */
  .dock-tool__remove .btn__label {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
  }

  .dock-tool__remove:is(:hover, :focus-visible) .btn__label {
    position: static;
    inline-size: auto;
    block-size: auto;
    clip-path: none;
    overflow: visible;
  }

  /* The verbs wait for the pointer — opacity, not display, so focus can reveal
     them and the keyboard never lands on something invisible (boards.css).
     The whole tile is the hover surface. */
  .dock-tool__remove,
  .dock-tool__blank .btn {
    opacity: 0;
    /* Not just invisible — gone from hit-testing too, or the blank card's
       centred invitation would take the door's clicks while unseen. */
    pointer-events: none;
    /* The rise is the appearing (BC's manner, fizzy pairs its reveals the
       same way) — motion earned by something arriving, not decoration, on
       the quick clock like every appearance. */
    translate: 0 2px;
    transition:
      opacity var(--speed-quick) var(--ease-out),
      translate var(--speed-quick) var(--ease-out);
  }

  .dock-tool:hover :is(.dock-tool__remove, .dock-tool__blank .btn),
  .dock-tool :is(.dock-tool__remove, .dock-tool__blank .btn):focus-visible {
    opacity: 1;
    pointer-events: auto;
    translate: 0 0;
  }

  .dock-tool__blank {
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--block-space);
    text-align: center;
    color: var(--color-ink-faint);
  }

  /* The preview is metadata: it says what is in the tool, quietly, and never
     competes with the tool's name. */
  .dock-tool__preview {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: var(--block-space-half);
    font-size: var(--text-small);
    color: var(--color-ink-subtle);
  }

  .dock-tool__lines {
    display: flex;
    flex-direction: column;
    gap: var(--block-space-half);
  }

  .dock-tool__lines li {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* The to-dos preview: each line wears the circle it would have on its own
     page, so the tile reads as a list you could check off. */
  .dock-tool__lines--circled li {
    display: flex;
    align-items: center;
    gap: var(--inline-space-half);

    &::before {
      content: "";
      inline-size: 1em;
      block-size: 1em;
      flex-shrink: 0;
      border: var(--border);
      border-radius: 50%;
    }
  }

  /* Adding a tool is a small dashed square where the next tile would start —
     BC's own control (user, 2026-08-09; the full-size flipping tile it
     replaces read as a broken card once the real tiles grew title rows). The
     top margin is the head row the real tiles carry — --dock-head-size plus
     the tile's own gap — so the button top-aligns with the cards. */
  .dock-add {
    margin-block-start: calc(var(--dock-head-size) + var(--block-space-half));
  }

  .dock-add__button {
    display: grid;
    place-items: center;
    inline-size: 3rem;
    block-size: 3rem;
    font-size: var(--text-large);
    color: var(--color-ink-faint);
    background-color: transparent;
    border: var(--border-size) dashed var(--color-line);
    border-radius: var(--border-radius);
    cursor: pointer;

    &:hover {
      color: var(--color-ink-subtle);
      background-color: var(--color-surface);
    }
  }

  /* The catalog floats where the tile it would add will land — over the tile's
     own corner rather than under the button, so it covers the space it is
     about to fill. Everything else a float wears is .popup's; this is the
     card-sized box and the corner, said as the two properties popups.css
     takes. Scoped to .dock-add because dock.css sorts before popups.css, so
     an unscoped rule would lose max-block-size to .popup's 80dvh. */
  .dock-add .dock-add__panel {
    --popup-area: span-block-end span-inline-end;

    margin-block-start: 0;
    inline-size: min(18rem, 80vw);
    max-block-size: 22rem;
  }

  /* On a phone the add square stands mid-screen and no side of it fits the
     card-sized panel, so the panel takes the full row instead — spanned
     across its anchor, centred. Same clamp, same reason as the boost picker
     (boosts.css, user 2026-08-24): a top-layer float hangs over the
     viewport, not the sheet, so the width query is the right question. */
  @media (width < 35rem) {
    .dock-add .dock-add__panel {
      --popup-area: span-block-end span-all;

      justify-self: center;
    }
  }

  /* A phone-wide sheet: BC's mobile dock — two small cards to a row, the
     grid at a glance instead of a column of full previews (user,
     2026-08-24). The previews clip; the door is the point. */
  @container main (max-width: 70ch) {
    .dock__tools {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--block-space-half) var(--inline-space);
    }

    .dock-tool__card {
      --card-min-height: 9rem;
    }
  }
}
