/* Pinned heads. The head of a sub-page stays at the top on a solid band; on
   Browse the search field and level chips also rise into it as the page scrolls.
   js/pin.js supplies --p, 0 to 1, and the distances; everything visual is here.
   Geometry below is that of a .view, whose padding this has to undo so the band
   can run edge to edge without moving anything at rest. */
:root {
  --pin-safe: env(safe-area-inset-top, 0px);
  --pin-row: 44px;
  --pin-top: calc(var(--pin-safe) + 8px);    /* above the row, stuck */
  --pin-band: calc(var(--pin-top) + var(--pin-row) + 8px);
}
/* js/pin.js writes the view's real padding and gap as --pin-pad, --pin-gutter and
   --pin-gap. These fallbacks are the portrait values. */
.view { --pin-lead: max(var(--pin-pad, 24px), var(--pin-top)); }    /* above the row, at rest */

.pin-heading, .browse-heading { display: contents; }   /* sticky reaches the whole view */

:root .view :is(.pin-head, .category-head) {
  position: sticky; top: calc(var(--pin-top) - var(--pin-lead)); z-index: 3;
  align-items: center; min-height: calc(var(--pin-lead) + var(--pin-row) + 8px);
  margin: calc(-1 * var(--pin-pad, 24px)) calc(-1 * var(--pin-gutter, 20px)) -8px;
  padding: var(--pin-lead) var(--pin-gutter, 20px) 8px;
  background: var(--ui-bg);
}
.pin-head > div { min-width: 0; }
:is(.pin-head, .category-head)::after {          /* once something can pass beneath */
  content: ''; position: absolute; inset: auto 0 0; height: 1px;
  background: var(--hairline); opacity: 0;
}
.view.scrolled:not(.browse) .pin-head::after { opacity: 1; }
.view .pin-head + .page-sub { margin-top: calc(4px - var(--pin-gap, 22px)); }

/* ------------------------------------------------------------- the Browse head */
.browse :is(.pin-head, .category-head)::after { opacity: clamp(0, calc(5 * var(--p, 0) - 4), 1); }
:root .browse:has(.browse-tabs:not([hidden])) .pin-head::after { opacity: 0; }
.browse :is(.category-head, .pin-head) .page-title {
  display: block; min-width: 0; max-width: var(--title-max, none);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  transform-origin: 0 50%;
  /* done before the field arrives, or a long title runs under it mid-way */
  scale: calc(1 - var(--title-cut, 0) * min(1, calc(var(--p, 0) / .7)));
}

.pin-mark { flex: none; height: 0; margin-bottom: calc(-1 * var(--pin-gap, 22px)); }

:root .browse .browse-tools {
  position: sticky; top: 0; z-index: 4;
  pointer-events: none;      /* the box spans the list; only its controls take taps */
  --q: min(1, calc(var(--p, 0) / .85));     /* the field arrives early, then swaps */
}
.browse-tools > .chips, .browse-tools > .search-slot { pointer-events: auto; }
.pin-compact .browse-tools > :is(.chips, .search-slot) { pointer-events: none; }
.pin-stuck .browse-tools > :is(.chips, .search-slot) { visibility: hidden; }

/* The field: a window on it closes from the left, while the field slides right
   behind that window. Only transforms, so the bar's ends stay round all the way
   and the field's own icon ends up centred on the tile. */
.search-slot {
  position: relative; overflow: hidden; border-radius: var(--radius);
  transform-origin: 100% 0;
  translate: calc(var(--slot-x, 0px) * var(--q)) calc(var(--slot-y, 0px) * var(--q));
  scale: calc(1 - var(--slot-s, 0) * var(--q));
  opacity: clamp(0, calc(10 - 10 * var(--p, 0)), 1);
}
.search-slot > .search-field { translate: calc(var(--field-x, 0px) * var(--q)) 0; }

/* The chips: each travels to its icon while its text fades. */
.browse-tools .chip {
  translate: calc(var(--dx, 0px) * var(--p, 0)) calc(var(--dy, 0px) * var(--p, 0));
  scale: calc(1 - .35 * var(--p, 0));
  opacity: clamp(0, calc(1.5 - 3 * var(--p, 0)), 1);
}
.browse-tools .chip.on { opacity: clamp(0, calc(2.1 - 3 * var(--p, 0)), 1); }

/* The compact controls, right of the title */
.pin-tools {
  position: absolute; top: var(--pin-top); right: 0; display: flex; gap: 6px;
  align-items: center; pointer-events: none;
  visibility: hidden;
}
.pin-compact .pin-tools { visibility: visible; pointer-events: auto; }
.pin-levels { display: flex; gap: 4px; }
.view[data-levels="menu"] .pin-levels, .view[data-levels="row"] .pin-level { display: none; }
.pin-tools .pin-search { opacity: clamp(0, calc(10 * var(--p, 0) - 8.5), 1); }
.pin-tools .pin-level { opacity: clamp(0, calc(4 * var(--p, 0) - 2.4), 1); }
.pin-tools .pin-lvl {
  translate: calc(var(--dx, 0px) * (1 - var(--p, 0))) calc(var(--dy, 0px) * (1 - var(--p, 0)));
  opacity: clamp(0, calc(4 * var(--p, 0) - 2.2), 1);
}
.pin-tool {
  flex: none; position: relative; display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
}
.lvl-ico { display: block; fill: currentColor; }
.lvl-ico .off { opacity: .3; }
/* a query is waiting behind the icon */
.pin-search.has-query { --tile-ink: var(--accent); }
.pin-search.has-query::after {
  content: ''; position: absolute; top: 7px; right: 7px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--tile);
}

/* Browse's tabs pin under the head. Ring shadows carry the band out to the page
   edges, so nothing shows round the well as it stays put. */
:root .browse .browse-tabs {
  position: sticky; top: var(--pin-band); z-index: 2;
  box-shadow: inset 0 1px 0 var(--well-shade), 0 1px 0 var(--well-rim),
    0 0 0 8px var(--ui-bg), var(--pin-gutter, 20px) 0 0 8px var(--ui-bg), calc(-1 * var(--pin-gutter, 20px)) 0 0 8px var(--ui-bg);
}

/* A landscape phone has no height to give: compact from the start, and the tabs
   scroll with the page. */
.browse.pin-always { --pin-lead: var(--pin-top); }
.browse.pin-always .pin-head + .page-sub { display: none; }
.browse.pin-always :is(.search-slot, .browse-tools > .chips) { display: none; }
:root .browse.pin-always .browse-tools {
  height: 0;
  margin-block: calc(-1 * (var(--pin-band) - 8px + var(--pin-gap, 22px))) calc(var(--pin-band) + 8px - var(--pin-gap, 22px));
}
:root .browse.pin-always .browse-tabs { position: relative; }

@media (prefers-reduced-motion: reduce) {
  /* No morph, so the full tools go under the head until they are swapped. */
  :root .browse:not(.pin-stuck) .browse-tools { z-index: 2; }
}

/* ------------------------------------------------------- search and level panels */
.pin-scrim { position: fixed; inset: 0; z-index: 200; background: transparent; }
.search-pop {
  position: absolute; display: flex; align-items: center; gap: 8px;
  min-height: var(--pin-band);
  padding: var(--pin-top) var(--pin-gutter, 20px) 8px;
  background: var(--ui-bg); box-shadow: 0 1px 0 var(--hairline), var(--shadow);
  animation: pin-drop 120ms ease-out;
}
@keyframes pin-drop { from { opacity: 0; translate: 0 -6px; } }
.search-pop .search-field { position: relative; flex: 1; min-width: 0; }
:root .view .search-pop .search { min-height: var(--pin-row); height: var(--pin-row); padding-block: 0; padding-right: 64px; }
:root .browse .search-pop .search-field > svg { left: 13px; top: 12px; }
:root .browse .search-pop .search { padding-left: 42px; }
:root .browse .search-pop .search-clear {
  top: 0; right: 0; width: auto; height: var(--pin-row); padding-inline: 12px;
  font-size: 14px; font-weight: 600; color: var(--accent);
}
.search-pop input::-webkit-search-cancel-button { display: none; }

:root .level-pop {
  position: absolute; display: flex; flex-direction: column; gap: 2px;
  min-width: 164px; padding: 6px;
  background: var(--floor); border-radius: 16px;
  box-shadow: inset 0 2px 0 var(--wall), 0 3px 0 var(--wall), var(--shadow);
  animation: menu-rise 120ms ease-out;
}
.level-opt {
  display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 8px 12px;
  border-radius: 10px; font-size: 15px; font-weight: 600; text-align: left; color: var(--ink);
}
.level-opt.on { background: var(--tile-bg); color: var(--tile-ink); }
.level-opt:is(:active, .down):not(.on) { background: var(--tile); }

@media (prefers-reduced-motion: reduce) {
  .search-pop, :root .level-pop { animation: none; }
}
