/* Motion and small interactions, after patterns from the Bencho library (bencho.dev), redrawn in Mikrolage's own
   material: flat fills, 2 px corners, ink / violet / orange. motion.js adds the moving parts. Everything here respects
   prefers-reduced-motion (see the end of the file). */

/* ── sliding selection (after "Icon bar"): one fill travels to the chosen option ─────────────────────────────────
   motion.js puts a .slide-ind into every tab strip and segmented control and moves it: first it stretches across
   the old and the new slot, then it settles on the new one with a little give. The options lose their own selected
   fill, so the travelling one is the only one. */
.slide { position: relative; isolation: isolate; }
.slide > .slide-ind { position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; background: var(--slide-bg, var(--violet));
  will-change: transform, width, height; }
.slide > .slide-ind[data-phase="stretch"] { transition: transform 190ms cubic-bezier(.22, 1, .36, 1), width 190ms cubic-bezier(.22, 1, .36, 1), height 190ms cubic-bezier(.22, 1, .36, 1); }
.slide > .slide-ind[data-phase="settle"] { transition: transform 420ms cubic-bezier(.28, 1.28, .36, 1), width 420ms cubic-bezier(.24, 1.34, .38, 1), height 420ms cubic-bezier(.24, 1.34, .38, 1); }
.slide > button { position: relative; z-index: 1; }
.seg.slide > button, .tabs.slide > button, .mini-seg.slide > button { background: transparent; transition: color 160ms ease; }
.seg.slide > button:not([aria-checked="true"]):hover, .tabs.slide > button:not([aria-selected="true"]):hover { background: var(--face-2); }
.seg.slide > button[aria-checked="true"], .tabs.slide > button[aria-selected="true"], .mini-seg.slide > button[aria-checked="true"] { background: transparent; }
/* each control keeps the colour its selection already had */
.seg.slide { --slide-bg: var(--violet); }
.levels.slide, .tabs.slide { --slide-bg: var(--ink); }
.mini-seg.slide { --slide-bg: var(--ink); }
.bar .mini-seg.slide { --slide-bg: #121212; }

/* ── bar sliders (after "Budget slider"): importance as a row of bars that fill and swell ───────────────────────
   motion.js hides the native range (it stays the keyboard and screen-reader control) and draws one bar per step,
   rising like a volume icon. Tap a bar or drag along them; the bars near the finger swell. */
.wbar-wrap { position: relative; display: flex; align-items: center; min-height: 32px; min-width: 0; width: 100%; touch-action: none; cursor: pointer; }
.wbar-wrap > input[type="range"] { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; pointer-events: none; }
.wbar-wrap:has(input:focus-visible) { outline: 2px solid var(--violet); outline-offset: 3px; border-radius: var(--r); }
.wbars { display: flex; align-items: flex-end; justify-content: space-between; gap: 4px; width: 100%; height: 30px; }
.wbars i { flex: 0 1 auto; width: clamp(12px, 17%, 26px); border-radius: 2px; background: color-mix(in srgb, var(--ink) 14%, transparent);
  height: calc(34% + var(--step) * 13% + var(--swell, 0) * 10%); transition: background-color 140ms ease, height 260ms cubic-bezier(.24, 1.34, .38, 1); }
.wbars i[data-on] { background: var(--violet); }
.wbar-wrap[data-held] .wbars i { transition: background-color 140ms ease, height 120ms ease-out; }
.wbar-wrap[data-off] .wbars i { background: color-mix(in srgb, var(--ink) 9%, transparent); }
.wbar-wrap[data-disabled] { cursor: default; opacity: .45; }
/* on a wide panel the row stays compact: bars, then their number, not spread over the whole width */
@media (min-width: 721px) {
  .w:has(.wbar-wrap) { grid-template-columns: 26px 18px 150px minmax(0, 220px) 34px; }
  .w-scale { width: 220px; margin-right: 0; }
}
/* the value as a small pill over the bars while you hold them */
.wbar-pill { position: absolute; top: -22px; left: var(--x, 50%); translate: -50% 0; padding: 1px 8px; border-radius: 999px; background: var(--violet);
  color: var(--on-violet); font: 800 .75rem/1.5 var(--font-semi); pointer-events: none; opacity: 0; scale: .8;
  transition: opacity 120ms ease, scale 220ms cubic-bezier(.24, 1.34, .38, 1), left 120ms ease-out; }
.wbar-wrap[data-held] .wbar-pill { opacity: 1; scale: 1; }

/* ── shimmer (after "Shimmer text" and "Image shimmer"): a band of light runs over what is still loading ────── */
.shimmer { position: relative; display: inline-block; color: color-mix(in srgb, var(--ink) 45%, var(--face)); }
.shimmer::before { content: attr(data-text); position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, transparent 0 40%, var(--ink) 50%, transparent 60% 100%) 0 0 / 400% 100% no-repeat;
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; animation: shm-sweep 2s linear infinite; }
@keyframes shm-sweep { from { background-position: 100% 0; } to { background-position: 0% 0; } }
/* placeholder rows for the street ranking while its data loads (after "Skeleton morph") */
.skel { display: grid; gap: 10px; margin: 6px 0 0; }
.skel i { display: block; height: 38px; border-radius: var(--r); background: linear-gradient(90deg, var(--face-2) 0 35%, color-mix(in srgb, var(--face-2) 40%, var(--face)) 50%, var(--face-2) 65% 100%) 0 0 / 300% 100%;
  animation: skel-sweep 1.4s linear infinite; }
.skel i:nth-child(2n) { width: 92%; } .skel i:nth-child(3n) { width: 84%; }
@keyframes skel-sweep { from { background-position: 100% 0; } to { background-position: 0% 0; } }

/* ── menus fold out of their field (after "Dropdown"): search suggestions, districts, city ───────────────────── */
.results:not([hidden]), .bez-menu:not([hidden]), .city-menu:not([hidden]) { transform-origin: 50% 0; animation: fold-in 220ms cubic-bezier(.24, 1.2, .38, 1) both; }
.results:not([hidden]) > li, .bez-menu:not([hidden]) > *, .city-menu:not([hidden]) li { animation: fold-item 260ms cubic-bezier(.22, 1, .36, 1) both; }
.results > li:nth-child(2), .bez-menu > :nth-child(2) { animation-delay: 20ms; }
.results > li:nth-child(3), .bez-menu > :nth-child(3) { animation-delay: 40ms; }
.results > li:nth-child(4), .bez-menu > :nth-child(4) { animation-delay: 60ms; }
.results > li:nth-child(n + 5), .bez-menu > :nth-child(n + 5) { animation-delay: 80ms; }
@keyframes fold-in { from { opacity: 0; transform: translateY(-4px) scaleY(.94); } to { opacity: 1; transform: none; } }
@keyframes fold-item { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* ── the place card rises in when you open another place (after "Text rise"); motion.js sets .rise ──────────── */
.verdict.rise .cell-badge { animation: rise-badge 420ms cubic-bezier(.24, 1.34, .38, 1) both; }
.verdict.rise .v-text > * { animation: rise-text 360ms cubic-bezier(.22, 1, .36, 1) both; }
.verdict.rise .v-text > :nth-child(2) { animation-delay: 40ms; } .verdict.rise .v-text > :nth-child(n + 3) { animation-delay: 80ms; }
@keyframes rise-badge { from { opacity: 0; transform: scale(.86); } to { opacity: 1; transform: none; } }
@keyframes rise-text { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ── undo with a fuse (after "Inline confirm"): a line under the toast burns down while undo is still possible ── */
#toast { position: fixed; }
#toast:has(button):not([hidden])::after { content: ""; position: absolute; left: 0; bottom: 0; height: 3px; width: 100%; background: var(--orange);
  transform-origin: 0 50%; animation: fuse 7s linear forwards; }
@keyframes fuse { from { transform: scaleX(1); } to { transform: scaleX(0); } }
/* the comparison card's own "remove?" answers in place with a little give */
.fcard.confirm { animation: give 320ms cubic-bezier(.24, 1.34, .38, 1) both; }
@keyframes give { from { transform: scale(.97); opacity: .6; } to { transform: none; opacity: 1; } }

/* ── labels that sit in the field and lift on typing (after "Label input"): the comparison form ──────────────
   motion.js wraps each label's words in .fl. Empty and not focused, the words sit inside the field like a
   placeholder; focus or type and they lift back to their place above it. */
.form label.float { padding-top: calc(0.75rem * 1.35 + 3px); }
.form label.float > .fl { position: absolute; left: 0; top: 0; transform-origin: 0 0; pointer-events: none;
  transition: transform 200ms cubic-bezier(.24, 1.2, .38, 1), color 160ms ease; }
.form label.float:has(input:placeholder-shown:not(:focus)) > .fl { transform: translate(11px, calc(0.75rem * 1.35 + 14px)) scale(1.12); color: color-mix(in srgb, var(--ink) 55%, var(--face)); }
.form label.float:has(input:placeholder-shown:not(:focus)) input::placeholder { color: transparent; }
.form label.float:has(input:focus) > .fl { color: var(--violet); }

@media (prefers-reduced-motion: reduce) {
  .slide > .slide-ind { transition: none !important; }
  .wbars i, .wbar-pill { transition: none; }
  .shimmer::before, .skel i { animation: none; }
  .results:not([hidden]), .bez-menu:not([hidden]), .city-menu:not([hidden]), .results > li, .bez-menu > *, .city-menu li,
  .verdict.rise .cell-badge, .verdict.rise .v-text > *, .fcard.confirm { animation: none; }
  #toast:has(button):not([hidden])::after { animation-duration: 7s; }
}
