/* ============================================================
   ESPEK — design system (teemaversio)
   Espek Pintakäsittely Oy · versio 1.0.0

   Vaalea, ilmava ja asiallinen. Yksi fonttiperhe (Inter),
   viisi typografista tasoa, ei laatikkoreunuksia.
   Rytmi syntyy tyhjästä tilasta, epäsymmetriasta ja kuvista —
   ei väripinnoista.

   Tämä on sama todennettu design-järjestelmä kuin Espek Ilme
   -lisäosassa, siirrettynä teemaksi. Luokat on siistitty: koska
   sivu ei enää kulje lohkoeditorin kautta, "wp-block-*"-luokkia
   ei tarvita — kaikki on nyt esp-etuliitteisiä, tarkoitushakuisia
   luokkia. Kaikki tyylit on rajattu .esp-juuri -luokkaan, joka on
   kiinnitetty <body>-elementtiin (ks. functions.php → body_class).
   ============================================================ */

/* ============================================================
   FONTIT — Inter, teeman omista tiedostoista
   Espek Pintakäsittely Oy

   Aiemmin Inter haettiin fonts.googleapis.com-osoitteesta
   wp_enqueue_style()-kutsulla (ks. functions.php, osio 3). Se oli
   renderöinnin ESTÄVÄ pyyntö kolmannen osapuolen palvelimelle
   (~230 ms PageSpeedin mittauksissa mobiilissa), ja se lähetti
   jokaisen kävijän IP-osoitteen Googlelle — tarpeeton tietosuojariski
   EU:ssa, ja hankala perustella sivustolla jolla on evästehyväksyntä.

   Tiedostot: assets/fonts/, Inter v20, latin-osajoukko, woff2.
   Neljä leikkausta = ne jotka ilme.css:ssä oikeasti esiintyvät
   (400, 500, 600, 700). CSS:ssä on kaksi font-weight: 800 -sääntöä,
   mutta 800:aa ei ladattu Google Fontsistakaan, joten selain on aina
   piirtänyt ne 700:lla — tilanne ei siis muutu.

   Polut ovat suhteellisia TÄHÄN tiedostoon nähden (assets/ilme.css →
   assets/fonts/), joten ne toimivat myös jos teema siirretään toiseen
   hakemistoon.

   unicode-range on tarkoituksella jätetty pois: sivusto on kokonaan
   latin-merkistöä, ja ilman rajausta Inter piirtää kaikki merkit
   joille sillä on glyfi.
   ============================================================ */

@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('fonts/inter-v20-latin-regular.woff2') format('woff2');
}

@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('fonts/inter-v20-latin-500.woff2') format('woff2');
}

@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('fonts/inter-v20-latin-600.woff2') format('woff2');
}

@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('fonts/inter-v20-latin-700.woff2') format('woff2');
}

.esp-juuri {
	/* ---- Värit --------------------------------------------
	   Grafiitti + teräksensininen. Ei mustaa, ei oranssia.
	   ------------------------------------------------------ */
	--muste:     #1e2429;   /* leipäteksti ja otsikot */
	--muste-2:   #4b545b;   /* toissijainen teksti — tummennettu (oli #59636b), jotta WCAG AA (4.5:1) täyttyy myös vaihtelevalla --tausta-pohjalla */
	--muste-3:   #606b74;   /* pienet etiketit — tummennettu (oli #8b959c, vain 3:1 valkealla, ei täyttänyt AA:ta pienelle tekstille) */
	--viiva:     #e3e6e7;   /* hiusviiva */
	--viiva-2:   #cdd3d5;
	--paperi:    #ffffff;
	--tausta:    #edf0f1;   /* vuorotteleva vaalea pohja */
	--sini:      #1c5c86;   /* korostus: painikkeet, linkit, luvut */
	--sini-2:    #14486a;   /* hover */
	--sini-3:    #e9f0f5;   /* pehmeä korostustausta */

	/* Toinen, "punchimpi" korostusväri — ei korvaa sinistä toiminnallista
	   väriä (napit/linkit pysyvät sinisinä, jotta klikattava pysyy aina
	   samana värinä), vaan käytetään säästeliäästi pelkkinä koristeellisina
	   kiintopisteinä (ikonikehät, pienet merkit, jälkeen-tunniste) — tuo
	   sivulle toisen sävyn sinisen rinnalle ilman että se muuttuu
	   epäselväksi mikä on klikattavaa. Vertailukypsä liekki-/hehkumetalli-
	   sävy — kytkeytyy suoraan tuotteen omaan aiheeseen (korroosiosuoja,
	   hehkuva metalli), ei asiakkaan kielletty hälyttävä liikennemerkki-
	   oranssi eikä musta. Ensimmäinen versio (#b5502e, tumma ruoste)
	   koettiin liian vaimeaksi/ei "pop"annut riittävästi vaaleaa tai
	   tummaa taustaa vasten — kirkastettu selvästi (saturaatio 59 % → 78 %,
	   vaaleus 45 % → 52 %) pitäen sävyn silti punaisen puolella
	   (H≈10°) eikä oranssin (H≈25–40°). --aksentti-2 on tarkoituksella
	   paljon tummempi sisarsävy, ei vain kevyt hover-tummennus — sitä
	   käytetään ainoana paikkana missä valkoinen teksti istuu suoraan
	   aksenttivärin päällä (esim. jälkeen-tunniste), jotta kirkkaampi
	   --aksentti ei riko tekstikontrastia siellä. */
	--aksentti:   #e44525;
	--aksentti-2: #b63116;

	/* Ristikkoikonin (espek_ikoni_ristikko) värit omina muuttujinaan,
	   jotta sama ikoni toimii sekä vaaleassa (hero) että tummassa
	   (kapasiteetti) jaksossa ilman erillistä PHP-haaraa. */
	--ristikko-tausta: var(--viiva-2);
	--ristikko-vari:   var(--sini);

	/* Yksi tietoinen tumma korostus vaalean sivun keskellä (ei koko
	   sivun tummuutta — ks. kapasiteetti-jakso). Grafiitti, ei musta. */
	--tumma:         #1b2226;
	--tumma-viiva:   rgba(255,255,255,.12);
	--tumma-teksti:  #dbe0e2;
	--tumma-himmea:  #93a0a5;
	--tumma-sini:    #7ec1ea;

	/* ---- Typografia: yksi perhe, viisi tasoa -------------- */
	--fontti:  'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

	--t-iso:    clamp(2.05rem, 1.35rem + 2.7vw, 3.35rem);  /* H1 — pienennetty, jotta hero-otsikko mahtuu kolmelle riville */
	--t-h2:     clamp(1.7rem, 1.25rem + 1.75vw, 2.5rem);   /* H2 */
	--t-h3:     clamp(1.05rem, .99rem + .3vw, 1.22rem);    /* H3 */
	--t-leipa:  clamp(1rem, .97rem + .18vw, 1.08rem);      /* leipä */
	--t-pieni:  .82rem;                                     /* etiketti */
	--t-luku:   clamp(2rem, 1.35rem + 2.4vw, 3.1rem);      /* mittaluvut */
	--t-ingressi: clamp(1.1rem, 1rem + .5vw, 1.3rem);

	/* ---- Mitat ------------------------------------------- */
	--kehys:   1180px;
	--kouru:   clamp(20px, 5vw, 48px);
	--jakso-y: clamp(46px, 5.4vw, 84px);
	--otsikko-korkeus: 68px;

	font-family: var(--fontti);
	font-size: var(--t-leipa);
	line-height: 1.6;
	color: var(--muste);
	background: var(--paperi);
	-webkit-font-smoothing: antialiased;
	font-feature-settings: 'kern' 1;
}

/* Huom: ei overflow-clipiä juuressa. Jos toinen akseli on clip ja
   toinen visible, selain muuttaa visiblen autoksi ja leikkaa myös
   pystysuunnassa — silloin heron limittyvä kuva katkeaisi. */
.esp-juuri *, .esp-juuri *::before, .esp-juuri *::after { box-sizing: border-box; }
.esp-juuri { margin: 0; }

/* Turvaverkko kaikille kuville: pysyy aina palstan levyisenä eikä
   venytä riviä, vaikka kuvalle ei olisi omaa laatikkoluokkaa. */
.esp-juuri img { max-width: 100%; height: auto; display: block; }

/* Ohita sisältöön -linkki näppäimistökäyttäjille */
.esp-skip {
	position: absolute; left: -9999px; top: 0;
	background: var(--sini); color: #fff;
	padding: 12px 18px; z-index: 1000;
	text-decoration: none; font-weight: 600; border-radius: 0 0 4px 0;
}
.esp-skip:focus { left: 0; top: 0; }

/* ============================================================
   0. PÄÄTUNNISTE (sivun ylätunniste, korvaa Astran headerin)
   ============================================================ */

.esp-paatunniste {
	position: sticky; top: 0; z-index: 40;
	background: var(--paperi);
	border-bottom: 1px solid var(--viiva);
}
.esp-paatunniste-rivi {
	width: min(100%, var(--kehys));
	margin-inline: auto;
	padding-inline: var(--kouru);
	min-height: var(--otsikko-korkeus);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
}
.esp-juuri .esp-logo {
	display: inline-flex;
	align-items: center;
	flex: none;
}
.esp-juuri .esp-logo img {
	display: block;
	height: clamp(26px, 3.2vw, 34px);
	width: auto;
}
.esp-nav-lista {
	display: flex;
	align-items: center;
	gap: clamp(16px, 2.2vw, 30px);
	list-style: none; margin: 0; padding: 0;
}
.esp-juuri .esp-nav-lista > li > a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 22px 0;
	color: var(--muste);
	text-decoration: none;
	font-size: .92rem;
	font-weight: 600;
	white-space: nowrap;
}
.esp-juuri .esp-nav-lista > li > a:hover { color: var(--sini); }

/* Pudotusvalikko: Pintakäsittelypalvelut-linkki on itsessään klikattava
   (vie palvelusivulle), ja sen alle avautuu hiiren tai näppäimistön
   kohdistuksella kaksi alipalvelua. Ei JS:ää — pelkkä hover/focus-within. */
.esp-nav-pudotus { position: relative; }
.esp-juuri .esp-nav-pudotus:hover > a,
.esp-juuri .esp-nav-pudotus:focus-within > a { color: var(--sini); }
.esp-nav-nuoli {
	flex: none;
	width: 7px; height: 7px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg) translateY(-2px);
	transition: transform .15s ease;
	opacity: .7;
}
.esp-nav-pudotus:hover .esp-nav-nuoli,
.esp-nav-pudotus:focus-within .esp-nav-nuoli { transform: rotate(225deg) translateY(2px); }

.esp-nav-alivalikko {
	list-style: none; margin: 0; padding: 8px;
	position: absolute; top: 100%; left: 50%;
	transform: translate(-50%, 4px);
	min-width: 210px;
	background: var(--paperi);
	border: 1px solid var(--viiva);
	border-radius: 10px;
	box-shadow: 0 14px 30px -8px rgba(30,36,41,.18), 0 2px 8px rgba(30,36,41,.06);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity .15s ease, transform .15s ease, visibility .15s;
	z-index: 50;
}
.esp-nav-pudotus:hover .esp-nav-alivalikko,
.esp-nav-pudotus:focus-within .esp-nav-alivalikko {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transform: translate(-50%, 0);
}
.esp-juuri .esp-nav-alivalikko a {
	display: block;
	padding: 11px 14px;
	border-radius: 6px;
	color: var(--muste-2);
	text-decoration: none;
	font-size: .9rem;
	font-weight: 500;
	white-space: nowrap;
}
.esp-juuri .esp-nav-alivalikko a:hover,
.esp-juuri .esp-nav-alivalikko a:focus-visible {
	background: var(--sini-3);
	color: var(--sini-2);
}

.esp-paatunniste-oikea { display: flex; align-items: center; gap: clamp(26px, 3.2vw, 44px); }
/* Tarkkuus .esp-nappi.esp-paatunniste-cta (ei pelkkä .esp-paatunniste-cta)
   TARKOITUKSELLA: pelkkä yhden luokan sääntö hävisi myöhemmin tiedostossa
   tulevalle .esp-juuri .esp-nappi -perussäännölle (sama tarkkuus, myöhempi
   sijainti voittaa) — nappi piirtyi koko ajan ison peruskoon mukaisena
   (17px/28px), ei tätä pienempää versiota, riippumatta näytön leveydestä.
   Sama tarkkuusbugi-perhe kuin faktarivin ja UKK:n aiemmat korjaukset. */
.esp-juuri .esp-nappi.esp-paatunniste-cta {
	padding: 11px 20px;
	font-size: .88rem;
	border-radius: 8px;
}

/* Mobiilivalikon avaaja-nappi: piilossa työpöydällä, näkyy vain
   pienellä näytöllä (ks. media-kysely alla). Ikoni vaihtuu napin
   omasta aria-expanded-tilasta CSS:llä, ei JS-ehdolla. */
.esp-nav-avaaja {
	display: none;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex: none;
	padding: 0;
	border: 1px solid var(--viiva);
	border-radius: 8px;
	background: var(--paperi);
	color: var(--muste);
	cursor: pointer;
}
.esp-nav-avaaja:hover { border-color: var(--sini-3); color: var(--sini); }
.esp-nav-avaaja .esp-ico-sulje { display: none; }
.esp-nav-avaaja[aria-expanded="true"] .esp-ico-valikko { display: none; }
.esp-nav-avaaja[aria-expanded="true"] .esp-ico-sulje { display: block; }

/* Mobiilivalikko: alle 760px leveydellä .esp-nav on oletuksena
   koottu (max-height:0, overflow hidden) täysleveä paneeli
   ylätunnisteen alla, ja avautuu footer.php:n skriptin lisäämällä
   .esp-nav--auki -luokalla. Aiemmin nav oli täysin piilossa
   (display:none) eikä sivulle päässyt ollenkaan käsiksi mobiilissa
   — käyttäjäpalaute. Alivalikko (Hiekkapuhallus/Märkämaalaus)
   näytetään mobiilissa aina auki-tilassa sisennettynä listana, ei
   hover/focus-dropdownina, koska kosketusnäytöllä ei ole hoveria. */
@media (max-width: 760px) {
	.esp-nav-avaaja { display: inline-flex; }
	/* CTA-nappi oli mobiilissa selvästi hamburger-nappia korkeampi
	   (käyttäjäpalaute) — sama kiinteä 40px-korkuinen laatikko kuin
	   .esp-nav-avaaja:lla, jotta molempien reunat ovat samalla
	   korkeudella riippumatta fontin omista mittasuhteista. */
	.esp-juuri .esp-nappi.esp-paatunniste-cta {
		height: 40px;
		padding: 0 16px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		font-size: .82rem;
	}
	/* Avautumisanimaatio (max-height + overflow:hidden) on tarkoituksella
	   .esp-nav-lista:lla, EI .esp-nav:lla itsellään — molemmat olivat
	   aiemmin samassa elementissä (.esp-nav), jolloin sen oma box-shadow
	   rajautui pois omalla overflow:hidden-säännöllään aina kun paneeli
	   oli auki (käyttäjäpalaute: "varjo... clippaa kun valikko avautuu").
	   Nyt overflow-rajaus on vain listalla, ja varjo on ehdollinen
	   (näkyy vain .esp-nav--auki-tilassa) ettei se jää näkymään ohuena
	   viivana myös kiinni-tilassa. */
	.esp-nav {
		display: block;
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		background: var(--paperi);
		border-bottom: 1px solid var(--viiva);
		box-shadow: none;
	}
	.esp-nav.esp-nav--auki { box-shadow: 0 16px 32px -12px rgba(30,36,41,.22); }
	/* Pystysuuntainen padding (8px/22px) on ehdollinen, EI kiinteä —
	   max-height:0 ei tosiasiassa puserra paddingia pois (todennettu
	   oikealla laitteella: laatikon korkeus jäi 30px:ään eli täsmälleen
	   padding-top + padding-bottom summaan, vaikka max-height oli 0 ja
	   box-sizing border-box), joten kiinni-tilassa listan alla näkyi
	   ohut raita ensimmäisen linkin tekstistä ("squiggly bits" / haamu-
	   teksti käyttäjäpalautteessa). Kun padding on 0 kiinni-tilassa, ei
	   ole mitään korkeutta joka voisi vuotaa näkyviin riippumatta tästä
	   max-height-oudosta. */
	.esp-nav-lista {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		width: min(100%, var(--kehys));
		margin-inline: auto;
		padding: 0 var(--kouru);
		max-height: 0;
		overflow: hidden;
		transition: max-height .25s ease, padding .25s ease;
	}
	.esp-nav.esp-nav--auki .esp-nav-lista {
		max-height: 80vh;
		overflow-y: auto;
		padding: 8px var(--kouru) 22px;
	}
	.esp-juuri .esp-nav-lista > li > a {
		width: 100%;
		padding: 14px 0;
		border-bottom: 1px solid var(--viiva);
	}
	.esp-nav-nuoli { display: none; }
	.esp-nav-alivalikko {
		position: static;
		opacity: 1;
		visibility: visible;
		pointer-events: auto;
		transform: none;
		min-width: 0;
		border: none;
		box-shadow: none;
		border-radius: 0;
		padding: 2px 0 10px 16px;
	}
	.esp-nav-pudotus:hover .esp-nav-alivalikko,
	.esp-nav-pudotus:focus-within .esp-nav-alivalikko {
		transform: none;
	}
	.esp-juuri .esp-nav-alivalikko a { padding: 10px 0; }
}

/* ============================================================
   1. RAKENNE
   ============================================================ */

.esp-jakso {
	position: relative;
	padding-block: var(--jakso-y);
	background: var(--paperi);
}
.esp-jakso.esp-pohja { background: var(--tausta); }
.esp-jakso.esp-sini  { background: var(--sini-3); }

/* Väli-CTA: täysleveä jakso Palvelut- ja Kapasiteetti-jaksojen välissä —
   sama rakennemalli kuin tummalla Kapasiteetti-jaksolla (väri suoraan
   <section>:lla reunasta reunaan), EI irrallinen kortti valkoisen pohjan
   päällä. Aiemmat yritykset (yksivärinen sininen, ristikkokuvio, sumeat
   hehkupallot + renkaat) koettiin joko tylsäksi tai huonoksi — vaihdettu
   valokuvataustaan: oikea työkuva (sama kuva jota käytetään muuallakin
   sivustolla, tässä paikallaan yksi asennuskehikko) + tumma grafiitti-
   sävytys päällä (EI sininen — asiakas halusi vaihtelua, kortti on jo
   liikaa sinistä). Sävytys on gradientti (tummempi tekstin puolella,
   kevyempi toisessa reunassa), jotta kuva näkyy mutta ei vie huomiota
   tekstiltä ja napeilta. */
.esp-jakso.esp-cta {
	position: relative;
	background-image:
		linear-gradient(120deg, rgba(27,34,38,.86) 0%, rgba(27,34,38,.68) 55%, rgba(27,34,38,.5) 100%),
		url('/wp-content/uploads/2026/09/ESPEK-11.jpg');
	background-size: cover;
	background-position: center 55%;
	background-repeat: no-repeat;
	text-align: center;
}
.esp-cta-sisalto {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	max-width: 46ch;
	margin-inline: auto;
}
/* Tarkkuus .esp-cta-sisalto .esp-cta-otsikko (ei pelkkä .esp-cta-otsikko)
   TARKOITUKSELLA: kun tätä luokkaa käytetään h2-elementissä (kuten
   pintakäsittelypalvelut-sivun päätös-CTA:ssa), pelkkä yhden luokan
   sääntö (0,1,0) hävisi typografiaosion ".esp-juuri h2"-säännölle
   (0,1,1) ja otsikko piirtyi tumman muste-värisenä tumman valokuvan
   päällä eli lähes näkymättömänä — sama tarkkuusbugi-perhe kuin
   muuallakin sivustolla (ks. faktarivin ja UKK:n aiemmat korjaukset). */
.esp-cta-sisalto .esp-cta-otsikko {
	margin: 0 0 10px;
	font-size: clamp(1.5rem, 1.15rem + 1.4vw, 1.9rem);
	font-weight: 800;
	letter-spacing: -.017em;
	line-height: 1.15;
	color: #fff;
	max-width: none;
}
.esp-cta-teksti { margin: 0; color: rgba(255,255,255,.88); font-size: 1.02rem; line-height: 1.5; }
.esp-cta-napit {
	display: flex;
	justify-content: center;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: clamp(22px, 2.6vw, 30px);
}
.esp-cta-napit .esp-nappi { flex: none; }
.esp-juuri .esp-cta .esp-nappi--toissijainen {
	background: #fff;
	border-color: #fff;
	color: var(--sini);
}
.esp-juuri .esp-cta .esp-nappi--toissijainen:hover,
.esp-juuri .esp-cta .esp-nappi--toissijainen:focus-visible {
	background: #fff;
	border-color: #fff;
	color: var(--sini-2);
}
/* Toinen, hillitympi nappi samalla kortilla: läpikuultava täyttö + valkea
   reunus. Kaksi kertaa valkoista täyttöä vierekkäin olisi raskas, joten
   toissijainen puhelinsoitto on selvästi kevyempi. */
.esp-juuri .esp-cta .esp-nappi--reunus {
	background: rgba(255,255,255,.1);
	border-color: rgba(255,255,255,.55);
	color: #fff;
}
.esp-juuri .esp-cta .esp-nappi--reunus:hover,
.esp-juuri .esp-cta .esp-nappi--reunus:focus-visible {
	background: rgba(255,255,255,.18);
	border-color: #fff;
	color: #fff;
}
.esp-juuri .esp-cta .esp-nappi--reunus .esp-ico-puh { color: #fff; }
@media (max-width: 560px) {
	.esp-cta-napit { flex-direction: column; align-items: stretch; width: 100%; }
	.esp-cta-napit .esp-nappi { width: 100%; justify-content: center; }
}

.esp-kehys {
	width: min(100%, var(--kehys));
	margin-inline: auto;
	padding-inline: var(--kouru);
	position: relative;
}

/* Kuva jatkuu kehyksen reunan yli. Ei vw-laskentaa: se aiheuttaisi
   vierityspalkin levyisen vaakavierityksen. */
.esp-vuoto-oikea { margin-right: calc(-1 * var(--kouru)); }
.esp-vuoto-vasen { margin-left:  calc(-1 * var(--kouru)); }

/* ============================================================
   2. TYPOGRAFIA — viisi tasoa, ei enempää
   ============================================================ */

.esp-juuri h1, .esp-juuri h2, .esp-juuri h3 {
	font-family: inherit;
	color: var(--muste);
	margin: 0 0 .55em;
	text-wrap: balance;
}
.esp-juuri h1 {
	font-size: var(--t-iso);
	font-weight: 700;
	line-height: 1.03;
	letter-spacing: -.031em;
}
.esp-juuri h2 {
	font-size: var(--t-h2);
	font-weight: 700;
	line-height: 1.12;
	letter-spacing: -.025em;
	max-width: 22ch;
}
.esp-juuri h3 {
	font-size: var(--t-h3);
	font-weight: 600;
	line-height: 1.32;
	letter-spacing: -.011em;
	margin-bottom: .5em;
}
.esp-juuri p { margin: 0 0 1.1em; }
.esp-juuri p:last-child { margin-bottom: 0; }

/* Pieni etiketti — ainoa versaalityyli koko sivustolla */
.esp-etiketti {
	font-size: var(--t-pieni);
	font-weight: 500;
	letter-spacing: .075em;
	text-transform: uppercase;
	color: var(--muste-3);
	margin: 0 0 1.2em;
	line-height: 1.5;
}

.esp-ingressi {
	font-size: var(--t-ingressi);
	line-height: 1.52;
	color: var(--muste-2);
	max-width: 48ch;
}
.esp-teksti { color: var(--muste-2); }
.esp-pieni  { font-size: .9rem; color: var(--muste-2); line-height: 1.55; }

/* Jakson otsikkorivi: otsikko YLLÄ, ingressi ALLA koko lohkon levyisenä
   (ei enää rinnakkaisina sarakkeina — kaksipalstainen versio näytti
   oudolta, kun otsikko ja ingressi olivat eripituisia ja "end"-
   kohdistus jätti otsikon roikkumaan alas ilman selvää syytä). */
.esp-otsikkorivi {
	display: flex;
	flex-direction: column;
	gap: clamp(12px, 1.6vw, 18px);
	margin-bottom: clamp(28px, 3.2vw, 46px);
	padding-bottom: clamp(16px, 1.8vw, 22px);
	border-bottom: 1px solid var(--viiva);
}
.esp-otsikkorivi > .esp-etiketti { margin-bottom: 0; }
.esp-otsikkorivi h2 { margin-bottom: 0; }
/* Artikkelit-sivun oma otsikkorivi käyttää H1:tä (sivun ainoa H1,
   oikein SEO:n ja saavutettavuuden kannalta), mutta sen pitää näyttää
   täsmälleen samalta kuin H2 muualla — muuten sivun aloitus poikkeaisi
   visuaalisesti kaikista muista jaksoista. */
.esp-otsikkorivi h1 {
	font-size: var(--t-h2);
	font-weight: 700;
	line-height: 1.12;
	letter-spacing: -.025em;
	max-width: 22ch;
	margin-bottom: 0;
}
/* Pieni korostusmerkki jokaisen jakso-otsikon yllä — sama pieni
   yksityiskohta toistuu jokaisen pääjakson kohdalla ilman että se on
   iso väripinta, ja tuo ruoste-aksenttivärin näkyviin myös vaaleilla
   jaksoilla, ei vain tummilla. */
.esp-otsikkorivi h2::before,
.esp-otsikkorivi h1::before {
	content: '';
	display: block;
	width: 36px;
	height: 4px;
	border-radius: 2px;
	background: var(--aksentti);
	margin-bottom: 16px;
}
.esp-otsikkorivi .esp-ingressi { max-width: none; width: 100%; }
/* Yhden sarakkeen otsikkorivi jaksoille ilman etikettiä/ingressiä
   (esim. kapasiteetti) — sama pinorakenne, ei erillistä sääntöä enää
   tarvita paitsi yhteensopivuuden vuoksi vanhalle luokkanimelle. */
.esp-otsikkorivi--yksi {}

/* ============================================================
   3. LINKIT JA PAINIKKEET
   ============================================================ */

.esp-napit {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.esp-juuri .esp-nappi {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-family: inherit;
	font-size: .96rem;
	font-weight: 700;
	line-height: 1;
	letter-spacing: -.006em;
	padding: 17px 28px;
	border: 1px solid var(--sini);
	/* Maltillinen pyöristys — ei täyspyöreä pilleri, ei myöskään terävä
	   90 asteen laatikko. Yleiskäyttöinen, ei erikoismuotoiltu kulma. */
	border-radius: 9px;
	background: var(--sini);
	color: #fff;
	text-decoration: none;
	box-shadow: 0 1px 2px rgba(30,36,41,.08), 0 10px 22px -6px rgba(28,92,134,.45);
	transition: background .16s ease, border-color .16s ease, color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.esp-juuri .esp-nappi:hover, .esp-juuri .esp-nappi:focus-visible {
	background: var(--sini-2);
	border-color: var(--sini-2);
	color: #fff;
	transform: translateY(-2px);
	box-shadow: 0 4px 8px rgba(30,36,41,.1), 0 16px 28px -6px rgba(28,92,134,.5);
}
.esp-juuri .esp-nappi--toissijainen {
	background: var(--paperi);
	border-color: var(--viiva-2);
	color: var(--muste);
	box-shadow: 0 1px 2px rgba(30,36,41,.05);
}
.esp-juuri .esp-nappi--toissijainen:hover {
	border-color: var(--muste);
	background: var(--paperi);
	color: var(--muste);
	box-shadow: 0 4px 8px rgba(30,36,41,.08);
}
.esp-nappi .esp-ico-puh, .esp-paatunniste-puh .esp-ico-puh {
	flex: none;
	width: 17px; height: 17px;
}
/* Puhelinikoni väritettynä sinisellä aina kun se ei jo istu sinisellä
   pohjalla (siellä currentColor=valkoinen riittää ja on parempi kontrasti). */
.esp-juuri .esp-nappi--toissijainen .esp-ico-puh,
.esp-juuri .esp-paatunniste-puh .esp-ico-puh {
	color: var(--sini);
}

.esp-juuri a { color: var(--sini); }
.esp-linkki a {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-weight: 500;
	font-size: .93rem;
	color: var(--sini);
	text-decoration: none;
	border-bottom: 1px solid var(--sini-3);
	padding-bottom: 2px;
	transition: border-color .15s ease;
}
.esp-linkki a:hover { border-bottom-color: var(--sini); }
.esp-linkki a::after {
	content: '';
	flex: none;
	width: 8px;
	height: 8px;
	border-right: 1.5px solid currentColor;
	border-top: 1.5px solid currentColor;
	transform: rotate(45deg) translate(-1px, 1px);
	transition: transform .15s ease;
}
.esp-linkki a:hover::after { transform: rotate(45deg) translate(1px, -1px); }

.esp-juuri a:focus-visible,
.esp-juuri summary:focus-visible,
.esp-juuri button:focus-visible {
	outline: 2px solid var(--sini);
	outline-offset: 3px;
	border-radius: 2px;
}

/* ============================================================
   4. HERO
   ============================================================ */

.esp-hero {
	background: var(--paperi);
	padding-top: clamp(32px, 4vw, 58px);
	padding-bottom: clamp(44px, 5.4vw, 80px);
}

/* Flexbox eikä grid: näin tekstisarake saa määrätä rivin korkeuden
   luonnostaan, ja kuvasarake voi venyä (align-items: stretch) täsmälleen
   saman korkuiseksi — kuvan alareuna asettuu aina "Kuva tai piirustus..."
   -tekstin alareunan tasalle, oli tekstiä vähän tai paljon. */
.esp-hero-grid {
	display: flex;
	align-items: stretch;
	gap: clamp(30px, 4.5vw, 60px);
}
.esp-hero-teksti { flex: 1.12 1 0%; min-width: 0; display: flex; flex-direction: column; }
.esp-hero h1 { margin-bottom: .42em; overflow-wrap: break-word; hyphens: auto; }
.esp-hero .esp-ingressi,
.esp-hero .is-style-espek-ingressi { max-width: 44ch; }
.esp-hero .esp-napit,
.esp-hero .wp-block-buttons { margin-top: clamp(20px, 2.4vw, 28px); gap: 12px; }
.esp-hero .esp-pieni { margin-top: 16px; color: var(--muste-3); font-size: .87rem; }

/* Herokuva: venyy tekstisarakkeen korkuiseksi (ks. yllä). Kuva ja figure
   ovat position:absolute + inset:0 omassa position:relative -laatikossaan,
   jotta kuvan OMA kuvasuhde ei koskaan vaikuta rivin korkeuteen (poissa
   dokumenttivirrasta = ei kontribuoi flex-rivin korkeuslaskentaan) —
   pelkkä tekstisarake määrää korkeuden, kuva vain "cover"-täyttää sen. */
.esp-hero-kuva { flex: 0 1 380px; max-width: 380px; position: relative; }
.esp-hero-kuva figure { margin: 0; position: absolute; inset: 0; }
.esp-hero-kuva img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 42%;
	border-radius: 6px;
}
@media (max-width: 980px) {
	.esp-hero-grid { flex-direction: column; gap: 28px; }
	/* Mobiilissa pinottuna ei ole riviä jonka korkeuteen venyä, joten
	   laatikolle annetaan kiinteä kuvasuhde — absoluuttiasemointi pitää
	   kuvan silti coverina sen sisällä. */
	.esp-hero-kuva { flex: none; max-width: 420px; margin-inline: auto; width: 100%; aspect-ratio: 16 / 10; }

	/* Pinottuna teksti keskitetään: otsikko, ingressi ja napit
	   näyttävät tasapainoisemmilta keskellä kapeaa palstaa kuin
	   vasempaan reunaan ankkuroituna. */
	.esp-hero-teksti { align-items: center; text-align: center; }
	.esp-hero .esp-ingressi,
	.esp-hero .is-style-espek-ingressi { max-width: 44ch; margin-inline: auto; }
	.esp-hero .esp-napit,
	.esp-hero .wp-block-buttons { justify-content: center; }
	.esp-hero .esp-pieni { text-align: center; }
}

/* Faktarivi: koko heron levyinen (teksti + kuva yhteensä), keskitetty
   sisältö per faktalaatikko — ei enää vain tekstisarakkeen levyinen. */
.esp-faktat {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 20px clamp(16px, 2.4vw, 28px);
	border-top: 1px solid var(--viiva);
	padding-top: 22px;
	margin-top: clamp(28px, 3.2vw, 44px);
	width: 100%;
	text-align: center;
}
.esp-fakta p { margin: 0; }
.esp-fakta-ikoni { margin: 0 auto 10px; display: flex; justify-content: center; }
.esp-fakta-ikoni .esp-ico-ristikko { display: block; width: 100%; max-width: 120px; height: 24px; }
.esp-fakta .esp-fakta-arvo {
	font-size: 1.06rem;
	font-weight: 600;
	letter-spacing: -.017em;
	line-height: 1.3;
	margin-bottom: 4px;
}
.esp-fakta .esp-fakta-nimi {
	font-size: .84rem;
	color: var(--muste-3);
	line-height: 1.45;
}
@media (max-width: 560px) {
	.esp-faktat { grid-template-columns: 1fr; gap: 18px; }
	.esp-fakta-ikoni .esp-ico-ristikko { max-width: 120px; }
}

/* ============================================================
   5. PALVELUT — 1×3 korttiruudukko, kuva ylhäällä, sisältö alla.
      Kolme ydinpalvelua rinnakkain samankokoisina pystykortteina;
      aiempi vaakakortti (kuva + teksti rinnan) ei istunut kolmeen
      palstaan, koska kapeat vaakakuvat litistyivät.
   ============================================================ */

.esp-palvelut,
.esp-artikkelit {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(18px, 2.4vw, 28px);
}
.esp-palvelu,
.esp-artikkeli {
	display: flex;
	flex-direction: column;
	border: 1px solid var(--viiva);
	border-radius: 8px;
	background: var(--paperi);
	box-shadow: 0 1px 2px rgba(30,36,41,.04);
	overflow: hidden;
	transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}
.esp-palvelu:hover,
.esp-artikkeli:hover {
	box-shadow: 0 14px 30px -10px rgba(30,36,41,.18);
	transform: translateY(-3px);
	border-color: var(--viiva-2);
}
.esp-palvelu-kuva,
.esp-artikkeli-kuva { display: block; aspect-ratio: 5 / 4; overflow: hidden; background: var(--ristikko-tausta); }
.esp-palvelu-kuva img,
.esp-artikkeli-kuva img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .45s ease; }
.esp-palvelu:hover .esp-palvelu-kuva img,
.esp-artikkeli:hover .esp-artikkeli-kuva img { transform: scale(1.06); }
.esp-palvelu-sisalto,
.esp-artikkeli-sisalto { flex: 1 1 auto; display: flex; flex-direction: column; padding: clamp(18px, 2.2vw, 24px); min-width: 0; }
.esp-palvelu-sisalto h3,
.esp-artikkeli-sisalto h3 { margin-bottom: .4em; }
.esp-juuri .esp-palvelu-sisalto h3 a,
.esp-juuri .esp-artikkeli-sisalto h3 a { color: var(--muste); text-decoration: none; }
.esp-juuri .esp-palvelu-sisalto h3 a:hover,
.esp-juuri .esp-artikkeli-sisalto h3 a:hover { color: var(--sini); }
.esp-palvelu .esp-teksti,
.esp-artikkeli .esp-teksti { font-size: .93rem; margin-bottom: 14px; flex: 1 1 auto; }
.esp-palvelu .esp-linkki,
.esp-artikkeli .esp-linkki { margin-top: auto; }
/* Julkaisupäivä-etiketti kortin sisällön yläreunassa on kevyempi
   kuin jakson otsikon oma etiketti (1.2em marginaali näyttäisi liian
   isolta pieneen korttiin), joten se saa oman tiiviimmän välinsä. */
.esp-artikkeli-sisalto > .esp-etiketti { margin-bottom: .5em; }
@media (max-width: 860px) {
	.esp-palvelut,
	.esp-artikkelit { grid-template-columns: 1fr; }
	.esp-palvelu-kuva,
	.esp-artikkeli-kuva { aspect-ratio: 16 / 9; }
}
@media (max-width: 1080px) and (min-width: 861px) {
	.esp-artikkelit { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ============================================================
   6. KAPASITEETTI — leipäteksti vasemmalla, kaksi hallikohtaista
      faktalaatikkoa oikealla (yksi per halli, ei geneeristä
      kolmen luvun riviä), ja niiden alla täysleveä vaakakuva.
   ============================================================ */

.esp-kapasiteetti {
	display: flex;
	flex-direction: column;
	gap: clamp(28px, 3.2vw, 44px);
}
.esp-kapasiteetti-ylarivi {
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
	gap: clamp(28px, 4vw, 56px);
	align-items: start;
}
.esp-kapasiteetti-teksti {
	display: flex;
	flex-direction: column;
	gap: 14px;
}
.esp-kapasiteetti-hallit {
	display: flex;
	flex-direction: column;
	gap: 14px;
}
.esp-halli {
	border: 1px solid var(--tumma-viiva);
	border-radius: 10px;
	padding: clamp(18px, 2vw, 24px) clamp(20px, 2.2vw, 26px);
	background: rgba(255,255,255,.03);
	transition: border-color .2s ease, background .2s ease, transform .2s ease;
}
.esp-halli:hover {
	border-color: rgba(255,255,255,.22);
	background: rgba(255,255,255,.055);
	transform: translateY(-2px);
}
.esp-halli p { margin: 0; }
.esp-halli-nimi {
	font-size: .8rem;
	font-weight: 600;
	letter-spacing: .03em;
	text-transform: uppercase;
	color: var(--tumma-himmea);
	margin-bottom: 12px;
}
.esp-halli-lista,
/* Hallilaatikon sisällä käytetään nykyään WordPressin OMAA
   Luettelo-lohkoa (core/list, ks. lohkot.js "Hallilaatikko" ja sen
   sisään lisättävä InnerBlocks) suoraan kovakoodatun <ul>:n sijaan —
   sama visuaalinen "pisteen sijaan aksenttipallo" -tyyli haetaan siis
   geneerisellä .esp-halli ul -kontekstivalitsimella, ei erillisellä
   luokalla, koska lohko ei voi lisätä omaa luokkaansa core/listin
   ulos tulevaan <ul>-elementtiin. */
.esp-halli ul {
	list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px;
}
.esp-halli-lista li,
.esp-halli ul li {
	position: relative;
	padding-left: 17px;
	color: var(--tumma-teksti);
	font-size: .95rem;
	line-height: 1.5;
}
.esp-halli-lista li::before,
.esp-halli ul li::before {
	content: '';
	position: absolute;
	left: 0;
	top: .6em;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--aksentti);
}

.esp-kapasiteetti-kuva figure { margin: 0; }
.esp-kapasiteetti-kuva img {
	display: block;
	width: 100%;
	height: clamp(220px, 26vw, 340px);
	object-fit: cover;
	object-position: 50% 50%;
	border-radius: 6px;
}
@media (max-width: 780px) {
	.esp-kapasiteetti-ylarivi { grid-template-columns: 1fr; }
	.esp-kapasiteetti-kuva img { height: clamp(200px, 50vw, 280px); }
}

/* ---- Tumma jakso (kapasiteetti) -----------------------------
   Yksi tietoinen tumma korostus keskellä muuten vaaleaa sivua —
   ei koko sivun tummuutta. Antaa painoa numeroille ja rytmittää
   sivun kulkua (vaalea → tumma → vaalea). */
.esp-jakso.esp-tumma { background: var(--tumma); color: var(--tumma-teksti); }
.esp-tumma .esp-etiketti { color: var(--tumma-himmea); }
.esp-tumma h2 { color: #fff; }
.esp-tumma .esp-ingressi { color: var(--tumma-teksti); }
.esp-tumma .esp-teksti { color: var(--tumma-teksti); }
.esp-tumma .esp-otsikkorivi { border-bottom-color: var(--tumma-viiva); }
/* Lohkoeditorissa lisätty TAVALLINEN (ei mitään erityistyyliä saanut)
   kappale tumman jakson sisään perii muuten koko sivun oletusvärin
   (var(--muste-2), tumma harmaa) ja katoaisi näkymättömiin tummaa
   taustaa vasten. Tämä on tarkoituksellinen "ei voi rikkoutua
   kuvaa/tekstiä vaihtaessa" -oletus: kuka tahansa voi pudottaa
   Kappale-lohkon tummaan jaksoon eikä tarvitse tietää erikseen
   valita mitään tyyliä saadakseen luettavan tekstin. */
/* :where() nollaa tarkkuuden, jotta tämä oletus häviää aina
   tarkemmalle tyylille (esim. is-style-espek-cta-otsikko) eikä
   koskaan "voita" tarkoituksella annettua väriä. */
.esp-tumma :where(p) { color: var(--tumma-teksti); }
/* Sama periaate CTA-kuvatausta-jaksossa (valokuva + tumma sävytys). */
.esp-cta :where(p) { color: rgba(255,255,255,.88); }

/* ============================================================
   7. PROSESSI — kolme vaihetta. Aiempi laskettu vaakaviiva
      pallosta palloon (calc()-leveys) näytti rikkinäiseltä/
      väärin kohdistuvalta osalla näyttöleveyksiä — poistettu
      kokonaan. Tilalle ohut PYSTYSUUNTAINEN erotinviiva
      sarakkeiden välissä (ruudukon oman gap-tilan keskellä,
      koko korkeuden yli) — erottaa vaiheet toisistaan ilman
      laatikko-/korttimaista reunusta minkään yksittäisen
      vaiheen ympärillä.
   ============================================================ */

.esp-vaiheet {
	--vaihe-vali: clamp(30px, 4.5vw, 64px);
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--vaihe-vali);
	padding-top: 4px;
	/* Numerointi on CSS-counter, ei lohkon oma attribuutti (ks.
	   inc/lohkot.php, osio 5) — vaiheen lisäys/poisto/järjestyksen
	   vaihto lohkoeditorissa ei siis voi koskaan jättää väärää
	   numeroa näkyviin. */
	counter-reset: esp-vaihe-laskuri;
}
.esp-vaihe { position: relative; counter-increment: esp-vaihe-laskuri; }
.esp-vaihe-nro::before { content: counter(esp-vaihe-laskuri); }
.esp-vaihe:not(:first-child)::before {
	content: '';
	position: absolute;
	top: 4px;
	bottom: 4px;
	left: calc(-1 * var(--vaihe-vali) / 2);
	width: 1px;
	background: var(--viiva-2);
}
.esp-vaihe-otsikko {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-bottom: .55em;
}
.esp-vaihe-nro {
	flex: none;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: var(--sini);
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 1.05rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}
.esp-vaihe-otsikko h3 { margin: 0; }
.esp-vaihe .esp-teksti { font-size: .96rem; margin: 0; }
@media (max-width: 860px) {
	.esp-vaiheet { grid-template-columns: 1fr; gap: 26px; padding-top: 0; }
	.esp-vaihe::before { display: none; }
	/* Vain 2. ja 3. vaihe saavat oman yläviivansa mobiilissa (sama
	   :not(:first-child)-rajaus kuin työpöydän pystyviivalla yllä) — jos
	   ensimmäinenkin vaihe saisi sen, se päätyisi aivan kiinni
	   otsikkorivin omaan alaviivaan ja näytti tupla/redundantilta
	   viivalta "Näin saat kestävän..." -otsikon alla. */
	.esp-vaihe:not(:first-child) { border-top: 1px solid var(--viiva-2); padding-top: 22px; }
}

/* Yleiskäyttöinen keskitetty CTA-rivi jakson sisällön alla (Prosessi,
   Faktarivi) — oma nappi omalla rivillään, keskitettynä, riittävällä
   yläväliä sisällöstä. */
.esp-jakso-cta {
	display: flex;
	justify-content: center;
	margin-top: clamp(32px, 4vw, 52px);
}
/* Tumma-jaksossa (Faktarivi) sininen täyttönappi jäi sinistä lähelle
   olevaa grafiittitaustaa vasten liian vaimeaksi ("negative color
   against the dark backdrop" — käyttäjän pyyntö). Käännetty negatiiviksi:
   valkoinen täyttö + sininen teksti, sama yhdistelmä joka on jo käytössä
   .esp-cta-jakson toissijaisessa napissa. */
.esp-tumma .esp-jakso-cta .esp-nappi {
	background: #fff;
	border-color: #fff;
	color: var(--sini);
	box-shadow: 0 1px 2px rgba(0,0,0,.2), 0 10px 22px -6px rgba(0,0,0,.35);
}
.esp-tumma .esp-jakso-cta .esp-nappi:hover,
.esp-tumma .esp-jakso-cta .esp-nappi:focus-visible {
	background: var(--tumma-teksti, #fff);
	border-color: var(--tumma-teksti, #fff);
	color: var(--sini);
}

/* ============================================================
   8. TYÖT — epäsymmetrinen kuvasommitelma
   ============================================================ */

.esp-tyot {
	display: grid;
	grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
	gap: clamp(22px, 3vw, 40px);
	align-items: start;
}
.esp-tyot-oikea { display: grid; gap: clamp(22px, 3vw, 40px); }
@media (max-width: 860px) { .esp-tyot { grid-template-columns: 1fr; } }

.esp-tyo figure { margin: 0; }
.esp-tyo img {
	display: block;
	width: 100%;
	border-radius: 4px;
	object-fit: cover;
	object-position: 50% 50%;
}
.esp-tyo--iso img { height: clamp(300px, 42vw, 528px); }
.esp-tyo--pieni img { height: clamp(190px, 20vw, 244px); }
.esp-tyo .esp-tyo-nimi {
	font-size: .97rem;
	font-weight: 600;
	letter-spacing: -.012em;
	margin: 14px 0 3px;
}
.esp-tyo .esp-tyo-selite { font-size: .88rem; color: var(--muste-3); margin: 0; }

/* Ennen/jälkeen-vertailu — vain kahdella pienemmällä työkuvalla (ei
   isolla vasemmanpuoleisella). Vedettävä pystyviiva paljastaa "ennen"-
   kuvan vasemmalta, "jälkeen"-kuva näkyy oikealta. Native
   <input type="range"> koko laatikon päällä (näkymätön) hoitaa sekä
   raahauksen että näppäimistö-/kosketuskäytön — CSS-muuttuja --ej
   päivitetään JS:llä (assets/ennen-jalkeen.js) ja ohjaa sekä leikkausta
   että kahvan sijaintia, joten mitään ei jouduta laskemaan kahteen
   kertaan. */
.esp-tyo--pieni .esp-ennen-jalkeen {
	--ej: 50%;
	position: relative;
	height: clamp(190px, 20vw, 244px);
	border-radius: 4px;
	overflow: hidden;
}
.esp-tyo--pieni .esp-ennen-jalkeen figure { position: absolute; inset: 0; margin: 0; }
.esp-tyo--pieni .esp-ennen-jalkeen img { height: 100%; }
.esp-ej-jalkeen { z-index: 0; }
.esp-ej-ennen {
	z-index: 1;
	clip-path: inset(0 calc(100% - var(--ej)) 0 0);
}
.esp-ej-kahva {
	position: absolute;
	top: 0;
	bottom: 0;
	left: var(--ej);
	width: 2px;
	background: #fff;
	transform: translateX(-50%);
	z-index: 2;
	pointer-events: none;
	box-shadow: 0 0 0 1px rgba(27,36,41,.15);
}
/* Kahva on nyt oma elementti (ei ::after), jotta ympyrälle jää omat
   ::before/::after-pseudoelementit kahdelle pienelle nuolelle — yksi
   vasemmalle, yksi oikealle. Yksittäinen vain-vasemmalle-osoittava
   nuoli näytti oudolta "vetopalkilta"; kaksi vastakkaista nuolta
   ("‹ ›") viestii selvemmin, että vetäminen onnistuu kumpaankin
   suuntaan. */
.esp-ej-kahva-ympyra {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	background: #fff;
	transform: translate(-50%, -50%);
	box-shadow: 0 2px 10px rgba(27,36,41,.28);
}
.esp-ej-kahva-ympyra::before,
.esp-ej-kahva-ympyra::after {
	content: '';
	position: absolute;
	top: 50%;
	width: 7px;
	height: 7px;
	border-bottom: 1.75px solid var(--muste);
}
.esp-ej-kahva-ympyra::before {
	left: 40%;
	border-left: 1.75px solid var(--muste);
	transform: translate(-50%, -50%) rotate(45deg);
}
.esp-ej-kahva-ympyra::after {
	left: 60%;
	border-right: 1.75px solid var(--muste);
	transform: translate(-50%, -50%) rotate(-45deg);
}
.esp-ej-tunniste {
	position: absolute;
	top: 10px;
	z-index: 2;
	font-size: .68rem;
	font-weight: 600;
	letter-spacing: .05em;
	text-transform: uppercase;
	color: #fff;
	background: rgba(27,34,38,.55);
	padding: 4px 9px;
	border-radius: 100px;
	pointer-events: none;
}
.esp-ej-tunniste--ennen { left: 10px; }
/* "Jälkeen"-tunniste aksenttivärillä — ohjaa katsetta tarkoituksella
   tulokseen, ei vain lähtötilanteeseen. Käyttää tummempaa --aksentti-2:ta,
   ei kirkasta --aksentti:ia, koska tekstinä on pieni (.68rem) lihavoitu
   VALKOINEN teksti suoraan värin päällä — kirkkaampi sävy ei riittäisi
   WCAG AA:n 4.5:1-vaatimukseen tässä käyttötavassa. */
.esp-ej-tunniste--jalkeen { right: 10px; background: var(--aksentti-2); }
.esp-ej-liuku {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	opacity: 0;
	cursor: ew-resize;
	z-index: 3;
	-webkit-appearance: none;
	appearance: none;
	background: transparent;
}
.esp-ej-liuku::-webkit-slider-runnable-track { background: transparent; }
.esp-ej-liuku::-moz-range-track { background: transparent; border: none; }
.esp-ej-liuku::-webkit-slider-thumb { -webkit-appearance: none; width: 2px; height: 100%; background: transparent; }
.esp-ej-liuku::-moz-range-thumb { width: 2px; height: 100%; background: transparent; border: none; }

/* Asiakkaan sanoin */
.esp-juuri .esp-sitaatti {
	margin: clamp(32px, 3.6vw, 54px) 0 0;
	padding: 0;
	border: 0;
	border-top: 1px solid var(--viiva);
	padding-top: clamp(20px, 2.4vw, 30px);
	max-width: 62ch;
}
.esp-juuri .esp-sitaatti p {
	font-size: clamp(1.15rem, 1rem + .7vw, 1.55rem);
	font-weight: 500;
	line-height: 1.42;
	letter-spacing: -.018em;
	color: var(--muste);
	margin: 0 0 16px;
	text-wrap: pretty;
}
.esp-juuri .esp-sitaatti cite {
	font-style: normal;
	font-size: .87rem;
	color: var(--muste-3);
	font-weight: 400;
}

/* ============================================================
   9. FAKTARIVI (korvaa entisen "Miksi Espek" -tekstijakson) —
      kolme lyhyttä myyntiväittämää tumman jakson päällä. Sama
      rakenteellinen idea kuin asiakkaan nykyisellä sivustolla, mutta
      sivun omalla tumma-grafiittipohjalla (ei mustaa) ja design-
      järjestelmän omilla viivaikoneilla.

      TIETOISESTI EPÄSYMMETRINEN (ei enää kolme tasaista saraketta):
      ensimmäinen fakta on koko rivin levyinen "pääväite" (vaakarakenne,
      isompi ikoni ja otsikko), loput kaksi pienempänä parina sen alla.
      Hero-faktarivi (.esp-faktat) on täysin symmetrinen, keskitetty
      3-sarakkeinen "mittaristo" (ikoni+luku+nimi, sama koko joka
      kohdassa) — kun tämäkin jakso oli sama tasainen 3-sarakerakenne,
      kaksi rakenteeltaan identtistä "kolme klooniruutua" -riviä alkoivat
      toistaa toisiaan liikaa vieritettäessä. Epäsymmetria + vasen
      kohdistus + hierarkia (yksi nostettu pääväite kahden tukevan
      rinnalle) erottaa tämän hero-faktoista rakenteellisesti, ei enää
      pelkällä värillä/kohdistuksella. */

.esp-faktarivi-ruudukko {
	--faktarivi-vali: clamp(24px, 3.4vw, 44px);
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	column-gap: clamp(28px, 4vw, 56px);
	row-gap: clamp(30px, 3.6vw, 44px);
}
.esp-faktarivi-kohta { position: relative; display: flex; flex-direction: column; align-items: flex-start; }

/* Ikoni ja otsikko ovat AINA oma vaakarivinsä (.esp-faktarivi-otsikko),
   keskitetty toisiaan vasten align-items: center:llä — ei enää kolmea
   erillistä flex-lasta (ikoni, otsikko, teksti) samalla rivillä, mikä
   sai leipätekstin näyttämään irralliselta/väärin keskitetyltä ikoniin
   nähden (jokainen keskittyi vain omaan korkeuteensa, ei toisiinsa).
   Leipäteksti on oma rivinsä otsikkorivin alla — ei enää yritä
   keskittyä ikonia vasten lainkaan, joten ongelma ei voi enää toistua. */
.esp-faktarivi-otsikko {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 16px;
	margin-bottom: 12px;
}
/* h3:n oma oletus-margin-bottom (.5em, ks. osio 2) laskettiin mukaan
   otsikkorivin korkeuteen, minkä vuoksi align-items: center keskitti
   ikonin ja otsikon eri kohtiin (otsikon NÄKYVÄ teksti näytti n. 5px
   ikonin yläpuolella, koska sen "täysi" laatikko sisälsi näkymättömän
   marginaalin alla) — käyttäjä huomasi tämän kahdesti. Nollataan tässä
   kontekstissa, rivin oma `gap` hoitaa välit joka tapauksessa. */
.esp-faktarivi-otsikko h3 { margin-bottom: 0; }

/* Ensimmäinen fakta = pääväite: koko rivin levyinen, kaikki kolme osaa
   (ikoni, otsikko, teksti) samalla vaakarivillä — käyttäjän toiveesta
   pidetty tässä tarkoituksella "all horizontal", toisin kuin alempi pari.
   Ikoni+otsikko on omana ryhmänään (.esp-faktarivi-otsikko), joten se
   keskittyy yhtenä kokonaisuutena leipätekstiä vasten (align-items:
   center koko rivillä) sen sijaan että kolme erillistä osaa keskittyisivät
   kukin omillaan — tämä oli alkuperäinen keskitysongelma, ei itse
   vaakarakenne. */
.esp-faktarivi-kohta:first-child {
	grid-column: 1 / -1;
	flex-direction: row;
	align-items: center;
	gap: clamp(28px, 3.6vw, 48px);
	padding-bottom: clamp(26px, 3.2vw, 40px);
	border-bottom: 1px solid var(--tumma-viiva);
}
.esp-faktarivi-kohta:first-child .esp-faktarivi-otsikko { gap: clamp(20px, 3vw, 32px); margin-bottom: 0; flex: none; }
.esp-faktarivi-kohta:first-child .esp-faktarivi-ikoni {
	width: 84px;
	height: 84px;
	flex: none;
	margin-bottom: 0;
}
.esp-faktarivi-kohta:first-child .esp-faktarivi-ikoni .esp-ico-faktarivi { width: 38px; height: 38px; }
/* Erikoistarkkuus (.esp-tumma .esp-faktarivi-kohta:first-child h3) tässä
   TARKOITUKSELLA, ei vahinko: pelkkä ".esp-faktarivi-kohta:first-child h3"
   oli sama spesifisyys kuin alempi ".esp-tumma .esp-faktarivi-kohta h3"
   -sääntö, ja koska jälkimmäinen tulee tiedostossa myöhemmin, se voitti
   ja pääväite renderöityi vahingossa samalla pienellä fontilla kuin
   tukeva pari — huomattiin vasta kun ikoni+otsikko-keskitystä
   diagnosoitiin tarkemmin. */
.esp-tumma .esp-faktarivi-kohta:first-child h3 { font-size: clamp(1.32rem, 1.1rem + .75vw, 1.62rem); max-width: 26ch; }
.esp-faktarivi-kohta:first-child .esp-teksti { max-width: 58ch; margin: 0; }

/* Toinen ja kolmas fakta = tukeva pari, sama ohut pystysuuntainen
   erotinviiva-idea kuin Prosessi-jaksossa (ks. .esp-vaihe) — tuttu,
   jo todennettu motiivi, ei uusi keksintö. */
.esp-faktarivi-kohta:nth-child(3)::before {
	content: '';
	position: absolute;
	top: 6px;
	bottom: 6px;
	left: calc(-1 * var(--faktarivi-vali) / 2 - 14px);
	width: 1px;
	background: var(--tumma-viiva);
}
.esp-faktarivi-ikoni {
	width: 52px;
	height: 52px;
	border-radius: 50%;
	background: rgba(228, 69, 37, .16);
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	color: var(--aksentti);
}
.esp-faktarivi-ikoni .esp-ico-faktarivi { width: 24px; height: 24px; stroke-width: 1.6; }
/* Ei max-width:ch-rajaa täällä (oli aiemmin 24ch): ch-yksikkö perustuu
   fontin "0"-merkin leveyteen, joka ei vastaa todellisten sanojen
   leveyttä — "Kokonaisvaltainen palveluntarjoaja" ja "Tuotteita
   Suomessa ja maailmalla" ovat lähes yhtä pitkiä merkkimäärältään,
   mutta jälkimmäisessä on kapeampia kirjaimia, joten se mahtui 24ch:n
   sisään ja edellinen ei — tabletilla kaksi rakenteeltaan identtistä
   otsikkoa rivittyivät siis eri tavalla ilman todellista tilasyytä.
   Otsikko rivittyy nyt vain kun ruudukon sarakkeen oikea leveys ei
   riitä (flex-lapsen oma min-width:auto + rivin gap riittää rajaksi),
   ei enää keinotekoisen merkkirajan takia. */
.esp-tumma .esp-faktarivi-kohta h3 {
	color: #fff;
	font-size: clamp(1.06rem, 1rem + .3vw, 1.22rem);
	font-weight: 700;
}
.esp-faktarivi-kohta .esp-teksti { max-width: 46ch; font-size: .93rem; }
/* Raja nostettu 760px:stä 1023px:ään (oli sama kuin mobiilivalikon raja,
   mutta se oli sattumaa, ei tarkoituksellista): parin (facts 2 & 3)
   2-sarakerakenne on liian kapea n. 761–1023px leveydellä oikealle
   ikoni+otsikko-rivin tilantarpeelle — "Kokonaisvaltainen palveluntarjoaja"
   rivittyi kahdelle riville tabletilla vaikka "Tuotteita Suomessa ja
   maailmalla" mahtui yhdelle, koska sarakkeen todellinen leveys ei
   riittänyt kummallekaan lähelle rajaa olevalle otsikolle — vahvistettu
   oikealla Inter-fontilla (ei esikatselun varafontilla) mittaamalla
   otsikoiden todellinen rivimäärä eri leveyksillä: 900px vielä rivittää,
   960px ei enää. Yksinkertaisin luotettava korjaus ei ole ikonin/välin
   pienentäminen pikselintarkasti rajan tuntumaan, vaan sama pystysuora
   pino-asettelu kuin mobiilissa käytetään aina 1024px asti, jolloin
   2-sarakepari tulee käyttöön vasta kun se oikeasti mahtuu. */
@media (max-width: 1023px) {
	.esp-faktarivi-ruudukko { grid-template-columns: 1fr; row-gap: 28px; }
	.esp-faktarivi-kohta:first-child {
		grid-column: auto;
		flex-direction: column;
		align-items: flex-start;
		gap: 0;
		padding-bottom: 26px;
	}
	.esp-faktarivi-kohta:first-child .esp-faktarivi-otsikko { margin-bottom: 16px; }
	.esp-faktarivi-kohta:first-child .esp-faktarivi-ikoni {
		width: 60px;
		height: 60px;
	}
	.esp-faktarivi-kohta:first-child .esp-faktarivi-ikoni .esp-ico-faktarivi { width: 28px; height: 28px; }
	.esp-faktarivi-kohta:nth-child(3)::before { display: none; }
	.esp-faktarivi-kohta:nth-child(3) { border-top: 1px solid var(--tumma-viiva); padding-top: 26px; }
	/* Pääväitteen otsikko on työpöydällä tarkoituksella isompi
	   (ks. yllä), mutta mobiilissa kolme allekkaista otsikkoa vierekkäin
	   näyttivät hämmentävän eri kokoisilta ("these headings are in
	   different size"). Yhtenäistetty samaksi kuin kahden muun faktan
	   otsikko pelkästään mobiilissa. */
	.esp-tumma .esp-faktarivi-kohta:first-child h3 { font-size: clamp(1.06rem, 1rem + .3vw, 1.22rem); max-width: none; }
}

/* ============================================================
   10. TAUSTAKUVIO + TOIMINTA-ALUE
   ============================================================ */

/* Uudelleenkäytettävä .esp-kuviotausta-luokka: hyvin himmeä, suurikokoinen
   ristikkokuvio (sama espek_ikoni_ristikko()-funktio, jota käytetään jo
   herossa) jakson taustalla tuo tekstuuria ja kytkee kuvion toistuvaksi
   teemaksi sen sijaan että se näkyisi vain kerran herossa — ei uusi
   kuva-assetti, ei häiritse luettavuutta (opasiteetti ~6 %). Käytössä
   Palvelut- ja UKK-jaksoissa (aiemmin myös omana Kenelle-jaksonaan, joka
   yhdistettiin Palvelut-osioon kahdeksannen kierroksen jälkeen). */
.esp-kuviotausta { position: relative; overflow: hidden; }
.esp-kuviotausta-kuvio {
	--ristikko-tausta: var(--muste-3);
	--ristikko-vari: var(--muste-3);
	position: absolute;
	bottom: clamp(14px, 3vw, 42px);
	top: auto;
	right: -50px;
	width: clamp(320px, 38vw, 560px);
	opacity: .05;
	pointer-events: none;
	z-index: 0;
}
.esp-kuviotausta-kuvio .esp-ico-ristikko { display: block; width: 100%; height: auto; }
.esp-kuviotausta > .esp-kehys { position: relative; z-index: 1; }
@media (max-width: 760px) {
	.esp-kuviotausta-kuvio { width: 260px; right: -60px; }
}

/* Asiakaslista — "tarkistuslista"-tyylinen 3-sarakkeinen ruudukko (rasti +
   teksti per kohta) korvasi aiemman pystylistän jossa kohdat erotti vain
   vaakaviiva. Viisi kohtaa asettuu 3+2-riviksi. Nykyisin Palvelut-osion
   kolmen kortin alapuolella (siirretty pois entisestä Kenelle-jaksosta) —
   oma yläviiva ja väli erottaa sen kortiston omasta rytmistä. */
.esp-tarkistuslista {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 20px clamp(20px, 3vw, 40px);
}
.esp-palvelut + .esp-tarkistuslista {
	margin-top: clamp(32px, 4vw, 52px);
	padding-top: clamp(24px, 3vw, 36px);
	border-top: 1px solid var(--viiva);
}
.esp-tarkistuslista li {
	display: flex;
	align-items: flex-start;
	gap: 11px;
	color: var(--muste-2);
	font-size: .98rem;
	line-height: 1.4;
}
.esp-tarkistuslista .esp-ico-tarkistus {
	width: 19px;
	height: 19px;
	flex: none;
	margin-top: 2px;
	color: var(--aksentti);
}
@media (max-width: 760px) {
	.esp-tarkistuslista { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
	.esp-tarkistuslista { grid-template-columns: 1fr; }
}

/* Saapuminen-jakso: teksti vasemmalla, kartta oikealla — sama 2-palstainen
   idea kuin Yhteys-osiossa, mutta tasaisempi jako koska kumpikaan puoli ei
   tarvitse selvästi enemmän tilaa kuin toinen. */
.esp-saapuminen-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: clamp(32px, 5vw, 72px);
	align-items: start;
}
@media (max-width: 860px) {
	.esp-saapuminen-grid { grid-template-columns: 1fr; gap: 34px; }
}
.esp-saapuminen-teksti .esp-otsikkorivi { border-bottom: none; padding-bottom: 0; }

/* Toiminta-alueen kartta — korvasi aiemman paikkakuntapillien rivin
   (esp-paikat, poistettu) suoralla Google Maps -upotuksella, koska
   konkreettinen sijainti kartalla kertoo saavutettavuudesta paremmin
   kuin lista kaupunkien nimiä. .esp-kartta on itse upotuksen (iframe)
   säiliö — käytetään sellaisenaan .esp-kartta-kortin SISÄLLÄ alla. */
.esp-kartta {
	position: relative;
	width: 100%;
	max-width: 640px;
	aspect-ratio: 4 / 3;
	border-radius: 12px;
	overflow: hidden;
	border: 1px solid var(--viiva-2);
}
.esp-kartta iframe { position: absolute; inset: 0; width: 100%; height: 100%; }
@media (max-width: 560px) {
	.esp-kartta { aspect-ratio: 5 / 4; }
}

/* Karttaupotus-lohko (espek/map-embed, inc/lohkot.php) — kokonainen
   "kortti": kartta + osoite/nimikepaneeli + kaksi toimintonappia
   ("Hae reittiohjeet" ensisijaisena, "Avaa Google Mapsissa" toissi-
   jaisena) samassa kehyksessä. Korvasi aiemman version, jossa kartan
   ALLA oli vain yksi pieni tekstirivi + linkki — käyttäjäpalaute
   "make this map element a nicer, more complete element block". */
.esp-kartta-kortti {
	display: grid;
	grid-template-columns: minmax(0, 3fr) minmax(240px, 2fr);
	background: var(--paperi);
	border: 1px solid var(--viiva-2);
	border-radius: 12px;
	overflow: hidden;
	box-shadow: 0 1px 2px rgba(30,36,41,.05), 0 12px 34px rgba(30,36,41,.06);
}
.esp-kartta-kortti .esp-kartta {
	max-width: none;
	aspect-ratio: auto;
	min-height: 320px;
	border: 0;
	border-radius: 0;
}
.esp-kartta-kortti-tiedot {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 14px;
	padding: clamp(22px, 2.6vw, 32px);
}
.esp-kartta-kortti-nimike {
	display: flex;
	align-items: center;
	gap: 9px;
	margin: 0;
	font-size: 1.05rem;
	font-weight: 700;
	color: var(--muste);
}
.esp-kartta-kortti-nimike .esp-ico-sijainti { flex: none; color: var(--sini); }
.esp-kartta-kortti-osoite {
	margin: 0;
	font-size: .96rem;
	color: var(--muste-2);
	line-height: 1.5;
}
.esp-kartta-kortti-napit {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-top: 4px;
}
.esp-kartta-kortti-napit .esp-nappi { padding: 12px 20px; font-size: .9rem; }
.esp-kartta-kortti-napit .esp-ico-reitti { flex: none; }
@media (max-width: 700px) {
	.esp-kartta-kortti { grid-template-columns: 1fr; }
	.esp-kartta-kortti .esp-kartta { aspect-ratio: 5 / 4; min-height: 0; }
}

/* ============================================================
   11. UKK
   ============================================================ */

/* "Etkö löytänyt vastausta?" -puhelinsivupalkki poistettu — UKK on nyt
   pelkkä kysymyslista, ei enää kaksipalstainen ruudukko. Kevyt
   max-width pitää vastaustekstin rivipituuden siistinä nyt kun lista
   ei enää ole rajattu grid-sarakkeeseen. */
.esp-ukk { max-width: 760px; }

/* Otsikkorivin oma alaviiva poistettu tässä jaksossa — listan
   ensimmäinen kysymys piirtää joka tapauksessa oman yläviivansa
   (details:first-of-type, alla), joten kaksi viivaa aivan lähekkäin
   näytti tarpeettomalta tuplaukselta. */
#ukk .esp-otsikkorivi { border-bottom: none; padding-bottom: 0; }

.esp-juuri .esp-ukk details { border-bottom: 1px solid var(--viiva); }
.esp-juuri .esp-ukk details:first-of-type { border-top: 1px solid var(--viiva); }
.esp-juuri .esp-ukk summary {
	list-style: none;
	cursor: pointer;
	position: relative;
	padding: 21px 42px 21px 0;
	font-size: 1.02rem;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: -.012em;
	transition: color .15s ease;
}
.esp-juuri .esp-ukk summary::-webkit-details-marker { display: none; }
.esp-juuri .esp-ukk summary:hover { color: var(--sini); }
/* Plus/miinus-risti korvattu pyörivällä chevronilla — kahden erillisen
   palkin ristikkäinen skaalaus/haalistus (::before + ::after) näytti
   rikkinäiseltä/nykivältä siirtymän aikana. Yksi ainoa "v"-muotoinen
   kulma (border-right + border-bottom, kierretty 45°) kääntyy
   simppelisti 180° auki-kiinni-tilan välillä, ei erillistä katoamista/
   ilmaantumista tarvita. */
.esp-juuri .esp-ukk summary::before {
	content: "";
	position: absolute;
	right: 8px;
	top: 50%;
	width: 9px;
	height: 9px;
	border-right: 2px solid var(--aksentti);
	border-bottom: 2px solid var(--aksentti);
	border-radius: 0 0 2px 0;
	transform: translateY(-65%) rotate(45deg);
	transition: transform .25s ease;
}
.esp-juuri .esp-ukk details[open] summary::before {
	transform: translateY(-35%) rotate(225deg);
}
.esp-juuri .esp-ukk details > *:not(summary) {
	margin: 0 0 22px;
	max-width: 66ch;
	color: var(--muste-2);
	font-size: .97rem;
}

/* ============================================================
   12. YHTEYS
   ============================================================ */

/* Yhteystiedot vasemmalla, lomake oikealla (40 % / 60 %) — lomake sai
   selvästi enemmän tilaa, jotta kentät eivät jää turhan kapeiksi keskelle
   muuten leveää riviä. */
.esp-yhteys-grid {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
	gap: clamp(32px, 5vw, 72px);
	align-items: start;
}
@media (max-width: 900px) { .esp-yhteys-grid { grid-template-columns: 1fr; gap: 34px; } }

.esp-lomake {
	background: var(--paperi);
	border-radius: 6px;
	padding: clamp(18px, 2.2vw, 28px);
	box-shadow: 0 1px 2px rgba(30,36,41,.05), 0 12px 34px rgba(30,36,41,.06);
}
.esp-juuri .esp-lomake label {
	display: block;
	font-size: .85rem;
	font-weight: 500;
	margin-bottom: 5px;
	color: var(--muste);
}
/* CF7:n kenttärivi on tyyliin "Label*<br>[kenttä]" — koska label on jo
   display:block (pakottaa oman rivinsä), <br> sen jälkeen lisää TÄYSerase
   tyhjän rivin päälle, jolloin tekstin ja kentän väliin jäi paljon
   enemmän tyhjää kuin label-margin (7px) yksinään selittäisi. Piilotetaan
   ylimääräinen rivinvaihto — label/kenttäteksti hoitaa rivityksen jo itse. */
.esp-juuri .esp-lomake p br { display: none; }
/* Yksi ainoa paikka joka hallitsee kenttäryhmien välistä pystyväliä
   (aiemmin sekä kentän oma margin-bottom ETTÄ CF7:n automaattisesti
   ympäröimän <p>:n yleinen 1,1em-marginaali (.esp-juuri p) vaikuttivat
   samaan aikaan, mikä teki välistä tarpeettoman suuren — "vertical
   spacing is still quite large"). Kentän oma margin-bottom nollattu alla,
   ja tämä sääntö korvaa yleisen p-marginaalin pelkästään lomakkeen
   sisällä. */
.esp-juuri .esp-lomake p { margin: 0 0 11px; }
.esp-juuri .esp-lomake input[type="text"],
.esp-juuri .esp-lomake input[type="email"],
.esp-juuri .esp-lomake input[type="tel"],
.esp-juuri .esp-lomake input[type="file"],
.esp-juuri .esp-lomake select,
.esp-juuri .esp-lomake textarea {
	width: 100%;
	font-family: inherit;
	font-size: .94rem;
	color: var(--muste);
	padding: 9px 12px;
	border: 1px solid var(--viiva-2);
	border-radius: 4px;
	background: var(--paperi);
	margin-bottom: 0;
	transition: border-color .15s ease, box-shadow .15s ease;
}
/* Kompaktimpi viesti-kenttä (oli 116px — "footer form box is still quite
   long" -palautteen jälkeen tiivistetty koko lomake, tämä oli suurin
   yksittäinen korkeuden syöjä). Edelleen venytettävissä (resize:vertical),
   jos käyttäjä tarvitsee enemmän tilaa pidemmälle viestille. */
.esp-juuri .esp-lomake textarea { min-height: 76px; resize: vertical; }
.esp-juuri .esp-lomake input:focus,
.esp-juuri .esp-lomake textarea:focus,
.esp-juuri .esp-lomake select:focus {
	outline: none;
	border-color: var(--sini);
	box-shadow: 0 0 0 3px var(--sini-3);
}
.esp-juuri .esp-lomake input[type="submit"],
.esp-juuri .esp-lomake .wpcf7-submit {
	width: auto;
	background: var(--sini);
	color: #fff;
	border: 1px solid var(--sini);
	font-family: inherit;
	font-weight: 600;
	font-size: .94rem;
	padding: 13px 28px;
	border-radius: 4px;
	cursor: pointer;
	margin: 2px 0 0;
	transition: background .16s ease;
}
.esp-juuri .esp-lomake input[type="submit"]:hover { background: var(--sini-2); }

/* Kahden kentän rivi CF7-lomakkeessa — käytä näitä luokkia CF7:n omassa
   lomakepohjassa (Ulkoasu → Lomakkeet), esim.
   <div class="form-row"><span class="form-half">[text* nimi]</span>
   <span class="form-half">[tel puhelin]</span></div>. Label/kenttäleveys-
   säännöt ovat jo olemassa yllä (.esp-juuri .esp-lomake label/input), joten
   tässä lisätään vain itse rivitys. */
.esp-juuri .esp-lomake .form-row {
	display: flex;
	gap: 16px;
	margin-bottom: 11px;
}
.esp-juuri .esp-lomake .form-half {
	flex: 1;
	min-width: 0;
}
.esp-juuri .esp-lomake .form-row p,
.esp-juuri .esp-lomake .form-half p { margin: 0; }
@media (max-width: 768px) {
	.esp-juuri .esp-lomake .form-row {
		flex-direction: column;
		gap: 0;
		margin-bottom: 0;
	}
	.esp-juuri .esp-lomake .form-half { margin-bottom: 11px; }
}

/* Yhteys-osion tiedot — puhelin, sähköposti, käyntiosoite ja yritys yhtenä
   kompaktina 2×2-ruudukkona (aiemmin puhelin/sähköposti olivat isokokoisina
   .esp-yht-lohkoina erillään käyntiosoite/yritys-rivistä — yhdistetty
   yhdeksi tiiviiksi ruudukoksi, jotta kaikki neljä tietoa mahtuu samaan
   kahden sarakkeen tilaan). */
.esp-tiedot {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 22px clamp(20px, 3vw, 36px);
}
.esp-tieto p { margin: 0; }
.esp-tieto .esp-tieto-nimi {
	font-size: .8rem;
	color: var(--muste-3);
	margin-bottom: 4px;
	letter-spacing: .02em;
}
.esp-tieto .esp-tieto-arvo { font-size: .96rem; color: var(--muste); line-height: 1.5; }
.esp-tieto a { color: var(--muste); text-decoration: none; border-bottom: 1px solid var(--viiva-2); }
.esp-tieto a:hover { color: var(--sini); border-color: var(--sini); }
@media (max-width: 520px) { .esp-tiedot { grid-template-columns: 1fr; } }

/* ============================================================
   13. ALATUNNISTE (sivun footer, korvaa Astran footerin)
   ============================================================ */

.esp-alatunniste {
	background: var(--tausta);
	border-top: 1px solid var(--viiva);
	padding-block: clamp(26px, 3.6vw, 38px);
}
.esp-alatunniste-rivi {
	width: min(100%, var(--kehys));
	margin-inline: auto;
	padding-inline: var(--kouru);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 12px 24px;
	font-size: .86rem;
	color: var(--muste-3);
}
.esp-alatunniste a { color: var(--muste-2); text-decoration: none; }
.esp-alatunniste a:hover { color: var(--sini); }
.esp-alatunniste-ikoni { flex: none; width: 20px; height: 20px; display: block; }
.esp-alatunniste-teksti { margin: 0; }

/* ============================================================
   14. PINTAKÄSITTELYPALVELUT-SIVU
       Käytössä page-pintakasittelypalvelut.php-mallissa: kuva+teksti
       -esittelyrivit (Hiekkapuhallus/Märkämaalaus, sama hero-grid-idea
       kuin osiossa 4 mutta puolittain jaettuna ja vuorotellen
       käännettynä epäsymmetrian vuoksi), tarkistuslistan 2-sarakkeinen
       muunnos neljälle kohteelle (kolme saraketta olisi jättänyt
       viimeisen rivin kolmasosaan tyhjää) ja Standardit-osion kortti.
   ============================================================ */

.esp-ominaisuudet { display: flex; flex-direction: column; gap: clamp(48px, 6vw, 84px); }

.esp-ominaisuus-rivi {
	display: flex;
	align-items: stretch;
	gap: clamp(32px, 5vw, 64px);
}
.esp-ominaisuus-rivi--kaanteinen { flex-direction: row-reverse; }
.esp-ominaisuus-teksti { flex: 1 1 0%; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.esp-ominaisuus-teksti h2 { max-width: none; }
.esp-ominaisuus-teksti .esp-linkki { margin-top: 4px; }
.esp-ominaisuus-kuva { flex: 0 1 420px; max-width: 420px; position: relative; min-height: 260px; border-radius: 8px; overflow: hidden; }
.esp-ominaisuus-kuva img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	position: absolute;
	inset: 0;
}
@media (max-width: 860px) {
	.esp-ominaisuus-rivi,
	.esp-ominaisuus-rivi--kaanteinen { flex-direction: column; gap: 22px; }
	.esp-ominaisuus-kuva { flex: none; max-width: none; width: 100%; aspect-ratio: 16 / 10; min-height: 0; }
}

/* Neljä kohdetta istuu paremmin 2×2-ruudukkoon kuin oletuksen
   3-sarakkeiseen (ks. osio 10), joka jättäisi viimeiselle riville
   yhden kohdan ja kaksi tyhjää saraketta. */
.esp-tarkistuslista--kaksi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 480px) {
	.esp-tarkistuslista--kaksi { grid-template-columns: 1fr; }
}

.esp-standardit-grid {
	display: grid;
	grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
	gap: clamp(28px, 4vw, 56px);
	align-items: start;
}
.esp-standardit-teksti p:last-child { margin-bottom: 0; }
/* Kortti sai aiemmin pelkän ohuen reunuksen + aksenttiviivan yläkulmaan —
   käyttäjäpalaute "make it more visually appealing". Vaihdettu pehmeään
   sinertävään täyttöön (sama --sini-3 kuin muualla sivustolla, ei uusi
   väri). Maalipisara-ikoni ei ole enää pieni badge tekstin vieressä, vaan
   suuri, himmeä taustakuvio kortin kulmassa — sama idea kuin sivun muissa
   kohdissa käytetty ristikkokuvio-vesileima (.esp-kuviotausta), pienessä
   koossa yhden kortin sisällä. */
.esp-standardit-kortti {
	position: relative;
	background: var(--sini-3);
	border-radius: 10px;
	padding: clamp(24px, 2.8vw, 32px);
	overflow: hidden;
}
.esp-standardit-kortti-kuvio {
	position: absolute;
	right: 18px;
	bottom: 18px;
	width: 84px;
	height: 84px;
	color: var(--sini);
	opacity: .16;
	pointer-events: none;
	z-index: 0;
}
.esp-standardit-kortti-kuvio .esp-ico-maali { display: block; width: 100%; height: 100%; stroke-width: .8; }
/* Sama vesileimakortti kelpaa myös faktarivi-ikonisarjan (timantti/
   maapallo/tähti) neliömäisille 24×24-viewBox-ikoneille, esim.
   hiekkapuhallus-sivun Laatutyötä-osion väittämäkortissa — sama
   sääntö kuin maalipisaralle, koska molemmat ovat neliönmuotoisia
   viivapiirroksia. */
.esp-standardit-kortti-kuvio .esp-ico-faktarivi { display: block; width: 100%; height: 100%; stroke-width: .8; }
.esp-standardit-kortti p {
	position: relative;
	z-index: 1;
	margin: 0;
	/* 34ch sopi hyvin pintakäsittelypalvelut-sivun lyhyemmälle maali-
	   tekstille, mutta hiekkapuhallus-sivun pidempi väittämäteksti (4
	   riviä) täytti kapealla mobiilileveydellä koko kortin, jolloin
	   teksti alkoi mennä vesileimaikonin päälle. min() varaa aina
	   vähintään 90px tilaa ikonille kortin oikeaan reunaan riippumatta
	   kortin todellisesta leveydestä. */
	max-width: min(34ch, 100% - 90px);
	color: var(--muste);
	font-size: 1.02rem;
	line-height: 1.5;
}
@media (max-width: 860px) {
	.esp-standardit-grid { grid-template-columns: 1fr; }
}

/* Tumma hero-muunnos (pintakäsittelypalvelut-sivu): `.esp-tumma`-luokan
   omat säännöt hoitavat jo h2:n, .esp-ingressin ja .esp-tekstin värit
   heron sisällä, mutta h1:lle ei ollut aiemmin tumma-muunnosta (heroa ei
   ole aiemmin käytetty tummalla pohjalla) ja napit tarvitsevat oman
   negatiivi-värityksensä samaan tapaan kuin `.esp-cta`/`.esp-tumma
   .esp-jakso-cta`:ssa jo tehtiin — muuten sininen täyttönappi ja sen
   tumma reunus hukkuisivat tummaan taustaan. */
.esp-hero.esp-tumma { background: var(--tumma); }
.esp-hero.esp-tumma h1 { color: #fff; }
.esp-hero.esp-tumma .esp-napit .esp-nappi {
	background: #fff;
	border-color: #fff;
	color: var(--sini);
}
.esp-hero.esp-tumma .esp-napit .esp-nappi:hover,
.esp-hero.esp-tumma .esp-napit .esp-nappi:focus-visible {
	background: var(--tumma-teksti);
	border-color: var(--tumma-teksti);
	color: var(--sini);
}
.esp-hero.esp-tumma .esp-napit .esp-nappi--toissijainen {
	background: rgba(255,255,255,.1);
	border-color: rgba(255,255,255,.55);
	color: #fff;
}
.esp-hero.esp-tumma .esp-napit .esp-nappi--toissijainen:hover,
.esp-hero.esp-tumma .esp-napit .esp-nappi--toissijainen:focus-visible {
	background: rgba(255,255,255,.18);
	border-color: #fff;
	color: #fff;
}
.esp-hero.esp-tumma .esp-napit .esp-nappi--toissijainen .esp-ico-puh { color: #fff; }

/* Pintakäsittelypalvelut-sivun faktarivi (.esp-faktat) siirrettiin pois
   tummalta herolta omaksi vaaleaksi osiokseen — käyttäjän täsmennys "This
   doesn't need to be in dark color, keep it like it is in the frontpage".
   .esp-faktat kantaa siis oletusvärinsä (kuten etusivun herossa), ei tarvita
   erillistä tumma-muunnosta. Tässä vain siistitään osion oma pystyväli: kun
   .esp-faktat on ainoa sisältö omassa .esp-jakso-osiossaan, sen sisäinen
   yläreunus/-marginaali (suunniteltu jatkoksi heron muulle sisällölle) olisi
   päällekkäinen .esp-jakson oman padding-blockin kanssa. */
.esp-faktat-jakso .esp-faktat { border-top: 0; margin-top: 0; padding-top: 0; }
/* Ohut jakoviiva faktarivin ja seuraavan (Ominaisuusrivit-)osion välissä,
   koska molemmat ovat samaa vaaleaa taustaväriä eikä taustavärin vaihtoa
   ole erottamassa niitä toisistaan. Rajattu sisältökehyksen levyiseksi
   (sama .esp-kehys jonka sisällä kolme faktalaatikkoa on), EI täysleveä
   reunasta reunaan — käyttäjän täsmennys viittasi otsikkorivin
   (`.esp-otsikkorivi`) omaan, sisältöleveyteen rajattuun alareunukseen. */
.esp-faktat-jakso .esp-kehys {
	border-bottom: 1px solid var(--viiva);
	padding-bottom: clamp(28px, 3.2vw, 44px);
}

/* Päätös-CTA:n leipäteksti oli oletus-46ch-leveydellä liian kapea (neljä
   riviä) — käyttäjäpalaute "make it wider so it fits in two rows". Oma
   muunnosluokka `.esp-cta`:n perussäännön päälle, ei muutosta jaettuun
   `.esp-cta-sisalto`-luokkaan itseensä (käytössä myös etusivun Väli-
   CTA:ssa lyhyemmällä tekstillä, jolle 46ch toimii jo hyvin). */
.esp-cta-sisalto--leveampi { max-width: 90ch; }

/* ============================================================
   15. HIEKKAPUHALLUS- JA MÄRKÄMAALAUS-SIVUT
   Molemmat sivut käyttävät samaa komponenttikirjastoa kuin
   pintakäsittelypalvelut-sivu (hero, faktat-jakso, ominaisuusrivi,
   faktarivi, standardit-grid, cta, yhteys) — vain tämä yksi pieni
   lisäluokka on niiden omaa: lyhyt johdantolause juuri ennen
   tarkistuslistaa (esim. "Hiekkapuhallamme muun muassa:"), joka
   tarvitsee hieman tavallista enemmän tilaa allensa erottuakseen
   listasta ilman että se on osa otsikkorivin omaa ingressiä.
   ============================================================ */
.esp-tarkistuslista-esittely { margin: 0 0 20px; }

/* ============================================================
   16. ARTIKKELIT-SIVU
   Uusin artikkeli esitellään "hero"-osiona, jonka koko tausta on
   artikkelin oma kuva (tumma liukuväri PHP:ssä inline-tyylinä, sama
   periaate kuin CTA-osion background-image, ks. osio 4/CTA yllä) —
   teksti valkoisena kuvan päällä. Loput 3×3-ruudukossa (ks. osio 5,
   .esp-artikkelit/.esp-artikkeli — samat säännöt kuin .esp-palvelut/
   .esp-palvelu), julkaisupäivä pillerinä kuvan vasemmassa yläkulmassa.
   Sivutus (.esp-sivutus) on tämän sivun oma, paginate_links()-
   tulosteelle tehty tyyli.
   ============================================================ */
/* Otsikko-osio yllä tuo jo oman alareunan tyhjänsä + rajaviivan, joten
   tämän jakson oma yläreunan täyte nollataan — muuten väli otsikon ja
   hero-kuvan välissä oli tuplasti liian iso (kahden jakson täytteet
   summautuivat). Alareunan täyte pysyy ennallaan, se erottaa hero-
   laatikon alla olevasta ruudukosta. */
.esp-artikkelit-otsikko-jakso { padding-bottom: 0; }
.esp-artikkeli-hero-jakso { padding-top: 28px; }

/* Itse hero on nyt pyöristetty, sivun sisältöleveyteen rajattu laatikko
   (EI enää reunasta reunaan -tausta) 16:9-suhteessa — käyttäjäpalaute.
   Teksti on pohjassa vasemmalla, sama tumma liukuväri-tekniikka kuin
   CTA-osiossa mutta pystysuunnassa (tumma alhaalla, haalenee ylöspäin),
   koska teksti on nyt laatikon alareunassa eikä koko korkeudella. */
.esp-artikkeli-hero {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: 10px;
	overflow: hidden;
	display: flex;
	align-items: flex-end;
}
/* Taustakuva on omalla ::before-kerroksellaan (ei enää suoraan
   .esp-artikkeli-hero:n background-image:nä), jotta hover/focus-zoomaus
   (transform: scale()) voi kohdistua VAIN kuvaan, ei sisältöön (otsikko,
   teksti, pvm-pilleri) — käyttäjäpalaute: otsikon aiempi vaalean-
   sininen hover-väri ("light blue") ei toiminut, tilalle kevyt kuvan
   zoomaus hover-tilan merkiksi, teksti pidetään ennallaan. PHP asettaa
   vain --hero-kuva-muuttujan (pelkkä valokuva-url), liukuväri on tässä
   kokonaan CSS:n puolella. :not(--ei-kuvaa) varmistaa ettei liukuväri
   piirry kuvattomalle tekstiversiolle, jossa --hero-kuva puuttuu. */
.esp-artikkeli-hero:not(.esp-artikkeli-hero--ei-kuvaa)::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 0;
	background-image: linear-gradient(to top, rgba(27,34,38,.95) 0%, rgba(27,34,38,.75) 32%, rgba(27,34,38,.32) 58%, rgba(27,34,38,0) 82%), var(--hero-kuva);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	transform: scale(1);
	transition: transform .5s ease;
}
.esp-artikkeli-hero:hover:not(.esp-artikkeli-hero--ei-kuvaa)::before,
.esp-artikkeli-hero:focus-within:not(.esp-artikkeli-hero--ei-kuvaa)::before {
	transform: scale(1.06);
}
@media (prefers-reduced-motion: reduce) {
	.esp-artikkeli-hero::before { transition: none; }
}
.esp-artikkeli-hero-sisalto {
	position: relative;
	z-index: 1;
	max-width: 56ch;
	padding: clamp(22px, 3.6vw, 44px);
}
.esp-artikkeli-hero-pvm {
	display: inline-flex;
	align-items: center;
	padding: 6px 14px;
	border-radius: 999px;
	background: rgba(255,255,255,.14);
	border: 1px solid rgba(255,255,255,.3);
	color: #fff;
	font-size: .78rem;
	font-weight: 500;
	letter-spacing: .04em;
	text-transform: uppercase;
	margin-bottom: 16px;
}
.esp-artikkeli-hero-sisalto h2 { color: #fff; max-width: none; }
.esp-juuri .esp-artikkeli-hero-sisalto h2 a { color: #fff; text-decoration: none; }
.esp-artikkeli-hero-sisalto .esp-teksti { color: rgba(255,255,255,.9); max-width: 52ch; }
.esp-artikkeli-hero-sisalto .esp-linkki a { color: #fff; border-bottom-color: rgba(255,255,255,.5); }
.esp-artikkeli-hero-sisalto .esp-linkki a:hover { border-bottom-color: #fff; }
.esp-artikkeli-hero-sisalto .esp-linkki a::after { border-color: #fff; }
/* Kuvaton artikkeli (harvinainen poikkeus): pudotus vaaleaan
   tekstiversioon, koska tumma liukuväri ei ole tarpeen ilman kuvaa. */
.esp-artikkeli-hero--ei-kuvaa { background: var(--paperi); border: 1px solid var(--viiva); align-items: center; }
.esp-artikkeli-hero--ei-kuvaa .esp-artikkeli-hero-sisalto { max-width: 60ch; padding: clamp(28px, 4vw, 48px); }
.esp-artikkeli-hero--ei-kuvaa .esp-artikkeli-hero-pvm {
	background: none;
	border: none;
	padding: 0;
	color: var(--muste-3);
}
.esp-artikkeli-hero--ei-kuvaa .esp-artikkeli-hero-sisalto h2,
.esp-juuri .esp-artikkeli-hero--ei-kuvaa .esp-artikkeli-hero-sisalto h2 a { color: var(--muste); }
.esp-artikkeli-hero--ei-kuvaa .esp-artikkeli-hero-sisalto .esp-teksti { color: var(--muste-2); }
.esp-artikkeli-hero--ei-kuvaa .esp-artikkeli-hero-sisalto .esp-linkki a { color: var(--sini); border-bottom-color: var(--sini-3); }
.esp-artikkeli-hero--ei-kuvaa .esp-artikkeli-hero-sisalto .esp-linkki a::after { border-color: currentColor; }
@media (max-width: 640px) {
	.esp-artikkeli-hero { aspect-ratio: auto; min-height: 480px; }
	.esp-artikkeli-hero--ei-kuvaa { min-height: 0; }
	/* Käyttäjäpalaute 2026-09-08: "article hero is difficult to read in
	   mobile" — 16:9-suhteelle mitoitettu liukuväri (osio 16 yllä) ei
	   riitä mobiilin korkeammalle min-height:480px-laatikolle, jossa
	   tekstilohko vie suhteessa pienemmän osan kuvan korkeudesta kuin
	   työpöydällä. Korjattu kahdella tavalla: tummempi/pidemmälle
	   ulottuva liukuväri VAIN mobiilissa (ei muuteta työpöydän ilmettä),
	   ja text-shadow otsikkoon/ingressiin varmuuden vuoksi vaaleitakin
	   kuvia vasten. */
	.esp-artikkeli-hero:not(.esp-artikkeli-hero--ei-kuvaa)::before {
		background-image: linear-gradient(to top, rgba(20,25,28,.97) 0%, rgba(20,25,28,.92) 26%, rgba(20,25,28,.62) 50%, rgba(20,25,28,.2) 72%, rgba(20,25,28,0) 92%), var(--hero-kuva);
	}
	.esp-artikkeli-hero-sisalto h2,
	.esp-artikkeli-hero-sisalto .esp-teksti {
		text-shadow: 0 1px 4px rgba(0,0,0,.45);
	}
}

/* ============================================================
   17. YHTEYSTIEDOT-SIVU
   Otsikko-osion johdantoteksti + pikanapit rajataan kapeammaksi
   palstaksi (sama periaate kuin CTA-osion .esp-cta-sisalto, mutta
   vasemmalle tasattuna, ei keskitettynä — tämä ei ole CTA-osio).
   Itse #yhteys-osio on sama jaettu komponentti kuin muilla sivuilla.
   ============================================================ */
.esp-yhteystiedot-intro { max-width: 60ch; }
.esp-yhteystiedot-intro .esp-teksti { margin-bottom: 22px; }

/* Ruudukon julkaisupäivä-pilleri kuvan päällä (käyttäjäpalaute: "date
   in a pill element on top of the image, top left corner"), korvaa
   aiemman tekstirivin otsikon yllä. Kuvaton kortti käyttää yhä
   tavallista etikettiä (ks. osio 5 .esp-artikkeli-sisalto > .esp-etiketti). */
.esp-artikkeli-kuva { position: relative; }
.esp-artikkeli-pvm {
	position: absolute;
	top: 14px;
	left: 14px;
	z-index: 1;
	display: inline-flex;
	align-items: center;
	padding: 5px 12px;
	border-radius: 999px;
	background: rgba(255,255,255,.94);
	color: var(--muste-2);
	font-size: .76rem;
	font-weight: 600;
	letter-spacing: .01em;
	box-shadow: 0 2px 6px rgba(30,36,41,.16);
}

.esp-sivutus {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 8px;
	margin-top: clamp(36px, 4.5vw, 56px);
}
.esp-sivutus .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 42px;
	height: 42px;
	padding: 0 14px;
	border-radius: 6px;
	border: 1px solid var(--viiva);
	background: var(--paperi);
	color: var(--muste-2);
	font-size: .93rem;
	font-weight: 500;
	text-decoration: none;
	transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.esp-juuri .esp-sivutus a.page-numbers:hover { border-color: var(--sini-3); color: var(--sini); }
.esp-sivutus .page-numbers.current { background: var(--sini); border-color: var(--sini); color: #fff; }
.esp-sivutus .page-numbers.dots { border-color: transparent; background: none; }

/* ============================================================
   18. ARTIKKELIN SISÄLTÖSIVU (single.php)
      Rakenne: otsikko-hero (kuva + H1) → metarivi → kaksi saraketta
      (pääsisältö: tiivistelmä, numeroitu sisällysluettelo, itse
      teksti, UKK, kirjoittajalaatikko | sivupalkki: sticky CTA-
      kortti). Tiivistelmä/sisällysluettelo/UKK on poimittu itse
      sisällöstä PHP:ssä (espek_artikkeli_jasenna(), functions.php),
      ei erillisistä kentistä — CSS ei siis tarvitse tietää mistä
      data tulee, vain miltä sen pitää näyttää.
   ============================================================ */

.esp-artikkeli-yksittainen { padding-bottom: clamp(48px, 5vw, 80px); }

/* -- Otsikko-hero: sama --hero-kuva-muuttuja + liukuväritekniikka
   kuin artikkelilistauksen hero (ks. osio 16), mutta ilman hover-
   zoomausta (staattinen H1-otsikko, ei linkki) ja ilman kiinteää
   16:9-suhdetta, koska H1-pituus vaihtelee artikkeleittain enemmän
   kuin listauksen H2-otsikot.
   Käyttäjäpalaute: hero ei saa jättää tyhjää tilaa ylätunnisteen
   alle — kuvan pitää alkaa suoraan headerin alareunasta. Aiempi
   `margin-top` poistettu kokonaan (EI vain pienennetty), ja sama
   pystytila on siirretty suoraan kuvan omaan korkeuteen (min-height-
   clampin molemmat päät nostettu n. 40px) — "venytetty kuvasuhde",
   ei poistettu tila. Myös pyöristys (`border-radius`) poistettu
   käyttäjän pyynnöstä, kuva on nyt terävä suorakulmio reunasta
   reunaan sekä vaaka- että pystysuunnassa. */
.esp-artikkeli-otsikko-hero {
	position: relative;
	min-height: clamp(320px, 37vw, 460px);
	display: flex;
	align-items: flex-end;
	margin-top: 0;
}
.esp-artikkeli-otsikko-hero .esp-kehys {
	width: 100%;
	position: relative;
	z-index: 1;
}
.esp-artikkeli-otsikko-hero::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	background-image: linear-gradient(to top, rgba(27,34,38,.94) 0%, rgba(27,34,38,.72) 38%, rgba(27,34,38,.28) 68%, rgba(27,34,38,.05) 100%), var(--hero-kuva);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}
/* Kehys on jo leveysrajattu (ks. .esp-kehys), mutta itse tumma/kuva-
   laatikko piirretään koko .esp-artikkeli-otsikko-hero:n levylle
   (reunasta reunaan sisäkkäisessä kehyksessä) — siksi overflow on
   ::before:llä, joka on absoluuttisesti koko yläelementin kokoinen,
   EI .esp-kehys:llä (joka on vain sisällön leveysrajoitin). */
.esp-artikkeli-otsikko-hero::before { left: 0; right: 0; }
.esp-artikkeli-otsikko-sisalto {
	position: relative;
	max-width: 70ch;
	padding: clamp(28px, 4.4vw, 56px) clamp(28px, 4.4vw, 56px);
}
.esp-artikkeli-otsikko-sisalto .esp-artikkeli-hero-pvm { margin-bottom: 18px; }
/* Käyttäjäpalaute 2026-09-08: "singlepost hero text is also too wide" —
   h1:llä ei ole sivustolla mitään oletus-max-width:ia (vain h2/h3:lla,
   ks. osio 2), joten otsikko venyi koko .esp-artikkeli-otsikko-sisalto
   -kehyksen levyiseksi (70ch, mitoitettu ARVL muulle sisällölle, ei
   itse otsikolle). 26ch antaa otsikolle saman visuaalisen leveyden kuin
   sivuston pääherolla (osio 4, .esp-hero-teksti-palsta) suhteutettuna
   tämän ison h1-koon (--t-iso) fonttikokoon. */
.esp-artikkeli-otsikko-hero h1 { color: #fff; max-width: 26ch; }
/* Kuvaton artikkeli (harvinainen poikkeus): kevyt vaalea laatikko
   ilman liukuväriä, sama periaate kuin listauksen hero-fallback. */
.esp-artikkeli-otsikko-hero--ei-kuvaa::before {
	background: var(--paperi);
	border: 1px solid var(--viiva);
}
.esp-artikkeli-otsikko-hero--ei-kuvaa { align-items: center; min-height: 0; }
.esp-artikkeli-otsikko-hero--ei-kuvaa h1 { color: var(--muste); }
.esp-artikkeli-otsikko-hero--ei-kuvaa .esp-artikkeli-hero-pvm {
	background: none; border: none; padding: 0; color: var(--muste-3);
}

/* -- Metarivi: kirjoittaja · julkaisupäivä · (muokattu) · lukuaika -- */
.esp-artikkeli-runko { padding-top: clamp(20px, 2.6vw, 32px); }
.esp-artikkeli-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px 14px;
	margin-bottom: clamp(28px, 3.2vw, 40px);
	padding-bottom: clamp(20px, 2.4vw, 28px);
	border-bottom: 1px solid var(--viiva);
	font-size: .89rem;
	color: var(--muste-3);
}
.esp-artikkeli-meta-kohta { position: relative; padding-left: 16px; }
.esp-artikkeli-meta-kohta:first-child { padding-left: 0; }
.esp-artikkeli-meta-kohta:not(:first-child)::before {
	content: '';
	position: absolute; left: 4px; top: 50%;
	width: 3px; height: 3px; border-radius: 50%;
	background: var(--viiva-2);
	transform: translateY(-50%);
}
.esp-juuri .esp-artikkeli-meta a { color: var(--muste-2); text-decoration: none; font-weight: 600; }
.esp-juuri .esp-artikkeli-meta a:hover { color: var(--sini); }

/* -- Kaksi saraketta: pääsisältö + sticky sivupalkki -- */
/* align-items on TARKOITUKSELLA oletus (stretch), EI start: sivupalkin
   sarake tarvitsee koko pääsisältöpalstan korkuisen tilan, jotta sen
   sisällä oleva position:sticky-kortti pysyy mukana koko lukemisen ajan
   — start olisi rajannut sivupalkin korkeuden vain kortin omaan
   (lyhyeen) korkeuteen, jolloin "seuraaminen" olisi loppunut heti
   kortin oman korkeuden jälkeen. */
.esp-artikkeli-ruudukko {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 300px;
	gap: clamp(32px, 4vw, 64px);
}
.esp-artikkeli-paasisalto { min-width: 0; }
@media (max-width: 1080px) {
	.esp-artikkeli-ruudukko { grid-template-columns: 1fr; }
	.esp-artikkeli-sivupalkki { order: 2; }
}

/* -- Tiivistelmälaatikko "Lyhyesti artikkelista": ensimmäinen
   varsinainen sisältöelementti, kevyt tausta + aksenttiviiva
   erottaa sen muusta leipätekstistä ilman että se on kortti/
   laatikko täydellä reunuksella (sama hillitty ote kuin muuallakin
   sivustolla — ei uutta laatikkomuotoilua joka ei istu järjestelmään). -- */
.esp-artikkeli-tiivistelma {
	background: var(--tausta);
	border-left: 3px solid var(--aksentti);
	border-radius: 0 8px 8px 0;
	padding: clamp(18px, 2.4vw, 26px) clamp(20px, 2.8vw, 30px);
	margin-bottom: clamp(28px, 3.2vw, 40px);
}
.esp-artikkeli-tiivistelma-otsikko {
	margin: 0 0 10px;
	font-size: .78rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--muste-3);
}
.esp-artikkeli-tiivistelma p { color: var(--muste-2); font-size: .97rem; }
.esp-artikkeli-tiivistelma p:last-child { margin-bottom: 0; }

/* -- Sisällysluettelo: numeroitu (ei enää pelkkä luettelomerkki-
   lista) — CSS-laskuri, koska <ol>:n oma numero on liian pieni/
   irrallinen tähän visuaaliseen kieleen (sama "numeroitu pyöreä
   merkki" -idiomi kuin .esp-tarkistuslista/.esp-vaihe muualla
   sivustolla, ei uusi keksintö). -- */
.esp-sisallysluettelo {
	border: 1px solid var(--viiva);
	border-radius: 10px;
	padding: clamp(18px, 2.4vw, 26px) clamp(20px, 2.8vw, 30px);
	margin-bottom: clamp(28px, 3.2vw, 40px);
	background: var(--paperi);
}
.esp-sisallysluettelo-otsikko {
	margin: 0 0 12px;
	font-size: .78rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--muste-3);
}
.esp-sisallysluettelo-lista {
	list-style: none;
	counter-reset: esp-toc;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.esp-sisallysluettelo-lista li { counter-increment: esp-toc; }
.esp-juuri .esp-sisallysluettelo-lista a {
	display: flex;
	align-items: baseline;
	gap: 10px;
	padding: 7px 4px;
	border-radius: 6px;
	color: var(--muste-2);
	text-decoration: none;
	font-size: .93rem;
	line-height: 1.4;
	transition: color .15s ease, background .15s ease;
}
.esp-juuri .esp-sisallysluettelo-lista a:hover { color: var(--sini); background: var(--sini-3); }
.esp-sisallysluettelo-lista a::before {
	content: counter(esp-toc);
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 20px; height: 20px;
	border-radius: 50%;
	background: var(--ristikko-tausta);
	color: var(--muste-3);
	font-size: .72rem;
	font-weight: 700;
}
.esp-juuri .esp-sisallysluettelo-lista a:hover::before { background: var(--sini); color: #fff; }

/* -- Itse artikkelin teksti: lohkoeditorin oma HTML (wp-block-*
   -luokat), skaalataan sivuston tekstijärjestelmään. H2:n yleinen
   22ch-max-width (ks. osio 2, tarkoitettu lyhyille jaksootsikoille)
   ylikirjoitetaan tässä — artikkelin H2-otsikot ovat kokonaisia
   lauseita, eivät 1-3 sanan jaksonimiä. scroll-margin-top pitää
   ankkurihypyt (sisällysluettelo, myöhemmin selaimen oma #-linkki)
   kiinteän ylätunnisteen alta näkyviin, ei sen taakse piiloon. -- */
/* Ei enää kiinteää 72ch-kattoa: pääsisältöpalsta (.esp-artikkeli-
   paasisalto) on jo itsessään kohtuullisen kapea (sivupalkin viemän
   tilan vuoksi, ks. .esp-artikkeli-ruudukko), ja 72ch jätti tekstin
   roikkumaan vasempaan laitaan kapeampana kuin yläpuolen tiivistelmä-/
   sisällysluettelolaatikot — näytti siltä ettei teksti ole
   keskitetty/sivun levyinen. Teksti täyttää nyt saman leveyden kuin
   muutkin palstan elementit. */
.esp-artikkeli-teksti h2 {
	/* Sivunlaajuinen --t-h2 (jopa 2.5rem) on mitoitettu isoille jakso-
	   otsikoille (yksi per etusivun osio) — artikkelin sisällä, jossa
	   H2:ita on useita ja H3 seuraa heti perässä, sama koko näytti
	   suhteettoman isolta H3:een ja leipätekstiin nähden. Oma, artikkelin
	   sisällölle mitoitettu, maltillisempi asteikko. */
	max-width: none;
	font-size: clamp(1.4rem, 1.18rem + 1vw, 1.8rem);
	scroll-margin-top: calc(var(--otsikko-korkeus) + 20px);
	padding-top: clamp(28px, 3vw, 40px);
	margin-top: clamp(4px, .6vw, 10px);
}
.esp-artikkeli-teksti > h2:first-child { padding-top: 0; margin-top: 0; }
.esp-artikkeli-teksti h3 { margin-top: clamp(18px, 2vw, 26px); }
.esp-artikkeli-teksti p,
.esp-artikkeli-teksti li { color: var(--muste-2); }
.esp-artikkeli-teksti ul,
.esp-artikkeli-teksti ol { margin: 0 0 1.1em; padding-left: 1.3em; }
.esp-artikkeli-teksti li { margin-bottom: .4em; }
.esp-artikkeli-teksti li:last-child { margin-bottom: 0; }
.esp-juuri .esp-artikkeli-teksti a { color: var(--sini); text-decoration: underline; text-decoration-color: var(--sini-3); text-underline-offset: 2px; }
.esp-juuri .esp-artikkeli-teksti a:hover { text-decoration-color: var(--sini); }

/* Taulukot: lohkoeditori kääri taulukon <figure class="wp-block-table">
   -elementtiin ja voi lisätä has-fixed-layout-luokan — molemmat
   tuetaan, mutta osa sisällöstä (esim. suoraan liitetty HTML-taulukko)
   ei tuota tätä kääreitä lainkaan, joten reunus/pyöristys/vieritys on
   nyt itse <table>-elementissä eikä pelkässä .wp-block-table-kääreessä
   — toimii siis kummassakin tapauksessa. */
/* Taulukolla oli aiemmin vain rivien väliset viivat (border-bottom),
   ei mitään reunaa koko taulukon ympärillä — se sai taulukon näyttämään
   siltä että se "loppuu kesken" tyhjään tilaan, ei omaan, suljettuun
   elementtiinsä. Nyt sama kevyt reunus+pyöristys-kehys kuin muillakin
   sivuston laatikoilla (.esp-sisallysluettelo, .esp-kirjoittaja-laatikko
   ym.). HUOM (löydetty 2026-09-08 käyttäjäpalautteesta "edges/corners
   don't go well"): `border-radius` EI leikkaa kulmia oikein yhdessä
   `border-collapse: collapse`:n kanssa useimmissa selaimissa — solujen
   taustat/reunat piirtyvät rajauslaatikon ULKOPUOLELLE eikä overflow:
   hidden silloin ehdi leikata niitä. Korjattu vaihtamalla
   `border-collapse: separate; border-spacing: 0;`, jolloin
   `overflow: hidden` + `border-radius` toimivat luotettavasti suoraan
   <table>-elementissä (soluilla ei ole vasempaa/ylintä reunaa, joten
   erottelu ei tuota mitään kaksinkertaisia viivoja). */
.esp-artikkeli-teksti .wp-block-table {
	margin: 0;
	overflow-x: auto;
	overflow-y: hidden;
}
.esp-artikkeli-teksti table {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0;
	margin: 0 0 1.6em;
	font-size: .92rem;
	line-height: 1.45;
	border: 1px solid var(--viiva);
	border-radius: 0;
	overflow: hidden;
}
.esp-artikkeli-teksti th,
.esp-artikkeli-teksti td {
	padding: 12px 16px;
	text-align: left;
	border-bottom: 1px solid var(--viiva);
	border-right: 1px solid var(--viiva);
	vertical-align: top;
}
.esp-artikkeli-teksti th:last-child,
.esp-artikkeli-teksti td:last-child { border-right: none; }
.esp-artikkeli-teksti thead th {
	background: var(--tausta);
	color: var(--muste);
	font-weight: 700;
	font-size: .82rem;
	letter-spacing: .02em;
	text-transform: uppercase;
	border-bottom: 1px solid var(--viiva-2);
}
.esp-artikkeli-teksti tbody tr:hover { background: var(--tausta); }
.esp-artikkeli-teksti tbody tr:last-child td { border-bottom: none; }

@media (max-width: 700px) {
	.esp-artikkeli-teksti table {
		width: auto;
		min-width: 640px;
	}
}

/* -- UKK: sama .esp-ukk-harmonikka kuin etusivulla (osio 11). Otsikko
   on tavallinen h2 (single.php), EI omaa pientä etikettityyliä — jos
   artikkelin sisällössä oli jo oma "Usein kysyttyä..." -otsikko Rank
   Math -lohkon edellä, se poistetaan jäsennyksessä (functions.php),
   ettei sama otsikko toistuisi kahteen kertaan peräkkäin. */
.esp-artikkeli-ukk {
	margin-top: clamp(36px, 4vw, 56px);
	scroll-margin-top: calc(var(--otsikko-korkeus) + 20px);
}
.esp-artikkeli-ukk h2 { margin-bottom: .5em; }

/* -- Kirjoittajalaatikko -- */
.esp-kirjoittaja-laatikko {
	display: flex;
	gap: 18px;
	align-items: flex-start;
	margin-top: clamp(40px, 4.4vw, 60px);
	padding: clamp(20px, 2.6vw, 28px);
	border: 1px solid var(--viiva);
	border-radius: 10px;
	background: var(--paperi);
	scroll-margin-top: calc(var(--otsikko-korkeus) + 20px);
}
.esp-kirjoittaja-laatikko .esp-kirjoittaja-kuva {
	flex: none;
	width: 56px; height: 56px;
	border-radius: 50%;
	display: block;
}
.esp-kirjoittaja-etiketti {
	margin: 0 0 2px;
	font-size: .74rem;
	font-weight: 600;
	letter-spacing: .05em;
	text-transform: uppercase;
	color: var(--muste-3);
}
.esp-kirjoittaja-nimi { margin: 0 0 6px; font-size: 1.02rem; font-weight: 700; }
.esp-kirjoittaja-esittely { margin: 0; color: var(--muste-2); font-size: .93rem; line-height: 1.55; }

/* -- Sivupalkin sticky CTA-kortti: alun perin tumma (--tumma) kortti,
   vaihdettu vaaleaksi käyttäjäpalautteesta "quite gloomy" — pysyvästi
   näkyvissä koko lukuajan (toisin kuin esim. Kapasiteetti-jakson kertaluon-
   toinen tumma korostus), joten jatkuva tumma pinta koettiin raskaaksi.
   Sama vaalea kortti-idiomi kuin muualla sivustolla (valkoinen pohja,
   ohut reunus, pehmeä varjo) + pieni aksentti-korostuspalkki yläkulmassa
   samaan tapaan kuin jakso-otsikoiden oma `h2::before`-tunnusmerkki —
   aksentti on tässäkin puhtaasti koristeellinen, ei klikattava. Nappi ja
   puhelinnumero säilyvät samoina komponentteina kuin ennen. Sticky vain
   työpöydällä (ks. media-kysely yllä, mobiilissa kortti on tavallinen
   palstan viimeinen elementti). */
.esp-artikkeli-cta-kortti {
	position: sticky;
	top: calc(var(--otsikko-korkeus) + 24px);
	background: var(--paperi);
	color: var(--muste-2);
	border: 1px solid var(--viiva);
	border-radius: 12px;
	padding: clamp(22px, 2.6vw, 28px);
	display: flex;
	flex-direction: column;
	gap: 14px;
	box-shadow: 0 18px 38px -22px rgba(30,36,41,.22);
}
.esp-artikkeli-cta-kortti::before {
	content: '';
	display: block;
	width: 36px;
	height: 4px;
	border-radius: 2px;
	background: var(--aksentti);
}
.esp-artikkeli-cta-otsikko { margin: 0; color: var(--muste); font-size: 1.08rem; font-weight: 700; letter-spacing: -.014em; }
.esp-artikkeli-cta-teksti { margin: 0; color: var(--muste-2); font-size: .9rem; line-height: 1.5; }
.esp-artikkeli-cta-kortti .esp-nappi { justify-content: center; width: 100%; }
.esp-juuri .esp-artikkeli-cta-puhelin {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	color: var(--sini);
	text-decoration: none;
	font-size: .92rem;
	font-weight: 600;
}
.esp-juuri .esp-artikkeli-cta-puhelin:hover { color: var(--muste); }
.esp-artikkeli-cta-puhelin .esp-ico-puh { width: 15px; height: 15px; }
@media (max-width: 1080px) {
	.esp-artikkeli-cta-kortti { position: static; }
}
/* Käyttäjäpyyntö 2026-09-08: "Sticky CTA can be hidden in mobile" —
   kortti piilotetaan kokonaan pienellä näytöllä (sama 640px-raja kuin
   muualla mobiili-erikoistapauksissa tällä sivustolla), koska
   ylätunnisteen oma "Pyydä tarjous" -nappi (header.php, aina näkyvissä)
   ja artikkelin lopussa oleva "Ota yhteyttä" -osio (footer.php) hoitavat
   saman toiminnon ilman että kortti vie tilaa jokaisen artikkelin
   päässä. Piilotetaan koko <aside>, ei vain korttia, ettei tyhjä
   ruudukon sarake jää turhaan tilaa vieväksi. */
@media (max-width: 640px) {
	.esp-artikkeli-sivupalkki { display: none; }
}

/* -- Vanhan espek-blogipohja-lisäosan oma kiinteä mobiilipalkki
   ("Pyydä tarjous" + "Soita ...", .espek-mobiili-cta) piirtyy yhä
   jokaisella artikkelisivulla, koska se tulee lisäosan omasta
   wp_footer-koukusta (anonyymi closure espek-blogipohja.php:ssä) eikä
   liity mitenkään uuteen single.php-malliin. Käyttäjäpalaute: "remove
   the bottom bar in mobile article" — uusi malli sisältää jo saman
   toiminnon (sivupalkin sticky CTA-kortti, joka mobiilissa on artikkelin
   viimeinen elementti pääsisällössä), joten kiinteä palkki on tarpeeton
   tuplakappale. EI voitu poistaa remove_action():lla, koska koukku on
   nimetön closure eikä sitä voi kohdistaa ilman lisäosan omaa tiedosto-
   muutosta — eikä lisäosaa poisteta/deaktivoida (asiakkaan pysyvä
   ohjeistus). Neutraloitu siis teeman puolelta CSS:llä, sama
   periaate kuin espek-ilmeen dequeue-neutralointi functions.php:ssä. */
.espek-mobiili-cta { display: none !important; }

/* -- Uusi, teeman oma kiinteä mobiilipalkki artikkeleille (syyskuu 2026).
   Yllä oleva neutralointi ja sivupalkin oma piilotus (ks. .esp-artikkeli-
   sivupalkki, media max-width:640px, muutama rivi ylempänä) tarkoittivat
   yhdessä että pienillä puhelinnäytöillä (<=640px) artikkelisivuilla ei
   tosiasiassa ollut enää MITÄÄN kiinteää/pysyvää tarjouspyyntö-CTA:ta —
   vain ylätunnisteen nappi (vaatii vierityksen takaisin ylös) ja
   artikkelin lopun "Ota yhteyttä" -osio. Tämä palkki korvaa lisäosan
   version teeman omalla .esp-nappi-komponentilla lisäosan tumman/
   keltavihreän värityksen sijaan, ja tekee lisäosan poistamisesta
   turvallista. Sama <=1023px-raja kuin lisäosan alkuperäisellä
   palkilla; markup single.php:ssä. */
.esp-mobiili-cta { display: none; }
@media (max-width: 1023px) {
	.esp-mobiili-cta {
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		z-index: 45;
		display: flex;
		gap: 10px;
		padding: 10px var(--kouru) calc(10px + env(safe-area-inset-bottom));
		background: var(--paperi);
		border-top: 1px solid var(--viiva);
		box-shadow: 0 -6px 20px -4px rgba(30,36,41,.12);
	}
	.esp-mobiili-cta .esp-nappi {
		flex: 1;
		justify-content: center;
		padding: 12px 10px;
		font-size: .86rem;
	}
	body.single-post { padding-bottom: 78px; }
}

/* ============================================================
   19. APULUOKAT
   ============================================================ */

.esp-juuri .screen-reader-text {
	position: absolute; width: 1px; height: 1px;
	padding: 0; margin: -1px; overflow: hidden;
	clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
	.esp-juuri *, .esp-juuri *::before, .esp-juuri *::after {
		transition-duration: .01ms !important;
		animation-duration: .01ms !important;
	}
}

@media print {
	.esp-paatunniste { display: none !important; }
	.esp-jakso { padding-block: 24px; background: #fff !important; }
}

/* ============================================================
   20. LOHKOTYYLIVARIANTIT — syyskuu 2026 arkkitehtuurimuutos
   ------------------------------------------------------------
   Sivujen sisältö siirtyi kovakoodatusta PHP:stä oikeiksi,
   lohkoeditorissa muokattaviksi WordPress-lohkoiksi (ks.
   inc/lohkot.php). espek/jakso-lohko tulostaa AINA samat
   luokat kuin vanha kovakoodattu <section class="esp-jakso
   esp-tumma">-rakenne (esp-pohja/esp-tumma/esp-sini/esp-cta,
   ks. inc/lohkot.php osio 11), joten KAIKKI olemassa olevat
   ".esp-tumma …" / ".esp-cta …" -säännöt yllä toimivat
   muuttumattomina myös uudella lohkolla. Tämä osio kattaa vain
   AIDOSTI uudet asiat: natiivien WP-lohkojen (core/group,
   core/button, core/paragraph, core/columns) tyylivariantit,
   joita vanhassa kovakoodatussa merkkauksessa ei tarvittu.
   ============================================================ */

/* ---- Otsikkorivi (core/group, is-style-espek-otsikkorivi) —
   sama ulkoasu kuin vanhalla .esp-otsikkorivi-luokalla. ---- */
.is-style-espek-otsikkorivi {
	display: flex;
	flex-direction: column;
	gap: clamp(12px, 1.6vw, 18px);
	margin-bottom: clamp(28px, 3.2vw, 46px);
	padding-bottom: clamp(16px, 1.8vw, 22px);
	border-bottom: 1px solid var(--viiva);
}
.esp-tumma .is-style-espek-otsikkorivi { border-bottom-color: var(--tumma-viiva); }
.is-style-espek-otsikkorivi h1,
.is-style-espek-otsikkorivi h2 { margin-bottom: 0; }
.is-style-espek-otsikkorivi h2::before,
.is-style-espek-otsikkorivi h1::before {
	content: '';
	display: block;
	width: 36px;
	height: 4px;
	border-radius: 2px;
	background: var(--aksentti);
	margin-bottom: 16px;
}
.is-style-espek-otsikkorivi .esp-ingressi,
.is-style-espek-otsikkorivi .is-style-espek-ingressi { max-width: none; width: 100%; }

/* ---- CTA-sisältö (core/group, is-style-espek-cta-sisalto) —
   keskitetty, kapea palsta Väli-CTA-tyyppisissä jaksoissa. ---- */
.is-style-espek-cta-sisalto {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	max-width: 46ch;
	margin-inline: auto;
	text-align: center;
}
.is-style-espek-cta-sisalto .wp-block-buttons {
	justify-content: center;
	gap: 12px;
	margin-top: clamp(22px, 2.6vw, 30px);
}
@media (max-width: 560px) {
	.is-style-espek-cta-sisalto .wp-block-buttons { flex-direction: column; align-items: stretch; width: 100%; }
}

/* ---- Nappirivi (core/group, is-style-espek-cta-rivi) —
   yksi keskitetty nappi jakson sisällön alla (Prosessi,
   Faktarivi), sama kuin vanha .esp-jakso-cta. ---- */
.is-style-espek-cta-rivi {
	display: flex;
	justify-content: center;
	margin-top: clamp(32px, 4vw, 52px);
}
/* Tumma-jaksossa sininen täyttönappi jäisi lähelle grafiittitaustaa
   liian vaimeaksi — käännetty negatiiviksi kuten ennenkin. */
.esp-tumma .is-style-espek-cta-rivi .is-style-espek-ensisijainen .wp-block-button__link {
	background: #fff;
	border-color: #fff;
	color: var(--sini);
	box-shadow: 0 1px 2px rgba(0,0,0,.2), 0 10px 22px -6px rgba(0,0,0,.35);
}
.esp-tumma .is-style-espek-cta-rivi .is-style-espek-ensisijainen .wp-block-button__link:hover,
.esp-tumma .is-style-espek-cta-rivi .is-style-espek-ensisijainen .wp-block-button__link:focus-visible {
	background: var(--tumma-teksti);
	border-color: var(--tumma-teksti);
	color: var(--sini);
}

/* ---- Napit (core/button, is-style-espek-*) — sama ulkoasu
   kuin vanhoilla .esp-nappi / .esp-nappi--toissijainen /
   .esp-nappi--reunus -luokilla. WP tulostaa is-style-…-luokan
   ULKOKUOREEN (.wp-block-button), varsinainen <a> saa aina
   oman .wp-block-button__link-luokkansa. ---- */
.esp-juuri .wp-block-button.is-style-espek-ensisijainen .wp-block-button__link,
.esp-juuri .wp-block-button.is-style-espek-toissijainen .wp-block-button__link,
.esp-juuri .wp-block-button.is-style-espek-reunus .wp-block-button__link,
.esp-juuri .wp-block-button.is-style-espek-puhelin .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-family: inherit;
	font-size: .96rem;
	font-weight: 700;
	line-height: 1;
	letter-spacing: -.006em;
	padding: 17px 28px;
	border: 1px solid transparent;
	border-radius: 9px;
	text-decoration: none;
	transition: background .16s ease, border-color .16s ease, color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.esp-juuri .wp-block-button.is-style-espek-ensisijainen .wp-block-button__link,
.esp-juuri .wp-block-button.is-style-espek-puhelin .wp-block-button__link {
	border-color: var(--sini);
	background: var(--sini);
	color: #fff;
	box-shadow: 0 1px 2px rgba(30,36,41,.08), 0 10px 22px -6px rgba(28,92,134,.45);
}
.esp-juuri .wp-block-button.is-style-espek-ensisijainen .wp-block-button__link:hover,
.esp-juuri .wp-block-button.is-style-espek-ensisijainen .wp-block-button__link:focus-visible,
.esp-juuri .wp-block-button.is-style-espek-puhelin .wp-block-button__link:hover,
.esp-juuri .wp-block-button.is-style-espek-puhelin .wp-block-button__link:focus-visible {
	background: var(--sini-2);
	border-color: var(--sini-2);
	color: #fff;
	transform: translateY(-2px);
	box-shadow: 0 4px 8px rgba(30,36,41,.1), 0 16px 28px -6px rgba(28,92,134,.5);
}
.esp-juuri .wp-block-button.is-style-espek-toissijainen .wp-block-button__link {
	border-color: var(--viiva-2);
	background: var(--paperi);
	color: var(--muste);
	box-shadow: 0 1px 2px rgba(30,36,41,.05);
}
.esp-juuri .wp-block-button.is-style-espek-toissijainen .wp-block-button__link:hover,
.esp-juuri .wp-block-button.is-style-espek-toissijainen .wp-block-button__link:focus-visible {
	border-color: var(--muste);
	background: var(--paperi);
	color: var(--muste);
	box-shadow: 0 4px 8px rgba(30,36,41,.08);
}
.esp-juuri .wp-block-button.is-style-espek-reunus .wp-block-button__link {
	border-color: var(--viiva-2);
	background: transparent;
	color: var(--muste);
}
/* Reunus-nappi CTA-kuvatausta- ja tumma-jaksoissa: läpikuultava
   täyttö + valkea reunus, sama kuin vanhalla .esp-nappi--reunus. */
.esp-cta .wp-block-button.is-style-espek-reunus .wp-block-button__link,
.esp-tumma .wp-block-button.is-style-espek-reunus .wp-block-button__link {
	background: rgba(255,255,255,.1);
	border-color: rgba(255,255,255,.55);
	color: #fff;
}
.esp-cta .wp-block-button.is-style-espek-reunus .wp-block-button__link:hover,
.esp-cta .wp-block-button.is-style-espek-reunus .wp-block-button__link:focus-visible,
.esp-tumma .wp-block-button.is-style-espek-reunus .wp-block-button__link:hover,
.esp-tumma .wp-block-button.is-style-espek-reunus .wp-block-button__link:focus-visible {
	background: rgba(255,255,255,.18);
	border-color: #fff;
	color: #fff;
}
/* CTA-kuvatausta-jaksossa "toissijainen" on itse asiassa jakson
   PÄÄnappi (valkea täyttö) — sama poikkeus kuin vanhalla
   .esp-cta .esp-nappi--toissijainen -säännöllä. */
.esp-cta .wp-block-button.is-style-espek-toissijainen .wp-block-button__link {
	background: #fff;
	border-color: #fff;
	color: var(--sini);
}
.esp-cta .wp-block-button.is-style-espek-toissijainen .wp-block-button__link:hover,
.esp-cta .wp-block-button.is-style-espek-toissijainen .wp-block-button__link:focus-visible {
	background: #fff;
	border-color: #fff;
	color: var(--sini-2);
}
/* Puhelinikoni napin edessä AINA kun napin linkki alkaa "tel:"illä —
   ei sidottu tiettyyn tyylivarianttiin (ensisijainen/toissijainen/
   reunus voivat kaikki olla puhelinlinkkejä), vaan puhtaasti
   semanttinen href-valitsin. Ikoni piirretään CSS mask-imagella
   samasta puhelinluurin muodosta kuin functions.php:n
   espek_ikoni_puhelin() SVG, jotta väri periytyy aina napin
   tekstiväristä (currentColor) riippumatta taustasta. */
.esp-juuri .wp-block-button__link[href^="tel:"] {
	display: inline-flex;
	align-items: center;
	gap: 10px;
}
.esp-juuri .wp-block-button__link[href^="tel:"]::before {
	content: '';
	flex: none;
	width: 16px;
	height: 16px;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.7 3.3c1.1-1.1 2.9-1.1 4 0l1.5 1.5c1 1 1 2.7 0 3.7l-.8.8c-.3.3-.4.8-.1 1.1.9 1.7 2.3 3.1 4 4 .3.3.8.2 1.1-.1l.8-.8c1-1 2.7-1 3.7 0l1.5 1.5c1.1 1.1 1.1 2.9 0 4l-1 1c-1 1-2.5 1.4-3.9 1-5.8-1.6-10.4-6.2-12-12-.4-1.4 0-2.9 1-3.9l1-1Z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.7 3.3c1.1-1.1 2.9-1.1 4 0l1.5 1.5c1 1 1 2.7 0 3.7l-.8.8c-.3.3-.4.8-.1 1.1.9 1.7 2.3 3.1 4 4 .3.3.8.2 1.1-.1l.8-.8c1-1 2.7-1 3.7 0l1.5 1.5c1.1 1.1 1.1 2.9 0 4l-1 1c-1 1-2.5 1.4-3.9 1-5.8-1.6-10.4-6.2-12-12-.4-1.4 0-2.9 1-3.9l1-1Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
.esp-juuri .wp-block-button.is-style-espek-toissijainen .wp-block-button__link[href^="tel:"] { color: var(--sini); }
.esp-cta .wp-block-button__link[href^="tel:"],
.esp-tumma .wp-block-button__link[href^="tel:"] { color: #fff; }

/* ---- Leipätekstin tyylit (core/paragraph, is-style-espek-*) ---- */
.is-style-espek-ingressi {
	font-size: var(--t-ingressi);
	line-height: 1.52;
	color: var(--muste-2);
	max-width: 48ch;
}
.esp-tumma .is-style-espek-ingressi { color: var(--tumma-teksti); }
.is-style-espek-etiketti {
	font-size: var(--t-pieni);
	font-weight: 500;
	letter-spacing: .075em;
	text-transform: uppercase;
	color: var(--muste-3);
	margin: 0 0 1.2em;
	line-height: 1.5;
}
.esp-tumma .is-style-espek-etiketti { color: var(--tumma-himmea); }
.is-style-espek-cta-otsikko {
	margin: 0 0 10px;
	font-size: clamp(1.5rem, 1.15rem + 1.4vw, 1.9rem);
	font-weight: 800;
	letter-spacing: -.017em;
	line-height: 1.15;
	color: #fff;
	max-width: none;
}
.esp-juuri .is-style-espek-linkki a {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-weight: 500;
	font-size: .93rem;
	color: var(--sini);
	text-decoration: none;
	border-bottom: 1px solid var(--sini-3);
	padding-bottom: 2px;
	transition: border-color .15s ease;
}
.esp-juuri .is-style-espek-linkki a:hover { border-bottom-color: var(--sini); }
.esp-juuri .is-style-espek-linkki a::after {
	content: '';
	flex: none;
	width: 8px;
	height: 8px;
	border-right: 1.5px solid currentColor;
	border-top: 1.5px solid currentColor;
	transform: rotate(45deg) translate(-1px, 1px);
	transition: transform .15s ease;
}
.esp-juuri .is-style-espek-linkki a:hover::after { transform: rotate(45deg) translate(1px, -1px); }

/* ---- Kapasiteetti-jakson sisällä oleva core/columns-rivi
   (teksti | hallilaatikot) — sama leveyssuhde/väli kuin vanhalla
   .esp-kapasiteetti-ylarivi-luokalla, mutta natiivilla,
   editorissa vapaasti säädettävällä Sarakkeet-lohkolla. ---- */
.esp-kapasiteetti > .wp-block-columns {
	gap: clamp(28px, 4vw, 56px);
	margin-bottom: 0;
}
.esp-kapasiteetti .wp-block-column > p { margin: 0 0 14px; }
.esp-kapasiteetti .wp-block-column > p:last-child { margin-bottom: 0; }

/* ---- Jakso-lohkon editorinäkymän pieni nimikeotsikko
   (espek-lohko-nimike, ks. lohkot.js) sivun ETUOSASSA näkyy vain
   editorissa (lohkot-editor.css), ei julkisella sivulla. ---- */

/* ============================================================
   MURUPOLKU (.esp-murupolku) — pieni, huomaamaton navigointiapu
   sivun ylälaidassa (header.php, jokaisella sivulla paitsi
   etusivulla). Sama data ajaa myös BreadcrumbList-JSON-LD:tä
   (functions.php, osio 9), joten näkyvä polku ja hakukoneille
   näkyvä merkintä eivät voi ajautua erilleen.
   ============================================================ */
.esp-juuri .esp-murupolku {
	border-bottom: 1px solid var(--viiva);
	background: var(--paperi);
}
.esp-juuri .esp-murupolku-lista {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0;
	padding: 10px 0;
	list-style: none;
	font-size: var(--t-pieni);
	color: var(--muste-2);
}
.esp-juuri .esp-murupolku-lista li {
	display: flex;
	align-items: center;
	gap: 6px;
}
.esp-juuri .esp-murupolku-lista li:not(:first-child)::before {
	content: '/';
	color: var(--muste-3, var(--muste-2));
}
.esp-juuri .esp-murupolku-lista a {
	color: var(--muste-2);
	text-decoration: none;
}
.esp-juuri .esp-murupolku-lista a:hover {
	color: var(--sini);
	text-decoration: underline;
}
.esp-juuri .esp-murupolku-lista span[aria-current="page"] {
	color: var(--muste);
	font-weight: 500;
}
