/* ==========================================================================
   KOUKKU TAITURI — KÄYTTÖÖNOTTODOKUMENTAATION KUORI
   Yksi tyylitiedosto kaikille /kayttoonotto/-sivuille. Sivut sisältävät vain
   sisältöä; kaikki ulkoasu on täällä ja kaikki käyttäytyminen docs.js:ssä.
   Tarkoitus: sivun lisääminen on sisällön kirjoittamista, ei tyylin
   kopiointia — muuten viides sivu ajautuu ensimmäisestä erilleen.
   ========================================================================== */

:root {
  --pinta: #ffffff;
  --tausta: #f6f7f9;
  --teksti: #14161a;
  /* 🔴 LEIPÄTEKSTILLÄ ON OMA VÄRI (22.8.2026). Ennen tätä proosa käytti
     `--himmea`a eli TOISSIJAISEN tekstin väriä (#5a6472, 5,6:1). Se läpäisee
     AA:n, mutta kun sivun jokainen kappale on toissijaisen värissä, mikään
     ei ole ensisijaista — ja sivu näyttää luonnokselta, ei julkaisulta.
     Mitattu: #3c4257 antaa 9,1:1 sivun taustaa ja 10,0:1 valkoista vasten.
     `--himmea` jää siihen mihin se on tarkoitettu: kuvatekstit, metatiedot,
     taulukon toissijaiset solut. */
  --leipa: #3c4257;
  --himmea: #5a6472;
  /* Oli #8a93a0 = 2,89 : 1 sivun taustaa vasten. Se on WCAG AA -rike, ja se
     osui sivuston jokaiseen pikkutekstiin: yläpalkin "Käyttöönotto",
     sivupalkin ryhmäotsikko, "Tällä sivulla", "Päivitetty", edellinen/
     seuraava-suunnat. Nyt 4,61 : 1 taustaa ja 4,94 : 1 valkoista vasten.
     Hierarkia leipätekstiin (--himmea) tehdään koolla, versaalilla ja
     harvennuksella — ei enää haalistamalla lukukelvottomaksi. */
  --hyvin-himmea: #68717e;
  --viiva: #e4e7ec;
  --viiva-vahva: #d3d8e0;
  --brandi: #c81e24;
  --brandi-tumma: #a3161b;

  /* ---- Osavärit ----------------------------------------------------------
     Viisi osiota, viisi sävyä. Sävykulma etenee osajärjestyksessä (358° → 30°
     → 171° → 212° → 277°), joten väri koodaa myös lukujärjestyksen eikä vain
     aihepiiriä. Brändipunainen on osa 1, koska se on sisääntulo.

     JOKAINEN on valittu kantamaan VALKOISTA leipätekstiä: mitattu kontrasti
     valkoiseen on 5,73 / 6,16 / 6,50 / 6,63 / 7,55 : 1, ja korttien
     geometrisen kuvion (valkoinen 9 %) kanssa pahimmillaan 5,06 : 1.
     Vaatimus on 4,5 : 1. Suhde on (L1+0,05)/(L2+0,05) sRGB:n suhteellisista
     luminansseista.

     axe EI vahdi näitä: se merkitsee korttien 15 tekstisolmua
     "incomplete"-tilaan, koska ::before-gradientin takia se ei osaa päätellä
     taustaa — color-contrast-sääntö ei siis aja niille lainkaan. Todistettu:
     sävy 2,95 : 1:een vaalennettuna axe-portti näytti yhä vihreää.

     Siksi kontrasti mitataan pikseleistä omassa portissaan:
     e2e/a11y.spec.js → "käyttöönoton osakortit (leveä/kapea ruutu)". Se
     kuvaa kortin teksti piilotettuna ja etsii jokaisen tekstilaatikon alta
     pahimman taustapikselin. Jos muutat näitä viittä arvoa, aja se testi —
     pelkkä axe-ajo näyttää vihreää myös rikkinäisenä. */
  --osa-1: #c81e24;  /* punainen  — Mitä asennetaan (brändi, sisääntulo)   */
  --osa-2: #94500b;  /* pronssi   — Jakelu (käsityö koneella, lämmin)      */
  --osa-3: #0c6a5c;  /* petroli   — Lisensointi (hallinto, kylmenee)       */
  --osa-4: #1f5da5;  /* meri      — Suljettu verkko (infra, eristys)       */
  --osa-5: #733a97;  /* luumu     — Vaatimustenmukaisuus (päätepiste)      */
  --osa-6: #0f6ea8;  /* syaani    — Apuri (paikallinen tekoäly)            */
  --osa-7: #4a5568;  /* grafiitti — Työkaluluettelo (hakemisto, neutraali) */

  --koodi-tausta: #14161a;
  --koodi-teksti: #e8eaed;
  --sivupalkki: 264px;
  --sisallys: 216px;
  --ylapalkki: 56px;
  --radius: 10px;
  --varjo: 0 1px 2px rgba(20, 22, 26, .04), 0 4px 12px -4px rgba(20, 22, 26, .06);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; scroll-padding-top: calc(var(--ylapalkki) + 20px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--tausta);
  color: var(--teksti);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  /* Suomen yhdyssana on pisin rivielementti tällä sivustolla, ja
     tekstizoomissa se ei enää mahdu riville: 200 %:n zoomilla 375 px:n
     ruudulla "Vaatimustenmukaisuus"-otsikko työnsi KOKO SIVUN 240 px
     vaakavieritykseen (WCAG 1.4.4/1.4.10). break-word katkaisee sanan VAIN
     kun se ei muuten mahdu — normaalikoossa mikään ei muutu. Ominaisuus
     periytyy, joten yksi sääntö kattaa otsikot, leipätekstin ja kortit;
     white-space: pre (koodilohkot) ja nowrap (taulukon otsikot) ohittavat
     sen omissa kohdissaan. */
  overflow-wrap: break-word;
}

a { color: var(--brandi); text-decoration: none; font-weight: 550; }
a:hover { color: var(--brandi-tumma); text-decoration: underline; }
:focus-visible { outline: 2px solid var(--brandi); outline-offset: 2px; border-radius: 4px; }

/* Ohita navigaatio -linkki: näppäimistökäyttäjä pääsee suoraan sisältöön. */
.ohita {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  background: var(--teksti); color: #fff; padding: .7rem 1.1rem;
  border-radius: 0 0 var(--radius) 0; font-weight: 600;
}
.ohita:focus { left: 0; color: #fff; text-decoration: none; }

/* ---------- Yläpalkki ---------- */
.docs-ylapalkki {
  position: sticky; top: 0; z-index: 40;
  height: var(--ylapalkki);
  background: rgba(255, 255, 255, .88);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--viiva);
  display: flex; align-items: center; gap: 1rem;
  padding: 0 1.25rem;
}
.docs-merkki { display: flex; align-items: center; gap: .6rem; font-weight: 700; color: var(--teksti); font-size: .95rem; }
.docs-merkki:hover { text-decoration: none; color: var(--teksti); }
/* Merkki on kuva (favicon.svg), ei kirjain — tausta ja pyöristys tulevat siitä. */
.docs-merkki .piste { width: 22px; height: 22px; display: block; }
.docs-merkki .osa { color: var(--hyvin-himmea); font-weight: 500; }
.docs-ylapalkki .oikea { margin-left: auto; display: flex; align-items: center; gap: 1rem; font-size: .85rem; }
.docs-ylapalkki .oikea a { color: var(--himmea); font-weight: 500; }
.docs-ylapalkki .oikea a:hover { color: var(--teksti); }

/* Valikkopainike näkyy vain kapealla ruudulla. */
.docs-valikkonappi {
  display: none; align-items: center; gap: .45rem;
  background: none; border: 1px solid var(--viiva-vahva); border-radius: 8px;
  padding: .35rem .7rem; font: inherit; font-size: .85rem; font-weight: 600;
  color: var(--teksti); cursor: pointer;
}

/* ---------- Asettelu ---------- */
.docs-kehys {
  display: grid;
  grid-template-columns: var(--sivupalkki) minmax(0, 1fr) var(--sisallys);
  gap: 2.5rem;
  max-width: 1400px; margin: 0 auto;
  padding: 0 1.5rem;
  align-items: start;
}

/* ---------- Sivupalkki ---------- */
.docs-sivupalkki {
  position: sticky; top: var(--ylapalkki);
  max-height: calc(100vh - var(--ylapalkki));
  overflow-y: auto;
  padding: 2rem .5rem 3rem 0;
}
.docs-sivupalkki .ryhma--jatko { margin-top: 1.5rem; padding-top: 1.1rem; border-top: 1px solid var(--viiva); }
.docs-sivupalkki .ryhma { font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--hyvin-himmea); padding: 0 .75rem; margin-bottom: .6rem; }
.docs-sivupalkki ol { list-style: none; }
.docs-sivupalkki li { margin-bottom: 1px; }
.docs-sivupalkki .linkki {
  display: flex; gap: .7rem; align-items: baseline;
  padding: .5rem .75rem; border-radius: 8px;
  color: var(--himmea); font-weight: 500; font-size: .9rem; line-height: 1.4;
}
.docs-sivupalkki .linkki:hover { background: #eef0f3; color: var(--teksti); text-decoration: none; }
.docs-sivupalkki .linkki .nro { color: var(--hyvin-himmea); font-size: .78rem; font-weight: 600; font-variant-numeric: tabular-nums; flex: none; }
.docs-sivupalkki .linkki[aria-current="page"] { background: #fdeaea; color: var(--brandi-tumma); font-weight: 650; }
.docs-sivupalkki .linkki[aria-current="page"] .nro { color: var(--brandi); }
.docs-sivupalkki .erotin { height: 1px; background: var(--viiva); margin: 1.25rem .75rem; }
.docs-sivupalkki .lisa { display: block; padding: .4rem .75rem; font-size: .86rem; color: var(--himmea); font-weight: 500; }
.docs-sivupalkki .lisa:hover { color: var(--teksti); text-decoration: none; }

/* ---------- Sisältö ---------- */
.docs-sisalto { padding: 2.5rem 0 4rem; min-width: 0; }

.docs-otsikko { margin-bottom: 2rem; }
.docs-otsikko .kicker {
  display: flex; align-items: center; gap: .6rem;
  font-size: .76rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--osa, var(--brandi));
}
/* Sävypalkki kickerin edessä sitoo alasivun siihen korttiin, josta lukija
   tuli: osa 3 on petrolinvihreä kortilla JA sivun otsikossa. Etusivulla
   sävyä ei ole, jolloin palkki on brändinpunainen. */
.docs-otsikko .kicker::before {
  content: ''; flex: none; width: 1.5rem; height: 3px; border-radius: 2px;
  background: currentColor;
}
.docs-otsikko h1 { font-size: clamp(1.85rem, 3.2vw, 2.4rem); font-weight: 700; letter-spacing: -.025em; line-height: 1.15; margin: .45rem 0 0; text-wrap: balance; }
.docs-otsikko .kuvaus { margin-top: .85rem; font-size: 1.06rem; color: var(--himmea); max-width: 62ch; text-wrap: pretty; }
.docs-otsikko .paivitetty { margin-top: .9rem; font-size: .82rem; color: var(--hyvin-himmea); }

/* Alasivun sävy. Attribuutti on <html>-elementissä, jotta muuttuja on
   käytettävissä myös docs.js:n rakentamassa sivupalkissa. */
/* Osan sävyn hyvin vaalea pinta "vastaus ensin" -tiivistykselle. Sävy on
   sama kuin osavärillä mutta 96 % vaaleampi: se erottaa tiivistyksen
   leipätekstistä ilman että se kilpailee varoituslaatikoiden kanssa. */
html[data-osa="1"] { --osa: var(--osa-1); --osa-pinta: #fdf3f3; }
html[data-osa="2"] { --osa: var(--osa-2); --osa-pinta: #fdf6ee; }
html[data-osa="3"] { --osa: var(--osa-3); --osa-pinta: #eef7f5; }
html[data-osa="4"] { --osa: var(--osa-4); --osa-pinta: #eff4fb; }
html[data-osa="5"] { --osa: var(--osa-5); --osa-pinta: #f7f1fb; }
html[data-osa="6"] { --osa: var(--osa-6); --osa-pinta: #eef5fa; }
html[data-osa="7"] { --osa: var(--osa-7); --osa-pinta: #f2f3f5; }

/* ---- Etusivun otsikko: mittasuhde, joka ohjaa katseen ----
   Suhde otsikko : korttiotsikko on 50 px : 21 px ≈ 2,4×. Ilman sitä sivun
   iso otsikko ja viisi korttiotsikkoa kilpailevat samasta huomiosta eikä
   mikään kerro mistä aloittaa. Osioiden väliotsikot asettuvat väliin
   (29 px), jolloin porrastus on otsikko → osio → kortti. */
.docs-otsikko--etu { margin-bottom: 2.4rem; }
.docs-otsikko--etu h1 {
  font-size: clamp(2.1rem, 4.6vw, 3.15rem);
  font-weight: 600; letter-spacing: -.034em; line-height: 1.07;
  margin-top: .7rem;
}
.docs-otsikko--etu .kuvaus { font-size: 1.13rem; max-width: 48ch; margin-top: 1rem; }
.docs-otsikko--etu ~ section > h2 { font-size: 1.8rem; font-weight: 600; letter-spacing: -.026em; margin-top: 3.5rem; }

/* Etusivun aloitusnosto ei ole "vinkki" vaan sivun teesi. Vihreä
   onnistumislaatikko antoi sille väärän merkityksen ja vei huomion juuri
   siitä kohdasta, jossa katseen pitää siirtyä otsikosta kortteihin —
   siksi se on tässä hiljainen. Sisältö on ennallaan. */
.docs-otsikko--etu + .hyva {
  background: var(--pinta); border: 1px solid var(--viiva);
  border-left: 3px solid var(--brandi);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1.1rem 1.3rem; max-width: 62ch;
}
.docs-otsikko--etu + .hyva p { color: var(--himmea); }
.docs-otsikko--etu + .hyva strong { color: var(--teksti); font-weight: 640; }

/* Sivupalkin numerot ovat sivuston värilegenda: sama sävy kuin kortilla.
   Kaikki sävyt yltävät ≥ 5,0 : 1 valkoista sivupalkkia vasten. */
.docs-sivupalkki ol li:nth-child(1) .nro { color: var(--osa-1); }
.docs-sivupalkki ol li:nth-child(2) .nro { color: var(--osa-2); }
.docs-sivupalkki ol li:nth-child(3) .nro { color: var(--osa-3); }
.docs-sivupalkki ol li:nth-child(4) .nro { color: var(--osa-4); }
.docs-sivupalkki ol li:nth-child(5) .nro { color: var(--osa-5); }
/* Auki oleva sivu saa oman sävynsä myös korostuksena — muuten petrolinvihreä
   osa 3 istuisi vaaleanpunaisella pohjalla. Punainen jää varalle selaimille,
   jotka eivät tunne color-mixiä. */
html[data-osa] .docs-sivupalkki .linkki[aria-current="page"] {
  background: #fdeaea;
  background: color-mix(in srgb, var(--osa) 9%, #fff);
  color: var(--osa);
}
html[data-osa] .docs-sivupalkki .linkki[aria-current="page"] .nro { color: var(--osa); }

/* Ankkurikohteen etäisyys navista. 🔴 KOSKEE MYÖS h3[id]:tä: docs.js tekee
   ankkurilinkin jokaiseen h3[id]-otsikkoon, mutta suoja oli vain sectionilla.
   Mitattu 320 px:llä: yläpalkki venyy siinä kolmelle riville (144 px), kun
   scroll-padding-top lupaa vain 108 px — lisensointi.html:n yhdeksän h3-
   ankkuria laskeutuivat 36 px navin ALLE (WCAG 2.4.11). Sectionit selvisivät
   vain siksi, että niillä oli tämä sääntö. */
.docs-sisalto section,
.docs-sisalto h3[id] { scroll-margin-top: calc(var(--ylapalkki) + 24px); }
.docs-sisalto section { padding-top: .5rem; }

/* 🔴 OSIORYTMI (22.8.2026). h2:n yläreunus oli 16 px, joten osiot eivät
   erottuneet toisistaan ja sivu luki yhtenä nauhana — juuri se "pliisu"
   tunne. Hiusviiva + ilma tekee osiosta silmäiltävän: lukija näkee
   rakenteen ennen kuin lukee sanaakaan. Ensimmäinen osio ei saa viivaa,
   koska sen yläpuolella on jo sivun otsikko. */
.docs-sisalto section + section {
  /* 44 + 32 = 76 px eli SAMA osioväli kuin ennen viivaa (mitattu 66-76 px).
     Viiva tekee siis työn, jota ennen yritettiin tehdä pelkällä tyhjällä
     tilalla — ja tyhjä tila yksin ei erota osiota, se vain pidentää sivua.

     🔴 Tarkkuuden vuoksi: tämä muutos on korkeuden suhteen neutraali, mutta
     koko sivu piteni silti ~6 % (yleiskuva.html 9276 → 9877 px). Kasvu tulee
     h3:n ylämarginaalista ja taulukon otsikkorivistä, ei tästä. Älä lue
     tätä lupaukseksi siitä, ettei sivu kasva. */
  margin-top: 2.75rem;
  padding-top: 2rem;
  border-top: 1px solid var(--viiva);
}
.docs-sisalto h2 {
  font-size: 1.4rem; font-weight: 680; letter-spacing: -.02em;
  margin: 2.75rem 0 .5rem; padding-top: .5rem;
  position: relative;
}
.docs-sisalto section:first-of-type h2 { margin-top: 1rem; }
.docs-sisalto h3 { font-size: 1.05rem; font-weight: 650; margin: 1.9rem 0 .4rem; }
.docs-sisalto p { color: var(--leipa); margin-bottom: .85rem; max-width: 68ch; text-wrap: pretty; }
.docs-sisalto strong { color: var(--teksti); font-weight: 620; }
.docs-sisalto ul, .docs-sisalto ol { color: var(--leipa); margin: 0 0 1rem 1.35rem; max-width: 66ch; }
/* Listan rivivälistys: 199 px seitsemälle kohdalle oli 28 px/kohta. */
.docs-sisalto li { margin-bottom: .3rem; }
.docs-sisalto li::marker { color: var(--hyvin-himmea); }

/* Osion aloittava tiivistys — lukija näkee heti mitä osiossa tehdään.
   🔴 VASTAUS ENSIN, EI KORISTE. Tämä oli haalea reunaviiva jonka silmä
   ohitti, vaikka se on osion tärkein rivi: se kertoo mitä osiossa tehdään.
   Nyt sillä on oma pinta ja osan väri, joten se erottuu leipätekstistä
   ilman että se huutaa kuin varoituslaatikko. */
.tiivis {
  font-size: .95rem; color: var(--teksti); font-weight: 500;
  background: var(--osa-pinta, #f8f9fb);
  border-left: 3px solid var(--osa, var(--viiva-vahva));
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: .6rem .95rem; margin: 0 0 1.15rem !important;
}
.tiivis em, .tiivis i { font-style: normal; }

/* Ankkurilinkki otsikon perässä (docs.js lisää). */
/* 🔴 h3 EROTTUU MUUTEN KUIN KOOLLA (22.8.2026). Mitattu: h3 on 16,8 px ja
   leipäteksti 16 px — 0,8 px:n ero on käytännössä näkymätön, joten
   väliotsikko hukkui tekstiin. Ero tehdään nyt värillä ja harvennuksella;
   koko saa pysyä lähellä leipätekstiä, koska h3 on askel eikä luku. */
.docs-sisalto h3 { color: var(--teksti); letter-spacing: -.005em; margin-top: 1.9rem; }
.docs-sisalto h3 + p, .docs-sisalto h3 + ul, .docs-sisalto h3 + .taulukko { margin-top: .5rem; }

.ankkuri { opacity: 0; margin-left: .5rem; font-weight: 400; color: var(--hyvin-himmea); font-size: .85em; }
h2:hover .ankkuri, h3:hover .ankkuri, .ankkuri:focus { opacity: 1; text-decoration: none; }

/* ---------- Laatikot ---------- */
/* 🔴 VÄRI REUNAAN, EI TEKSTIIN (22.8.2026). `.hyva p` värjäsi koko
   kappaleen vihreäksi (#065f46) ja `.huomio p` ruskeaksi. Värillinen
   leipäteksti on se yksittäinen piirre, josta sivu näyttää harrastelijan
   tekemältä — ja se heikentää luettavuutta ilman että se lisää tietoa.
   Väri siirtyy vasempaan reunaan, jossa se koodaa laatikon LAJIN. Teksti
   pysyy samana kuin muualla, joten laatikon sisältö on yhtä luettavaa kuin
   proosa sen ympärillä. Sama rakenne kuin `.rajaus`illa — kolme laatikkoa
   ovat nyt yksi perhe eivätkä kolme eri tapaa. */
.huomio, .hyva, .rajaus {
  border: 1px solid var(--viiva); border-left-width: 4px;
  border-radius: 6px; padding: .9rem 1.15rem; margin: 1.25rem 0;
  font-size: .95rem; max-width: 68ch;
}
.huomio { background: #fffcf3; border-left-color: #d99b09; }
.hyva { background: #f4fbf6; border-left-color: #12805c; }
.huomio p, .huomio li, .hyva p, .hyva li { color: var(--leipa); }
.huomio p:last-child, .hyva p:last-child, .rajaus p:last-child { margin-bottom: 0; }
.huomio strong, .hyva strong, .rajaus strong { color: var(--teksti); font-weight: 700; }
/* Valinnainen nimilappu. Sitä KÄYTETÄÄN silloin kun laatikon puheakti ei käy
   ilmi sisällöstä — käytännössä rajauksissa ("Rehellinen rajaus"). Lyhyt
   vastaus istuu jo oman otsikkonsa alla, joten sille lappu olisi kohinaa.

   🔴 Väri ei ole ainoa erottelukeino: laatikon sisältö ja sijainti kertovat
   lajin. Lappu on lisäkeino, ei se ainoa — älä kirjoita tähän WCAG-väitettä
   jota 25 laatikkoa 27:stä ei täytä. */
.huomio > .nimilappu, .hyva > .nimilappu, .rajaus > .nimilappu {
  display: block; font-size: .72rem; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; margin-bottom: .35rem;
}
.huomio > .nimilappu { color: #96660a; }
.hyva > .nimilappu { color: #0d6a4c; }

/* ---------- Koodi ---------- */
code {
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  font-size: .86em;
  background: #eef0f3; border: 1px solid var(--viiva);
  border-radius: 5px; padding: .1em .38em; color: var(--teksti);
  overflow-wrap: break-word;
}
/* Vierivä säiliö on PRE ITSE — ei docs.js:n lisäämä .koodilohko-kääre.
   Kääreeseen sidottuna overflow-x jäi kokonaan pois ympäristössä, jossa
   JavaScript on estetty: komentorivi vuoti ulos laatikostaan ja vieritti
   KOKO SIVUA vaakasuunnassa (mitattu 596 px jakelu.html ja 649 px
   vaatimustenmukaisuus.html, 375 px:n ruudulla). Kunnan työasemakäytäntö
   saa estää skriptit — sivun asettelu ei saa hajota siitä. Kääre on enää
   kopiointipainikkeen ankkuri. */
.docs-sisalto pre {
  background: var(--koodi-tausta); color: var(--koodi-teksti);
  border-radius: var(--radius); padding: 1.05rem 1.15rem; overflow-x: auto;
  font-size: .86rem; line-height: 1.6;
  margin: 1rem 0 1.35rem; max-width: 68ch;
}
.docs-sisalto pre code { background: none; border: 0; padding: 0; color: inherit; font-size: 1em; }
.koodilohko { position: relative; margin: 1rem 0 1.35rem; max-width: 68ch; }
.koodilohko pre { margin: 0; max-width: none; }
.kopioi {
  position: absolute; top: .55rem; right: .55rem;
  background: rgba(255, 255, 255, .1); color: #cfd4da;
  border: 1px solid rgba(255, 255, 255, .16); border-radius: 7px;
  padding: .32rem .6rem; font: inherit; font-size: .76rem; font-weight: 600;
  cursor: pointer; transition: background .15s, color .15s; opacity: 0;
}
.koodilohko:hover .kopioi, .kopioi:focus { opacity: 1; }
.kopioi:hover { background: rgba(255, 255, 255, .2); color: #fff; }
.kopioi[data-tila="ok"] { opacity: 1; background: #16a34a; border-color: #16a34a; color: #fff; }

/* ---------- Taulukot ---------- */
/* 🔴 PROOSA JA AINEISTO ERI LEVEYDELLÄ. Kappaleet pidetään 68 merkissä, koska
   se on lukemisen raja — mutta taulukolla, koodilla ja laatikolla sitä rajaa
   ei ole: ne ovat katsottavia, eivät luettavia. Kun ne saavat koko palstan,
   solut rivittyvät vähemmän ja rivit madaltuvat. Tämä on ainoa kohta jossa
   leveys VÄHENTÄÄ korkeutta. */
/* 🔴 KEHYS POIS, RAKENNE JÄÄ (22.8.2026). Taulukolla oli reunus, pyöristys
   ja taustasävy, eli jokainen taulukko oli oma laatikkonsa. Kolme laatikkoa
   peräkkäin lukee seinänä. Rakenne syntyy otsikkorivin viivasta, ei
   kehyksestä. Vierityssäiliö JÄÄ: se estää kapealla ruudulla koko sivun
   vaakavierityksen, mikä on mitattu vika eikä tyyliseikka. */
.taulukko { overflow-x: auto; margin: 1.1rem 0 1.6rem; }
/* docs.js tekee vierivistä alueista näppäimistöllä tavoitettavia. Yleinen
   :focus-visible pyöristäisi ne 4 px:iin kesken fokuksen — säilytetään muoto. */
.taulukko:focus-visible, .docs-sisalto pre:focus-visible { border-radius: var(--radius); outline-offset: 2px; }
.taulukko table { width: 100%; border-collapse: collapse; font-size: .92rem; }
/* 🔴 TIHEYS MITATTIIN, EI ARVATTU (22.8.2026). yleiskuva.html oli 9431 px
   korkea 1484 sanalle: ensimmäinen osio vei 975 px 151 sanalle, ja siitä
   taulukko 298 px (6 riviä) ja lista 199 px. Lukija selasi yhdeksän
   ruudullista saadakseen yhden sivullisen asiaa — se on se "pliisu" tunne.
   Solun pystypehmuste .75rem -> .5rem säästää ~4 px riviltä. */
.taulukko th, .taulukko td { text-align: left; padding: .5rem .85rem; border-bottom: 1px solid var(--viiva); vertical-align: top; }
.taulukko tr:last-child td { border-bottom: 0; }
.taulukko th {
  font-weight: 650; color: var(--teksti); white-space: nowrap;
  font-size: .82rem; letter-spacing: .04em; text-transform: uppercase;
  border-bottom: 1px solid var(--viiva-vahva);
  padding-bottom: .45rem;
}
.taulukko tr:last-child td { border-bottom: 1px solid var(--viiva); }
.taulukko td { color: var(--leipa); }
.taulukko code { font-size: .82em; }

/* ---------- Ympäristövalitsin ----------
   Napit rakentaa docs.js. Ilman skriptiä laatikko jää tyhjäksi — tyhjä
   reunustettu laatikko olisi pelkkä hämmennys, joten se ei renderöidy. */
.ymparisto:empty { display: none; }
.ymparisto {
  background: var(--pinta); border: 1px solid var(--viiva);
  border-radius: var(--radius); padding: 1.1rem 1.25rem; margin: 0 0 2rem;
  box-shadow: var(--varjo); max-width: 68ch;
}
.ymparisto .kysymys { font-weight: 650; color: var(--teksti); margin-bottom: .25rem; }
.ymparisto .apu { font-size: .88rem; color: var(--himmea); margin-bottom: .85rem; }
.ymparisto .napit { display: flex; flex-wrap: wrap; gap: .5rem; }
.ymparisto button {
  font: inherit; font-size: .89rem; font-weight: 600;
  background: var(--pinta); color: var(--himmea);
  border: 1px solid var(--viiva-vahva); border-radius: 8px;
  padding: .5rem .9rem; cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.ymparisto button:hover { border-color: var(--hyvin-himmea); color: var(--teksti); }
.ymparisto button[aria-pressed="true"] { background: var(--brandi); border-color: var(--brandi); color: #fff; }
[data-ymparisto] { display: block; }
[data-ymparisto].piilossa { display: none; }

/* ---------- Sisällysluettelo oikealla ---------- */
.docs-sisallys {
  position: sticky; top: var(--ylapalkki);
  max-height: calc(100vh - var(--ylapalkki));
  overflow-y: auto; padding: 2.9rem 0 3rem;
  font-size: .85rem;
}
.docs-sisallys .otsikko { font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--hyvin-himmea); margin-bottom: .7rem; }
.docs-sisallys ul { list-style: none; border-left: 1px solid var(--viiva); }
.docs-sisallys a { display: block; padding: .32rem 0 .32rem .9rem; margin-left: -1px; border-left: 2px solid transparent; color: var(--himmea); font-weight: 500; line-height: 1.45; }
.docs-sisallys a:hover { color: var(--teksti); text-decoration: none; }
.docs-sisallys a[aria-current="true"] { color: var(--brandi); border-left-color: var(--brandi); font-weight: 600; }

/* ---------- Sivunavigointi alhaalla ---------- */
/* minmax(0, 1fr), ei auto eikä 1fr: ruudukkorata ei saa venyä sisällön
   VÄHIMMÄISLEVEYTEEN. 200 %:n tekstizoomilla sana "Lisensointi" ei mahtunut
   301 px:n sisältösarakkeeseen, rata venyi sen mittaiseksi ja koko sivu vieri
   81 px vaakasuunnassa (ilmavali.html @375). Huom: bodyn overflow-wrap:
   break-word EI yksin riitä tähän — se estää rivin ylivuodon mutta ei pienennä
   min-content-kokoa, joka ruudukkoradan mitoittaa. Siksi rata on nollattava. */
.docs-seuraava {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem;
  margin-top: 3.5rem; padding-top: 2rem; border-top: 1px solid var(--viiva);
}
@media (min-width: 640px) { .docs-seuraava { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.docs-seuraava a {
  border: 1px solid var(--viiva); border-radius: var(--radius); padding: .9rem 1.1rem;
  background: var(--pinta); display: block;
}
.docs-seuraava a:hover { border-color: var(--viiva-vahva); text-decoration: none; box-shadow: var(--varjo); }
.docs-seuraava .suunta { font-size: .76rem; color: var(--hyvin-himmea); font-weight: 600; }
.docs-seuraava .nimi { color: var(--teksti); font-weight: 650; margin-top: .15rem; }
.docs-seuraava .edellinen { text-align: left; }
.docs-seuraava .seuraava { text-align: right; }
.docs-seuraava .seuraava:only-child { grid-column: 2; }

.docs-alatunniste { margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--viiva); font-size: .87rem; color: var(--himmea); max-width: 68ch; }

/* ==========================================================================
   ETUSIVUN OSAKORTIT
   Kortti EI ole valkoinen laatikko harmaalla reunuksella. Se on täysvärinen
   pinta, jonka ainoa erottava tekijä on sävy — ei reunusta, ei varjoa, ei
   ikonia. Näin viisi korttia eroaa toisistaan yhdellä silmäyksellä eikä
   lukijan tarvitse lukea otsikoita erottaakseen ne.

   KAIKKI korttiteksti on puhdasta valkoista. Se on tarkoituksellista: heti
   kun osa tekstistä olisi läpinäkyvää valkoista, jokainen sävy pitäisi
   mitata erikseen jokaisella läpinäkyvyysasteella. Hierarkia tehdään
   koolla, paksuudella ja harvennuksella — ei himmentämällä.
   ========================================================================== */

.docs-kortit { display: grid; gap: 1rem; margin: 1.75rem 0 0; }

.docs-kortti {
  --siirto: 0rem;
  /* Varaväri: kortti jolta puuttuu data-osa on LUETTAVA eikä näkymätön.
     Ilman tätä puuttuva muuttuja tuottaa läpinäkyvän taustan valkoisella
     tekstillä — kontrasti 1,07, eikä se näytä rikkinäiseltä vaan tyhjältä. */
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--osa, var(--osa-7)); color: #fff;
  border: 0; border-radius: 14px;
  padding: 1.35rem 1.4rem 2.9rem;
  transform: translateY(var(--siirto));
  transition: transform .18s ease, box-shadow .18s ease;
}
.docs-kortti[data-osa="1"] { --osa: var(--osa-1); }
.docs-kortti[data-osa="2"] { --osa: var(--osa-2); }
.docs-kortti[data-osa="3"] { --osa: var(--osa-3); }
.docs-kortti[data-osa="4"] { --osa: var(--osa-4); }
.docs-kortti[data-osa="5"] { --osa: var(--osa-5); }
.docs-kortti[data-osa="6"] { --osa: var(--osa-6); }
.docs-kortti[data-osa="7"] { --osa: var(--osa-7); }

/* Osanumero: ei himmennystä vaan harvennus ja sitä jatkava hiusviiva.
   Sama luettavuus kuin otsikolla, eri tekstuuri. */
.docs-kortti .nro {
  display: flex; align-items: center; gap: .6rem;
  font-size: .76rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: #fff;
}
.docs-kortti .nro::after {
  content: ''; flex: 1 1 auto; height: 1px; max-width: 3.5rem;
  background: rgba(255, 255, 255, .55);
}
.docs-kortti h2 {
  font-size: 1.32rem !important; font-weight: 620; letter-spacing: -.018em;
  line-height: 1.24; color: #fff; text-wrap: balance;
  margin: .7rem 0 .5rem !important; padding: 0 !important;
}
.docs-kortti p {
  font-size: .93rem; line-height: 1.55; color: #fff; margin: 0;
  max-width: 40ch;
}

/* Geometrinen kuviointi: pelkkää CSS-gradienttia, ei kuvatiedostoja —
   sisältöturvakäytäntö estää ulkoiset varat. Jokaisella kortilla on OMA
   kuvionsa, koska viisi kertaa sama kuvio on sama vika kuin viisi kertaa
   sama harmaa reunus. Valkoisen enimmäispeitto on 9 %, ja kontrasti on
   mitattu sen kanssa (heikoin 5,06 : 1). */
.docs-kortti::before {
  content: ''; position: absolute; z-index: -1; pointer-events: none;
  right: -12%; bottom: -22%; width: 78%; height: 86%;
  opacity: .95; transition: opacity .18s ease;
}
.docs-kortit > :nth-child(1)::before {   /* samankeskiset kaaret */
  background: repeating-radial-gradient(circle at 78% 92%,
    transparent 0 27px, rgba(255, 255, 255, .09) 27px 29px);
}
.docs-kortit > :nth-child(2)::before {   /* vino viivoitus */
  background: repeating-linear-gradient(48deg,
    transparent 0 14px, rgba(255, 255, 255, .085) 14px 16px);
}
.docs-kortit > :nth-child(3)::before {   /* ristikko */
  background:
    repeating-linear-gradient(0deg, transparent 0 22px, rgba(255, 255, 255, .05) 22px 23px),
    repeating-linear-gradient(90deg, transparent 0 22px, rgba(255, 255, 255, .05) 22px 23px);
}
.docs-kortit > :nth-child(4)::before {   /* renkaat + vaakaviivasto */
  background:
    repeating-radial-gradient(circle at 22% 88%, transparent 0 19px, rgba(255, 255, 255, .075) 19px 21px),
    repeating-linear-gradient(0deg, transparent 0 11px, rgba(255, 255, 255, .04) 11px 12px);
}
.docs-kortti--palkki::before {   /* sisäkkäiset neliöt */
  background: repeating-conic-gradient(from 45deg at 88% 96%,
    rgba(255, 255, 255, .075) 0 25%, transparent 0 50%);
  background-size: 46px 46px;
}

/* Kulmanuoli: reunuksista taitettu, ei merkkiä eikä ikonifonttia — mikään
   ruudunlukija ei lue sitä, koska sisältöä ei ole. */
.docs-kortti::after {
  content: ''; position: absolute; right: 1.5rem; bottom: 1.45rem;
  width: 9px; height: 9px;
  border: 2px solid #fff; border-left: 0; border-bottom: 0;
  transform: rotate(45deg); opacity: .9;
  transition: transform .18s ease, opacity .18s ease;
}

.docs-kortti:hover { text-decoration: none; color: #fff; }
@media (hover: hover) {
  .docs-kortti:hover {
    transform: translateY(calc(var(--siirto) - 3px));
    /* Varjo kortin OMASSA sävyssä, ei geneerinen harmaa. Neutraali varjo
       ensin, jotta vanha selain ilman color-mixiä saa silti nostovihjeen. */
    box-shadow: 0 16px 34px -14px rgba(20, 22, 26, .38);
    box-shadow: 0 16px 34px -14px color-mix(in srgb, var(--osa) 72%, #000);
  }
  .docs-kortti:hover::after { transform: translateX(4px) rotate(45deg); opacity: 1; }
  .docs-kortti:hover::before { opacity: 1; }
}
/* Fokusrengas: brändipunainen ei näy punaisella kortilla. Valkoinen sisään,
   tumma ulos — erottuu sekä kortista että sivun taustasta. */
.docs-kortti:focus-visible {
  outline: 3px solid #fff; outline-offset: -7px;
  box-shadow: 0 0 0 3px var(--teksti);
}
@media (prefers-reduced-motion: reduce) {
  .docs-kortti, .docs-kortti::after, .docs-kortti::before { transition: none; }
  .docs-kortti:hover { transform: translateY(var(--siirto)); }
  .docs-kortti:hover::after { transform: rotate(45deg); }
}

/* ---- Kaksi saraketta: osat 1–4 pareina, osa 5 päätepalkkina ---- */
@media (min-width: 700px) {
  .docs-kortit { grid-template-columns: 1fr 1fr; gap: 1.25rem; }
  .docs-kortti { min-height: 15.5rem; padding: 1.5rem 1.6rem 3rem; }
  /* 🔴 PÄÄTEPALKKI MERKITÄÄN LUOKALLA, EI ASEMALLA (22.8.2026).
     Sääntö oli `:nth-child(5)`, koska päätepalkki sattui olemaan viides.
     Kun lisäsin kaksi sivua, leveä palkki jäi keskelle ruudukkoa ja
     viimeinen kortti jäi orvoksi nurkkaan. Asemaan sidottu tyyli kertoo
     "viides", vaikka tarkoitus on "eri laji kuin muut". */
  .docs-kortti--palkki {
    grid-column: 1 / -1; min-height: 0;
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    column-gap: 2.5rem; align-items: start;
    padding: 1.6rem 1.8rem 1.75rem;
  }
  .docs-kortti--palkki .nro { grid-column: 1; grid-row: 1; }
  .docs-kortti--palkki h2 { grid-column: 1; grid-row: 2; margin: .55rem 0 0 !important; }
  .docs-kortti--palkki p { grid-column: 2; grid-row: 1 / span 2; max-width: 48ch; }
  .docs-kortti--palkki::before { width: 42%; height: 150%; bottom: -40%; }
  .docs-kortti--palkki::after { bottom: 1.7rem; right: 1.8rem; }
}

/* ---- Porrastus: oikea sarake laskeutuu ----
   Toteutus on transform eikä margin, jotta ruudukon rivikorkeudet pysyvät
   ennallaan — marginaali kasvattaisi rivirataa ja repisi epätasaiset raot
   korttien väliin. Porrastus on VAIN leveällä ruudulla: kapealla se olisi
   pelkkää hukkatilaa, joten se katoaa tarkoituksella. */
@media (min-width: 900px) {
  .docs-kortit > :nth-child(even) { --siirto: 2.6rem; }
  .docs-kortti--palkki { --siirto: 0rem; }
  .docs-kortti--palkki { margin-top: 2.6rem; }
}

/* ---- Kapea ruutu: porrastus pois, pino jäljelle ----
   Mitattu 375 px:llä. Kortit ovat lohkoja yhden sarakkeen ruudukossa, joten
   vaakavieritystä ei synny; pitkät yhdyssanat ("Vaatimustenmukaisuus")
   mahtuvat 1,32 rem:llä kortin sisäleveyteen. Koko kortti on linkki, joten
   kosketuskohde on satoja pikseleitä — nuoli on pelkkä vihje. */
@media (max-width: 699px) {
  .docs-kortit { gap: .9rem; margin-top: 1.4rem; }
  .docs-kortti { padding: 1.25rem 1.3rem 2.7rem; border-radius: 12px; }
  .docs-kortti h2 { font-size: 1.22rem !important; }
  .docs-kortti p { max-width: none; }
  .docs-otsikko--etu .kuvaus { font-size: 1.05rem; }
  .docs-otsikko--etu ~ section > h2 { font-size: 1.45rem; margin-top: 2.75rem; }
}

/* ---------- Kapea ruutu ---------- */
@media (max-width: 1180px) {
  .docs-kehys { grid-template-columns: var(--sivupalkki) minmax(0, 1fr); gap: 2rem; }
  .docs-sisallys { display: none; }
}
@media (max-width: 860px) {
  .docs-kehys { grid-template-columns: minmax(0, 1fr); gap: 0; padding: 0 1.15rem; }
  .docs-valikkonappi { display: inline-flex; }
  .docs-sivupalkki {
    position: fixed; inset: var(--ylapalkki) auto 0 0; width: min(300px, 84vw);
    background: var(--pinta); border-right: 1px solid var(--viiva);
    padding: 1.25rem 1rem 2rem; z-index: 35;
    transform: translateX(-102%); transition: transform .2s ease;
    box-shadow: 0 12px 40px -12px rgba(20, 22, 26, .2);
  }
  .docs-sivupalkki.auki { transform: none; }
  .docs-sisalto { padding-top: 1.75rem; }
  .docs-otsikko h1 { font-size: 1.75rem; }
  /* Etusivun otsikko pysyy kortteja selvästi isompana myös puhelimessa
     (32 px vs. 19,5 px ≈ 1,6×) — muuten pinotut kortit kilpailevat sen
     kanssa eikä sivun aloituskohta erotu. */
  .docs-otsikko--etu h1 { font-size: 2rem; }
}
@media (prefers-reduced-motion: reduce) { .docs-sivupalkki { transition: none; } }

/* Tulostus: navigaatio pois, sisältö täyteen leveyteen. */
@media print {
  .docs-ylapalkki, .docs-sivupalkki, .docs-sisallys, .docs-seuraava, .kopioi, .ohita, .ymparisto .napit { display: none !important; }
  body { background: #fff; }
  .docs-kehys { grid-template-columns: 1fr; padding: 0; }
  .docs-sisalto p, .docs-sisalto ul { max-width: none; }
  [data-ymparisto].piilossa { display: block !important; }
  .docs-sisalto pre { background: #f4f4f5; color: #14161a; border: 1px solid #d4d4d8; }
  /* 🔴 Paperia ei voi vierittää. overflow-x: auto jäi tulostuksessa päälle,
     joten jokainen laatikkoaan pidempi komento KATKESI kesken — mitattu
     8 lohkoa jakelu.html-sivulla ja 1 lisensointi.html-sivulla A4:llä.
     Juuri ne komennot ovat se syy, jonka takia sivu tulostetaan hankinnan
     liitteeksi. Rivitetään sen sijaan, ja katkaistaan pitkä polku mistä
     tahansa kohtaa jos muuta ei ole. */
  .docs-sisalto pre {
    overflow-x: visible !important;
    white-space: pre-wrap; overflow-wrap: anywhere; max-width: none;
  }
  .koodilohko { display: block !important; max-width: none; }
  code { overflow-wrap: anywhere; }
  .taulukko { overflow-x: visible !important; }
  /* Tulostimet jättävät taustavärit yleensä pois — valkoinen teksti
     valkoisella paperilla katoaisi. Kortit muuttuvat tulostettaessa
     mustavalkoisiksi lohkoiksi, joissa sävy on vain reunaviivana. */
  .docs-kortit { grid-template-columns: 1fr !important; gap: .6rem !important; }
  .docs-kortti {
    background: #fff !important; color: #14161a !important;
    border: 1px solid #d4d4d8 !important; border-left: 4px solid var(--osa) !important;
    border-radius: 0 !important; min-height: 0 !important;
    padding: .7rem .9rem !important; transform: none !important;
    margin-top: 0 !important; display: block !important;
    break-inside: avoid;
  }
  .docs-kortti .nro { color: var(--osa) !important; }
  .docs-kortti .nro::after { background: #d4d4d8 !important; }
  .docs-kortti h2, .docs-kortti p { color: #14161a !important; max-width: none !important; }
  .docs-kortti::before, .docs-kortti::after { display: none !important; }
}

/* ==========================================================================
   MOBIILIOPTIMOINTI — mitattu Playwrightilla 360 / 375 / 414 / 768 px
   Periaate: mitään ei piiloteta mahtumisen vuoksi.
   ========================================================================== */

/* ---------- Yläpalkki: ei vaakavieritystä ----------
   Mitattu ennen: 360 px:n ruudulla palkin sisältö oli 416 px leveä, jolloin
   selain levitti asettelun 416 px:iin ja koko sivu vieri sivusuunnassa.
   Alle 560 px palkki rivittyy kahdelle riville — mikään linkki ei katoa. */
@media (max-width: 860px) {
  .docs-ylapalkki { gap: .6rem; padding: 0 .9rem; }
  /* min-width: 0 antaa merkin kutistua, mutta yhdellä rivillä teksti vuotaa
     silloin ulos laatikostaan (mitattu +16 px 200 %:n tekstizoomilla).
     Sallitaan rivitys: merkki kasvaa korkeussuunnassa, ei ulos ruudulta. */
  .docs-merkki { font-size: .9rem; min-width: 0; flex-wrap: wrap; row-gap: 0; }
  .docs-ylapalkki .oikea { gap: .75rem; }
}
@media (max-width: 560px) {
  :root { --ylapalkki: 88px; }
  .docs-ylapalkki {
    height: auto; min-height: var(--ylapalkki);
    flex-wrap: wrap; align-content: center;
    padding: .35rem .9rem; row-gap: 0;
  }
  .docs-ylapalkki .oikea { margin-left: 0; width: 100%; gap: 1.25rem; }
}

/* ---------- Kosketuskohteet 44x44 px (WCAG 2.5.5) ---------- */
@media (max-width: 860px) {
  .docs-valikkonappi { min-height: 44px; padding: .35rem .8rem; }
  .docs-merkki { min-height: 44px; }
  .docs-ylapalkki .oikea a,
  .docs-sivupalkki .linkki,
  .docs-sivupalkki .lisa,
  .ymparisto button,
  .kopioi,
  .docs-sisallys a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .docs-sivupalkki .linkki,
  .docs-sivupalkki .lisa { display: flex; }
  .docs-sivupalkki .linkki { align-items: center; }
}

/* ---------- Kopiointipainike näkyviin kosketuslaitteella ----------
   .kopioi paljastui vain :hoverilla, joten sormella koodilohkoa ei voinut
   kopioida lainkaan — toiminto oli tosiasiassa poissa mobiilista.

   🔴 Painike EI saa maata koodin päällä kosketuslaitteella. Kelluvana se
   peitti lyhyen komentolohkon oikean laidan, ja siitä alkanut sormiveto ei
   vierittänyt lohkoa lainkaan: mitattu lisensointi.html @375, lohko jonka
   sisältö on 499 px ja laatikko 317 px, scrollLeft 0 → 0. Käyttäjä ei
   päässyt komennon loppuun millään eleellä. Muissa lohkoissa sama veto
   toimi (0 → 122…135), joten ero oli nimenomaan painike kosketuspisteen
   alla. Nyt painike on omalla rivillään koodin yläpuolella — se ei peitä
   riviäkään eikä ole vedon tiellä. */
@media (hover: none), (pointer: coarse) {
  .kopioi { opacity: 1; }
  .koodilohko { display: flex; flex-direction: column; align-items: flex-end; }
  .koodilohko pre { align-self: stretch; }
  .kopioi {
    position: static; order: -1; margin-bottom: .35rem;
    background: #eef0f3; color: var(--teksti);
    border-color: var(--viiva-vahva);
  }
  .kopioi:hover { background: #e4e7ec; color: var(--teksti); }
}

/* ---------- "Tällä sivulla" -sisällys myös kapealla ----------
   Oli display:none alle 1180 px, eli sivun osioluettelo katosi kokonaan
   mobiilissa ja tabletissa. Nyt se näkyy sisällön yläpuolella tiiviinä
   linkkiryhmänä — sama tieto, vähemmän pystytilaa. */
@media (max-width: 1180px) {
  .docs-sisallys {
    display: block;
    position: static; order: -1;
    max-height: none; overflow: visible;
    margin: 1.6rem 0 0; padding: .85rem 1rem;
    background: var(--pinta); border: 1px solid var(--viiva);
    border-radius: var(--radius);
  }
  /* Yksi rivi, joka vierii omassa laatikossaan: pystysuunnassa tämä vie
     ~70 px eikä puolta ruutua, ja jokainen osio on yhä tavoitettavissa.

     🔴 EI scroll-snappia. Mitattu lisensointi.html @375: selaimen oma
     "vieritä fokusoitu elementti näkyviin" EI toimi tällä rivillä — Tab
     jätti sirun "Sanasto, jos termit…" 179 px rivin oikean reunan taakse
     scrollLeft pysyessä nollassa, eli fokusrengasta ei näkynyt lainkaan
     (WCAG 2.4.7). docs.js vierittää sirun siksi itse, ja snap kumoaisi juuri
     sen ohjelmallisen vierityksen napsauttamalla rivin takaisin lähimpään
     sirunalkuun. Snap oli koriste; fokuksen näkyminen ei ole. */
  .docs-sisallys ul {
    border-left: 0; display: flex; flex-wrap: nowrap; gap: .4rem;
    overflow-x: auto;
    padding-bottom: .25rem; -webkit-overflow-scrolling: touch;
  }
  .docs-sisallys li { flex: none; }
  .docs-sisallys a {
    display: inline-flex; align-items: center; min-height: 44px;
    margin-left: 0; padding: .35rem .8rem; white-space: nowrap;
    border-left: 0; border-radius: 999px; background: #f2f4f7;
  }
  .docs-sisallys a[aria-current="true"] { background: #fdeaea; border-left: 0; }
}
@media (max-width: 1180px) and (min-width: 861px) {
  .docs-sisallys { grid-column: 2; }
}

/* ---------- Tekstikoko, rivitys ja kosketusleveys ----------
   🔴 EHTO OLI SIDOTTU VÄÄRÄÄN AVAIMEEN. Lattia kirjoitettiin aikanaan
   `max-width: 768px` -kyselyyn, mutta puhelin VAAKA-ASENNOSSA on 812 px
   leveä: siinä asennossa jokainen näistä säännöistä katosi. Mitattu
   812 × 375: koodi 12,07 px, "Tällä sivulla" 11,52 px, päivitysleima
   13,12 px ja yläpalkin "Hinnat" 41,4 px leveä (WCAG 2.5.5 vaatii 44).
   Avaimessa on nyt myös osoitinlaji: karkea osoitin = sormi, ruudun
   leveydestä riippumatta.

   Lattia koskee myös kuoren pikkutekstejä (kicker, osanumerot, sivupalkin
   ryhmäotsikko, kopiointipainike): mitattuna ne olivat 11,52–13,76 px
   jokaisella puhelinleveydellä. Hierarkia tehdään versaalilla,
   harvennuksella ja paksuudella — ei koolla luettavan rajan alta. */
@media (max-width: 768px), (pointer: coarse) {
  .docs-otsikko .paivitetty,
  .docs-alatunniste,
  .taulukko table { font-size: .875rem; }
  /* max() antaa 14 px:n lattian rikkomatta suhteellista kokoa isommilla. */
  code { font-size: max(.875rem, .9em); }
  .taulukko code { font-size: max(.875rem, 1em); }
  .docs-sisalto pre, .docs-sisalto pre code { font-size: .875rem; }
  /* Pitkät rekisteripolut ja avaimet rivittyvät leipätekstissä. */
  .docs-sisalto p code, .docs-sisalto li code { overflow-wrap: anywhere; }

  .docs-valikkonappi,
  .docs-ylapalkki .oikea a,
  .docs-sivupalkki .ryhma,
  .docs-sivupalkki .linkki .nro,
  .docs-sivupalkki .lisa,
  .docs-sisallys .otsikko,
  .docs-sisallys a,
  .docs-otsikko .kicker,
  .docs-kortti .nro,
  .docs-seuraava .suunta,
  .kopioi { font-size: .875rem; }

  /* Yläpalkin oikeat linkit: korkeus oli jo 44, leveys 41. */
  .docs-ylapalkki .oikea a { min-width: 44px; justify-content: center; }
}

/* ---------- Työkaluluettelo (generoitu, ks. scripts/docs/rakenna-tyokalulista.mjs) ----------
   Kaksi saraketta leveällä näytöllä, yksi kapealla. Ei ruudukkoa jossa
   korkeus lukittuu: kuvaukset ovat eri mittaisia, ja lukittu korkeus
   pakottaisi joko katkaisun tai tyhjää. */
.tyokalulista {
  /* 🔴 `min(19rem, 100%)` EIKÄ pelkkä `19rem` (22.8.2026). Sarakkeen alaraja
     oli 19rem, joka on rem-mitta ja siis kasvaa tekstizoomin mukana: 200 %:n
     zoomilla (juuri 32 px) se on 608 px, ja 375 px:n ruudulla ruudukko vuoti
     ulos — mitattu 270 px vaakavieritystä, mikä on WCAG 1.4.10 -rike.
     `min(…, 100%)` antaa sarakkeen kutistua säiliön levyiseksi silloin kun
     alaraja ei mahdu. Normaalikoossa mikään ei muutu. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
  gap: .9rem; margin: 1.1rem 0;
  /* EI 68ch-kattoa kuten proosalla: 68ch = 587 px, ja kaksi 19rem-saraketta
     valilyonteineen vaatii 622 px — katto pakotti yhden sarakkeen 1280 px:n
     naytolla (mitattu). Luettavuusraja koskee tekstirivia, ei korttiruudukkoa;
     kortit pitavat oman leveytensa. */
}
.tyokalu {
  border: 1px solid var(--viiva); border-radius: var(--radius);
  padding: .85rem 1rem; background: var(--tausta-kortti, #fff);
}
.tyokalu h3 { margin: 0 0 .3rem; font-size: 1rem; }
.tyokalu p { margin: 0 0 .5rem; font-size: .92rem; color: var(--himmea); }
.tyokalu code {
  font-size: .78rem; color: var(--hyvin-himmea);
  background: transparent; padding: 0;
}

/* ---------- Rehellinen rajaus ------------------------------------------
   🔴 MIKSI OMA ELEMENTTI (22.8.2026). Sisältöauditointi mittasi, että
   rajauslaatikot — "tämä ei toimi näin", "tätä emme voi luvata" — käyttivät
   samaa `.huomio`-tyyliä kuin muistutukset tyyliin "muistakaa poistaa
   testikone". Kun sama laatikko kantaa kuutta eri puheaktia, lukija oppii
   ohittamaan ne kaikki.

   Rajaus on tämän tuotteen VAHVIN erottautumiskeino: kilpailija ei kerro
   mitä hänen tuotteensa ei osaa. Perusmuoto tulee laatikkoperheestä
   (ks. "Laatikot"); täällä vain se, mikä erottaa sen muista. */
.rajaus { background: #fafbfc; border-left-color: #6b7280; }
.rajaus > .nimilappu { color: #5b6472; }

/* HUOM: tummaa tilaa EI lisätä tähän. Mitattu 22.8.2026: docs.css ei toteuta
   tummaa tilaa lainkaan, joten `prefers-color-scheme: dark` -lohko teki
   laatikosta tumman VAALEALLE sivulle — tekstin kontrastiksi mitattiin 2,87,
   kun WCAG AA vaatii 4,5. Puolittainen tumma tila on huonompi kuin ei
   yhtään. Jos tumma tila tehdään, se tehdään koko tyylitiedostoon kerralla. */
