@layer components {
  /* ——— A folder in grid view ———
     Square tiles, four to a sheet and two on a phone. Asked of #main, which
     narrows when the panel opens, so a viewport query would ask the wrong
     question (AGENTS.md). */
  .tiles {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;

    @container main (width < 40rem) {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: var(--inline-space);
    }
  }

  .tile {
    position: relative;
    aspect-ratio: 1;
    border-radius: var(--border-radius);
    overflow: clip;
  }

  /* A picture fills its square, cropped, with no frame: its edge is its own. */
  .tile__picture {
    display: block;
    block-size: 100%;

    img {
      display: block;
      inline-size: 100%;
      block-size: 100%;
      object-fit: cover;
    }
  }

  /* A PDF's first page stands whole on the surface, a sheet of paper with a
     hairline edge — not cropped like a picture, because it is a page. */
  .tile__picture--page {
    display: grid;
    place-items: center;
    background-color: var(--color-surface);

    img {
      inline-size: auto;
      max-inline-size: 70%;
      block-size: 80%;
      object-fit: contain;
      box-shadow: 0 0 0 var(--border-size) var(--color-line);
    }
  }

  /* The picture's name, on a strip the pointer brings — and a phone, which
     has no pointer to bring it, keeps. It appears, so it earns the quick
     transition (AGENTS.md, Motion). */
  .tile__strip {
    position: absolute;
    inset: auto 0 0;
    padding: 0.4375rem 0.625rem;
    font-size: var(--text-small);
    color: var(--color-ink);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background-color: var(--color-canvas);
    opacity: 0;
    transition: opacity var(--speed-quick) var(--ease-out);
  }

  .tile:is(:hover, :focus-within) .tile__strip {
    opacity: 1;
  }

  @media (any-hover: none) {
    .tile__strip {
      opacity: 1;
    }
  }

  /* Everything that is not a picture is a door the size of the tile: a
     folder, a document's card, a file's glyph. A hairline gives it the edge
     a picture has of itself; the wash is the pointer's, as on the dock. */
  /* Clear of whatever stands in its corner — a draft's stamp (below), the
     selection's box (selections.css) — the larger of the two. */
  .tile__door {
    display: flex;
    flex-direction: column;
    gap: var(--inline-space);
    block-size: 100%;
    padding: 0.75rem;
    padding-block-start: max(0.75rem, var(--door-under-stamp, 0px), var(--door-under-box, 0px));
    color: inherit;
    text-decoration: none;
    border: var(--border);
    border-radius: inherit;

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

  /* A file that is neither a picture nor a page: its glyph at the top, its
     name and size at the foot. */
  .tile__door--file {
    justify-content: space-between;
  }

  /* A folder's line, the same as its row's (file-rows.css): its glyph in its
     colour, its name, what it holds — then its pictures under it. */
  .tile__folder {
    --icon-size: 1.375rem;

    display: grid;
    grid-template-columns: 1.75rem minmax(0, 1fr);
    column-gap: var(--inline-space);
    align-items: center;
  }

  /* An empty folder says where things go, in the dashed line that means a
     place to drop (drag_and_drop.css). */
  .tile__drop {
    display: grid;
    flex: 1;
    place-items: center;
    padding: var(--inline-space);
    font-size: var(--text-x-small);
    color: var(--color-ink-faint);
    text-align: center;
    border: var(--border-size) dashed var(--color-ink-faint);
    border-radius: var(--border-radius);
  }

  /* Files dropped on a folder's tile go up into that folder, a bar each over
     its foot, on paper so they read over its pictures. */
  .tile__uploads {
    position: absolute;
    inset: auto 0.75rem 0.75rem;

    .pending-upload {
      background-color: var(--color-canvas);
    }
  }

  /* The corner: the dotted count, on paper so it reads over a picture — or
     a draft's stamp, which has no thread to count. */
  .tile > :is(.comment-count, .badge) {
    position: absolute;
    inset-block-start: var(--inline-space);
    inset-inline-end: var(--inline-space);
  }

  .tile > .comment-count {
    padding: 0 var(--inline-space-half);
    background-color: var(--color-canvas);
    border-radius: var(--border-radius);
  }

  /* A stamped door starts under its stamp. */
  .tile:has(> .badge) {
    --door-under-stamp: 2.75rem;
  }
}
