/* =============================================================================
   OEF tokenikerros  ·  brandbook v2.0 §3-§7
   Luotu 14.9.2026, ilmepäivityksen LOHKO A.

   TÄMÄ TIEDOSTO ON ADDITIIVINEN. Se ei poista eikä korvaa yhtään olemassa
   olevaa sääntöä. Se tekee kaksi asiaa:
     1. julistaa brandbookin tokenit (§3 väri, §5 typo, §6 tila, §7 kulmat),
     2. korjaa mitatut WCAG 2.2 AA -rikkeet väritasolla.

   LAYOUT EI MUUTU. Typoskaalan ja tilarytmin tokenit on julistettu tässä mutta
   niitä EI vielä sovelleta mihinkään valitsimeen: se on lohko B. Jos sovellat
   niitä täällä, lohko A:n kontrastitodiste sekoittuu layout-muutokseen eikä
   kumpaakaan voi enää todistaa erikseen.

   KAKSI KASKADIANSAA JOIDEN TAKIA VALITSIMET NÄYTTÄVÄT YLIMITOITETUILTA:

   a) Tailwind CDN kääntää luokkansa selaimessa ja lisää oman <style>-lohkonsa
      headiin ajon aikana. Sen sääntö `.text-slate-500` on tarkkuudeltaan
      (0,1,0) ja se voi päätyä TÄMÄN tiedoston jälkeen. Siksi jokainen
      Tailwind-korvaus kirjoitetaan muodossa `html .luokka` = (0,1,1), joka
      voittaa riippumatta latausjärjestyksestä.

   b) `.content-section a { color: var(--primary) }` on (0,1,1) ja voittaa
      jokaisen yhden luokan nappisäännön. Juuri siitä syntyi 12.9.2026 oranssi
      nappi oranssilla tekstillä, 1,49:1, joka näytti kuvassa oikean muotoiselta.
      Siksi jokainen nappisääntö kirjoitetaan myös scopen kanssa.
   ========================================================================== */

:root {
  /* --- §3.2 Pinnat ja syvyys. Kolme arvotasoa, ei enempää. --------------- */
  --oef-bg:           #0A0F14;
  --oef-bg-syva:      #0F1419;
  --oef-pinta-1:      rgba(255,255,255,0.035);
  --oef-pinta-2:      rgba(255,255,255,0.06);
  --oef-viiva:        rgba(255,255,255,0.10);
  --oef-viiva-heikko: rgba(255,255,255,0.06);

  /* --- §3.1 Merkityskartta: yksi merkitys per väri koko sivustolla. ------
     oranssi   = TOIMINTA ja MÄÄRÄAIKA
     syaani    = SITOVA EHTO
     valkoinen = itse vastaus (otsikko, luku)
     slate     = ihmisen kirjoittama kieli ja metatieto
     vihreä    = toteutunut tila
     punaista  ei ole paletissa lainkaan.                                  */

  /* §3.3 Oranssi on KAKSI väriä, ei yksi. Tämä on brandbook v1.0:n vakavin
     virhe ja korjauksen ydin. Aksentti on teksti ja merkki, täyte on painike.
     Mitattu: #FF5C00 + valkoinen = 3,10:1 FAIL. #CC4A08 + valkoinen = 4,61:1. */
  --toiminta:              #FF5C00;  /* aksentti: teksti 6,22:1, merkit, reunat */
  --toiminta-pinta:        #CC4A08;  /* täyte, valkoisella tekstillä 4,61:1 AA  */
  --toiminta-pinta-hover:  #B34107;  /* 5,71:1                                   */
  --toiminta-pinta-active: #9C3906;  /* 7,00:1                                   */
  --toiminta-linkki:       #FF9A4C;  /* oranssi linkki leivässä, 9,14:1          */

  --ehto:        #00E5FF;  /* syaani aksentti, 12,51:1. EI koskaan painike. */
  --ehto-palkki: #2FB8CC;  /* datapalkin täyte, tummalla merkinnällä 8,11:1 */

  --toteutunut:  #4ADE80;  /* vihreä, 11,04:1. Vain vahvistus ja onnistuminen. */

  /* §4.1 Tekstiportaikko. Jokainen arvo on mitattu, ei arvioitu.
     #64748B (Tailwindin slate-500) on POISTETTU: 4,04:1 pohjalla ja 3,55:1
     kortilla, eli se failaa jokaisella pinnalla. Korvaaja #7C8CA1 = 5,61:1. */
  --teksti-1: #FFFFFF;  /* 19,24:1 */
  --teksti-2: #CBD5E1;  /* 12,96:1 */
  --teksti-3: #94A3B8;  /*  7,50:1 */
  --teksti-4: #7C8CA1;  /*  5,61:1 pohjalla, 5,06:1 kortilla #141B23 */

  /* --- §7.1 Reunakulmat ------------------------------------------------- */
  --r-pieni:   6px;
  --r-kortti:  12px;
  --r-iso:     20px;
  --r-ympyra:  9999px;

  /* --- §7.3 Varjot. Muita ei ole. --------------------------------------- */
  --varjo-nosto:   0 8px 30px rgba(255,92,0,0.28);
  --varjo-modaali: 0 24px 80px rgba(0,0,0,0.6);

  /* --- §10 Liike -------------------------------------------------------- */
  --ease:      cubic-bezier(0.2, 0, 0, 1);
  --dur-nopea: 120ms;
  --dur:       200ms;

  /* --- §6.1 Tilayksikkö 4 px. JULISTETTU, EI VIELÄ SOVELLETTU (lohko B). - */
  --v1:4px; --v2:8px; --v3:12px; --v4:16px; --v5:20px;
  --v6:24px; --v8:32px; --v12:48px; --v16:64px; --v24:96px;

  /* --- §5.1-5.2 Typografia. JULISTETTU, EI VIELÄ SOVELLETTU (lohko B). --- */
  --f-naytto: 'Satoshi', 'Inter', system-ui, sans-serif;
  --f-leipa:  'Inter', system-ui, -apple-system, sans-serif;
  --f-kone:   'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --t-0: 11px; --t-1: 13px; --t-2: 16px; --t-3: 21px; --t-4: 28px; --t-5: 44px;
  --t-h1: clamp(34px, 5.2vw, 56px);
}

@media (max-width: 820px) {
  :root { --t-2: 15px; --t-3: 19px; --t-4: 24px; --t-5: 34px; }
}

/* =============================================================================
   §4.3 FOKUSRENGAS
   Fokusrengas ei ole brändiväri. Oranssi #FF5C00 oranssin napin #CC4A08 päällä
   on 1,49:1 ja syaani syaanin palkin päällä 1,54:1: brändiväri katoaa omaan
   komponenttiinsa. Kaksikerroksinen valkoinen erottuu jokaisella sivun pinnalla.
   ========================================================================== */
a:focus-visible, button:focus-visible, summary:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
details:focus-visible, [tabindex]:focus-visible {
  /* POIKKEAMA brandbookin §4.3 snippetista, ja se on mittaustulos eika makuasia.

     Brandbook maaraa renkaan kaksikerroksisena box-shadowina
     (`0 0 0 2px var(--bg), 0 0 0 4px #fff`). Tallaisenaan se HAVIAA HILJAA
     tallä sivustolla. Mitattu 14.9.2026 nappaimistokavelylla:

       .floating-cta a { ... box-shadow: 0 12px 40px rgba(255,92,0,0.5) }

     on tarkkuudeltaan (0,1,1) eli TASAN SAMA kuin `a:focus-visible`, ja se
     asuu sivun omassa <style>-lohkossa joka ladataan taman tiedoston jalkeen.
     Tasapelin ratkaisee jarjestys, joten sivun oma hehku voittaa ja rengas
     katoaa. getComputedStyle ei paljasta sita mitenkaan: se palauttaa
     taysin validin box-shadowin, vain vaaran. Sama toistui jokaisella
     napilla jolla on oma varjo.

     `outline` ei voi tormata box-shadowin kanssa lainkaan, koska ne ovat eri
     omaisuus. Siksi rengas on outline. Kaksikerroksinen vaikutelma syntyy
     `outline-offset: 2px` -raosta, jossa nakyy napin ymparysta (tumma pinta),
     eli valkoinen viiva erottuu myos oranssin napin paalla:
     #FFFFFF vs #0A0F14 = 19,24:1 ja #FFFFFF vs #CC4A08 = 4,61:1.

     Outline ei myoskaan vaikuta asetteluun, joten se ei voi muuttaa layouttia.

     HUOM: brandbookin §4.3 snippetissa on myos `border-radius: 6px`. Sita EI
     oteta lohko A:ssa, koska sivuston painikkeet ovat viela pillereita
     (9999px) ja saanto pyoristaisi ne uudelleen juuri fokushetkella. Se olisi
     nakyva muodonmuutos, ei varikorjaus. Kulmat ovat lohko B / G. */
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

/* KASKADIREIKA joka loytyi vasta nappaimistokavelylla 14.9.2026, ei koodia
   lukemalla. styles.css:ssa on kolme saantoa jotka nollaavat renkaan:

     .form-input:focus            { outline: none; ... }   (0,2,0)
     .wizard-option:focus-visible { outline: none; ... }   (0,2,0)
     .wizard-checkbox:focus-visible { outline: none; ... } (0,2,0)

   Kaksi jalkimmaista HAVIAVAT tokenikerrokselle oikein, koska tassa
   tiedostossa on niille tasan yhta tarkat valitsimet ja tama tiedosto
   ladataan styles.css:n JALKEEN, jolloin tasapelin ratkaisee jarjestys.

   `.form-input:focus` ei havia, koska sita vastaan oli vain `input:focus-visible`
   = (0,1,1), ja (0,2,0) voittaa sen. Mitattu: laskettu outline-style oli `none`
   contact.html:n jokaisella kentalla ja valikolla. Korvaava hehku
   `box-shadow: 0 0 0 3px rgba(255,92,0,0.1)` on 10 prosentin alfalla
   kaytannossa nakymatton, eli rengasta ei ollut lainkaan.

   Korjaus on `html`-etuliite = (0,2,1), joka voittaa riippumatta
   latausjarjestyksesta. Molemmat pseudoluokat otetaan mukaan koska sivun oma
   saanto kayttaa `:focus`ia: pelkka `:focus-visible` jattaisi hiirella
   kohdistetun tekstikentan sivun oman nollauksen varaan. */
html .form-input:focus,
html .form-input:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

/* Poikkeus: leikkaava sailio. `overflow: hidden` leikkaisi ULKOPUOLELLE
   piirtyvan renkaan pois, eika laskettu tyyli paljasta sita: getComputedStyle
   palauttaa oikean renkaan vaikka se on leikattu. Negatiivinen offset piirtaa
   renkaan elementin SISAAN, jolloin leikkaava sailio ei haittaa.
   Inset box-shadow EI kelpaa korjaukseksi: se haviaa hiljaa heti kun samassa
   komponentissa on hiusviiva box-shadowina, ja 4 px sisarengas syo tiheän
   rivin tekstin paalle. */
.vastauspalkki a:focus-visible,
.ruudukko > :focus-visible,
.wizard-option:focus-visible,
.wizard-checkbox:focus-visible,
.package-card a:focus-visible,
table tr:focus-visible,
.overflow-hidden :focus-visible,
/* details > summary lisattiin 14.9.2026 kun nappaimistokavely + kuvavertailu
   paljasti etta FAQ-summaryissa EI OLLUT RENGASTA LAINKAAN, vaikka laskettu
   tyyli palautti taysin kelvollisen `2px solid rgb(255,255,255)` offsetilla
   2px. Leikkaavat sailiot ovat `details.faq-item { overflow: hidden }`
   (mita-varke- ja asetusluonnos-sivut) ja `div.katto { overflow: hidden }`
   (hakuopas). Summary on niissa taysleveä, joten ulospain piirtyva rengas
   osuu tasan sailion reunaan ja katoaa kokonaan.

   TAMA ON SE TAPAUS JOTA EI LOYDA MITTAAMALLA TYYLEJA. Ainoa tapa nahda se on
   verrata fokusoitua ja fokusoimatonta kuvaa samasta rajauksesta: 24 summarya
   kolmella sivulla tuotti nolla muuttunutta pikselia. Valitsin on
   `details summary:focus-visible` = (0,1,2), joka voittaa yleissaannon
   `summary:focus-visible` = (0,1,1) tarkkuudella eika jarjestyksella. */
details summary:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: -2px;
  box-shadow: none;
}

/* =============================================================================
   TAILWIND CDN -KORVAUKSET
   Tarkkuus (0,1,1) `html`-etuliitteellä, koska Tailwindin oma (0,1,0) -sääntö
   voi päätyä tämän tiedoston jälkeen headiin (ks. kaskadiansa a yllä).
   ========================================================================== */

/* §4.1: slate-500 #64748B = 4,04:1 (203 esiintymää 10 sivulla),
   slate-600 #475569 = 2,54:1 (40 esiintymää) ja slate-700 #334155 = 1,86:1
   (1 esiintymä) failaavat kaikki. Jokainen korvataan mitatulla
   #7C8CA1 = 5,61:1.

   slate-700 on energiaoppaan alanavin erotinpiste `·`. Sen voisi jattaa
   koskematta koristeena (WCAG 1.4.3 ei vaadi kontrastia puhtaalta
   koristeelta), mutta 1,86:1 tarkoittaa etta erotin on kaytannossa
   nakymatton eika siis tee tyotaan. Lisaksi jokainen mittarin poikkeus on
   kohta jossa mittaus alkaa valehdella, joten nolla otetaan ilman
   poikkeuslistaa. --teksti-4 on paletin himmein AA:n lapaiseva arvo, eli
   erotin pysyy hierarkiassa linkkien alapuolella. */
html .text-slate-500,
html .text-slate-600,
html .text-slate-700 { color: var(--teksti-4, #7C8CA1); }

/* §3.3: täytetty painike. VAIN kun elementillä on valkoinen teksti.
   Paljas `.bg-primary` ilman tekstiä on koristepalkki (esim.
   `absolute left-0 w-1 h-full bg-primary`) ja se SAA olla kirkas #FF5C00,
   koska aksenttioranssi on juuri sitä varten. Siksi korvaus sidotaan
   `.text-white`-luokkaan eikä `.bg-primary`-luokkaan yksin. */
html .bg-primary.text-white,
html .content-section a.bg-primary.text-white {
  background-color: var(--toiminta-pinta, #CC4A08);
}
html .bg-primary.text-white:hover,
html .hover\:bg-orange-600.text-white:hover {
  background-color: var(--toiminta-pinta-hover, #B34107);
}
html .bg-primary.text-white:active { background-color: var(--toiminta-pinta-active, #9C3906); }

/* §3.4 Läpinäkyvyyden ansa: alfa syö kontrastin eikä sitä näe koodista.
   Mitattu kortilla #141B23: /70 = 3,30:1 · /50 = 2,24:1 · /30 = 1,53:1.
   Kaikki kolme ovat vaiheotsikoita ("Vaihe 2/3/4") joiden himmeneminen
   välittyy vasemman koristepalkin alfasta (`bg-primary/70` jne.), ei tekstin.
   Teksti saa siis täyden aksenttioranssin, ja porrastus säilyy palkissa. */
html .text-primary\/70,
html .text-primary\/50,
html .text-primary\/30 { color: var(--toiminta, #FF5C00); }

/* §5.4 Gradienttiteksti on kielletty. Kolme mitattavaa syyta:
   1. Vari menee mutaiseksi keskelta: oranssin ja syaanin valissa sana kulkee
      khaki-oliivin lapi, savya jota ei ole paletissa eika merkityskartassa.
   2. Kontrastia EI VOI mitata: laskettu `color` on rgba(0,0,0,0), joten jokainen
      mittari raportoi 1:1 eika yksikaan portti voi todistaa mitaan.
   3. Teksti katoaa Windows High Contrast -tilassa ja tulostuksessa.

   KORVAAVA VARI ON SOLIDI AKSENTTIORANSSI, EI VALKOINEN. Otsikon lopullinen
   ilme on lohko F:n (etusivu) paatos jonka Dani tekee prototyyppikuvista.
   Lohko A tekee vain sen minka se voi todistaa: purkaa gradientin ja antaa
   otsikolle mitattavan varin. #FF5C00 pohjaa #0A0F14 vasten = 6,22:1, eli se
   lapaisee AA:n seka normaalina etta isona tekstina. Nakyva muutos on
   pienin mahdollinen: oranssi otsikko pysyy oranssina. */
html .bg-clip-text.text-transparent,
html .gradient-text {
  color: var(--toiminta, #FF5C00);
  background-image: none;
  -webkit-text-fill-color: var(--toiminta, #FF5C00);
}

/* §5.4.1 KAKSISAVYINEN OTSIKKO ON MYOS KIELLETTY. Danin saanto 14.9.2026:
   "en tykkaa yhtaan kun kontrastia haetaan erivaritetyilla statement sanoilla.
   Se tuo ai-sloppia."

   TAMA KUMOAA LOHKO A:N RATKAISUN. Lohko A purki gradientin ja antoi otsikon
   jalkimmaiselle puoliskolle oman mitattavan varin (`h1 .grad` -> --teksti-3).
   Se seurasi brandbookin silloista §5.4:aa ja oli kontrastimitaltaan oikein,
   mutta se sailytti sen kuvion joka oli koko ajan varsinainen vika: otsikko
   pilkottuna kahteen savyyn. Varin vaihtaminen ei korjaa varijakoa.

   OTSIKKO ON YHDELLA VARILLA. Kun rivi tarvitsee keventamista, se tehdaan
   SIJAINNILLA: oma rivi, oma alkulinja, ymparilla oleva tila. Siksi `.grad`
   ja `.vaimea` eivat saa uutta varia vaan ne on POISTETTU lahteesta, ja
   tilalle tuli `.otsikko-rivi` joka on pelkka rivinvaihto ilman varia.

   `color: inherit` yksin ei riita: Tailwindin `.text-transparent` ja vanhat
   gradienttijulistukset asettavat `-webkit-text-fill-color`-arvon, joka
   VOITTAA lasketun `color`-arvon. Molemmat on nollattava, muuten otsikon
   toinen rivi jaa lapinakyvaksi ja portti nakee sen varina 'GRADIENTTI'. */
h1 .otsikko-rivi,
h2 .otsikko-rivi,
h3 .otsikko-rivi {
  display: block;
  color: inherit;
  -webkit-text-fill-color: currentColor;
  background-image: none;
  background-clip: border-box;
  -webkit-background-clip: border-box;
  opacity: 1;
}

/* §5.4.1: "Aksenttivari ei katoa, se muuttaa paikkaa ... ikoni."
   Aksenttivarinen ikoniligatuuri OTSIKON SISALLA on portille kaksi varia
   samassa otsikossa, ja poikkeuksen kirjoittaminen porttiin olisi juuri se
   auditoimaton pakotie jolla portti muuttuu takaisin valevihreaksi. Siksi
   ikoni siirrettiin lahteessa ULOS otsikosta sisarelementiksi, ja tama kaare
   pitaa ladonnan ennallaan: ikoni ja otsikko samalla rivilla, perusviivat
   kohdakkain. Otsikon oma alamarginaali siirtyy kaareelle, muuten se
   kasvattaisi riviin ylimaaraisen korkeuden. */
.otsikko-ikonirivi {
  display: flex;
  align-items: baseline;
  gap: var(--v2, 8px);
  margin: 0 0 var(--v5, 20px);
}
.otsikko-ikonirivi > h1,
.otsikko-ikonirivi > h2,
.otsikko-ikonirivi > h3 { margin: 0; }
.otsikko-ikonirivi__ikoni { flex-shrink: 0; color: var(--toiminta, #FF5C00); }

/* §10 Liike ei kuulu lohko A:han. Globaali `prefers-reduced-motion`-nollaus
   muuttaisi sivun kayttaytymista kesken kontrastikorjauksen mittausta, jolloin
   layoutin muuttumattomuutta ei voisi enaa todistaa erikseen. Se kirjataan
   lohko B:n listalle. Liiketokenit (--ease, --dur) on julistettu yllä. */

/* =============================================================================
   §7.1 REUNAKULMAT (lohko C)
   Brandbook v2.0 §7.1: painike/lomakekentta/merkki 6 px, kortti/kehys/
   harmonikka/info-lohko 12 px, modaali ja koko sivun levyinen nostolaatikko
   20 px. 9999px jaa VAIN tilapisteelle, edistymispisteelle ja avatarille.
   Ja: yhdella sivulla on enintaan KAKSI eri reunakulmaa kehyksellisissa
   elementeissa.

   MIKSI TAMA KERROS ON OLEMASSA. Sivuston kulmat tulevat kolmesta lahteesta:
   (1) css/styles.css, (2) sivukohtaiset <style>-lohkot, (3) Tailwind CDN:n
   apuluokat markupissa (185 x rounded-xl, 162 x rounded-2xl, 101 x
   rounded-full, 51 x rounded-3xl, 26 x rounded-<sivu>-*). Lahteet 1 ja 2
   korjataan LAHTEESSA, koska silloin tarkkuus ei muutu lainkaan eika
   kaskadissa voi syntya uutta kilpailua. Lahde 3 on markupissa 525 kohdassa,
   eika sita voi korjata lahteessa ilman etta sama muutos tehdaan 525 kertaa
   kasin. Se korjataan siksi tassa kerroksessa.

   MIKSI VALITSIMESSA ON `html`. Tailwind CDN injektoi omat saantonsa ajon
   aikana <style>-elementtina, joka paatyy taman tiedoston JALKEEN. Paljas
   `.rounded-xl` (0,1,0) olisi tasapelissa Tailwindin oman saannon kanssa ja
   havisi jarjestyksella. `html .rounded-xl` (0,1,1) voittaa tarkkuudella,
   eika tarvita yhtaan !importantia. Sama ansa kuin §4.3:n fokusrenkaassa.

   MIKSI EI YKSINKERTAISESTI `* { border-radius: ... }`. Se pyoristaisi myos
   ne elementit joilla ei ole kulmaa lainkaan, eli muuttaisi sivuston ilmetta
   paljon enemman kuin brandbook pyytaa. Kulma muutetaan vain siella missa
   kulma jo on.
   ========================================================================== */

/* Kortti, kehys, harmonikka, info-lohko: 12 px. */
html .rounded,
html .rounded-md,
html .rounded-lg,
html .rounded-xl,
html .rounded-2xl,
html .rounded-3xl   { border-radius: var(--r-kortti); }

/* Sivukohtaiset kulmat sailyttavat suuntansa mutta saavat korttikulman. */
html .rounded-l-2xl { border-radius: var(--r-kortti) 0 0 var(--r-kortti); }
html .rounded-tr-2xl{ border-top-right-radius: var(--r-kortti); }
html .rounded-bl-xl { border-bottom-left-radius: var(--r-kortti); }

/* Painike, merkki, pilleri: 6 px. `rounded-full` on tallä sivustolla
   mitattuna 101 kohdassa, ja niista valtaosa on LEVEA elementti eli pilleri:
   nappi, rintamerkki tai linkkilaatta. Ne ovat tasan se ryhma jonka
   brandbook v2.0 siirsi pois pilleristä. */
html .rounded-full  { border-radius: var(--r-pieni); }

/* POIKKEUS, JA SE ON NIMETTY JA LASKETTAVISSA. Brandbook sallii 9999px:n
   tilapisteelle, edistymispisteelle ja avatarille. Mitattuna 18 sivulta nama
   ovat aina TASAN 1:1 -elementteja (3x3, 4x4, 8x8, 14x14, 16x16, 24x24,
   48x48, 96x96, 160x160) ja jokainen kielletty pilleri on leveampi kuin
   korkea (suhde 2,2-12,6). Geometriaa ei voi valita valitsimella, joten
   poikkeus merkitaan markupiin luokalla `oef-ympyra`. Silloin poikkeusten
   MAARA on laskettavissa git-diffista ja mittarista, eika se ole
   auditoimaton pakotie. */
html .oef-ympyra,
html .rounded-full.oef-ympyra { border-radius: var(--r-ympyra); }

/* =============================================================================
   §8  PAANAVIGAATION RYTMI (lohko I osa 2)
   Tyopoytanaviin tuli seitsemas linkki (Energia-avustus). Mitattuna ENNEN
   lisaysta navin ja logon valiin jai 45 px kaikilla >= 1280 px leveyksilla ja
   TASAN 0 px leveydella 1024. Seitsemas linkki soi sen varan kokonaan: 1024
   px:lla navi meni 39 px logon PAALLE, eli makuportin paallekkaisyysmitta
   kaatui.

   Korjaus ei ole linkin poisto eika pienempi kirjasin vaan VALI. Tailwindin
   `gap-8` (32 px) on navin ainoa saadettava mitta, ja 32 px oli valittu
   kuudelle linkille. Seitsemalle oikea arvo on 20 px, joka on yha
   tilayksikon (4 px) kerrannainen eika siis riko §2:n tilaporrasta.

   Mitattu jalkeen: vali logoon >= 45 px kaikilla viidella leveydella
   (1024, 1152, 1280, 1440, 1600, 1920) ja dokumentin vaakavuoto 0.

   Tarkkuus: `html header nav.lg\:flex` = (0,2,2) voittaa Tailwindin
   `.gap-8`:n (0,1,0). Ei !importantia. Sama kuvio kuin §7.1.
   varke.html:n oma navi on `md:flex gap-7`, eika se osu tahan.
   ========================================================================== */
html header nav.lg\:flex { gap: var(--v5, 20px); }

/* POISTOTESTI (makuportti §1 testi 3) AJETTU TASSA. Ensimmainen versio antoi
   CTA-painikkeelle 12 px lisamarginaalin jotta se erottuisi tekstilinkeista
   omaksi rekisterikseen. Testi: poista se, katosiko jotain. Ei katonnut.
   Painikkeella on oma reunus, oma vari ja oma mono-ladonta, joten se erottuu
   ilman lisatilaa. Marginaali maksoi 1152 px:lla tasan sen 12 px jolla
   painike alkoi kutistua, eli se olisi ostanut nakymatonta ilmaa nakyvalla
   rivityksella. Siksi sita EI ole. */

/* -----------------------------------------------------------------------------
   §8.1  TYOPOYTANAVI VASTA 1200 px:STA, ALLE SEN LAATIKKO
   Mitattu ENNEN tata lohkoa, siis jo ilman seitsematta linkkia: kuuden linkin
   navi EI mahtunut leveyksille 1024-1151. Painike "Ota yhteyttä asiantuntijaan"
   rivittyi kahdelle riville (166x53 ja 242x53 px, kun ehja on 255x38) ja navin
   ja logon valiin jai 0 px. Se oli vanha vika, ei taman lohkon tekema.

   Seitsemas linkki leventaa saman vian kaistan 1024-1199:aan. Kaksi vaihtoehtoa:
   (a) hyvaksya leveampi rikkinainen kaista, (b) nayttaa tyopoytanavi vasta
   siella missa se on ehja ja antaa alle sen saman laatikon jota 1023 px jo
   kayttaa. (b) valittiin, koska se poistaa myos vanhan vian eika vain jata sita
   ennalleen. Laatikossa on TAYSI linkkilista, myos Energia-avustus, joten
   mikaan kohde ei katoa.

   Mitattu JALKEEN: navi nakyy vain >= 1200 px, jolloin vali logoon on
   18 px (1200), 98 px (1280-1920) ja painike on 255x38 eli yhdella rivilla
   kaikilla mitatuilla leveyksilla.

   Tarkkuus (0,2,2) > Tailwindin (0,1,0). Ei !importantia.
   -------------------------------------------------------------------------- */
@media (min-width: 1024px) and (max-width: 1199.98px) {
  html header nav.lg\:flex   { display: none; }
  html header div.lg\:hidden { display: flex; }
}

/* -----------------------------------------------------------------------------
   §9  KATKEAMATON OSOITE EI SAA VENYTTAA PALSTAA (K1)
   Sahkopostiosoite on yksi katkeamaton merkkijono. 16 px leipatekstissa
   `rasmus.vuorilinna@oefinland.fi` on 221 px ja `marko.paasu@oefinland.fi`
   270 px leveä, eikä siinä ole yhtään kohtaa jossa rivi saisi vaihtua.

   MIKSI YKSI OSOITE RIKKOO KOKO SIVUN. Flex- ja grid-itemin automaattinen
   vahimmaiskoko on sen min-content-koko. Katkeamattomalla osoitteella se on
   koko osoitteen leveys, joten SAILIO ei voi kutistua sen alle vaikka ruutua
   kuinka kaventaisi. contact.html:n tiimikortissa ketju on: osoite 270 +
   ikonisarake 48 + gap 16 + kortin padding 2 x 32 = 398, ja ruudukon
   automaattinen sarake venyi 400 px:iin vaikka sailio oli 312 px.
   Mitattu todiste: getComputedStyle(grid).gridTemplateColumns === "400px"
   kun grid.getBoundingClientRect().width === 312.

   MIKSI `anywhere` EIKA `break-word`. Nama eroavat tasan siina mita ne
   tekevat min-content-koolle. `break-word` sallii katkon RENDEROINNISSA
   mutta jattaa min-content-koon ennalleen, joten sarake venyisi edelleen
   400 px:iin ja vaakavuoto sailyisi. Vain `anywhere` pienentaa min-content-
   koon, ja se on juuri se luku jota ruudukko tassa lukee. Mitattu: pelkka
   `break-word` jattaa contact.html:n vuodon 64 px:iin.

   MIKSI EI `word-break: break-all`. Se katkoo JOKAISEN sanan mista tahansa
   kohdasta riippumatta siita mahtuuko rivi. `anywhere` katkaisee vasta kun
   rivi ei muuten mahdu. Ero nakyy suoraan: break-all pilkkoisi myos ne
   osoitteet jotka mahtuvat kokonaan.

   MIKSI VALITSIN ON ATTRIBUUTTI EIKA LUOKKA. `a[href^="mailto:"]` osuu
   jokaiseen sahkopostilinkkiin kaikilla 18 sivulla jotka lataavat taman
   tiedoston, myos niihin joita ei ole viela kirjoitettu. Utility-luokka
   olisi pitanyt lisata 25 kohtaan kasin ja se olisi unohtunut seuraavasta.

   Mitattu ENNEN (19 sivua x 360/768/1440 = 57 mittausta): 13 vaakavuotoa.
   contact 360 -> 64 px, kuusi palvelusivua 768 -> 64 px, index 768 -> 41 px.
   Mitattu JALKEEN: ks. raportti docs/2026-09-16-oef-k1-og-varke.md.

   Tarkkuus (0,1,1) eika `html`-prefiksia tarvita: Tailwind CDN ei julista
   `overflow-wrap`-arvoa yhdellekaan naista linkeista, joten kilpailua ei ole.
   -------------------------------------------------------------------------- */
a[href^="mailto:"] {
  overflow-wrap: anywhere;
}

/* -----------------------------------------------------------------------------
   §9.1  PITKA YHDYSSANA EI SAA VUOTAA RUUDUN ULKOPUOLELLE
   Suomi ei ole tassa sama kieli kuin englanti. Yhdyssanassa ei ole valilyontia
   eika tavuviivaa, joten kapea palsta ei ole reunatapaus vaan normaali tila.
   Mitattu: aurinkosahko.html 360 px, h1 "Aurinkosahkokartoitus" tarvitsee
   362 px ja saa 312 px. Otsikko on keskitetty, joten ylivuoto jakautuu
   molemmille reunoille ja dokumentti vuotaa puolet siita, 26 px.

   `break-word` EIKA `anywhere`, ja tama on tarkoituksella eri arvo kuin §9:ssa.
   Ne ratkaisevat eri ongelman:
     §9   osoite on flex-itemin min-content-koko joka VENYTTAA sailiota.
          Vain `anywhere` pienentaa min-content-koon, joten se tarvitaan.
     §9.1 otsikko ei venyta mitaan, se vain vuotaa omasta laatikostaan.
          `break-word` riittaa, ja se on tassa ainoa oikea: `anywhere`
          pienentaisi myos otsikon min-content-koon, jolloin ruudukko antaisi
          sarakkeelle VAHEMMAN tilaa ja katko tulisi viela aikaisemmin.
          Mitattu aiemmin tassa projektissa: "Aurinkosahkoselvity / s".

   Kumpikaan ei katkaise sanaa joka mahtuu. Saanto on siis nakymaton siihen
   asti kunnes ruutu on liian kapea, ja silloin vaihtoehto ei ole ehja sana
   vaan sana joka on osittain ruudun ulkopuolella.
   -------------------------------------------------------------------------- */
h1, h2, h3, h4 {
  overflow-wrap: break-word;
}
