/* shelf: a reading list for anyone's site (Sha, Oct 13, 2026). Works grouped by topic, one row each
   (year, title, who made it, what kind of thing it is); pointing at a row on a computer shows its cover
   in the margin beside the list, crossfading from one to the next; tapping it opens it in place, with its cover
   if it has one, a few details, the owner's note and a link to read, watch or see it. A site sets its
   own type and colors with the custom properties below; the rest stays the same everywhere. Used
   first by Maya's /library (labs/bymayao/library/). */

.shelf{
  --shelf-ink:var(--ink, #111); --shelf-soft:var(--soft, #6f6a63); --shelf-faint:var(--faint, #b3aea6);
  --shelf-line:var(--line, #e8e5e0); --shelf-wash:var(--wash, #f4f2ef); --shelf-paper:var(--paper, #fff);
  --shelf-ease:var(--breath, cubic-bezier(.22,.55,.3,1)); --shelf-slow:var(--slow, .6s);
  color:var(--shelf-ink);
}

/* the filters: the topics first, then, smaller, the kinds (each only when there is more than one); the
   chosen one in ink with a fine underline. On a phone each stays one line that swipes sideways */
.shelf .topics, .shelf .kinds{ display:flex; flex-wrap:wrap; gap:0 1.1rem; }
.shelf .topics button, .shelf .kinds button{ font:inherit; font-size:1.02rem; padding:.35rem 0; min-height:44px; background:none; border:0; cursor:pointer;
  color:var(--shelf-soft); white-space:nowrap; transition:color .3s var(--shelf-ease); touch-action:manipulation; -webkit-tap-highlight-color:transparent; }
.shelf .kinds{ margin:-.25rem 0 0; }
.shelf .kinds button{ font-size:.9rem; }
.shelf .kinds button[hidden]{ display:none; }
.shelf .topics button[aria-pressed="true"], .shelf .kinds button[aria-pressed="true"]{ color:var(--shelf-ink);
  text-decoration-line:underline; text-decoration-thickness:1px; text-underline-offset:.4em; text-decoration-color:var(--shelf-faint); }
@media (hover:hover){ .shelf .topics button:hover, .shelf .kinds button:hover{ color:var(--shelf-ink); } }
@media (max-width:30rem){
  .shelf .topics, .shelf .kinds{ flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none; overscroll-behavior-x:contain;
    margin-inline:calc(-1 * var(--shelf-bleed, 16px)); padding-inline:var(--shelf-bleed, 16px); scroll-padding-inline:var(--shelf-bleed, 16px); }
  .shelf .topics::-webkit-scrollbar, .shelf .kinds::-webkit-scrollbar{ display:none; }
}

/* a topic: its name, then its works; one topic chosen, its works as one list with no headings */
.shelf .group{ margin-top:clamp(2rem, 5vh, 2.8rem); }
.shelf .group[hidden]{ display:none; }
.shelf .topic{ margin:0 0 .55rem; font-weight:400; font-size:clamp(1.2rem, 4vw, 1.35rem); line-height:1.2; font-style:italic; color:var(--shelf-ink); }
.shelf.one-topic .topic{ display:none; }
.shelf.one-topic .group + .group{ margin-top:0; }
.shelf.one-topic .group + .group .items{ border-top:0; }
.shelf .none{ margin:1.6rem 0 0; font-style:italic; color:var(--shelf-soft); }
.shelf .none[hidden]{ display:none; }
.shelf .items{ list-style:none; margin:0; padding:0; border-top:1px solid var(--shelf-line); }
.shelf .item{ border-bottom:1px solid var(--shelf-line); scroll-margin-top:var(--shelf-offset, 1rem); }   /* a site with a fixed bar sets --shelf-offset to clear it */
.shelf .item[hidden]{ display:none; }

/* a row: the year, the title with who made it under it, the kind */
.shelf .row{ display:grid; grid-template-columns:3.4rem minmax(0, 1fr) auto; gap:.2rem 1rem; align-items:baseline; width:100%;
  padding:.95rem 0 1rem; margin:0; border:0; background:none; font:inherit; color:inherit; text-align:left; cursor:pointer;
  touch-action:manipulation; -webkit-tap-highlight-color:transparent; }
.shelf .row:focus-visible{ outline-offset:-2px; }
.shelf .year{ grid-row:1 / span 2; font-size:.92rem; color:var(--shelf-soft); font-variant-numeric:lining-nums tabular-nums; }
.shelf .title{ font-size:clamp(1.2rem, 4.2vw, 1.45rem); line-height:1.22; letter-spacing:-.01em; text-wrap:balance; transition:opacity var(--shelf-slow) var(--shelf-ease); }
.shelf .by{ grid-column:2; font-size:.98rem; color:var(--shelf-soft); }
.shelf .kind{ grid-column:3; grid-row:1; font-size:.88rem; color:var(--shelf-soft); white-space:nowrap; }
@media (hover:hover){ .shelf .row:hover .title{ opacity:.6; } .shelf.covering .row:hover .title{ opacity:1; } }   /* a cover showing: the title stays readable */
.shelf .item.open .title{ opacity:1; }
@media (max-width:30rem){
  .shelf .row{ grid-template-columns:2.9rem minmax(0, 1fr); }
  .shelf .kind{ display:none; }
}

/* the detail, opening in place on the row's own curve */
.shelf .detail{ display:grid; grid-template-rows:0fr; opacity:0; }
.shelf .item.open .detail{ grid-template-rows:1fr; opacity:1; }
.shelf.ready .detail{ transition:grid-template-rows var(--shelf-slow) var(--shelf-ease), opacity .45s var(--shelf-ease); }
.shelf .detail > .inner{ min-height:0; overflow:hidden; }
.shelf .card{ display:grid; grid-template-columns:minmax(0, 9.5rem) minmax(0, 1fr); gap:1.2rem; padding:.1rem 0 1.25rem 4.4rem; }
@media (max-width:30rem){ .shelf .card{ grid-template-columns:minmax(0, 7rem) minmax(0, 1fr); gap:1rem; padding-left:0; } }
.shelf .card.bare{ grid-template-columns:minmax(0, 1fr); }   /* no cover: the details take the room */
@media (max-width:30rem){ .shelf .card.bare{ padding-left:3.9rem; } }   /* hanging from the title, as the row does */
.shelf .card dl{ margin:0; display:grid; grid-template-columns:auto 1fr; gap:.15rem .8rem; font-size:.95rem; line-height:1.45; align-content:start; }
.shelf .card dt{ color:var(--shelf-soft); }
.shelf .card dd{ margin:0; }
.shelf .card .note{ grid-column:1 / -1; margin:.2rem 0 0; font-size:1.02rem; line-height:1.55; text-wrap:pretty; }
.shelf .card .go{ grid-column:1 / -1; margin:0; }
.shelf .card .go a{ display:inline-block; padding-block:.4rem; }
.shelf .card a{ color:inherit; text-decoration-line:underline; text-decoration-thickness:1px; text-underline-offset:.2em; text-decoration-color:var(--shelf-faint);
  transition:text-decoration-color var(--shelf-slow) var(--shelf-ease); }
.shelf .card a:hover{ text-decoration-color:var(--shelf-ink); }
.shelf .card a:focus-visible{ outline-offset:2px; }
.shelf .facts{ display:grid; gap:.7rem; align-content:start; }

/* a cover, in its own shape (a work without one shows none: the row already says what it is) */
.shelf .cover{ margin:0; aspect-ratio:2 / 3; background:var(--shelf-wash); overflow:hidden; }
.shelf .cover img, .shelf-float .cover img{ display:block; width:100%; height:100%; object-fit:cover; }

/* on a computer: the cover sits in the margin beside the list, level with the pointer (beside the pointer
   when there is no margin); the next one fades in over it quickly, so covers never flash against each other */
.shelf-float{ position:fixed; z-index:30; left:0; top:0; width:9.5rem; aspect-ratio:2 / 3; pointer-events:none; opacity:0; visibility:hidden;
  background:var(--shelf-wash, var(--wash, #f4f2ef)); box-shadow:0 1px 2px rgba(0, 0, 0, .06), 0 10px 30px rgba(0, 0, 0, .1);
  transition:opacity .2s var(--shelf-ease, var(--breath, cubic-bezier(.22,.55,.3,1))), visibility 0s linear .2s; will-change:transform; }
.shelf-float.on{ opacity:1; visibility:visible; transition:opacity .2s var(--shelf-ease, var(--breath, cubic-bezier(.22,.55,.3,1))), visibility 0s; }
.shelf-float .layer{ position:absolute; inset:0; margin:0; overflow:hidden; opacity:0; transition:opacity .16s ease-out; }
.shelf-float .layer.in{ opacity:1; }

@media (prefers-reduced-motion:reduce){ .shelf.ready .detail, .shelf .title, .shelf-float, .shelf-float .layer{ transition:none; } }
