/* =========================================================
   TiivisKoti — liike.

   MITÄ TÄÄLLÄ ON: kaksi asiaa, jotka tekevät sivusta elävän ilman että
   mikään "esittää animaatiota". Ensin sisääntulo (elementti nousee ja
   tarkentuu paikalleen kun se tulee ruutuun), sitten mikroliike
   (osoitin kertoo mikä on klikattavissa jo ennen klikkausta).

   MIKSI EI KIRJASTOA: mallina ollut aaltoair.fi tekee saman pelkillä
   CSS-keyframeillä — sen sivulta ei löydy GSAP:ia, AOS:ia eikä muutakaan
   animaatiokirjastoa. Sama tyyli syntyy tässä ilman yhtään uutta
   riippuvuutta ja ilman yhtään lisäkilotavua JavaScriptiä. Sivun oma
   IntersectionObserver (_shared.js) hoitaa jo ilmestymisen; tämä tiedosto
   antaa sille paremman liikkeen ja lisää mikroliikkeet.

   PEHMEÄ EASING: cubic-bezier(.16,1,.3,1) on nopea alussa ja pysähtyy
   pehmeästi. Se saa 18 pikselin matkan tuntumaan siltä että elementti
   asettuu paikalleen eikä liu'u sinne.

   LIIKE EI SAA VIIVYTTÄÄ MITÄÄN. Sisääntulo kestää 0,55 s ja porrastus on
   enintään 5 × 60 ms, joten alin kortti on paikallaan alle sekunnissa.
   Mikään sisältö ei ole liikkeen takana: JS:n estyessä .rv-elementit
   näkyvät sellaisenaan (ks. _shared.js:n varapolku).

   prefers-reduced-motion: KAIKKI pois. Osa ihmisistä saa liikkeestä
   fyysisen oireen, eikä koristeliike ole sen arvoista. Tiedoston lopussa.
   ========================================================= */

:root{
  --anim-ease: cubic-bezier(.16, 1, .3, 1);
  --anim-fast: .18s;
  --anim-base: .28s;
}

/* ---------- 1. SISÄÄNTULO ----------
   Arvot ovat suoraan aaltoair.fi:ltä mitatut, koska juuri sen liike oli
   se mitä haluttiin: elementti nousee 24 px ja häivähtää esiin 0,7
   sekunnissa käyrällä cubic-bezier(.16,1,.3,1). Peräkkäiset kortit
   porrastuvat 80 ms välein.

   EI SKAALAUSTA. Kokeilin ensin 0.97 → 1 -skaalausta, mutta aaltoairilla
   sitä ei ole, ja se on syystä: skaalaus saa tekstin sumenemaan liikkeen
   ajaksi. Pelkkä nosto pysyy terävänä koko matkan.

   Yksikkö on lohko, ei rivi: otsikko ja sen ylätunniste nousevat yhdessä
   (.center.rv), ja jokainen kortti omanaan. Sama jako kuin aaltoairilla. */
/* Säännöt ovat tiedoston LOPUSSA — ks. "sisääntulon säännöt" siellä.
   Syy: .card ja .btn määrittelevät oman `transition`-listansa, ja
   `transition` on yksi ominaisuus: myöhempi sääntö korvaa koko listan.
   Jos reveal olisi tässä, korttien sisääntulo menettäisi siirtymänsä
   kokonaan ja ne vain pomppaisivat esiin. */

/* Hero: sisältö purkautuu rivi riviltä heti latauksessa. Tämä EI odota
   vieritystä — hero on jo ruudussa.

   HITAAMPI JA PIDEMPI KUIN MUU SIVU, ja se on tarkoitus. Mitattu
   aaltoair.fi:ltä: 0,8 s per elementti ja viiveet 0,2 → 1,05 s, eli
   koko hero avautuu vajaassa kahdessa sekunnissa. Ensimmäinen versioni
   oli 0,5 s ja ohi 0,74 sekunnissa — tekninen ero on pieni, mutta
   katsojalle toinen "välähtää paikalleen" ja toinen "laskeutuu".

   Otsikko on jaettu riveihin (span.hl), koska juuri se tekee vaikutelman:
   rivit tulevat peräkkäin eikä koko otsikko yhtenä palikkana. */
@keyframes tk-nousu{
  from{ opacity:0; transform: translateY(20px); }
  to  { opacity:1; transform:none; }
}
@keyframes tk-nousu-iso{
  from{ opacity:0; transform: translateY(30px); }
  to  { opacity:1; transform:none; }
}
.hero .rating, .hero h1 .hl, .hero .hero-sub, .hero .hero-cta, .hero .hero-fine{
  animation: tk-nousu .8s var(--anim-ease) both;
}
.hero h1 .hl{ display:inline-block; animation-name: tk-nousu-iso; }
.hero .rating          { animation-delay:.20s }
.hero h1 .hl:first-of-type   { animation-delay:.35s }
.hero h1 .hl + br + .hl,
.hero h1 .hl:last-of-type    { animation-delay:.55s }
.hero .hero-sub        { animation-delay:.75s }
.hero .hero-cta        { animation-delay:.90s }
.hero .hero-fine       { animation-delay:1.05s }

/* Sivuilla joilla otsikkoa ei ole jaettu riveihin, koko otsikko nousee
   yhtenä samalla ajoituksella — hitaus on se mikä tekee vaikutelman,
   ei riviin jako. */
.hero h1:not(:has(.hl)){ animation: tk-nousu-iso .8s var(--anim-ease) .35s both; }

/* ---------- 2. MIKROLIIKE ----------
   Kortti nousee, reunus värittyy ja kuva zoomaa hitaammin kuin kortti
   liikkuu. Eri nopeudet tekevät liikkeestä orgaanisen; sama nopeus
   näyttäisi siltä että koko kortti on tarra. */
/* HOVER KÄYTTÄÄ `translate`-OMINAISUUTTA, EI `transform`ia. Kortti on myös
   .rv-elementti, jonka sisääntulo animoi transformia 0,7 sekunnissa. Jos
   hover käyttäisi samaa ominaisuutta, myöhempi sääntö veisi voiton ja
   sisääntulo kutistuisi hoverin 0,28 sekuntiin — juuri niin kävi ensin.
   Erilliset ominaisuudet (translate/scale/rotate) yhdistyvät toisiinsa,
   joten kumpikin liike saa oman kestonsa eivätkä ne kilpaile. */
.card{ transition: translate var(--anim-base) var(--anim-ease),
                   border-color var(--anim-base) var(--anim-ease),
                   box-shadow var(--anim-base) var(--anim-ease); }
.card:hover{
  translate: 0 -6px;
  border-color: var(--green);
  box-shadow: 0 2px 4px rgba(24,58,40,.05), 0 26px 50px -28px rgba(24,58,40,.42);
}
.card-fig .pic{ transition: transform .6s var(--anim-ease); }
.card:hover .card-fig .pic{ transform: scale(1.055); }

/* Linkin nuoli nytkähtää eteenpäin. Sama liike on jo napeissa; tässä se
   annetaan myös tekstilinkeille, jotka ovat korttien pääkutsu. */
.lnk .arrow{ transition: transform var(--anim-fast) var(--anim-ease); }
.lnk:hover .arrow, .card:hover .lnk .arrow{ transform: translateX(4px); }
.lnk{ transition: color var(--anim-fast) var(--anim-ease); }

/* Napit: kevyt nousu ja varjo, painallus takaisin alas. Painallus on se
   osa joka kertoo että klikki rekisteröityi — ilman sitä nappi tuntuu
   kuolleelta kosketusnäytöllä. */
.btn{ transition: translate var(--anim-fast) var(--anim-ease),
                  scale var(--anim-fast) var(--anim-ease),
                  background-color var(--anim-fast) var(--anim-ease),
                  box-shadow var(--anim-fast) var(--anim-ease),
                  border-color var(--anim-fast) var(--anim-ease); }
.btn-p:hover{ translate: 0 -2px; box-shadow: 0 10px 24px -12px rgba(33,122,78,.65); }
.btn:active{ translate: 0 0; scale: .985; }

/* Laskurin määräpainikkeet: napautus tuntuu heti. */
.stp{ transition: scale var(--anim-fast) var(--anim-ease),
                  background-color var(--anim-fast) var(--anim-ease); }
.stp:active{ scale: .9; }

/* Kalenterin aika: valinta on tärkein klikki koko sivulla. */
.slot{ transition: translate var(--anim-fast) var(--anim-ease),
                   scale var(--anim-fast) var(--anim-ease),
                   border-color var(--anim-fast) var(--anim-ease),
                   background-color var(--anim-fast) var(--anim-ease); }
.slot:hover{ translate: 0 -2px; }
.slot:active{ scale: .96; }

/* Palveluruudukon ja hinnaston rivit: hienovarainen taustan kirkastuminen. */
.wtype{ transition: background-color var(--anim-fast) var(--anim-ease); }
.wtype:hover{ background: var(--green-soft); }

/* ---------- 3. HUOMIO ----------
   Yksi ainoa huomioliike koko sivulla, ja se on hinnalla: kun summa
   päivittyy, luku "hengähtää". Enemmän huomioliikettä kilpailisi itsensä
   kanssa, ja silloin mikään ei enää huomioita.

   Luokan lisää _shared.js hinnan päivittyessä ja poistaa animaation
   päätyttyä, jotta sama liike voi toistua seuraavalla muutoksella. */
@keyframes tk-hinta{
  0%  { transform: none; }
  35% { transform: scale(1.045); }
  100%{ transform: none; }
}
.q-total .pv.tk-paivittyi{ animation: tk-hinta .42s var(--anim-ease); }

/* ---------- 4. PIENET ASIAT ---------- */
/* Navin linkin alleviivaus kasvaa keskeltä. */
.nlinks a{ position:relative; }
.nlinks a::after{
  content:''; position:absolute; left:50%; right:50%; bottom:-4px; height:2px;
  background: var(--green); border-radius:2px;
  transition: left var(--anim-base) var(--anim-ease), right var(--anim-base) var(--anim-ease);
}
.nlinks a:hover::after{ left:0; right:0; }

/* Avattavat osiot (Muut kohteet, UKK) kääntyvät pehmeästi. */
summary, .morecats{ transition: color var(--anim-fast) var(--anim-ease); }
.morecats .cv, details summary svg{ transition: transform var(--anim-base) var(--anim-ease); }
.morecats[aria-expanded="true"] .cv, details[open] summary svg{ transform: rotate(180deg); }

/* ---------- ENSIMMÄINEN VAPAA AIKA ----------
   Vihreä piste + rivi varauskortin yläreunassa. Piste sykkii kerran
   hitaasti — se on koko sivun ainoa toistuva liike, ja se on siinä
   koska "vapaana" on tila eikä tapahtuma: sykkivä piste lukee
   "juuri nyt", pysähtynyt piste lukisi "joskus". */
.tk-vapaa{
  /* KOKO LEVEYS. Laskurivaihe on kaksipalstainen grid (.order + .quote).
     Ilman tätä rivi menisi omaksi sarakkeekseen, kohdelista kutistuisi
     oikeaan palstaan ja yhteenveto putoaisi kokonaan toiselle riville —
     juuri niin kävi ensin. */
  grid-column: 1 / -1;
  display:flex; align-items:center; gap:8px;
  margin:0 0 12px; font-size:14px; font-weight:700; color:var(--green);
}
.tk-vapaa-piste{
  position:relative; flex:none; width:8px; height:8px; border-radius:50%;
  background:var(--green-l);
}
.tk-vapaa-piste::after{
  content:''; position:absolute; inset:0; border-radius:50%;
  background:var(--green-l); animation: tk-syke 2.4s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes tk-syke{
  0%  { opacity:.55; transform: scale(1); }
  70%,100%{ opacity:0; transform: scale(2.6); }
}
@media (prefers-reduced-motion: reduce){
  .tk-vapaa-piste::after{ animation:none !important; opacity:0 !important; }
}

/* ---------- SISÄÄNTULON SÄÄNNÖT (tarkoituksella viimeisenä) ----------
   Nämä tulevat komponenttien jälkeen, jotta niiden `transition` voittaa
   .cardin ja .btn:n oman listan. Reveal koskee jokaista .rv-elementtiä
   riippumatta siitä mikä komponentti se on. */
.rv{
  opacity:0;
  transform: translateY(24px);
  transition: opacity .7s var(--anim-ease), transform .7s var(--anim-ease);
  will-change: opacity, transform;
}
.rv.in{ opacity:1; transform:none; will-change:auto; }

/* Porrastus: ruudukon kortit tulevat peräkkäin eivätkä yhtenä möykkynä.
   Viive tulee JS:stä (--rv-i), jotta sama sääntö toimii miten monella
   kortilla tahansa. Katto 5 × 80 ms = 400 ms. */
.rv.stagger{ transition-delay: calc(var(--rv-i, 0) * 80ms); }

/* ---------- 5. LIIKKUMATTOMUUS ----------
   Ei "vähemmän liikettä" vaan ei liikettä. Puolittainen animaatio on
   pahinta: se kestää yhtä kauan mutta näyttää rikkinäiseltä. */
@media (prefers-reduced-motion: reduce){
  .rv, .rv.in{ opacity:1 !important; transform:none !important; transition:none !important; }
  .hero h1, .hero h1 .hl, .hero .hero-sub, .hero .hero-cta, .hero .rating, .hero .hero-fine{
    animation:none !important; opacity:1 !important; transform:none !important; }
  .q-total .pv.tk-paivittyi{ animation:none !important; }
  *, *::before, *::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important;
  }
}
