/* ==========================================================================
   OPTOPRO — komponenttikerros
   Nordic Clinical B2B — Product-led, Human, Visual

   ── VÄRIT EIVÄT OLE LUKITTUJA ────────────────────────────────────────────

   Reference Design v1 avasi väripaletin uudelleen. Siksi tässä tiedostossa
   EI viitata suoraan yhteenkään palettiarvoon (--wp--preset--color--*).
   Kaikki värit tulevat SEMANTTISINA ROOLEINA theme.jsonin custom-kerroksesta:

     --wp--custom--pinta--*      mikä on tausta
     --wp--custom--teksti--*     mikä on luettavaa
     --wp--custom--toiminto--*   mitä voi klikata
     --wp--custom--reuna--*      mikä erottaa
     --wp--custom--focus--*      mikä on kohdistettuna
     --wp--custom--nappi--*      painikkeiden roolit

   Kun Product Owner vaihtaa paletin, muutos tehdään theme.jsonissa
   ROOLIIN — ei sadan komponentin sisälle. Jos tänne ilmestyy heksa-arvo,
   se on takaisin siinä tilanteessa, jota tämä kerros nimenomaan estää.

   Ainoa poikkeus on tunnusväri, jolla on oma perustelunsa kohdassa 9.
   ========================================================================== */

:root {
  --op-shell: var(--wp--custom--leveys--sivu);
  --op-prose: 42rem;
  --op-radius: var(--wp--custom--radius--pieni);
  --op-radius-lg: var(--wp--custom--radius--keski);
  --op-radius-xl: var(--wp--custom--radius--suuri);
  --op-line: 1px solid var(--wp--custom--reuna--hienovarainen);
  --op-line-dark: 1px solid var(--wp--custom--reuna--tummalla);
}

/* ==========================================================================
   1. RYTMI JA KAISTAT
   ========================================================================== */

.op-band { padding-block: var(--wp--preset--spacing--osio); }

/* PAATTAVA KEHOTEKAISTA. Tuotekorttien ja kehotteen valiin kertyi
   edellisen kaistan alavali + tumman kaistan ylavali. Tumma tausta
   erottaa kaistan jo itsessaan, joten se ei tarvitse yhta suurta
   ylavalia kuin vaalea kaista vaalean vieressa. */
.op-band--dark { padding-block: var(--wp--preset--spacing--osio-tiivis); }
.op-band--tight { padding-block: var(--wp--preset--spacing--osio-tiivis); }

/* PERÄKKÄISTEN KAISTOJEN PEHMUSTEET EIVÄT SAA KASAUTUA.
   Mitattu 14.8.2026: kaksi vierekkäistä vaaleaa kaistaa tuotti 224 px
   tyhjää, koska molemmat maksoivat oman osiovälinsä. Se ei näytä
   väljyydeltä vaan rikkinäiseltä. Kun kaistalla on oma taustaväri, se
   tarvitsee yläpehmusteen omaa reunaansa vasten — siksi sävytetyt ja
   tummat kaistat on rajattu pois.

   17.8.2026 TARKENNUS: EDELLISENKIN KAISTAN ON OLTAVA VÄRITÖN.
   Alkuperäinen sääntö katsoi vain jälkimmäistä kaistaa. Kun tuotesivun
   osiot alkoivat vuorotella vaalea/sävy, jokainen vaalea kaista menetti
   yläpehmusteensa myös sävytetyn kaistan JÄLKEEN — vaikka siinä kohtaa on
   näkyvä väriraja, joka tarvitsee ilmaa molemmin puolin. Mitattu tulos oli
   vuorotteleva 144 px / 72 px -rytmi, joka näyttää epäjärjestykseltä.
   Nyt pehmuste romahtaa vain kun rajaa ei ole eli molemmat kaistat ovat
   värittömiä. */
.op-band:not(.op-band--tint):not(.op-band--wash):not(.op-band--dark)
  + .op-band:not(.op-band--tint):not(.op-band--wash):not(.op-band--dark) {
  padding-top: 0;
}

/* Sisällön vaakarajaus dynaamisille lohkoille.
   Lohkot renderöivät oman <section>-elementtinsä, joka EI ole WordPressin
   constrained-asettelun sisällä — silloin `alignwide` ei tee mitään ja
   sisältö leviää selaimen reunaan. Mitattu: otsikko alkoi x = 0. */
.op-shell {
  max-width: var(--wp--custom--leveys--sivu);
  margin-inline: auto;
  padding-inline: var(--wp--preset--spacing--40);
}
.op-band--tint  { background: var(--wp--custom--pinta--vaihto); }
.op-band--wash  { background: var(--wp--custom--pinta--aksentti); }
.op-band--dark  {
  background: var(--wp--custom--pinta--tumma);
  color: var(--wp--custom--teksti--tummalla);
}
.op-band--dark h1,
.op-band--dark h2,
.op-band--dark h3 { color: var(--wp--custom--teksti--kaanteinen); }
/* Tumman kaistan linkkiväri koskee TEKSTILINKKEJÄ, ei painikkeita.
   Poikkeuslistalta puuttui `.op-btn`, joten sääntö voitti painikkeen oman
   värin korkeammalla spesifisyydellä: ensisijainen painike renderöityi
   tummalla kaistalla vaaleansinisenä omalla tummalla taustallaan.
   Mitattu axe-corella 23.8.2026: #4fb3c4 / #12626f = 2,85:1, kun
   WCAG 2.2 AA vaatii 4,5:1. Vika koski viittä sivua. */
.op-band--dark a:not(.wp-element-button):not(.op-btn) { color: var(--wp--custom--toiminto--tummalla); }

.op-eyebrow {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--wp--custom--toiminto--perus);
  margin-bottom: var(--wp--preset--spacing--20);
}
.op-band--dark .op-eyebrow,
.op-hero .op-eyebrow { color: var(--wp--custom--toiminto--tummalla); }

.op-lead {
  font-size: var(--wp--preset--font-size--medium);
  color: var(--wp--custom--teksti--toissijainen);
  max-width: var(--wp--custom--measure--lead);
}
.op-band--dark .op-lead { color: var(--wp--custom--teksti--tummalla-toissijainen); }

/* Osion otsikkorivi: otsikko vasemmalla, "katso kaikki" oikealla. */
.op-secthead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--wp--preset--spacing--40);
  margin-bottom: var(--wp--preset--spacing--60);
}
.op-secthead > * { margin: 0; }

/* Tertiäärinen toiminto: tekstilinkki + nuoli. */
.op-more {
  font-family: var(--wp--preset--font-family--display);
  font-weight: 600;
  font-size: var(--wp--preset--font-size--small);
  text-decoration: none;
  color: var(--wp--custom--toiminto--perus);
}
.op-more:hover { text-decoration: underline; }
/* Sitomaton välilyönti pitää nuolen kiinni viimeisessä sanassa, jotta se
   ei jää yksin uudelle riville. Koko elementtiä EI estetä rivittymästä:
   mitattu, että lauseenmittainen kehote ("Tarvitsetko apua sopivan
   ratkaisun valintaan? Kysy asiantuntijalta") tuotti vaakaylivuodon
   kaikilla leveyksillä, kun `white-space: nowrap` oli voimassa. */
.op-more::after { content: "\00a0\2192"; }
.op-band--dark .op-more { color: var(--wp--custom--toiminto--tummalla); }

/* ==========================================================================
   2. HERO — teksti 5/12, media 7/12
   ========================================================================== */

/* HERON PYSTYTIHEYS (PO 21.8.2026).
   Mitattu 1440 x 768: hero 731 px, ja seuraavaa osiota EI nakynyt lainkaan
   -- kavijan piti vierittaa ennen kuin sivulla oli nakyvasti muuta.
   Kolme muutosta, EI typografian pienentamista:
     1. pehmuste 2 x 104 px -> 2 x ~52 px
     2. H1:n rivimitta 16ch -> 22ch (leveys, ei kirjasinkoko -> 4 rivia 3:ksi)
     3. mediapaikan kuvasuhde 16/10 -> 16/9 ja kattokorkeus
   Kirjasinkoot, painot ja painikkeet ovat ennallaan. */
.op-hero {
  background: var(--wp--custom--pinta--tumma);
  color: var(--wp--custom--teksti--tummalla);
  padding-block: clamp(1.5rem, 0.9rem + 1.6vw, 2.5rem);
}
.op-hero h1 {
  color: var(--wp--custom--teksti--kaanteinen);
  /* 22ch -> 34ch: otsikko taittuu kahdelle rivilla kolmen sijaan.
     Rivimitta, EI kirjasinkoko -- H1 on yha 48,8 px. */
  max-width: 34ch;
}
.op-hero .op-lead {
  color: var(--wp--custom--teksti--tummalla-toissijainen);
  max-width: 62ch;
}

.op-hero__grid {
  display: grid;
  gap: var(--wp--preset--spacing--70);
  align-items: center;
}
@media (min-width: 62rem) {
  /* 5fr 7fr -> 7fr 5fr (PO 22.8.2026).
     Tekstisarake oli 507 px, joten H1 taittui kolmelle rivilla vaikka
     rivimitta salli kaksi -- SARAKE oli rajoite, ei kirjasinkoko.
     Leveampi tekstisarake vie otsikon kahdelle rivilla ja kaventaa samalla
     kuvakortin tiiviimmaksi. Kumpikaan ei pienenna typografiaa. */
  .op-hero__grid { grid-template-columns: 7fr 5fr; gap: var(--wp--preset--spacing--70); }
}

.op-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wp--preset--spacing--40);
  margin-top: var(--wp--preset--spacing--40);
}

/* HERON ELEMENTTIVALIT.
   Mitattu 22.8.2026: tekstipylvaassa oli ~100 px pelkkia marginaaleja
   (H1 32,7 px ylla ja alla). Ne ovat teeman yleisia otsikkovaleja, jotka
   sopivat leipatekstiin mutta ovat herossa liikaa. Tiivistetaan VAIN
   herossa -- kirjasinkoot ja painot ovat ennallaan. */
.op-hero h1 { margin-block: var(--wp--preset--spacing--40); }
.op-hero .op-lead { margin-block: var(--wp--preset--spacing--30) 0; }
.op-hero .op-eyebrow { margin-top: 0; }

/* HERO ALKAA HETI YLATUNNISTEEN ALTA.
   WordPressin blockGap antaa <main>-elementille 24 px ylamarginaalin.
   Hero on taysleveä TUMMA kaista, joten marginaali piirtyi VALKOISENA
   raitana ylatunnisteen ja heron valiin -- mitattu 1440 x 768: hero alkoi
   y = 93, vaikka ylatunniste paattyy 69:aan. Rako ei ollut suunniteltu.

   Ensimmainen yritys kohdisti heroon (`main > .op-hero:first-child`) eika
   purrut: marginaali on <main>-elementilla itsellaan, ei sen lapsella.

   Rajattu ETUSIVUUN. Sama 24 px on muillakin sivuilla, mutta tuotesivut
   ovat PO:n katselmoimassa tilassa -- niiden ylareunaa ei muuteta tassa
   tyopaketissa ilman erillista paatosta. */
/* KUOREN YLAVALI — mitattu vika, ei makuasia (22.8.2026).
   Ylatunniste ja <main> ovat sisaraiheita samassa lohkokehyksessa, joten
   WordPress asettaa niiden valiin globaalin blockGapin (24 px). Tulos on
   valkoinen raita tumman ylatunnisteen ja sivun ensimmaisen kaistan
   valissa — se ei ole suunniteltu vali vaan kehyksen sivuvaikutus.
   Sivujen OMA ylavali tulee kaistoilta ja arkistojen otsikkolohkolta,
   eika se muutu tasta: /palvelut/ pitaa 104 px padding-topinsa. */
main { margin-block-start: 0; }

/* SAMA VIKA YHDEN TASON SYVEMMÄLLÄ: kaistat ovat <main>:in sisaruksia,
   joten blockGap asettaa myös NIIDEN väliin 24 px. Kahden sävykaistan
   rajalla se näkyy valkoisena saumana (todennettu /tuotteet/-arkistossa
   22.8.2026). Kaistat on suunniteltu rajautumaan toisiinsa: pystyrytmi
   tulee kaistan omasta padding-arvosta, ei niiden välistä. */
main > .op-band + .op-band { margin-block-start: 0; }

/* MEDIAPAIKKA.
   Säiliö on rakennettu niin, että myöhempi still-kuva, poster tai muted
   video voidaan pudottaa sisään ILMAN että heron rakennetta muutetaan:
   kiinteä kuvasuhde + object-fit hoitaa kaikki kolme.
   HERO MEDIA = OPEN. Tässä on tarkoituksellinen paikanvaraaja, ei kuva. */
/* HERON MEDIA — TUOTEKUVA VAALEALLA KORTILLA (PO 22.8.2026).

   Tyhja harmaa suorakaide korvattiin oikealla laitekuvalla
   (CM-100 + AP-800, toimitettu Canton-kuvasto).

   ── MIKSI VAALEA KORTTI EIKA PALJAS LAPINAKYVYYS ────────────────────
   Toimitetun PNG:n lapinakyvyys on tehty vain osittain: laitteen
   ymparille on jaanyt alkuperaisen valkoisen taustan halo (mitattu
   22 457 osittain lapinakyvaa pikselia + peittavia lahes-valkoisia
   alueita). Tummaa heroa vasten se nakyi harmaana sumuna laitteen
   ympärilla.

   Haloa EI poistettu kuvasta: se olisi ollut destruktiivinen muokkaus,
   johon ei ole oikeutta (PO 21.8.2026). Sen sijaan kuva asetetaan
   vaalealle kortille — samalle komponentille, jota tuotesivut jo
   kayttavat. Halo katoaa nakyvista, koska tausta on vaalea, ja alkuperainen
   tiedosto pysyy koskemattomana.

   Korkeus on rajattu, jotta pystysuuntainen laitekuva ei maaraa heron
   korkeutta: teksti saa olla korkein elementti. Kuvan vaihto myohemmin =
   yksi <img>-rivi front-page.html:ssa. */
/* KORTTI MYOTAILEE KUVAA, EI PAINVASTOIN (22.8.2026).
   Mitattu: kuva 182 x 224 px venytetyssa 511 x 256 px:n kortissa = 31 %
   pinta-alasta. Laitekuva on pystysuuntainen, kortti oli vaakasuuntainen,
   joten laitteen molemmin puolin jai leveat valkoiset kaistat. Kortti
   kutistuu nyt kuvan levyiseksi ja keskittyy sarakkeeseensa. Heron
   korkeus ei muutu: sen maaraa yha kuvan 14rem-katto. */
.op-hero__media {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}
.op-hero__media > img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 14rem;
  object-fit: contain;
  display: block;
}
/* Video kayttaa yha tayttavaa asettelua; kuva ei.
   Aiempi saanto koski MOLEMPIA ja tuli tiedostossa oman kuvasaantoni
   JALKEEN, joten se voitti kaskadissa: kuva venyi 699 x 48 px:iin
   (mitattu 22.8.2026). Se oli tyhjan paikanvaraajan ajalta, jolloin
   kuvaa ei ollut. */
.op-hero__media > video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.op-hero__media--tyhja {
  display: grid;
  place-items: center;
  padding: var(--wp--preset--spacing--60);
  text-align: center;
}
.op-hero__media--tyhja p {
  color: var(--wp--custom--teksti--tummalla-hillitty);
  font-size: var(--wp--preset--font-size--small);
  margin: 0;
  max-width: 30ch;
}

/* ==========================================================================
   3. LUOTTAMUSNAUHA — kevyt signaali heron rajalla, ei oma osionsa
   ========================================================================== */

/* Luottamuskaista ei ole `op-band`, joten `main > .op-band + .op-band`
   -saanto ei koskenut sita: sen molemmin puolin jai WordPressin 24 px:n
   blockGap. Yhdessa seuraavan kaistan osiovalin kanssa se tuotti 128 px
   tyhjaa juuri siina kohdassa, jossa kavijan katse siirtyy herosta
   sisaltoon (mitattu 24.8.2026). */
main > .op-trust-strip { margin-block: 0; }
main > .op-trust-strip + .op-band { margin-block-start: 0; }

.op-trust-strip {
  background: var(--wp--custom--pinta--vaihto);
  border-bottom: var(--op-line);
}
.op-trust-strip ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--70);
  list-style: none;
  margin: 0;
  padding: var(--wp--preset--spacing--40) 0;
}
.op-trust-strip li {
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
  margin: 0;
}

/* ==========================================================================
   4. KOLME PÄÄREITTIÄ — sisäänkäyntejä, EI reunustettuja laatikoita
   ========================================================================== */

.op-routes {
  display: grid;
  gap: var(--wp--preset--spacing--60);
  list-style: none;
  padding-left: 0;
  margin: 0;
}
@media (min-width: 48rem) { .op-routes { grid-template-columns: repeat(3, 1fr); } }

/* Ei rajaa, ei taustaa. Interaktion lupaus tulee yläviivasta, joka
   kasvaa täyteen leveyteen kohdistuksessa — se toimii myös ilman väriä. */
.op-route {
  position: relative;
  padding-top: var(--wp--preset--spacing--50);
  border-top: 2px solid var(--wp--custom--reuna--hienovarainen);
}
.op-route::before {
  content: "";
  position: absolute;
  top: -2px; left: 0;
  width: 2.5rem; height: 2px;
  background: var(--wp--custom--toiminto--perus);
  transition: width .18s ease;
}
.op-route:hover::before,
.op-route:focus-within::before { width: 100%; }
.op-route__eyebrow {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--wp--custom--teksti--toissijainen);
}
/* Reitit ovat sivun YLÄTASON osioita, joten ne ovat H2 — muuten
   otsikkotaso hyppäisi H1:stä H3:een heti heron jälkeen. Koko tulee
   luokasta, ei tagista, joten ulkoasu on sama kuin muilla korttiotsikoilla. */
.op-route h2 {
  margin: var(--wp--preset--spacing--20) 0 var(--wp--preset--spacing--30);
  font-size: var(--wp--preset--font-size--large);
  letter-spacing: -.015em;
}
.op-route p {
  color: var(--wp--custom--teksti--toissijainen);
  font-size: var(--wp--preset--font-size--small);
  margin: 0 0 var(--wp--preset--spacing--40);
}
.op-route__link { text-decoration: none; font-weight: 600; }
.op-route__link::after { content: ""; position: absolute; inset: 0; }

@media (prefers-reduced-motion: reduce) {
  .op-route::before { transition: none; }
}

/* ==========================================================================
   7. TUOTEKORTTI — kuva tekee kortin, ei reunus
   ========================================================================== */

.op-products {
  display: grid;
  gap: var(--wp--preset--spacing--60);
  list-style: none;
  padding-left: 0;
  margin: 0;
}
@media (min-width: 34rem) { .op-products { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 60rem) { .op-products { grid-template-columns: repeat(3, 1fr); } }

.op-product { position: relative; display: flex; flex-direction: column; }
.op-product__media {
  aspect-ratio: 4 / 3;
  border-radius: var(--op-radius-lg);
  overflow: hidden;
  background: var(--wp--custom--pinta--vaihto);
  margin-bottom: var(--wp--preset--spacing--40);
  /* FLEX, EI GRID. Mitattu: grid + place-items:center antoi kuvalle
     386 px kontissa, jonka sisäleveys oli 371 px — prosentuaalinen
     max-height ei ratkennut grid-alueesta ja kuva vuoti. Flexissä sama
     kuva asettui 308 px:iin eli kontin sisäkorkeuden mukaan, kuten pitää. */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--wp--preset--spacing--40);
}
/* SAMA KUVASÄÄNTÖ KUIN TUOTESIVULLA (PO 17.8.2026, Phase 12).
   Aiemmin kortti käytti `cover` + `width: 100%`: laitekuva rajautui
   kehykseen ja 403 px:n kuva piirtyi 435 px:iin (mitattu). Tuotesivu taas
   käyttää `contain` ilman yliskaalausta. Sama kuva näytti siis kahdella
   pinnalla eri laitteelta. Yksi sääntö, ei kahta ajelehtivaa. */
.op-product__media img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}

/* EI-KUVAA-TILA on tarkoituksellinen, ei rikkinäinen. Tuotekoodi toimii
   typografisena tunnisteena, kun varmennettua kuvaa ei ole.
   Mitattu: 4/3-laatikko oli 303 px korkea tyhjänä — se näytti unohtuneelta
   paikkamerkiltä, ei tarkoitukselliselta tilalta. Tyhjä tila on matalampi
   kuin kuvallinen, jotta kävijä ei etsi latautumatonta kuvaa. */
.op-product__media--tyhja {
  aspect-ratio: auto;
  min-height: 7.5rem;
  border: 1px dashed var(--wp--custom--reuna--hienovarainen);
  background: transparent;
}
.op-product__media--tyhja span {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--small);
  letter-spacing: .08em;
  color: var(--wp--custom--teksti--toissijainen);
}
.op-product__ryhma {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--wp--custom--teksti--toissijainen);
}
.op-product h2,
.op-product h3 {
  margin: var(--wp--preset--spacing--20) 0 var(--wp--preset--spacing--20);
  font-size: var(--wp--preset--font-size--large);
}
.op-product h2 a,
.op-product h3 a { text-decoration: none; color: inherit; }
.op-product h2 a::after,
.op-product h3 a::after { content: ""; position: absolute; inset: 0; }
.op-product p {
  color: var(--wp--custom--teksti--toissijainen);
  font-size: var(--wp--preset--font-size--small);
  margin: 0 0 var(--wp--preset--spacing--40);
}
.op-product__foot { margin-top: auto; }

/* ==========================================================================
   8. PALVELUKORTTI — 4 × 1 → 2 × 2 → 1
   ========================================================================== */

.op-services {
  display: grid;
  gap: var(--wp--preset--spacing--50);
  list-style: none;
  padding-left: 0;
  margin: 0;
}
/* 2 × 2 ennen 4 × 1: neljä saraketta otetaan käyttöön vasta kun jokaiselle
   jää luettava rivinpituus. Kolmen sarakkeen välivaihetta ei ole, koska
   se tuottaisi kielletyn 3 + 1 -asettelun. */
@media (min-width: 36rem) { .op-services { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 72rem) { .op-services { grid-template-columns: repeat(4, 1fr); } }

.op-service {
  position: relative;
  display: flex;
  flex-direction: column;
  padding-top: var(--wp--preset--spacing--50);
  border-top: 2px solid var(--wp--custom--reuna--hienovarainen);
}
.op-service::before {
  content: "";
  position: absolute;
  top: -2px; left: 0;
  width: 2.5rem; height: 2px;
  background: var(--wp--custom--toiminto--perus);
  transition: width .18s ease;
}
.op-service:hover::before,
.op-service:focus-within::before { width: 100%; }
.op-service h3 {
  margin: 0 0 var(--wp--preset--spacing--20);
  font-size: var(--wp--preset--font-size--large);
}
.op-service h3 a { text-decoration: none; color: inherit; }
.op-service h3 a::after { content: ""; position: absolute; inset: 0; }
.op-service p {
  color: var(--wp--custom--teksti--toissijainen);
  font-size: var(--wp--preset--font-size--small);
  margin: 0 0 var(--wp--preset--spacing--40);
}
.op-service__foot { margin-top: auto; }

@media (prefers-reduced-motion: reduce) { .op-service::before { transition: none; } }

/* ==========================================================================
   9. LEVEÄ FEATURE — Optopro Learning. Ei viides palvelukortti.
   ========================================================================== */

.op-feature {
  display: grid;
  gap: var(--wp--preset--spacing--70);
  align-items: center;
}
@media (min-width: 62rem) {
  .op-feature { grid-template-columns: 5fr 7fr; gap: var(--wp--preset--spacing--80); }
  .op-feature--kaanteinen > :first-child { order: 2; }
}
.op-feature__media {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--op-radius-xl);
  overflow: hidden;
  background: var(--wp--custom--pinta--korotettu);
  border: var(--op-line);
}
.op-feature__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.op-feature__media--tyhja { display: grid; place-items: center; padding: var(--wp--preset--spacing--60); text-align: center; }
.op-feature__media--tyhja p {
  color: var(--wp--custom--teksti--toissijainen);
  font-size: var(--wp--preset--font-size--small);
  margin: 0;
  max-width: 32ch;
}
.op-band--dark .op-feature__media { background: var(--wp--custom--reuna--tummalla); border: var(--op-line-dark); }
.op-band--dark .op-feature__media--tyhja p { color: var(--wp--custom--teksti--tummalla-hillitty); }

/* ==========================================================================
   10. EDITORIAALINEN SISÄLTÖ — 1 pääjuttu + 3 nostoa
   ========================================================================== */

.op-editorial { display: grid; gap: var(--wp--preset--spacing--70); }
@media (min-width: 62rem) { .op-editorial { grid-template-columns: 7fr 5fr; } }

.op-article { position: relative; }
.op-article__media {
  aspect-ratio: 16 / 9;
  border-radius: var(--op-radius-lg);
  overflow: hidden;
  background: var(--wp--custom--pinta--vaihto);
  margin-bottom: var(--wp--preset--spacing--40);
}
.op-article__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.op-article__meta {
  font-size: var(--wp--preset--font-size--x-small);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wp--custom--teksti--toissijainen);
}
.op-article h3 { margin: var(--wp--preset--spacing--20) 0; }
.op-article h3 a { text-decoration: none; color: inherit; }
.op-article h3 a::after { content: ""; position: absolute; inset: 0; }
.op-article p {
  color: var(--wp--custom--teksti--toissijainen);
  font-size: var(--wp--preset--font-size--small);
}
.op-article--paa h3 { font-size: var(--wp--preset--font-size--x-large); }

/* Sivunostot: ei kuvaa, ei laatikkoa. Typografia hoitaa hierarkian, jotta
   puuttuva kuva ei riko osiota. */
.op-article-list { list-style: none; margin: 0; padding-left: 0; display: grid; gap: var(--wp--preset--spacing--50); }
.op-article-list > li { position: relative; padding-bottom: var(--wp--preset--spacing--50); border-bottom: var(--op-line); }
.op-article-list > li:last-child { border-bottom: 0; padding-bottom: 0; }
.op-article-list h3 { font-size: var(--wp--preset--font-size--normal); margin: var(--wp--preset--spacing--10) 0 0; }

/* ==========================================================================
   11. LUOTTAMUSOSIO — avoimet sarakkeet, ei kortteja
   ========================================================================== */

.op-trust {
  display: grid;
  gap: var(--wp--preset--spacing--60);
  list-style: none;
  padding-left: 0;
  margin: 0;
}
@media (min-width: 40rem) { .op-trust { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .op-trust { grid-template-columns: repeat(4, 1fr); } }
.op-trust h3 {
  font-size: var(--wp--preset--font-size--normal);
  margin: 0 0 var(--wp--preset--spacing--20);
  padding-top: var(--wp--preset--spacing--30);
  border-top: 2px solid var(--wp--custom--toiminto--perus);
}
.op-trust p { color: var(--wp--custom--teksti--toissijainen); font-size: var(--wp--preset--font-size--small); margin: 0; }
.op-band--dark .op-trust p { color: var(--wp--custom--teksti--tummalla-toissijainen); }
.op-band--dark .op-trust h3 { border-top-color: var(--wp--custom--toiminto--tummalla); }

/* ==========================================================================
   12. TIETORIVIT, LISTAT, TUNNISTEET  (säilyneet komponentit)
   ========================================================================== */

.op-facts { margin: 0; border-top: var(--op-line); }
.op-facts > div {
  display: grid;
  grid-template-columns: minmax(9rem, 38%) 1fr;
  gap: var(--wp--preset--spacing--40);
  padding-block: var(--wp--preset--spacing--30);
  border-bottom: var(--op-line);
}
.op-facts dt { font-size: var(--wp--preset--font-size--small); color: var(--wp--custom--teksti--toissijainen); margin: 0; }
.op-facts dd { margin: 0; font-variant-numeric: tabular-nums; }
@media (max-width: 30rem) {
  .op-facts > div { grid-template-columns: 1fr; gap: var(--wp--preset--spacing--10); }
}
.op-specs dd { font-family: var(--wp--preset--font-family--mono); font-size: .94em; }

.op-checklist { list-style: none; padding-left: 0; margin: 0; }
.op-checklist li { position: relative; padding-left: 1.75rem; margin-bottom: var(--wp--preset--spacing--30); }
.op-checklist li::before {
  content: "";
  position: absolute;
  left: 0; top: .45em;
  width: .7rem; height: .38rem;
  border-left: 2px solid var(--wp--custom--toiminto--perus);
  border-bottom: 2px solid var(--wp--custom--toiminto--perus);
  transform: rotate(-45deg);
}

.op-steps { list-style: none; counter-reset: op-step; padding-left: 0; margin: 0; }
.op-steps li {
  counter-increment: op-step;
  position: relative;
  padding-left: 3.25rem;
  padding-bottom: var(--wp--preset--spacing--60);
  border-left: var(--op-line);
  margin-left: 1rem;
}
.op-steps li:last-child { border-left-color: transparent; padding-bottom: 0; }
.op-steps li::before {
  content: counter(op-step);
  position: absolute;
  left: -1rem; top: -.15rem;
  width: 2rem; height: 2rem;
  display: grid; place-items: center;
  border-radius: var(--wp--custom--radius--ympyra);
  background: var(--wp--custom--toiminto--perus);
  color: var(--wp--custom--teksti--kaanteinen);
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--small);
  font-weight: 600;
}
.op-steps h3 { margin: 0 0 var(--wp--preset--spacing--20); }
.op-steps p { color: var(--wp--custom--teksti--toissijainen); margin: 0; }

.op-badge {
  display: inline-block;
  padding: .2em .7em;
  border-radius: 999px;
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 600;
  background: var(--wp--custom--toiminto--savy);
  color: var(--wp--custom--toiminto--hover);
}
.op-badge--neutral { background: var(--wp--custom--pinta--korotettu); color: var(--wp--custom--teksti--toissijainen); }

.op-note {
  border-left: 3px solid var(--wp--custom--toiminto--perus);
  background: var(--wp--custom--toiminto--savy);
  padding: var(--wp--preset--spacing--50);
  border-radius: 0 var(--op-radius) var(--op-radius) 0;
}
.op-note p:last-child { margin-bottom: 0; }

/* ==========================================================================
   13. YLÄTUNNISTE JA NAVIGAATIO
   ========================================================================== */

/* TARTTUVA YLATUNNISTE.
   `.op-header` julisti `position: sticky`, mutta se ei tarttunut: sen
   EMO on template partin `<header>`, joka on tasan ylatunnisteen
   korkuinen (69 px). Tarttuva elementti voi liikkua vain emonsa laatikon
   sisalla, joten liikkumavaraa oli nolla ja ylatunniste vieri pois
   normaalisti (mitattu 24.8.2026: y = -2000 px kun sivua oli vieritetty
   2000 px).

   Tarttuminen kuuluu siis SILLE elementille, jonka emo on koko sivu.
   Ulkoasu jaa `.op-header`ille. */
.wp-site-blocks > header {
  position: sticky;
  top: 0;
  z-index: 40;
}

/* Kirjautuneena WordPress lisaa ylapalkin: 32 px tyopoydalla, 46 px alle
   783 px:n. Alle 600 px:ssa palkki ei ole kiinnitetty vaan vierii pois,
   joten siirtymaa ei tarvita. Ilman tata ylatunniste piiloutuisi palkin
   alle. */
body.admin-bar .wp-site-blocks > header { top: 32px; }
@media (max-width: 782px) {
  body.admin-bar .wp-site-blocks > header { top: 46px; }
}
@media (max-width: 600px) {
  body.admin-bar .wp-site-blocks > header { top: 0; }
}

.op-header {
  background: var(--wp--custom--pinta--sivu);
  border-bottom: var(--op-line);
}

/* Ankkurilinkki ei saa jaada tarttuvan ylatunnisteen alle. */
:where(main) :target { scroll-margin-top: calc(var(--op-ylatunniste) + 1rem); }
.op-header__rivi {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wp--preset--spacing--50);
  min-height: 4.25rem;
}

/* ── TUNNUS (PO-päätös 10.8.2026) ────────────────────────────────────────
   Tunnusväri on ainoa heksa-arvo, joka saa elää roolikerroksen ulkopuolella
   — se on logokomponentin oma hyväksyntä, ei sivuston paletti. Arvo asuu
   theme.jsonissa roolina `brandi.tunnus`, jotta se on yhdessä paikassa
   mutta EI valittavissa muuhun käyttöön editorin paletista. */
.op-brand {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  flex: 0 0 auto;
}
.op-brand__mark { display: block; width: 34px; height: 34px; flex: 0 0 auto; }
.op-brand__word {
  font-family: var(--wp--preset--font-family--display);
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--wp--custom--brandi--tunnus);
  line-height: 1;
}
.op-band--dark .op-brand__mark,
.op-footer .op-brand__mark { filter: brightness(0) invert(1); }
.op-band--dark .op-brand__word,
.op-footer .op-brand__word { color: var(--wp--custom--teksti--kaanteinen); }

/* ── Päävalikko ─────────────────────────────────────────────────────────
   Rakenne: jokainen kohta on LINKKI. Alavalikollisilla on lisäksi ERILLINEN
   <button>, joka avaa paneelin. Linkki ei koskaan muutu painikkeeksi —
   se on koko mallin ydin: `/tuotteet/` on saavutettavissa myös ilman JS:ää. */
.op-nav { flex: 1 1 auto; display: flex; justify-content: flex-end; }
.op-nav__lista {
  display: flex;
  align-items: center;
  gap: clamp(.4rem, .1rem + .8vw, 1.1rem);
  list-style: none;
  margin: 0;
  padding: 0;
  flex-wrap: nowrap;
}
/* YKSI VUOROVAIKUTUSKIELI KOKO VALIKOLLE.

   PO-korjaus 14.8.2026: aiemmassa versiossa valikossa oli kolme eri
   kieltä yhtä aikaa — alleviivaus hoverilla, reunustettu painike
   Yhteydenotolla ja erillinen nuoli Tuotteilla. Ne näyttivät kolmelta eri
   järjestelmältä. Nyt jokainen kohta käyttää samaa käsittelyä:
   pehmeä taustapinta ja värinvaihto. Alavalikolliset saavat lisäksi
   nuolen — se on ainoa sallittu ero.

   Koko kohta (teksti + nuoli) on YKSI pinta: tausta piirretään
   .op-nav__kohta-tasolle, jolloin ne luetaan samaksi kontrolliksi
   eivätkä kahdeksi irralliseksi napiksi. */
.op-nav__kohta {
  display: flex;
  align-items: center;
  border-radius: var(--op-radius);
  transition: background-color .15s ease;
}
.op-nav__kohta:hover,
.op-nav__kohta:focus-within,
.op-nav__kohta[data-auki="true"] { background: var(--wp--custom--pinta--vaihto); }

/* Linkki ja levitin näyttävät identtisiltä. Ero on semanttinen:
   levitin ei navigoi, joten se on <button>. Tyylit jaetaan, jotta ne eivät
   voi ajautua erilleen. */
.op-nav__linkki,
.op-nav__nappi {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-family: inherit;
  font-size: var(--wp--preset--font-size--small);
  font-weight: 500;
  line-height: inherit;
  color: var(--wp--custom--teksti--ensisijainen);
  text-decoration: none;
  padding: .55rem .6rem;
  white-space: nowrap;
  background: none;
  border: 0;
  cursor: pointer;
}

.op-nav__kohta:hover .op-nav__linkki,
.op-nav__kohta:hover .op-nav__nappi,
.op-nav__kohta:focus-within .op-nav__linkki,
.op-nav__kohta:focus-within .op-nav__nappi,
.op-nav__kohta[data-auki="true"] .op-nav__nappi { color: var(--wp--custom--toiminto--perus); }

/* Nykyinen sivu erottuu painolla ja värillä, ei alleviivauksella. */
.op-nav__linkki[aria-current="page"] {
  color: var(--wp--custom--toiminto--perus);
  font-weight: 600;
}

.op-nav__nappi svg {
  width: .7rem;
  height: .7rem;
  flex: 0 0 auto;
  color: var(--wp--custom--teksti--toissijainen);
  transition: transform .18s ease;
}
.op-nav__kohta:hover .op-nav__nappi svg,
.op-nav__kohta[data-auki="true"] .op-nav__nappi svg { color: inherit; }
.op-nav__nappi[aria-expanded="true"] svg { transform: rotate(180deg); }

/* VARALTA ILMAN JAVASCRIPTIÄ.
   Levittimet ovat painikkeita, joten ilman JS:ää ne eivät avaisi mitään.
   Tämä sääntö on voimassa vain kunnes skripti merkitsee dokumentin —
   silloin JS ottaa vastuun eikä hover enää ohita sen tilaa. */
html:not(.op-js) .op-nav__kohta--paneeli:hover > .op-panel[hidden],
html:not(.op-js) .op-nav__kohta--paneeli:focus-within > .op-panel[hidden] {
  display: block;
}

/* HOVER-AVAUKSEN SILTA.
   Kohdistin ylittää pienen välin siirtyessään valikkokohdasta paneeliin.
   Ilman siltaa paneeli ehtisi sulkeutua kesken liikkeen.

   Silta on PANEELIN oma, ei kohdan: kohta ei ole enää sijoituskonteksti
   (ks. paneelin ankkurointi alla). Paneeli on kohdan lapsi, joten sillan
   päällä oleminen pitää kohdan :hover-tilan voimassa. */
.op-panel::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -1rem;
  height: 1rem;
}

@media (prefers-reduced-motion: reduce) { .op-nav__nappi svg { transition: none; } }

/* ── Alavalikkopaneeli ──────────────────────────────────────────────────
   Keskitetty headerin alle, ei koko näytön mega-menu. */
/* PANEELIN ANKKUROINTI.

   Paneeli sijoittuu HEADERIIN, ei valikkokohtaan. Perustelu on mitattu:
   kun paneeli keskitettiin kohtaansa, leveä tuotepaneeli valui 314 px yli
   näkymän heti kun valikkokohtien määrä muuttui ja Tuotteet siirtyi
   oikealle. Kohdan sijainti ei siis saa määrätä leveän paneelin sijaintia.

   `right` seuraa sisältösäiliön oikeaa reunaa, joten paneeli päättyy
   samaan linjaan muun sisällön kanssa eikä voi ylittää näkymää millään
   leveydellä. Header on `position: sticky` eli sijoitettu elementti, joten
   se toimii sijoituskontekstina ilman lisämäärittelyjä. */
.op-panel {
  /* Kouru = sisältösäiliön reunaväli. Sama arvo molemmilla puolilla, jotta
     paneeli ei voi valua kummastakaan reunasta yli. Leveys lasketaan
     kourusta, ei kiinteästä 2 rem:istä: muuten paneeli leikkautui
     vasemmalta 1280 px:ssä (mitattu vasen reuna -26 px). */
  --op-kouru: max(var(--wp--preset--spacing--40), calc((100vw - var(--wp--custom--leveys--sivu)) / 2));
  box-sizing: border-box;
  position: absolute;
  top: calc(100% + 1px);
  right: var(--op-kouru);
  left: auto;
  transform: none;
  width: min(var(--wp--custom--leveys--paneeli), calc(100vw - 2 * var(--op-kouru)));
  background: var(--wp--custom--pinta--sivu);
  border: var(--op-line);
  border-radius: var(--op-radius-lg);
  box-shadow: var(--wp--preset--shadow--nostettu);
  padding: var(--wp--preset--spacing--60);
  z-index: 50;
}
.op-panel[hidden] { display: none; }
.op-panel__grid {
  display: grid;
  gap: var(--wp--preset--spacing--40);
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 48rem) { .op-panel__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .op-panel__grid { grid-template-columns: repeat(3, 1fr); } }
.op-panel__foot {
  margin-top: var(--wp--preset--spacing--50);
  padding-top: var(--wp--preset--spacing--40);
  border-top: var(--op-line);
  text-align: right;
}

/* ══════════════════════════════════════════════════════════════════════
   TUOTERYHMÄT PUDOTUSPANEELISSA

   Product Owner valitsi vaihtoehdon B (14.8.2026). Vaihtoehdot A (täysi
   ympyrä) ja C (pyöristetty kohde ympyrämotiivilla) poistettiin, samoin
   väliaikainen `?ryhmat`-katselmointikytkin. Julkisia versioita on tasan
   yksi.

   PERIAATE: koko objekti on linkki. Ympyrä ja nimi ovat saman pinnan
   sisällä, joten ne luetaan yhtenä kohteena — ei pientä ikonia ja siitä
   irrallista tekstiä.

   Ympyrä on paikka lopulliselle tunnukselle. Kun visual proof valitsee
   symbolit, ne sijoitetaan sen sisään ilman rakennemuutosta.

   Tuotemääriä ei näytetä (PO 14.8.2026).

   PITKÄT NIMET. Pisin on "Koulutus- ja demonstraatiotuotteet" (33
   merkkiä). Sitä ei ratkaista kutistamalla tekstiä: nimi saa vaakatilaa,
   rivitys on hallittua ja riviväli tiivis.
   ══════════════════════════════════════════════════════════════════════ */

.op-cats {
  display: grid;
  gap: var(--wp--preset--spacing--50);
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 34rem) { .op-cats { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62rem) { .op-cats { grid-template-columns: repeat(3, 1fr); } }

/* PALVELUT: 2 × 2, ei 3 × 2 (PO 21.8.2026).
   Neljä palvelua kolmessa sarakkeessa jättäisi toiselle riville kaksi
   tyhjää ruutua — ruudukko näyttäisi keskeneräiseltä eikä neljälle
   suunnitellulta. Sama laatta, sama välistys, sama paneelin geometria;
   vain radan määrä on eri. */
@media (min-width: 62rem) { .op-cats--nelja { grid-template-columns: repeat(2, 1fr); } }

/* `1fr`-radan oletus on `min-width: auto`, jolloin pitkä sana voi
   kasvattaa radan yli säiliön ja koko ruudukko vuotaa. Mitattu 1440 px:llä
   arkistossa: 206 px ylivuoto, kun nimen fonttikokoa suurennettiin.
   `min-width: 0` antaa tekstin rivittyä sen sijaan. */
.op-cat { margin: 0; min-width: 0; }
.op-cat__linkki { min-width: 0; }
/* `anywhere` eikä `break-word`: vain `anywhere` pienentää myös radan
   min-content-leveyttä. `break-word` sallii sanan katkeamisen vasta kun
   ylivuoto on jo tapahtunut, jolloin ruudukon rata on ehtinyt kasvaa.
   Mitattu 1024 px:llä: "demonstraatiotuotteet" työnsi nimen 113 px yli. */
.op-cat__nimi { min-width: 0; overflow-wrap: anywhere; }

.op-cat__linkki {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  place-items: center start;
  gap: var(--wp--preset--spacing--40);
  min-height: 5.75rem;
  padding: .9rem 1.5rem .9rem 1rem;
  text-decoration: none;
  color: var(--wp--custom--teksti--ensisijainen);
  isolation: isolate;
}

/* Kapselipinta. Oma elementtinsä, jotta se voi olla nimen takana ilman
   että linkin oma tausta peittäisi ympyrän. */
.op-cat__kehys {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 999px;
  background: var(--wp--custom--pinta--vaihto);
  border: 1px solid transparent;
  transition: background-color .18s ease, border-color .18s ease;
}

/* Ympyrä on oma elementtinsä, koska sen sisällä on muoto. Täytetty ja
   rajattu — PO pyysi varmempaa ja näkyvämpää kuin proofin ensimmäinen
   versio, jossa ympyrä oli tyhjä ääriviiva.

   Muoto on paikanvaraaja. Lopullinen tunnus pudotetaan tähän ilman
   rakennemuutosta. */
.op-cat__ympyra {
  display: grid;
  place-items: center;
  width: 3.9rem;
  height: 3.9rem;
  flex: 0 0 auto;
  border-radius: var(--wp--custom--radius--ympyra);
  background: var(--wp--custom--pinta--sivu);
  border: 2px solid var(--wp--custom--reuna--hienovarainen);
  color: var(--wp--custom--toiminto--perus);
  transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.op-cat__ympyra svg { width: 52%; height: 52%; display: block; }

.op-cat__nimi {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--normal);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -.01em;
  text-wrap: balance;
}

/* Kohdistus vahvistaa koko kohdetta: pinta, ympyrän reunus ja tekstin
   väri muuttuvat yhdessä. Ei skaalausta eikä varjoa. */
.op-cat__linkki:hover .op-cat__kehys,
.op-cat__linkki:focus-visible .op-cat__kehys {
  background: var(--wp--custom--toiminto--savy);
  border-color: var(--wp--custom--toiminto--perus);
}
.op-cat__linkki:hover .op-cat__ympyra,
.op-cat__linkki:focus-visible .op-cat__ympyra {
  background: var(--wp--custom--toiminto--perus);
  border-color: var(--wp--custom--toiminto--perus);
  color: var(--wp--custom--teksti--kaanteinen);
}
.op-cat__linkki:hover .op-cat__nimi,
.op-cat__linkki:focus-visible .op-cat__nimi { color: var(--wp--custom--toiminto--hover); }

@media (prefers-reduced-motion: reduce) {
  .op-cat__kehys,
  .op-cat__ympyra { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   TUOTESIVU — RM-9000 Product Page Blueprint v1
   ══════════════════════════════════════════════════════════════════════ */

/* TUOTESIVUN YLÄREUNA.
   Blueprint kohta 1 nimeää nykystagingin ongelmaksi "too much unused space
   at the top". Osion vakiorytmi (112 px) on oikea osioiden VÄLIIN, mutta
   sivun ensimmäisen kaistan yläpehmusteena se työntää murupolun turhan
   kauas headerista. Mitattu 1440 px:llä: 140 px tyhjää ennen murupolkua.
   Yläpehmuste puolitetaan.

   17.8.2026: MYÖS ALAPEHMUSTE TIIVISTETTIIN. Osion vakiorytmi maksoi
   heron alla 104 px 1440 px:llä. Hero ei ole osio muiden joukossa vaan
   sivun aloitus.

   PO REV2 (17.8.2026): YLIN KAISTA ON JAETTU KAHTIA, koska "Tällä sivulla"
   siirtyi murupolun ja heron VÄLIIN. Sticky-elementti ei voi olla kaistan
   sisällä (tarttuisi vain kaistan omaan korkeuteen), joten murupolku ja
   hero ovat kumpikin omassa sävykaistassaan ja navi niiden välissä omana
   täysleveänä elementtinään. Kaksi kaistaa näyttävät yhdeltä, koska
   murupolkukaistalla ei ole alapehmustetta eikä herokaistalla
   yläpehmustetta — navin reunaviivat ovat ainoa näkyvä sauma. */
.op-tuote__ylin--murut {
  padding-top: var(--wp--preset--spacing--50);
  padding-bottom: var(--wp--preset--spacing--40);
}
.op-tuote__ylin--murut .op-murut { margin-bottom: 0; }
.op-tuote__ylin--hero {
  padding-top: var(--wp--preset--spacing--60);
  padding-bottom: var(--wp--preset--spacing--70);
}
/* Kaistojen romahdussääntö (.op-band + .op-band) ei koske sävykaistoja,
   joten herokaistan yläpehmuste on tässä eksplisiittinen eikä peritty. */

/* OSIOIDEN RYTMI TUOTESIVULLA.
   PO 17.8.2026: "The current content sections contain too much unused
   vertical space." Vakiorytmi (clamp → 112 px 1440 px:llä) on mitoitettu
   etusivun harvoille, kuvavetoisille osioille. Tuotesivulla osioita on
   seitsemän ja ne ovat tiheää asiatietoa, jolloin sama väli hajottaa
   sivun toisiinsa liittymättömiksi saarekkeiksi ja pakottaa vierittämään
   tyhjää. Tiivis rytmi (→ 72 px) säilyttää erottelun mutta ei väljyyttä
   väljyyden vuoksi. Tekstikokoon EI kosketa. */
.op-band--osio { padding-block: var(--wp--preset--spacing--osio-tiivis); }

/* Hero: teksti 5/12, kuva 7/12. Kuva on sivun ydinelementti. */
.op-tuote__hero {
  display: grid;
  gap: var(--wp--preset--spacing--70);
  align-items: center;
  margin-top: var(--wp--preset--spacing--40);
}
@media (min-width: 62rem) {
  .op-tuote__hero { grid-template-columns: 5fr 7fr; gap: var(--wp--preset--spacing--80); }
}
.op-tuote__tiedot > :first-child { margin-top: 0; }
.op-tuote__tiedot h1 { margin: 0 0 var(--wp--preset--spacing--30); }

/* Tagline on tuotteen lupaus yhdellä rivillä — vahvempi kuin leipäteksti,
   kevyempi kuin otsikko. */
.op-tuote__tagline {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--medium);
  font-weight: 600;
  line-height: 1.35;
  color: var(--wp--custom--teksti--ensisijainen);
  margin: 0 0 var(--wp--preset--spacing--40);
  max-width: 32ch;
}

/* Kuvakehys on vakio, kuva ei. `contain` säilyttää laitteen kokonaan:
   pysty- ja vaakakuva istuvat samaan kehykseen ilman rajausta. Näin
   valmistajan kuvaa ei tarvitse muokata, mikä on eri lupa kuin julkaisu. */
/* KEHYKSEN KORKEUS TULEE KUVASTA, EI KUVASUHTEESTA.
   Aiempi versio yhdisti `aspect-ratio: 4/3`, `max-height: 24rem` ja
   kuvan `max-height: 100%`. Yhdistelmä rajasi laitteen alareunan:
   prosentuaalinen max-height ei ratkennut katkaistusta korkeudesta,
   joten kuva piirtyi leveydestä johdetulla korkeudella ja `overflow`
   leikkasi ylimenevän osan pois.

   Mitattu 1440 px ennen korjausta (kehyksen sisämitta 512 × 384):
     ACP-1500        kuva 512 × 512  → alareunasta piiloon 128 px
     CM-100 + AP-800 kuva 512 × 512  → 128 px  (oikean ohjaimen jalusta)
     ACP905C         kuva 512 × 512  → 128 px
     ACP901          kuva 512 × 462  →  78 px
     LidVue          kuva 512 × 718  → 334 px  (alareunan merkit)
     iFlo            kuva 512 × 414  →  30 px  (vihreät ruksit)
   390 px:n leveydellä sama vika kosketti lisäksi KR-9600:aa ja
   RM-9600:aa. Sama vika oli korjattu tuotekortista jo 17.8. (osio 7)
   siirtymällä gridistä flexiin — tuotesivun kehys jäi korjaamatta.

   Nyt katto on kuvassa PIKSELEINÄ (`max-height: 24rem`), ei kehyksessä
   prosentteina. Kehys ei voi olla kuvaa matalampi, joten rajautuminen
   on rakenteellisesti mahdotonta, ei vain korjattu kerran. */
.op-tuote__media {
  margin: 0;
  border-radius: var(--op-radius-xl);
  background: var(--wp--custom--pinta--sivu);
  border: var(--op-line);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Väljyys kuvan ympärillä: piirroksissa merkinnät ulottuvat reunaan
     asti, ja kiinni kehyksessä ne näyttävät katkaistuilta silloinkin
     kun ne ovat kokonaan näkyvissä. */
  padding: var(--wp--preset--spacing--50);
  overflow: hidden;
  /* Pelastettu pikkukuva ei litistä kehystä nauhaksi. */
  min-height: 12rem;

  /* KEHYS MYÖTÄILEE KUVAA, EI PALSTAA.
     Vanha `aspect-ratio` johti kehyksen leveyden katkaistusta
     korkeudesta, joten kehys oli 546 px 699 px:n palstassa. Kun suhde
     poistettiin, kehys venyi koko palstan levyiseksi ja 384 px leveän
     kuvan ympärille jäi 315 px tyhjää. `fit-content` palauttaa
     entisen tiiviyden ilman rajaavaa suhdetta; alaraja estää
     pystykuvaa kutistamasta kehystä liuskaksi. */
  width: fit-content;
  max-width: 100%;
  min-width: min(100%, 22rem);
  margin-inline: auto;
  /* Pehmuste ja reuna MUKAAN leveyteen. Ilman tätä `width: 100%`
     kapealla näytöllä tarkoittaa palstan leveyttä + 32 px pehmustetta
     + 2 px reunaa, ja sivulle syntyy vaakavieritys. Mitattu: 18 px
     ylivuoto leveyksillä 768, 390 ja 320. */
  box-sizing: border-box;
}

/* KUVAA EI VENYTETÄ YLI SEN OMAN KOON.
   `width: 100%` skaalasi jokaisen kuvan kehyksen levyiseksi, myös
   pelastetut pikkukuvat: KR-9600:sta on tallella vain 354 px leveä
   tiedosto, ja se olisi piirretty 649 px levyisenä eli sumeana.
   `width: auto` + `max-width` antaa selaimen käyttää kuvan omaa
   luonnollista kokoa ylärajana ja kutistaa vain, jos kehys on pienempi. */
.op-tuote__media img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 24rem;
  object-fit: contain;
  display: block;
}
@media (max-width: 48rem) {
  /* Kapealla näytöllä kehys täyttää palstan: yksipalstaisessa
     asettelussa kapeampi kortti näyttäisi irralliselta. */
  .op-tuote__media { padding: var(--wp--preset--spacing--40); min-height: 9rem; width: 100%; min-width: 0; }
  .op-tuote__media img { max-height: 18rem; }
}
.op-tuote__media--tyhja { border-style: dashed; }
.op-tuote__media--tyhja span {
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--medium);
  letter-spacing: .1em;
  color: var(--wp--custom--teksti--toissijainen);
}

.op-tuote__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wp--preset--spacing--40);
  margin-top: var(--wp--preset--spacing--50);
}

/* Tuotekoodi on metatietoa, ei pääelementti. */
.op-tuote__koodi {
  margin: var(--wp--preset--spacing--50) 0 0;
  font-size: var(--wp--preset--font-size--x-small);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wp--custom--teksti--toissijainen);
}
.op-tuote__koodi span {
  font-family: var(--wp--preset--font-family--mono);
  letter-spacing: .04em;
  color: var(--wp--custom--teksti--ensisijainen);
}

/* OSION RYTMI.
   Blueprint kohta 12: otsikon ja ensimmäisen kohdan väliin on jäätävä
   selvä tila. Nykystagingissa "Keskeiset ominaisuudet" oli kiinni
   listassa. Väli on 32 px, ei 16–24 px minimi — otsikko on iso. */
.op-tuote__osio > h2 {
  font-size: var(--wp--preset--font-size--x-large);
  margin: 0 0 var(--wp--preset--spacing--60);
}
.op-tuote__osio > :last-child { margin-bottom: 0; }

/* Ominaisuudet: kaksi saraketta työpöydällä, ei kahdeksaa korttia. */
.op-piirteet,
.op-kohteet {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--70);
}
@media (min-width: 48rem) {
  .op-piirteet, .op-kohteet { grid-template-columns: repeat(2, 1fr); }
}
.op-piirteet li,
.op-kohteet li {
  position: relative;
  margin: 0;
  padding: 0 0 var(--wp--preset--spacing--40) 1.9rem;
  border-bottom: var(--op-line);
  font-size: var(--wp--preset--font-size--normal);
}
/* Merkki on koriste — teksti kertoo saman ilman sitä. */
.op-piirteet li::before {
  content: "";
  position: absolute;
  left: 0; top: .5em;
  width: .7rem; height: .38rem;
  border-left: 2px solid var(--wp--custom--toiminto--perus);
  border-bottom: 2px solid var(--wp--custom--toiminto--perus);
  transform: rotate(-45deg);
}
.op-kohteet li::before {
  content: "";
  position: absolute;
  left: .1rem; top: .62em;
  width: .45rem; height: .45rem;
  border-radius: var(--wp--custom--radius--ympyra);
  background: var(--wp--custom--toiminto--perus);
}

/* MDR-rajaus erottuu, mutta ei huuda: se on tosiasia, ei varoitusbanneri. */
.op-note--rajaus { border-left-color: var(--wp--custom--focus--vaalealla); background: var(--wp--custom--pinta--huomio); }
.op-note__otsikko {
  font-size: var(--wp--preset--font-size--small);
  letter-spacing: .06em;
  text-transform: uppercase;
  margin: 0 0 var(--wp--preset--spacing--20);
}

/* KÄYTTÖTARKOITUS. Proosa saa mittarajan, luettelot eivät: rivin pituus
   ratkaisee luettavuuden vain juoksevassa tekstissä. Ilman tätä
   käyttötarkoitus venyisi 80 rem levyiseksi yhdeksi kappaleeksi. */
.op-proosa { max-width: var(--wp--custom--measure--prose); }
.op-proosa > :first-child { margin-top: 0; }
.op-proosa > :last-child { margin-bottom: 0; }
.op-proosa p { margin-block: 0 var(--wp--preset--spacing--40); }

/* TEKNISTEN TIETOJEN RYHMÄT.
   Väliotsikko on pieni ja hillitty: se jäsentää taulukkoa eikä kilpaile
   osion H2:n kanssa. Ensimmäinen ryhmä ei saa yläväliä — se olisi tuplaväli
   heti H2:n jälkeen. */
.op-specs__ryhma {
  font-size: var(--wp--preset--font-size--small);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wp--custom--teksti--toissijainen);
  margin: var(--wp--preset--spacing--70) 0 var(--wp--preset--spacing--30);
}
.op-tuote__osio > h2 + .op-specs__ryhma { margin-top: 0; }

/* Lähdeviite. Pieni ja toissijainen — se on tarkistettavuutta, ei myyntiä. */
.op-specs__lahde {
  margin: var(--wp--preset--spacing--50) 0 0;
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
}

/* ── SIVUNAVIGAATIO — "Tällä sivulla" ──────────────────────────────────
   PO 17.8.2026: hero täytti työpöydällä lähes koko ensimmäisen näkymän
   (mitattu 1440 × 900: ylätunniste 69 px + hero 722 px = 791 px), joten
   kävijä saattoi olettaa sivun päättyvän siihen.

   TARTTUVUUS ON MITATTU, EI ARVATTU. Ylätunniste on `position: sticky;
   top: 0` ja 69 px korkea kaikilla mitatuilla leveyksillä (1440 → 320),
   joten `top` on vakio eikä vaadi JS:ää. Jos ylätunnisteen korkeus joskus
   muuttuu, tämä arvo on muutettava samalla — siksi se on oma muuttujansa
   eikä hajallaan sääntöjen sisällä.

   z-index jää ylätunnisteen (40) alle, jotta valikon paneeli piirtyy tämän
   päälle eikä toisin päin. */
/* Kirjautuneena ylatunniste on WP-palkin verran alempana, joten
   sivunavin tarttumiskohta siirtyy samalla. */
body.admin-bar .op-sivunavi { --op-ylatunniste: 101px; }
@media (max-width: 782px) {
  body.admin-bar .op-sivunavi { --op-ylatunniste: 115px; }
}
.op-sivunavi {
  --op-ylatunniste: 69px;
  position: sticky;
  top: var(--op-ylatunniste);
  z-index: 30;
  background: var(--wp--custom--pinta--sivu);
  border-block: var(--op-line);
}
/* Kuori on täysleveä, sisältö rajattu: tausta ja viivat ulottuvat reunasta
   reunaan kuten muutkin vyöhykkeet — mitattu, että 80 rem:iin rajattu
   kuori jätti sävypinnan näkyviin molemmille sivuille tarttuneena. */
.op-sivunavi__sisus {
  display: flex;
  align-items: baseline;
  gap: var(--wp--preset--spacing--50);
}
.op-sivunavi__otsikko {
  flex: 0 0 auto;
  margin: 0;
  padding-block: var(--wp--preset--spacing--30);
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--wp--custom--teksti--toissijainen);
}
/* Rivi vierii vaakasuunnassa sen sijaan että kietoutuisi monelle riville.
   Kuusi täyspitkää osionimeä ei mahdu 1440 px:iin yhdelle riville, ja
   kolmirivinen linkkimuuri veisi juuri sen tilan, joka tällä osiolla
   piti voittaa. Vieritys on sama ratkaisu mobiilissa ja työpöydällä —
   kaksi eri mallia eroaisi ensimmäisessä muutoksessa. */
.op-sivunavi__lista {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  gap: var(--wp--preset--spacing--50);
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.op-sivunavi__lista li { flex: 0 0 auto; }
.op-sivunavi__linkki {
  display: block;
  padding-block: var(--wp--preset--spacing--30);
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--ensisijainen);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.op-sivunavi__linkki:hover {
  color: var(--wp--custom--toiminto--perus);
  border-bottom-color: var(--wp--custom--toiminto--perus);
}
/* Fokusrengas ei saa jäädä vierityssäiliön leikkaamaksi, joten se on
   sisennetty ulkoreunan sijaan. */
.op-sivunavi__linkki:focus-visible { outline-offset: -2px; }

@media (max-width: 47.99rem) {
  /* Kapealla näytöllä otsikko on oman rivinsä arvoinen vain kerran:
     pystyyn ladottuna se ei vie linkkiriviltä tilaa. */
  .op-sivunavi__sisus { flex-direction: column; align-items: stretch; gap: 0; }
  .op-sivunavi__otsikko { padding-bottom: 0; }
}

/* ANKKURIN KOHDISTUS. Ilman tätä tarttuva rivi peittäisi juuri sen
   otsikon, johon linkki vie. Varaus = ylätunniste + sivunavi + hengitys. */
.op-tuote__osio { scroll-margin-top: 9.5rem; }

.op-tuote__cta { max-width: 46rem; }
.op-tuote__cta h2 { margin-top: 0; }

/* ── TUOTEARKISTO ──────────────────────────────────────────────────────
   Sama kategoriaobjekti kuin pudotusvalikossa, mutta väljemmässä
   rytmissä: arkiston tehtävä on orientaatio, valikon nopea navigointi
   (blueprint kohta 8). */
/* Arkiston navigaattori on suurempi kuin valikon versio, joten kolme
   saraketta vaatii enemmän tilaa. Mitattu 1024 px:llä: kolmella
   sarakkeella nimelle jäi 169 px ja "Koulutus- ja demonstraatiotuotteet"
   rivittyi viidelle riville. Blueprint kohta 31 määrää tabletille 2 × 3 —
   vaihto tapahtuu siis mitatun luettavuuden, ei arvatun rajan mukaan. */
.op-cats--valja {
  gap: var(--wp--preset--spacing--60);
  margin-top: var(--wp--preset--spacing--70);
  grid-template-columns: 1fr;
}
@media (min-width: 40rem) { .op-cats--valja { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 75rem) { .op-cats--valja { grid-template-columns: repeat(3, 1fr); } }
.op-cats--valja .op-cat__linkki { min-height: 6.5rem; padding: 1rem 1.75rem 1rem 1.1rem; }
.op-cats--valja .op-cat__ympyra { width: 4.5rem; height: 4.5rem; }
.op-cats--valja .op-cat__nimi { font-size: var(--wp--preset--font-size--large); }

/* Ryhmäosio. Otsikko kantaa rytmin — ei kehystettyä paneelia jokaiselle
   ryhmälle (blueprint kohta 36). */
.op-ryhma + .op-ryhma { margin-top: var(--wp--preset--spacing--osio); }
.op-ryhma__otsikko {
  font-size: var(--wp--preset--font-size--x-large);
  margin: 0 0 var(--wp--preset--spacing--60);
  padding-bottom: var(--wp--preset--spacing--30);
  border-bottom: var(--op-line);
}
.op-ryhma__otsikko a { text-decoration: none; color: inherit; }
.op-ryhma__otsikko a:hover { color: var(--wp--custom--toiminto--perus); }

/* Murupolku. Erotin on koristeellinen, joten se on aria-hidden
   merkkauksessa — ruudunlukija saa rakenteen linkeistä. */
.op-murut {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wp--preset--spacing--30);
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
  margin-bottom: var(--wp--preset--spacing--40);
}
.op-murut a { color: var(--wp--custom--toiminto--perus); text-decoration: none; }
.op-murut a:hover { text-decoration: underline; }

/* Tuotekortin kuvasääntö on osiossa 7 (.op-product__media img). Tässä
   ollut toinen sääntö lisäsi kuvalle 16 px paddingin kontin oman
   paddingin päälle; yhdessä max-height:100 %:n kanssa se pakotti kuvan
   laatikon täyteen korkeuteen ja venytti 229 px:n tiedoston 289 px:iin
   (mitattu 19.8.2026, RM-9600). Poistettu — yksi sääntö, yhdessä paikassa. */

/* ── KAPEA PANEELI — Palvelut ja Sisällöt ───────────────────────────────
   Neljä linkkiä ei tarvitse tuotepaneelin leveyttä, mutta kuuluu samaan
   perheeseen: sama tausta, reunus, varjo, pyöristys ja alarivi.

   ANKKUROITU KOHDAN OIKEAAN REUNAAN, ei keskitetty. Valikko on tasattu
   oikealle, joten keskitetty kapea paneeli valuisi näkymän ulkopuolelle
   valikon loppupään kohdilla. Oikeasta reunasta avautuva paneeli levittyy
   aina vasemmalle, missä tilaa on. */
.op-panel--kapea {
  width: min(32rem, calc(100vw - 2 * var(--op-kouru)));
  padding: var(--wp--preset--spacing--50);
}
.op-panel__ryhmat { display: grid; gap: var(--wp--preset--spacing--50); }
@media (min-width: 30rem) {
  .op-panel--kapea .op-panel__ryhmat { grid-template-columns: repeat(2, 1fr); }
}
.op-panel__otsikko {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--wp--custom--teksti--toissijainen);
  margin: 0 0 var(--wp--preset--spacing--20);
}
.op-panel__linkit { list-style: none; margin: 0; padding: 0; }
.op-panel__linkit li { margin: 0; }
.op-panel__linkit a {
  display: block;
  padding: .4rem 0;
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--ensisijainen);
  text-decoration: none;
}
.op-panel__linkit a:hover { color: var(--wp--custom--toiminto--perus); }

/* ── Mobiili ───────────────────────────────────────────────────────────
   KATKAISUKOHTA ON MITATTU, EI VALITTU.

   Mitattu uudelleen 14.8.2026, kun Palvelut ja Sisällöt saivat omat
   levityspainikkeensa. Ensimmäinen mittaus tehtiin yhdellä nuolella ja
   antoi 754 px; kolme nuolta ja pidemmät kohdat kasvattivat tarpeen:
     valikon seitsemän kohtaa                           630 px
     kuusi väliä (13 px)                                 78 px
     tunnus                                             127 px
     tunnuksen ja valikon kuilu                          24 px
     säiliön vaakapehmuste                               32 px
     ────────────────────────────────────────────────────────
     tarve yhdellä rivillä                              891 px

   Vaihto tapahtuu 60 rem = 960 px, eli 69 px ennen kuin tila loppuu.
   Vanha 832 px tuotti mitattuna 15 px vaakaylivuodon.
   Marginaali on tarkoituksella pieni mutta ei nollassa: se kestää
   valikkonimen pituuden kasvun ilman rivitystä. Typografiaa EI pienennetä
   rivityksen estämiseksi. */
.op-nav__hampurilainen { display: none; }

@media (max-width: 59.99rem) {
  .op-nav__hampurilainen {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    border: 1px solid var(--wp--custom--reuna--hienovarainen);
    border-radius: var(--op-radius);
    background: transparent;
    color: var(--wp--custom--teksti--ensisijainen);
    cursor: pointer;
  }
  .op-nav { justify-content: flex-end; }
  .op-nav__lista {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--wp--custom--pinta--sivu);
    border-top: var(--op-line);
    border-bottom: var(--op-line);
    padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
    max-height: calc(100vh - 4.25rem);
    overflow-y: auto;
  }
  .op-nav__lista[data-auki="true"] { display: flex; }
  .op-nav__kohta {
    flex-wrap: wrap;
    justify-content: space-between;
    border-bottom: var(--op-line);
  }
  .op-nav__kohta:last-child { border-bottom: 0; }
  /* Mobiilissa kohta on koko rivin levyinen, joten taustapinta ja
     pyöristys eivät kuulu siihen — rivit erottuvat viivalla. */
  .op-nav__kohta { border-radius: 0; background: transparent; }
  .op-nav__kohta:hover,
  .op-nav__kohta:focus-within,
  .op-nav__kohta[data-auki="true"] { background: transparent; }
  .op-nav__linkki { flex: 1 1 auto; padding: .95rem .25rem; }
  .op-nav__nappi { width: 100%; justify-content: space-between; min-height: 44px; padding: .95rem .25rem; }
  .op-nav__kohta::after { display: none !important; }
  /* Mobiilissa paneeli ei kellu vaan avautuu haitarina kohdan alle. */
  .op-panel {
    position: static;
    transform: none;
    width: 100%;
    flex: 1 0 100%;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0 0 var(--wp--preset--spacing--40);
    background: transparent;
  }
  .op-panel__grid { grid-template-columns: 1fr; gap: 0; }

  /* MOBIILIJOHDANNAINEN.
     Kuutta suurta ympyrää ei tungeta haitariin. Kaikki kolme varianttia
     pelkistyvät samaan tiiviiseen riviin: pieni ympyrä ja nimi. Sama
     visuaalinen kieli, pienempi mittakaava. Kosketuskohde on koko rivi. */
  /* Tiivis johdannainen koskee VAIN pudotuspaneelia. Ilman `.op-panel`
     -rajausta se valui myös tuotearkiston navigaattoriin, joka on eri
     konteksti: siellä ryhmät ovat orientaatiokerros, eivät valikkorivejä. */
  .op-panel .op-cats { gap: 0; grid-template-columns: 1fr; }
  .op-panel .op-cat__linkki {
    min-height: 52px;
    padding: .55rem .25rem;
  }
  /* Kapselipinta pois: haitarissa rivi täyttää koko leveyden, jolloin
     pyöristetty pinta lukisi turhana kehyksenä. Rivit erottuvat viivalla. */
  .op-panel .op-cat__kehys { display: none; }
  .op-panel .op-cat__ympyra {
    width: 2.4rem;
    height: 2.4rem;
    border-width: 1px;
  }
  .op-panel .op-cat__nimi { font-size: var(--wp--preset--font-size--small); }
  .op-panel .op-cat + .op-cat { border-top: var(--op-line); }
  .op-panel--kapea { width: 100%; padding: 0 0 var(--wp--preset--spacing--40); }
  .op-panel--kapea .op-panel__ryhmat { grid-template-columns: 1fr; gap: var(--wp--preset--spacing--40); }
  .op-panel__linkit a { padding: .6rem .25rem; }
  .op-panel__foot { text-align: left; }
}

/* ==========================================================================
   14. ALATUNNISTE
   ========================================================================== */

.op-footer { color: var(--wp--custom--teksti--tummalla-toissijainen); }
.op-footer h2 {
  font-size: var(--wp--preset--font-size--small);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--wp--custom--toiminto--tummalla);
}
.op-footer a { color: var(--wp--custom--teksti--tummalla); text-decoration: none; }
.op-footer a:hover { color: var(--wp--custom--teksti--kaanteinen); text-decoration: underline; }
.op-footer__list, .op-footer__legal { list-style: none; padding-left: 0; margin: 0; }
.op-footer__list li { margin-bottom: var(--wp--preset--spacing--20); }
.op-footer__legal { display: flex; flex-wrap: wrap; gap: var(--wp--preset--spacing--50); }

/* Some-kanavat (PO 4.9.2026): kaksi ikonilinkkiä yritystietojen alla.
   Hillitty: sama linkkiväri kuin muu alatunniste, ei omaa väriä, ei
   taustaa. Kosketuskohde 40 px vaikka ikoni on 20 px. */
.op-some {
  display: flex;
  gap: var(--wp--preset--spacing--30);
  list-style: none;
  padding: 0;
  margin: var(--wp--preset--spacing--40) 0 0;
}
.op-some li { margin: 0; }
.op-some__linkki {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  margin: -.625rem 0 -.625rem -.625rem;
  border-radius: var(--op-radius);
  color: var(--wp--custom--teksti--tummalla);
}
.op-some__linkki:hover { color: var(--wp--custom--teksti--kaanteinen); text-decoration: none; }
.op-some__ikoni { display: block; width: 20px; height: 20px; }

/* ==========================================================================
   15. PAINIKEROOLIT
   ========================================================================== */

.op-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: .85em 1.5em;
  border-radius: var(--wp--custom--nappi--radius);
  font-family: var(--wp--preset--font-family--display);
  font-weight: 600;
  font-size: var(--wp--preset--font-size--normal);
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
}
.op-btn--primary {
  background: var(--wp--custom--nappi--primary-tausta);
  color: var(--wp--custom--nappi--primary-teksti);
}
.op-btn--primary:hover { background: var(--wp--custom--nappi--primary-hover); }
.op-btn--secondary {
  background: transparent;
  color: var(--wp--custom--nappi--secondary-teksti);
  border-color: var(--wp--custom--nappi--secondary-reuna);
}
.op-btn--secondary:hover { background: var(--wp--custom--nappi--secondary-hover-tausta); }

/* Tummalla pinnalla sekundäärinen painike ei voi käyttää petrolia
   reunuksena — kontrasti tummaa vasten on liian matala. */
.op-hero .op-btn--secondary,
.op-band--dark .op-btn--secondary {
  color: var(--wp--custom--nappi--tummalla-teksti);
  border-color: var(--wp--custom--nappi--tummalla-reuna);
}
.op-hero .op-btn--secondary:hover,
.op-band--dark .op-btn--secondary:hover { background: var(--wp--custom--nappi--tummalla-hover-tausta); }

/* ==========================================================================
   16. SAAVUTETTAVUUS

   FOKUS ON KAKSIROOLINEN. Mitattu 14.8.2026: yksi messinkisävy ei riitä.
   Vaalea messinki valkoisella = 2,25:1 (vaadittu 3,0). Tumma messinki
   tummalla pinnalla = 2,79:1. Kumpikaan arvo ei siis yksinään läpäise
   molempia taustoja, joten rooleja on kaksi ja tumma pinta valitsee omansa.
   ========================================================================== */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--wp--custom--focus--width) solid var(--wp--custom--focus--vaalealla);
  outline-offset: var(--wp--custom--focus--offset);
  border-radius: 2px;
}
.op-hero :focus-visible,
.op-band--dark :focus-visible,
.op-footer :focus-visible {
  outline-color: var(--wp--custom--focus--tummalla);
}

.op-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--wp--custom--pinta--tumma);
  color: var(--wp--custom--teksti--kaanteinen);
  padding: .75rem 1.25rem;
  z-index: 100;
}
.op-skip:focus { left: 1rem; top: 1rem; }

.wp-element-button,
.wp-block-button__link {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

/* ==========================================================================
   17. LUKUPINTA
   ========================================================================== */

.op-prose > * { max-width: var(--op-prose); }
.op-prose > .alignwide, .op-prose > .alignfull { max-width: none; }

/* ==========================================================================
   17. YHTEYDENOTTO
   ========================================================================== */

/* Lomake ja yhteystiedot rinnakkain leveällä, allekkain kapealla.
   Lomake saa enemmän tilaa: se on sivun tehtävä, yhteystiedot ovat tuki. */
.op-yhteys { display: grid; gap: var(--wp--preset--spacing--70); }
@media (min-width: 62rem) {
  .op-yhteys { grid-template-columns: 7fr 4fr; align-items: start; }
  .op-yhteys > .op-note { grid-column: 1 / -1; }
}

/* NÄKYVÄ KONTEKSTI. Kävijä näkee heti, mistä tuotteesta on kyse, eikä
   joudu kirjoittamaan nimeä uudelleen. Erottuu ingressistä, muttei huuda. */
.op-yhteys__konteksti {
  margin: var(--wp--preset--spacing--40) 0 0;
  padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
  background: var(--wp--custom--pinta--korotettu);
  border-left: 3px solid var(--wp--custom--toiminto--perus);
  border-radius: var(--wp--custom--radius--pieni);
}
.op-yhteys__aihe {
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
}

.op-lomake { max-width: var(--wp--custom--measure--prose); }
.op-kentta { margin: 0 0 var(--wp--preset--spacing--50); }
.op-kentta label {
  display: block;
  margin-bottom: var(--wp--preset--spacing--20);
  font-size: var(--wp--preset--font-size--small);
  font-weight: 600;
}
.op-kentta input,
.op-kentta select,
.op-kentta textarea {
  width: 100%;
  box-sizing: border-box;
  padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40);
  font: inherit;
  color: var(--wp--custom--teksti--ensisijainen);
  background: var(--wp--custom--pinta--sivu);
  border: 1px solid var(--wp--custom--reuna--vahva);
  border-radius: var(--wp--custom--radius--pieni);
}
.op-kentta textarea { resize: vertical; min-height: 8rem; }

/* Kenttävirhe on sidottu ohjelmallisesti omaan kenttään. Nykyinen
   lomaketyyli säilyy; vain virheellinen kenttä saa tilavärin. */
.op-kentta [aria-invalid="true"] {
  border-color: var(--wp--custom--tila--virhe);
}
.op-kentta__virhe {
  display: block;
  margin-top: var(--wp--preset--spacing--20);
  color: var(--wp--custom--tila--virhe);
  font-size: var(--wp--preset--font-size--small);
  font-weight: 600;
}

/* HUNAJAPURKKI. Piilotus on visuaalinen, ei `type=hidden` eikä
   `display:none` — osa roboteista ohittaa molemmat, mutta täyttää
   näkyvän tekstikentän. `aria-hidden` ja `tabindex=-1` pitävät sen
   pois ruudunlukijalta ja sarkainjärjestyksestä. */
.op-ansa {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.op-lomake__varoitus,
.op-lomake__pakko {
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
}
.op-lomake__varoitus {
  padding: var(--wp--preset--spacing--40);
  background: var(--wp--custom--pinta--huomio);
  border-radius: var(--wp--custom--radius--pieni);
}

.op-yhteys__tiedot h2 {
  font-size: var(--wp--preset--font-size--large);
  margin-top: 0;
}

/* Onnistuminen ja virhe erottuvat toisistaan värillä JA otsikolla —
   pelkkä väri ei riitä, jos kävijä ei erota niitä. */
.op-note--ok    { border-left-color: var(--wp--custom--tila--ok);    background: var(--wp--custom--pinta--aksentti); }
.op-note--virhe { border-left-color: var(--wp--custom--tila--virhe); background: var(--wp--custom--pinta--huomio); }

/* ==========================================================================
   18. JULKINEN LEARNING JA OPTOPROSTA
   ========================================================================== */

/* Learningin hero on tumma ja tekstivetoinen — sama tiheysperiaate kuin
   etusivulla: vahva otsikko, ei koko ruutua täyttävää kaistaa. */
.op-learning__hero { padding-block: clamp(2rem, 1.2rem + 2vw, 3.25rem); }
.op-learning__hero h1 { max-width: 26ch; margin-block: var(--wp--preset--spacing--40); }
.op-learning__hero .op-lead { max-width: 62ch; margin-block: 0; }

/* Koulutuspolut ja periaatteet käyttävät samaa ruudukkologiikkaa kuin
   tuotekortit: kaksi saraketta leveällä, yksi kapealla. */
.op-polut,
.op-osat {
  display: grid;
  gap: var(--wp--preset--spacing--60);
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 48rem) { .op-polut { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 48rem) { .op-osat  { grid-template-columns: repeat(3, 1fr); } }

.op-polku,
.op-osa {
  padding: var(--wp--preset--spacing--50);
  background: var(--wp--custom--pinta--kortti);
  border: var(--op-line);
  border-radius: var(--op-radius-lg);
}
.op-polku h3,
.op-osa h3 { margin: var(--wp--preset--spacing--20) 0 var(--wp--preset--spacing--30); }
.op-polku p,
.op-osa p  { color: var(--wp--custom--teksti--toissijainen); margin: 0 0 var(--wp--preset--spacing--30); }

.op-polku__kohde {
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--x-small);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--wp--custom--toiminto--perus);
}
/* "Tulossa" on TILA, ei kehote: se ei näytä painikkeelta eikä ole
   klikattava. Kävijän ei pidä luulla, että koulutus on jo saatavilla. */
.op-polku__tila {
  display: inline-block;
  padding: var(--wp--preset--spacing--10) var(--wp--preset--spacing--30);
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
  background: var(--wp--custom--pinta--korotettu);
  border-radius: var(--wp--custom--radius--pieni);
}

.op-periaatteet {
  display: grid;
  gap: var(--wp--preset--spacing--60);
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 40rem) { .op-periaatteet { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 75rem) { .op-periaatteet { grid-template-columns: repeat(4, 1fr); } }
.op-periaate h3 { margin: var(--wp--preset--spacing--20) 0 var(--wp--preset--spacing--20); font-size: var(--wp--preset--font-size--large); }
.op-periaate p  { color: var(--wp--custom--teksti--toissijainen); margin: 0; }
.op-periaate__nro {
  display: block;
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--toiminto--perus);
  padding-bottom: var(--wp--preset--spacing--20);
  border-bottom: 2px solid var(--wp--custom--toiminto--perus);
}

/* ==========================================================================
   19. PALVELUKORTIT
   ========================================================================== */

/* Palvelukortti EI ole tuotekortti: sillä ei ole kuvaa eikä tuotekoodia,
   joten se ei varaa tilaa kummallekaan. Ruudukko on kaksisarakkeinen,
   koska kummassakin ryhmässä on kaksi palvelua — kolme saraketta jättäisi
   joka riville tyhjän paikan. */
.op-palvelut {
  display: grid;
  gap: var(--wp--preset--spacing--50);
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 48rem) { .op-palvelut { grid-template-columns: repeat(2, 1fr); } }

.op-palvelu {
  display: flex;
  flex-direction: column;
  padding: var(--wp--preset--spacing--50);
  background: var(--wp--custom--pinta--kortti);
  border: var(--op-line);
  border-radius: var(--op-radius-lg);
  transition: border-color .15s ease, transform .15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .op-palvelu:hover { border-color: var(--wp--custom--reuna--vahva); transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) { .op-palvelu { transition: none; } }
.op-palvelu:focus-within { border-color: var(--wp--custom--toiminto--perus); }

.op-palvelu__nimi { margin: 0 0 var(--wp--preset--spacing--30); font-size: var(--wp--preset--font-size--large); }
/* Koko kortti on klikattava, mutta linkki on silti otsikossa — siksi
   ::after-peite eikä <a>-kääre: kääre tekisi ruudunlukijalle yhden
   valtavan linkin, jonka nimi on kortin koko teksti. */
.op-palvelu__nimi a { color: inherit; text-decoration: none; }
.op-palvelu__nimi a::after { content: ""; position: absolute; inset: 0; }
.op-palvelu { position: relative; }

.op-palvelu__lupaus {
  margin: 0 0 var(--wp--preset--spacing--40);
  color: var(--wp--custom--teksti--toissijainen);
}
.op-palvelu__foot { margin-top: auto; }

.op-ryhma + .op-ryhma { margin-top: var(--wp--preset--spacing--80); }

/* Sivupalkin kehote täyttää leveyden kuten aiempi painike. */
.op-palvelu__kehote { margin-top: var(--wp--preset--spacing--60); }
/* `.op-btn` on content-box, joten pelkka width:100% laski leveyden ILMAN
   vaakatayttoa: painike levisi 401 px:iin 351 px:n laatikossa ja vuoti
   13 px yli oikealta (mitattu 22.8.2026). */
.op-palvelu__kehote .op-btn {
  display: block;
  box-sizing: border-box;
  width: 100%;
  text-align: center;
}

/* Tietosuojalinkki lomakkeella. Sama hillitty sävy kuin pakollisuus-
   merkinnällä: se on lakisääteinen tieto, ei toimintakehote. */
.op-lomake__tietosuoja {
  margin-block: var(--wp--preset--spacing--40) 0;
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
}


/* ==========================================================================
   20. HENKILOKUVA JA VIIMEISTELY
   ========================================================================== */

/* Kuva kelluu tekstin vierella leveilla naytoilla ja asettuu tekstin
   ylapuolelle kapeilla. Ei suurta muotokuvaa: sivu kertoo yrityksesta,
   ja kasvot ovat tukena — eivat aiheena. */
.op-henkilo__kuva {
  margin: 0 0 var(--wp--preset--spacing--50);
  max-width: 13rem;
}
.op-henkilo__kuva img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--op-radius-lg);
  background: var(--wp--custom--pinta--kortti);
}
.op-henkilo__kuva figcaption {
  margin-top: var(--wp--preset--spacing--30);
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
}
/* Henkilökohtainen LinkedIn-linkki (PO 4.9.2026) on kuvatekstin jatke:
   sama tertiäärinen tekstilinkki + nuoli kuin muualla, pieni väli. */
.op-henkilo__kuva figcaption .op-henkilo__linkedin {
  display: inline-block;
  margin-top: .35rem;
}
@media (min-width: 48rem) {
  .op-henkilo__kuva { float: right; margin-left: var(--wp--preset--spacing--70); }
  /* Kelluva kuva ei saa vuotaa osion ulkopuolelle. */
  .op-henkilo::after { content: ""; display: block; clear: both; }
}

/* Koulutuspolun oma kehote asettuu kortin alareunaan, jotta kaksi
   erikorkuista korttia paattyy samalle riville. */
.op-polku { display: flex; flex-direction: column; }
.op-polku__kehote { margin: auto 0 0; padding-top: var(--wp--preset--spacing--40); }

/* Yhteydenoton kayntiosoite. */
.op-yhteys__osoite { margin-block: var(--wp--preset--spacing--30) 0; }

/* ─────────────────────────────────────────────────────────────────────────
   21. KIELENVAIHTO JA EN-UUTISKIRJE

   Kielenvaihto on NÄKYMÄN vaihto, ei sivu. Siksi se erottuu valikon
   kohteista ohuella erottimella eikä omalla värillään: se ei saa
   kilpailla sisältökohtien kanssa, mutta sen on löydyttävä heti.

   Lippu on `aria-hidden` merkkauksessa (ks. class-kieli.php), joten se on
   tässä puhtaasti visuaalinen. Kielitunnus kantaa merkityksen, joten
   lipun katoaminen (fontti ei tue emojia) ei vie tietoa mukanaan.
   ───────────────────────────────────────────────────────────────────────── */

.op-kieli {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
}

.op-nav__kohta--kieli {
  margin-inline-start: .35rem;
  border-inline-start: 1px solid var(--wp--custom--reuna--hienovarainen);
}

/* Lippu on SVG (ks. class-kieli.php), joten se ei riipu fonteista.
   `flex: none` estaa sita kutistumasta kapealla valikolla. */
.op-kieli__lippu {
  flex: none;
  display: block;
  border-radius: 1px;
}

.op-kieli__koodi { letter-spacing: .02em; }

/* Alatunnisteessa kielenvaihto on tavallinen listalinkki. */
.op-footer .op-kieli { color: inherit; }

/* Mobiilivalikossa kohdat ovat allekkain, joten pystyviiva olisi vaaka-
   erottimen paikalla vaarin pain. */
@media (max-width: 60rem) {
  .op-nav__kohta--kieli {
    margin-inline-start: 0;
    border-inline-start: 0;
    border-block-start: 1px solid var(--wp--custom--reuna--hienovarainen);
  }
}

/* ── EN-uutiskirje ────────────────────────────────────────────────────────
   Lomake kayttaa samoja kenttatyyleja kuin yhteydenotto (.op-kentta),
   joten tassa on vain asettelu ja tilarivi. */

.op-uutiskirje__lomake {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--wp--preset--spacing--40);
  margin-block-start: var(--wp--preset--spacing--50);
}

.op-uutiskirje__lomake .op-kentta {
  flex: 1 1 18rem;
  max-width: 26rem;
  margin: 0;
}

.op-uutiskirje__tila {
  flex: 1 0 100%;
  margin: 0;
  min-height: 1.5rem;
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
}

/* Tietosuojalinkki lomakkeen alla. Sama sävy ja koko kuin tilarivillä:
   se on lomakkeen ehto, ei sen sisältöä. */
.op-uutiskirje__tietosuoja {
  flex: 1 0 100%;
  margin: 0;
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--custom--teksti--toissijainen);
}

/* Reittikaistan kaksi korttia.
   Perus-.op-routes on kiintea kolmen sarakkeen ruudukko. EN-sivustolla
   reitteja on kaksi (palveluhaaraa ei ole), jolloin kolmas sarake jaisi
   tyhjaksi ja kaista nayttaisi rikkinaiselta. Modifier tasapainottaa
   asettelun sen sijaan, etta jattaisi aukon. */
@media (min-width: 48rem) {
  .op-routes--kaksi { grid-template-columns: repeat(2, 1fr); }
}

/* ─────────────────────────────────────────────────────────────────────────
   22. HOME- JA LEARNING-HERON YHTEINEN VÄHIMMÄISKORKEUS (PO 2.9.2026)

   ── MITATTU ONGELMA ──────────────────────────────────────────────────────
   1440 px: Home-hero 390 px, Learning-hero 367 px. FI ja EN olivat
   keskenään identtiset, mutta kaksi heroa eri korkuiset.

   Ero EI johdu pehmusteista: Learningilla on jo ENEMMÄN pystypehmustetta
   (48 px vs 37,44 px). Se johtuu sisällöstä — etusivun herossa on kuva ja
   kaksi painiketta, Learningin herossa pelkkää tekstiä. Pehmustetta
   kasvattamalla ero ei siis korjaannu oikeasta syystä.

   ── RATKAISU ─────────────────────────────────────────────────────────────
   Molemmille YKSI jaettu vähimmäiskorkeus. Arvo on etusivun heron mitattu
   korkeus, joten etusivu ei muutu lainkaan ja Learning nousee samalle
   riville. Jaettu muuttuja on tarkoituksellinen: jos arvoa joskus
   muutetaan, molemmat siirtyvät yhdessä eivätkä pääse erkanemaan.

   `min-height` eikä `height`: otsikko saa yhä taittua vapaasti ja kasvaa
   yli tämän mitan. Mitään ei leikkaudu.

   ── VAIN DESKTOPILLA ─────────────────────────────────────────────────────
   Katko 62rem on sama, jolla etusivun hero muuttuu kaksipalstaiseksi
   (`.op-hero__grid`). Sen alapuolella etusivun hero pinoutuu ja kasvaa
   615 px:iin (768) ja 630–736 px:iin (390), joten sama vähimmäiskorkeus
   tuottaisi Learningiin 80–290 px tyhjää. Kapealla molemmat siis kasvavat
   sisällön mukaan kuten ennenkin.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  --op-hero-vahin: 390px;
}

@media (min-width: 62rem) {
  .op-hero,
  .op-learning__hero {
    min-height: var(--op-hero-vahin);
  }

  /* ── LAATIKKOMALLI ON OSA MITTAA ────────────────────────────────────
     Mitattu 2.9.2026: `.op-hero` on `border-box` (se on WordPressin
     lohkoryhmä, jolle ydin asettaa sen), mutta `.op-learning__hero` on
     lisäosan omaa merkkausta ja siksi `content-box`. Samalla
     `min-height`-arvolla ne kasvavat eri korkuisiksi: content-box lisää
     96 px pehmustetta mitan PÄÄLLE, jolloin Learning nousi 486 px:iin
     390:n sijaan.

     Laatikkomalli on siis yhtenäistettävä, tai jaettu vähimmäismitta
     ei tarkoita samaa asiaa kahdessa paikassa. */
  .op-learning__hero {
    box-sizing: border-box;

    /* Lisätila jaetaan ylä- ja alareunan kesken, ei kasata alas.
       Hero on yksilapsinen kääre (.op-shell), joten grid ei muuta
       sisäistä asettelua eikä otsikon rivittymistä. */
    display: grid;
    align-content: center;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   23. LEARNING-NOSTON KUVA (PO 2.9.2026)

   Etusivun Learning-noston oikea puoli oli tyhjä paikanvaraaja
   (`--tyhja`). Sen tilalla on nyt sama silmäkuva, joka on käytössä
   Optopro Learningin laskeutumissivun herossa — sama tiedosto, sama
   SHA-256, ei uutta assettia.

   ── MIKSI TÄMÄ TARVITSEE OMAN MODIFIERIN ─────────────────────────────────
   Kuva on läpinäkyvä (WebP, alfakanava). `.op-feature__media` antaa
   tummalla kaistalla laatikolle oman VAALEAMMAN taustan ja reunuksen,
   jolloin läpinäkyvä kuva istuisi näkyvän suorakulmion päällä — juuri se
   vika, joka Learning-projektissa korjattiin 21.8.2026. Tausta ja reunus
   poistetaan siis tältä yhdeltä laatikolta.

   `object-fit: contain` eikä perussäännön `cover`: kuvasuhde on 1,387 ja
   kehyksen 1,600, joten `cover` rajaisi silmästä reunat pois. `contain`
   sovittaa koko silmän, ja ylijäävä tila on läpinäkyvää eli näkymätöntä
   tummaa kaistaa vasten.

   Layout, mitoitus ja responsiivisuus eivät muutu: ruudukko, kuvasuhde,
   pyöristys ja `.op-feature`-katkot ovat ennallaan.
   ───────────────────────────────────────────────────────────────────────── */

.op-feature__media--kuva {
  background: none;
  border: 0;
}

.op-feature__media--kuva img {
  object-fit: contain;
}

.op-band--dark .op-feature__media--kuva {
  background: none;
  border: 0;
}
