/* zoom-slider.css — "Kronan", den steglösa zoom-ratten längs högerkanten.
   ────────────────────────────────────────────────────────────────────────────
   Inga egna färger: allt är designtokens ur styles.css (KANT-LAGEN, DESIGN.md §3).
   Ratten ska vara nästan omärklig i vila och tydlig under tummen — och den får
   aldrig konkurrera med omslagen om uppmärksamheten.

   GEOMETRIN, och varför:
     .zsl      lagret. Absolut i #app (INTE fixed): #app bär --vph-livremmen för
               iOS-standalone (ENHETSLAG L1) — en fixed-positionerad ratt hade
               mätt den trasiga layout-viewporten och hamnat ~62 pt fel.
     .zsl-hit  träffytan: 44 px bred (44 px-lagen) med `right: 24px`, alltså
               24 → 68 px från skärmkanten. De 24 px som lämnas fria är iOS
               kantzon för bakåt-/framåt-svepet (lag 17) — en tumme som börjar
               där tillhör systemet, inte oss.
     Strecket  ritas vid träffytans ytterkant (`right: 0` inuti .zsl-hit) = 24 px
               från skärmkanten. Visuellt "längs högerkanten", utan att någon
               nedsättning sker i systemets zon.
   Vertikalt slutar ratten ovanför den flytande tabbaren och under kontrollraden,
   så den aldrig ligger över en tryckyta. */

.zsl {
  position: absolute;
  right: 0;
  top: calc(var(--header-h) + 96px);
  bottom: calc(var(--tabbar-h) + 28px + var(--sab));
  width: 68px;
  z-index: 20;                 /* samma våning som tabbaren; under blad (120) och sidor (100) */
  pointer-events: none;        /* bara .zsl-hit tar tryck — resten är luft */
}
.zsl.is-off { display: none; }

.zsl-hit {
  position: absolute;
  right: 24px;                 /* ⚠️ RÖR INTE: iOS kantzon, se kommentaren överst */
  top: 0; bottom: 0;
  width: 44px;
  pointer-events: auto;
  touch-action: none;          /* ratten äger sitt eget drag; sidan får inte panorera */
  -webkit-user-select: none; user-select: none;
  cursor: ns-resize;
}
.zsl-hit:focus { outline: none; }
.zsl-hit:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: var(--r-pill); }

/* ── LOKALA TONER ────────────────────────────────────────────────────────────
   Kim 2026-09-04: "för diskret". Ratten var en 2 px hårstreckslinje i 6 %-tonen och
   en 8 px-knopp på 34 % opacitet — SETT PÅ BILD (kronan-FORE-vila-light/dark.png):
   i vila syntes i praktiken bara den översta pricken. En ratt man inte ser finns inte.
   Höjningen sker i TON, inte i storlek: samma tunna streck, men på 12 % av texten i
   stället för 6 %, och en kula i --accent i stället för en grå prick. Två tokens
   deklareras lokalt (de är toner av --txt precis som --glass-line, KANT-LAGEN §3) —
   de hör hemma i styles.css den dag fler komponenter behöver dem. */
.zsl {
  --zsl-rail: color-mix(in srgb, var(--txt) 12%, transparent);
  --zsl-pip:  color-mix(in srgb, var(--txt) 26%, transparent);
}
@supports not (color: color-mix(in srgb, red 50%, transparent)) {
  .zsl { --zsl-rail: var(--hairline); --zsl-pip: var(--txt-dim); }
}

/* ── SPÅRET ──────────────────────────────────────────────────────────────────
   3 px i vila (grinden: ≤ 3 px — ett streck, inte en list), 6 px under tummen. */
.zsl-track,
.zsl-fill {
  position: absolute;
  right: 0;
  top: 6px; bottom: 6px;
  width: 3px;
  border-radius: var(--r-pill);
  transition: width var(--dur-1) var(--ease-out), opacity var(--dur-1) var(--ease-out);
}
.zsl-track { background: var(--zsl-rail); }
/* Fyllnaden säger VAR i rampen man är. Den skalas från underkanten (z=0 nere,
   z=3 uppe) — transform, aldrig height, så den kostar ingen layout per bildruta.
   I vila är den en viskning under kulan; kulan är den som bär avläsningen. */
.zsl-fill {
  background: var(--accent);
  opacity: .30;
  transform-origin: 50% 100%;
  transform: scaleY(0);
}

/* ── SNÄPP-PUNKTERNA ─────────────────────────────────────────────────────────
   Fyra prickar på exakt z = 0/1/2/3 (positionen sätts i JS ur ZoomSurface.STOPS,
   så de kan aldrig hamna någon annanstans än där motorn faktiskt snäpper).
   De är rattens "skala": i vila säger de att det FINNS lägen att gå till. */
.zsl-stops { position: absolute; right: 0; top: 6px; bottom: 6px; width: 3px; }
.zsl-dot {
  position: absolute;
  right: -2px;
  width: 7px; height: 7px;
  margin-bottom: -3.5px;
  border-radius: 50%;
  background: var(--zsl-pip);
  transition: opacity var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out),
              background-color var(--dur-1) var(--ease-out);
}
.zsl-dot.on { background: var(--accent); transform: scale(1.3); }

/* ── KULAN ───────────────────────────────────────────────────────────────────
   Den bärande ändringen. Förr: en grå 8 px-prick på 34 % — osynlig mot både den
   ljusa salviegrunden och det mörka rummet. Nu: en liten kapsel i --accent (mörk
   salvie i ljust tema, blek mynta i mörkt) — samma färg som appens primära
   interaktion säger överallt annars. Den syns i vila utan att skrika, för den är
   liten (10×26) och sitter i kanten, inte i innehållet.
   Under tummen växer den till ett gripbart handtag med två greppstreck. Det är
   den ena halvan av kvittensen som ersätter haptiken (iOS saknar Vibration API). */
.zsl-thumb {
  position: absolute;
  right: -4px;
  top: 6px;
  width: 10px; height: 26px;
  margin-top: -13px;
  border-radius: var(--r-pill);
  background: var(--accent);
  opacity: .88;
  border: 0;
  box-shadow: var(--shadow-1);
  will-change: transform;
  transition: width var(--dur-1) var(--ease-out), height var(--dur-1) var(--ease-out),
              opacity var(--dur-1) var(--ease-out), right var(--dur-1) var(--ease-out),
              margin-top var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
/* Greppstrecken. De ritas i --on-accent, alltså den enda färg som per definition
   har kontrast mot --accent i båda teman. I vila är kulan för liten för dem. */
.zsl-thumb::before,
.zsl-thumb::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 6px; height: 1.5px;
  margin-left: -3px;
  border-radius: var(--r-pill);
  background: var(--on-accent);
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
.zsl-thumb::before { top: calc(50% - 4px); }
.zsl-thumb::after  { top: calc(50% + 2.5px); }

.zsl.is-live .zsl-track { width: 6px; }
.zsl.is-live .zsl-fill { width: 6px; opacity: .72; }
.zsl.is-live .zsl-thumb {
  right: -7px;
  width: 16px; height: 46px;
  margin-top: -23px;
  opacity: 1;
  box-shadow: var(--shadow-2);
}
.zsl.is-live .zsl-thumb::before,
.zsl.is-live .zsl-thumb::after { opacity: .55; }

/* ── ETIKETTEN ───────────────────────────────────────────────────────────────
   Den andra halvan av kvittensen: snäppet kan bara SES. Namnet på läget dyker upp
   vid tummen och puffar till när man passerar en snäpp-punkt. Den ligger till
   vänster om handtaget så den aldrig hamnar under fingret. */
.zsl-badge {
  position: absolute;
  right: 26px;
  top: 6px;
  margin-top: -16px;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  background: var(--surface-float);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: var(--shadow-2);
  color: var(--txt);
  font-size: 14px; font-weight: 600; line-height: 1.4;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  will-change: transform;
  transition: opacity var(--dur-1) var(--ease-out);
}
.zsl.is-live .zsl-badge { opacity: 1; }
/* Två klasser som växlar i stället för en enda som tas bort och sätts tillbaka:
   omstart av en animation via `void offsetWidth` hade tvingat fram en layout mitt
   i gestens dyraste bildruta. Nu kostar kvittensen ingenting alls.
   Klasserna sitter på ROTEN, så samma passering kvitteras på två ställen: etiketten
   puffar och kulan andas till. Det är så nära ett "snäpp i tummen" en webbapp på
   iOS kan komma — och steglösheten är orörd, motorn vet inte ens att det sker. */
.zsl.pop-a .zsl-badge b { animation: zsl-pop var(--dur-2) var(--ease-spring); }
.zsl.pop-b .zsl-badge b { animation: zsl-pop2 var(--dur-2) var(--ease-spring); }
.zsl.pop-a.is-live .zsl-thumb { animation: zsl-grip var(--dur-2) var(--ease-spring); }
.zsl.pop-b.is-live .zsl-thumb { animation: zsl-grip2 var(--dur-2) var(--ease-spring); }
.zsl-badge b { display: inline-block; font-weight: 600; }
@keyframes zsl-pop  { 0% { transform: scale(1); } 40% { transform: scale(1.14); } 100% { transform: scale(1); } }
@keyframes zsl-pop2 { 0% { transform: scale(1); } 40% { transform: scale(1.14); } 100% { transform: scale(1); } }
/* OBS: kulan flyttas med transform ur JS (LAG 2). En keyframe som rörde transform
   hade därför kastat den ur läge mitt i draget — kvittensen går i box-shadow. */
@keyframes zsl-grip  { 0% { box-shadow: var(--shadow-2); } 45% { box-shadow: var(--shadow-3); } 100% { box-shadow: var(--shadow-2); } }
@keyframes zsl-grip2 { 0% { box-shadow: var(--shadow-2); } 45% { box-shadow: var(--shadow-3); } 100% { box-shadow: var(--shadow-2); } }

/* Ljust tema: accenten är MÖRK och syns därför mer per procent opacitet. */
html[data-theme="light"] .zsl-thumb { opacity: .92; }
html[data-theme="light"] .zsl-fill { opacity: .26; }
html[data-theme="light"] .zsl.is-live .zsl-fill { opacity: .7; }

/* ── FOKUSLÄGET: ge plats åt ›-knappen ───────────────────────────────────────
   SETT PÅ BILD (kronan-mitt-i-drag-0-3.png): i fokus ligger .z-nav.next på
   right:14px, bottom: tabbar+18px — dess överkant hamnar rakt inne i rattens
   träffyta. Ratten har högre z-index och hade ätit halva knappen. Vi kortar
   ratten i stället för att flytta knappen: knappens plats är ett låst beslut
   (styles.css:3155), rattens längd är det inte. */
html.is-focus-chrome .zsl { bottom: calc(var(--tabbar-h) + 74px + var(--sab)); }

/* ── LANDSKAP ────────────────────────────────────────────────────────────────
   Liggande iPhone har ~390 px höjd totalt. Med portrait-avstånden (header+96 uppe,
   tabbar+28 nere) blir ratten kortare än sin egen kula, och ett negativt högt
   element beter sig oförutsägbart. Vi kortar in avstånden i stället — ratten
   ligger kvar i kanten och täcker fortfarande inget innehåll, eftersom hela
   .zsl-lagret är pointer-events: none utanför träffytan. */
@media (orientation: landscape) and (max-height: 500px) {
  .zsl { top: calc(var(--header-h) + 16px); bottom: calc(var(--tabbar-h) + 14px + var(--sab)); }
  html.is-focus-chrome .zsl { bottom: calc(var(--tabbar-h) + 58px + var(--sab)); }
}

@media (prefers-reduced-motion: reduce) {
  .zsl-track, .zsl-fill, .zsl-dot, .zsl-thumb, .zsl-badge { transition: none; }
  .zsl-thumb::before, .zsl-thumb::after { transition: none; }
  /* ALL information finns kvar (etikett, tänd prick, fyllnad, kulans läge) —
     bara puffarna tas bort. */
  .zsl.pop-a .zsl-badge b, .zsl.pop-b .zsl-badge b { animation: none; }
  .zsl.pop-a.is-live .zsl-thumb, .zsl.pop-b.is-live .zsl-thumb { animation: none; }
}
