/* =============================================================================
   Strategia-osion ilme v2 · perusta
   =============================================================================
   Lähde: docs/strategy/ilme/mockup-v2.html + STRATEGIA-ILMEKIRJA.md.
   Mockup on totuus ulkonäöstä; tämä tiedosto on sen käännös sovellukseen.

   Yksi pinta, ei kortteja. Marginaali kertoo mitä, sisältö kertoo miten.
   Vihreä = edistyminen. Ruoste = huomio. Muste = toiminto.

   SKOOPPI: kaikki elää `.ilme`-kääreen alla, ja tokenit + paperitausta
   `.console-main:has(.ilme)`-tasolla, jotta koko sisältöalue on paperia
   mutta mikään ei vuoda muihin pintoihin. Tumma teema on PELKKÄ tokenremap
   (ilmekirja §12.3: teema on pelkkä tokenvaihto, ei komponenttisääntö).

   Tämä tiedosto poikkeaa STYLEGUIDEsta tarkoituksella ja luvalla (Kare
   20.8.2026): ilmekirja voittaa tässä osiossa. Poikkeamat on kirjattu
   docs/strategy/ilme/TOTEUTUS.md:hen.
   ========================================================================== */

/* Sticky rail liimautuu scrollportin reunaan: vierittimen oma padding-top
   jättäisi railin yläpuolelle kaistan, jossa sisältö näkyy scrollatessa.
   Pehmuste siirtyy .ilme-wrapperille. Oma sääntönsä html.new-layout-
   prefiksillä, koska layout-v2:n padding-sääntö (0,2,1) voittaisi paljaan
   :has-scopen — ja token-scope ei saa nousta samaan spesifisyyteen, ettei
   dark-remap (0,3,0) häviä sille. */
html.new-layout .console-main:has(.ilme) {
    padding-top: 0;
}

/* Tokenit tulevat globaalisti variables.css:stä — ilmeellä ei ole enää
   omaa palettia. Tässä jää vain se, mikä on tälle pinnalle ominaista:
   sisältöalue on paperia reunasta reunaan. */
.console-main:has(.ilme) {
    background: var(--paper);
}

/* ── Perusta ──────────────────────────────────────────────────────────── */

/* Upotusvariantti: sanasto ilman asettelua. V3:n strategiasivu on oma
   sivunsa omalla leveydellään, mutta sen lohkot ovat ilmeen komponentteja.
   Ilman tätä `.ilme`-kääre toisi mukanaan max-widthin ja 52 px:n reunuksen
   keskelle toista asettelua. */
.ilme.ilme--embed {
    max-width: none;
    margin: 0;
    padding: 0;
}

.ilme {
    max-width: 1060px;
    margin: 0 auto;
    padding: 26px 52px 96px;
    font: 14px/1.5 var(--sans);
    color: var(--ink);
    -webkit-font-smoothing: antialiased;
    /* Ei `font-feature-settings` lainkaan — kumpikaan aiemmin tässä ollut
       asetus ei kuulu tälle riville.

       "tnum": mockup asettaa sen bodylle, mutta Schibsted Groteskin
       tabulaarisetti leventää myös pilkun ja pisteen numeronlevyisiksi,
       jolloin leipäteksti saa rakoja välimerkkien ympärille ("toiminut , ja"
       — mitattu 153.6 vs 144.6 px). Tabulaarisuus kuuluu vain koneluvuille:
       .num ja .mono hoitavat sen.

       "ss01": jäänne Interin ajalta, jossa se vaihtoi ykkösen päätteelliseen
       muotoon. Schibsted Groteskilla asetus ei tee mitään — mitattu
       canvas-pikselidiffillä 28.8.2026: nolla eroavaa pikseliä merkkijonolle
       "Suunta.ai 1lI 0O agäö". STYLEGUIDE §6.2 ja variables.css kielsivät sen
       jo, mutta kielto ei ollut päätynyt tänne. */
}

.ilme a { color: inherit; text-decoration: none; }

.ilme button {
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    text-align: left;
}

.ilme :focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 3px;
    border-radius: 2px;
}

/* Ikonit: FA Sharp Light, aina 1 em -laatikko, väri perii tai muted.
   Tila EI ole koskaan ikoni — tilamerkit ovat CSS-geometriaa (.mk). */
.ilme i.fa-sharp {
    display: inline-block;
    width: 1.15em;
    text-align: center;
    font-size: 14px;
    line-height: 1;
    color: var(--ink-3);
    flex: none;
}

.ilme .mono {
    font-family: var(--mono);
    font-size: var(--fs-mono);   /* 12px = pienin sallittu (§6.2) */
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.ilme .num { font-variant-numeric: tabular-nums; }

/* ── Sisäinen navigaatio ──────────────────────────────────────────────
   Välilehtirivin tyyli asuu jaetussa komponentissa
   (`components/sub-tab-rail.css`) 21.8.2026 alkaen: sama rivi on
   kuudella pinnalla, ja sivukohtainen ohitus tarkoitti että viisi muuta
   jäivät vanhaan ilmeeseen. Vain pinnan oma poikkeus jää tänne. */
.ilme .sub-tab-rail .smp-tabs__pending {
    color: var(--ink-3);
    opacity: .45;
}

/* Sivun vaihto: sisältö nousee 3 px ja häivyttyy sisään. Ainoa sivutason
   liike (ilmekirja P8). */
.ilme .view { animation: ilme-in .35s var(--ease) both; }
@keyframes ilme-in {
    from { opacity: 0; transform: translateY(3px); }
    to   { opacity: 1; transform: none; }
}

/* ── Sivuotsikko ──────────────────────────────────────────────────────── */

.ilme .ph {
    display: grid;
    grid-template-columns: 168px 1fr auto;
    gap: 0 32px;
    padding: 38px 0 8px;
    align-items: start;
}

.ilme .ph > .mono { padding-top: 8px; }

.ilme .ph h1 {
    margin: 0;
    font-size: 28px;
    line-height: 1.2;
    font-weight: 500;
    letter-spacing: -.022em;
    max-width: 24ch;
}

.ilme .ph h1.title { font-weight: 600; max-width: none; }
.ilme .ph h1.title span { color: var(--ink-3); font-weight: 400; }

.ilme .ph .meta {
    margin-top: 10px;
    color: var(--ink-3);
    font-size: 13px;
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
}

/* Luvut tasautuvat ARVOISSA, ei koko meta-rivillä.

   `tnum` koko rivillä varaa jokaiselle numerolle saman levyisen ruudun, ja
   numeroa seuraava välimerkki saa ruudun ylijäämän: "Talousarviovuosi 2026 ,"
   luki rakona ennen pilkkua. Vika on dokumentoitu (STYLEGUIDE §6.2, P11)
   mutta sen välttäminen jäi jokaisen kutsupaikan muistin varaan. Nyt
   meta-rivin kielioppi hoitaa sen: selite on proosaa, arvo on luku. */
.ilme .ph .meta b {
    color: var(--ink-2);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.ilme .ph .acts { display: flex; gap: 10px; padding-top: 4px; }

.ilme .ph p.intro {
    margin: 10px 0 0;
    color: var(--ink-2);
    max-width: 58ch;
    line-height: 1.55;
}

/* ── Painikkeet ja linkit ─────────────────────────────────────────────── */

.ilme .btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 36px;
    padding: 0 14px;
    border-radius: 6px;
    font-weight: 500;
    font-size: 13.5px;
    background: var(--ink);
    color: var(--paper);
    white-space: nowrap;
    transition: background .15s var(--ease), transform .15s var(--ease);
}

.ilme .btn:hover { background: var(--btn-hover); }
.ilme .btn:active { transform: translateY(1px); }
.ilme .btn:disabled { opacity: .4; cursor: default; }
.ilme .btn:disabled:hover { background: var(--ink); }
.ilme .btn:disabled:active { transform: none; }
.ilme .btn i.fa-sharp { font-size: 13px; color: inherit; opacity: .85; }

.ilme .btn.sec {
    background: var(--paper);
    color: var(--ink);
    box-shadow: inset 0 0 0 1px var(--line);
}

.ilme .btn.sec:hover { background: var(--wash); }
.ilme .btn.sec i.fa-sharp { color: var(--ink-2); }
.ilme .btn.sm { height: 30px; padding: 0 11px; font-size: 13px; }

.ilme .lnk { font-weight: 500; color: var(--ink); white-space: nowrap; }
.ilme .lnk::after { content: " →"; color: var(--ink-3); transition: color .15s var(--ease); }
.ilme .lnk:hover::after { color: var(--ink); }
.ilme .lnk.q { color: var(--ink-3); }
.ilme .lnk.q:hover { color: var(--ink); }

/* ==========================================
   RIVIN SISÄINEN SYÖTE JA VALITSIN
   ==========================================
   `.inp` ja `.sel` olivat käytössä Aineistot-sivulla ILMAN yhtäkään
   sääntöä: selain piirsi ne omilla oletuksillaan (22 px korkeus,
   `inset 2px` -reuna, selaimen oma harmaa tausta tummalla). Ne olivat
   ainoa kohta koko migroidulla pinnalla joka ei näyttänyt sovellukselta.

   MITTA POIKKEAA §11:n lomakekentästä, ja se on tietoinen: §11 määrää
   syötteelle 40 px, mutta se koskee Asetusten kenttäryhmiä joissa kenttä
   on rivin pääsisältö. Nämä ovat rivin SISÄISIÄ kontrolleja — mitattu
   24.8.2026: aineistorivi on 49 px, joten 40 px:n kenttä täyttäisi sen
   kokonaan ja pakottaisi rivin korkeammaksi. 32 px mahtuu riviin ja
   täyttää silti kosketuskohteen minimin (§6). Ristiriita on kirjattu
   STYLEGUIDE §11:een. */
.ilme .inp,
.ilme .sel {
    min-height: 32px;
    padding: 0 var(--space-2);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--radius-field);
    font: 400 13px var(--sans);
    color: var(--ink);
    transition: border-color .15s var(--ease);
}
.ilme .inp { width: 100%; }
.ilme .inp::placeholder { color: var(--ink-3); }

/* Hiljainen variantti: kenttä joka on tyhjä lähes aina eikä saa kilpailla
   rivin sisällön kanssa ennen kuin siihen kosketaan. */
.ilme .inp.q,
.ilme .sel.q {
    background: transparent;
    border-color: transparent;
    color: var(--ink-2);
}
.ilme .inp.q:hover,
.ilme .sel.q:hover,
.ilme .inp:hover,
.ilme .sel:hover { border-color: var(--ink-3); }

.ilme .inp:focus-visible,
.ilme .sel:focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 1px;
    border-color: var(--ink-3);
}
/* Fokuksessa hiljainen kenttä näyttää kentältä. */
.ilme .inp.q:focus,
.ilme .sel.q:focus {
    background: var(--paper);
    border-color: var(--ink-3);
    color: var(--ink);
}

/* Tekstivalitsin lomakkeessa (§11.7): kahden tai kolmen arvon valinta
   sanoina, ei valintaruutu eikä kytkin. Radiot ovat natiiveja ja
   piilotettu vain visuaalisesti, joten nuolinäppäimet ja lomakkeen
   lähetys toimivat ilman JS:ää. Valittu on 600 + 1,5 px alaviiva
   musteella; fokus vihreä kuten kaikkialla. */
.ilme .tsel {
    display: flex;
    flex-wrap: wrap;
    gap: 0 20px;
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 13px;
}
.ilme .tsel input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}
.ilme .tsel label {
    display: inline-flex;
    align-items: center;
    min-height: var(--touch-target-min, 32px);
    color: var(--ink-3);
    padding-bottom: 1px;
    border-bottom: 1.5px solid transparent;
    cursor: pointer;
    transition: color .15s var(--ease);
}
.ilme .tsel label:hover { color: var(--ink); }
.ilme .tsel input:checked + label {
    color: var(--ink);
    font-weight: 600;
    border-bottom-color: var(--ink);
}
.ilme .tsel input:focus-visible + label {
    outline: 2px solid var(--green);
    outline-offset: 3px;
    border-radius: 2px;
}

/* Toissijainen rivitoiminto näkyy vasta hoverissa tai fokuksessa (P5). */
.ilme .ghost { opacity: 0; transition: opacity .15s var(--ease); }

/* Ghost-toiminnot (Irrota, Poista, +) eivät saa .lnk-luokan nuolta:
   nuoli tarkoittaa siirtymää, nämä ovat toimintoja. "+ →" oli kaksi
   merkkiä yhdelle toiminnolle. */
.ilme .ghost.lnk.q::after { content: none; }

/* SAMA SÄÄNTÖ KAIKILLE PAINIKKEILLE, ei vain ghosteille.
   `<button>` ei koskaan ole siirtymä: se tekee jotain tällä sivulla.
   Sääntö oli ghost-kohtainen, ja siksi rungon "Jätä pois" ja "Palauta"
   piirsivät nuolen — merkki lupasi navigointia jota ei tapahdu. */
.ilme button.lnk::after { content: none; }

/* JA KAIKKI MIKÄ ON GHOST-RYHMÄN SISÄLLÄ. Ryhmä on rivin toimintojoukko;
   sen sisällä oleva linkki (esim. "nimeä") on toiminto siinä missä
   painikekin. Sääntö osui vain `.ghost`iin itseensä, joten ryhmän sisällä
   oleva `<a class="lnk">` piirsi nuolen — merkki lupasi siirtymää keskellä
   toimintorivistöä. */
.ilme .ghost .lnk::after { content: none; }

/* Plus-toiminto ("aloita tämä"): hieman isompi merkki ja kasvatettu
   klikkialue ilman että layout liikahtaa. */
.ilme .ghost.plus {
    font-size: 15px;
    padding: 6px 10px;
    margin: -6px -10px;
}
.ilme .row:hover .ghost,
.ilme .goal:hover .ghost,
.ilme .area:hover .ghost,
.ilme .rule:hover .ghost,
.ilme .file:hover .ghost,
.ilme .member:hover .ghost,
.ilme .unit-h:hover .ghost,
.ilme :focus-within > .ghost,
.ilme .ghost:focus-visible { opacity: 1; }

/* KOSKETUSLAITTEELLA EI OLE HOVERIA, joten hoverin takana oleva toiminto ei
   ole olemassa. Mitattu 24.8.2026 kosketusemulaatiolla (375 px): Aineistot-
   sivun kolme "Poista"-toimintoa laskivat `opacity: 0` — dokumenttia ei
   voinut poistaa puhelimella lainkaan. Ne olivat teknisesti klikattavia,
   mutta näkymätön toiminto ei ole toiminto.

   Sama koskee hiljaista kenttää: sen reuna paljastuu hoverissa, eikä
   kosketuksella siis koskaan.

   Toiminnot pysyvät hiljaisina (`.lnk.q` on `--ink-3`), joten rivi ei muutu
   meluisaksi — ne vain ovat olemassa. */
@media (hover: none) and (pointer: coarse) {
    .ilme .ghost { opacity: 1; }
    .ilme .inp.q,
    .ilme .sel.q { border-color: var(--line); }
    /* Rivitoiminto on 21 px korkea tekstilinkki, eli alle kosketuskohteen
       minimin (§14). Osumapinta kasvatetaan padding + negatiivinen
       marginaali -parilla, jolloin layout ei liikahda — sama temppu kuin
       `.ghost.plus`illa ja `.icon-rail__home`illa jo on.

       KOSKEE KAIKKIA `.lnk`ejä eikä vain ghostia (laajennettu 28.8.2026).
       Mitattu iPad landscape -profiilissa (1180 × 750, kosketus): sivun
       "Aloita" ja "Seuraavaksi" olivat 20 px korkeita, eli 3,8 mm iPadin
       pikselitiheydellä kun sormenpää on 8–10 mm. `.ghost` oli niistä
       vähemmistö.

       Pystysuunta tokenista, vaakasuunta kiinteä 8 px. Kaksi vierekkäistä
       rivitoimintoa ("Avaa · Poista") ovat tyypillisesti 12 px päässä
       toisistaan, ja tokenin mittainen vaakakasvu tekisi niiden
       osumapinnoista päällekkäiset. Pystykasvu on se joka tässä ratkaisee.

       `padding-block` inline-elementillä EI kasvata riviä mutta kasvattaa
       osumapintaa: inline-laatikon reunalaatikko ottaa osoittimen vastaan,
       vaikka se vuotaa rivilaatikon yli. Siksi layout pysyy paikallaan
       ilman negatiivista pystymarginaalia (jolla ei inlinessä olisi
       vaikutusta muutenkaan). */
    .ilme .lnk,
    .ilme .ghost.lnk {
        /* `min-height` EIKÄ laskettu `padding-block`. Ensimmäinen versio
           laski pehmusteen oletuksesta "sisältölaatikko on 20 px", ja se
           piti paikkansa useimmilla mutta ei kaikilla: Toteutuksen
           "Koko organisaatio" -linkin sisältö on 18 px, jolloin kaava
           tuotti 42 px eli kaksi pikseliä vajaan. Mitattu 29.8.2026.

           Oletus sisällön korkeudesta on väärä muoto: minimi pitää
           VAATIA, ei laskea. `inline-flex` on se mikä tekee
           `min-height`istä voimassa olevan inline-elementille, ja
           `.lnk` on jo `white-space: nowrap` joten se ei rivity
           sisäisesti — kirjoitussuunta ja rivitys eivät muutu. */
        display: inline-flex;
        align-items: center;
        min-height: var(--touch-target-min);
        padding-inline: 8px;
        margin-inline: -8px;
    }
}

/* ── Matala näyttö: pystyrytmi tiivistyy, typografia ei ───────────────
   iPad landscape on 1180 × 750 (Safarin viewport 11 tuuman laitteella).
   Sivuotsikko on mitoitettu 900 px korkealle ikkunalle: mitattu 28.8.2026
   strategian etusivulla, ensimmäinen sisältörivi alkoi 304 px kohdalta eli
   41 % näytöstä oli kromia ennen ensimmäistä riviä. Työpöydällä (900 px)
   sama on 34 %.

   Tiivistetään VÄLIT, ei typografiaa. Sama periaate kuin kapealla näytöllä
   jo on — `variables.css` osa 2 pienentää `--fs-lead`in ja `--fs-statement`in
   760 px:ssä — mutta toisin päin: pystysuunnassa loppuu rytmi, ei rivin
   leveys, joten pistekoko saa jäädä rauhaan.

   KORKEUS EIKÄ OSOITIN on tässä oikea akseli. Matala ikkuna työpöydällä
   kärsii samasta, ja pystyyn käännetyllä iPadilla ongelmaa ei ole vaikka
   osoitin on yhtä karkea. `min-width: 1024px` rajaa mobiilin ulkopuolelle:
   sillä on oma pystyrytminsä (MOBILE-DESIGN §A2) jonka päälle tämä ei saa
   mennä.

   AVOIN: sivuotsikon tekstilohko on 150 px (h1 + johtolause), eikä sitä
   tiivistetä tässä. Johtolause on väite tilasta ja ilmeen ydintä, eikä
   ilmekirjassa ole tablettisivua jota vasten sen voisi mitoittaa. Ristiriita
   kirjattu, ei arvattu: docs/console/IPAD-LANDSCAPE.md §4 vaihe 3. */
@media (min-width: 1024px) and (max-height: 820px) {
    .ilme { padding-top: var(--space-3); }
    .ilme .ph { padding-top: var(--space-4); }
    .ilme .sub-tab-rail { margin-bottom: var(--space-4); }
}

/* ── Lohko: marginaali + sisältö ─────────────────────────────────────── */

/* Lohko voi olla ankkurin kohde (esim. Minä-korkeuden "Katso luopumiset").
   Ilman `scroll-margin-top`ia hyppy laskeutuu kiinnittyvän välilehtirivin
   (`.sub-tab-rail`, position: sticky) alle ja lohkon otsikko jää piiloon.
   Sama sääntö kuin `.goal`illa. */
.ilme .blk {
    /* Ankkurimarginaali seuraa VALILEHTIRIVIN korkeutta, eika ole kiinteä
       48 px. Rivi on `position: sticky; top: 0`, ja sen korkeus on
       välilehden korkeus + 6 px pehmuste + 1 px viiva — eli se kasvaa
       tokenin mukana: 43 px hiirellä, 50 px sormella (mitattu 29.8.2026).
       Kiinteä 48 px jätti kosketuksella 2 px lohkon yläreunasta rivin alle.
       Kaava antaa 48 px hiirellä (sama kuin ennen) ja 60 px sormella. */
    scroll-margin-top: calc(var(--touch-target-min) + var(--space-4));
    display: grid;
    grid-template-columns: 168px 1fr;
    gap: 0 32px;
    padding: 30px 0 34px;
    border-top: 1px solid var(--line);
}

.ilme .blk.first { border-top: 0; }
/* Marginaalin rytmi on välitokeneilla, ei silmämääräisillä pikseleillä.
   Asteikko on 4 · 8 · 12 · 16 · 24 · 32 · 48, ja marginaali käyttää siitä
   kolmea pienintä: otsikko → 4 → alarivi → 12 → selite → 16 → toiminto.
   Aiemmat 3 / 10 / 14 px olivat kolme lukua asteikon ulkopuolelta, eivätkä
   ne osuneet sisältösarakkeen rytmiin millään kohdalla.

   `padding-top` kohdistaa monon versaalikorkeuden sisällön ensimmäiseen
   riviin; se on optinen eikä rakenteellinen, mutta 4 px osuu asteikkoon
   yhtä hyvin kuin 3.

   Sääntö itse on alempana `.kv`-lohkossa: se koskee sekä lohkon
   marginaalia että tietorivin avainta, ja yksi sääntö kahdelle on
   parempi kuin kaksi jotka ajautuvat erilleen. */

.ilme .lbl .n {
    font: 400 var(--fs-mono) var(--mono);
    color: var(--ink-3);
    margin-top: var(--space-1);
    display: block;
    letter-spacing: .02em;
    text-transform: none;
}

/* Selite on marginaalin ainoa proosa: kaksi riviä sen yllä ovat monoa
   (`.mono` versaali, `.n` gemena), ja tämä on se lause jonka ihminen
   lukee. Siksi se on sansia — ja siksi sen on oltava vähintään 13 px
   (§6.2). 12,5 px eli tässä 3.9.2026 asti, eikä se ollut edes §6.1:n
   asteikon askel: arvo oli yhtä aikaa säännön alapuolella ja asteikon
   ulkopuolella.

   MONOKSI VAIHTAMINEN olisi ollut toinen tapa täyttää sääntö, ja se on
   väärä: mono vie 168 px:ssä ~22 merkkiä riville sansin ~26:n sijaan,
   eli selitteen budjetti pienenisi kolmanneksella. Marginaali olisi myös
   yhtä ainoaa kirjasinta ylhäältä alas, jolloin §11.2:n kolmiosainen
   sanasto (otsikko · alarivi · selite) erottuisi enää kirjainkoosta.

   MITATTU SELAIMESSA 3.9.2026, 168 px sarake, kaikki 630 tuotannon
   selitettä (37 avainta × 18 kieltä): 555 pitää rivimääränsä, 75 saa
   yhden rivin lisää, yksikään ei saa kahta. Kolmen rivin mittaan
   (§11.2) mahtuu 12,5 px:llä ~80 ja 13 px:llä ~78 merkkiä, eli
   dokumentoitu 78 merkin katto pitää täsmälleen.

   HUOM: kattoa rikkoi jo ENNEN tätä muutosta 117 selitettä 630:stä
   (13 px:llä 136). Se on tekstin pituuden ongelma, ei pistekoon, eikä
   `tests/i18n/test_margin_fits_column.py` näe niistä valtaosaa: se
   lukee vain `pages/strategy_model/*.html` ja `strategy_model.json`. */
.ilme :is(.blk, .kv) > .lbl .note {
    font-family: var(--sans);
    font-size: var(--fs-meta);
    color: var(--ink-3);
    margin-top: var(--space-3);
    line-height: 1.5;
    text-transform: none;
    letter-spacing: 0;
    display: block;
}

.ilme :is(.blk, .kv) > .lbl .act {
    margin-top: var(--space-4);
    display: inline-block;
}

/* ── Tietorivi `.kv` ──────────────────────────────────────────────
   Kenttä ja sen arvo, korjattavissa napauttamalla.

   MIKSI TÄMÄ ON KOMPONENTTI. Sama rivi oli toteutettu NELJÄSTI eri
   sanastolla: `.rgc-row` (rekisteröinnin vahvistusnäyttö), `.ea-rrow`
   (alkukartoituksen lähtökuva), `.ek-row` (Organisaatio-välilehti) ja
   `.tm-profile__row` (Tiimi). Ne erosivat geometrialtaan (200 px vs
   168 px), tyypografialtaan (13 px sans vs 12 px mono) ja siinä mitkä
   niistä olivat muokattavia. Yksi kirjoitettiin mockupista
   (`ilmekirja/luonnos-rekisterointi.html` `.prow`, marginaalimallipäätös
   25.8.2026) ja kolme keksittiin uudelleen.

   Geometria on `.blk`in ruudukko sellaisenaan: 168 px marginaali kertoo
   MITÄ, sisältösarake MITEN. Rivi ei siis ole oma mittansa vaan lohkon
   rytmi pienempänä.

   Marginaalin sanasto on §11.2:n, ei uusi: `.mono` avain · `.n`
   provenienssi · `.note` selite. Siksi `test_margin_fits_column.py`
   mittaa nämä rivit automaattisesti. */

.ilme .kvs { border-top: 1px solid var(--line); }

.ilme .kv {
    display: grid;
    grid-template-columns: 168px 1fr;
    gap: 0 var(--space-8);
    padding: 13px 0 14px;
    border-bottom: 1px solid var(--line-2);
    align-items: start;
}

/* Arvosarake. 14,5 px on `.rgc-row__v`:n mitta: se on sisällön kokoa,
   ei otsikon — rivi on asiakirjan rivi eikä lomakekenttä. */
.ilme .kv > .v {
    font-size: 14.5px;
    line-height: 1.45;
    color: var(--ink);
    min-width: 0;
}

/* Tyhjä arvo on hiljainen mutta ei näkymätön: se on kysymys jota ei ole
   kysytty, ja sen pitää näyttää siltä että siihen voi vastata. */
.ilme .kv > .v .empty { color: var(--ink-3); }

/* NAPAUTETTAVA ARVO ON `<button>`, EI `<span role="button">`.
   Nappi saa Enterin ja välilyönnin ilmaiseksi ja on oikea AT-solmu;
   käsinkirjoitettu näppäinkäsittely oli `step-confirm.js`n neljä riviä
   joita ei tarvita.

   Ei painikkeen näköinen: negatiivinen marginaali kumoaa pehmusteen,
   joten teksti on samassa linjassa kuin ei-muokattava arvo eikä rivi
   hyppää kun kenttä muuttuu muokattavaksi. Hover on väri, ei nosto.

   SAMA NAPPI JÄSENRIVILLÄ JA YKSIKÖN OTSIKOSSA (`IlmeKV.attach`, 9/2026):
   solu on kutsujan, editori on tämä. Ilman jaettua sääntöä Tiimi-sivu
   olisi kirjoittanut viidennen `.edit`in. */
.ilme :is(.kv, .member, .unit-h) .edit {
    /* KORKEUS ON SAMA KUIN AUKI OLEVALLA KENTÄLLÄ, JA SE ON KAKSI ASIAA.
       1) Kosketuskohde: mitattu 25 px pelkällä pehmusteella, eli alle
          32 px:n minimin (STYLEGUIDE, saavutettavuus).
       2) Rivi ei hyppää: `.inp` ja `.sel` ovat 32 px, joten editorin
          avaaminen ei enää siirrä alla olevia rivejä seitsemää pikseliä
          alaspäin. Layout-shift on halvin korjata siinä kohdassa jossa
          se syntyy. */
    display: inline-flex;
    align-items: center;
    min-height: var(--touch-target-min, 32px);
    max-width: 100%;
    padding: 2px 6px;
    margin: 0 -6px;
    border: 0;
    border-radius: var(--radius-field);
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: text;
    transition: background .15s var(--ease);
}
.ilme :is(.kv, .member, .unit-h) .edit:hover { background: var(--wash); }
.ilme :is(.kv, .member, .unit-h) .edit:focus-visible {
    outline: 2px solid var(--green);
    outline-offset: 2px;
}
/* Solun sisällä avautuva kenttä perii `.inp`/`.sel`-mitat; leveys on
   solun, ei sisällön, jotta rivi ei levene avattaessa. */
.ilme :is(.member, .unit-h) .inp,
.ilme :is(.member, .unit-h) .sel { max-width: 100%; }

/* Auki oleva editori perii `.inp` / `.sel` -mitat (32 px, §11.10).
   Korkeutta EI aseteta tässä: `confirm.css` asetti 34 px ja se oli
   ainoa paikka koko ilmeessä jossa rivin sisäinen kenttä poikkesi. */
.ilme .kv .inp,
/* Rivi jolla ei ole ovea: arvo näkyy, mutta mikään ei lupaa napautusta.
   `preset` on tällainen — se kirjoitetaan rekisteröinnissä eikä sitä kysy
   yksikään ruutu. Sama geometria kuin `.edit`illä, ei osoitinta eikä
   hoveria: ero on vuorovaikutuksessa, ei asettelussa. */
.ilme .kv .edit--static { cursor: default; }
.ilme .kv .edit--static:hover { background: none; }

.ilme .kv .sel { max-width: 320px; }
/* Valitsin mitoittui sisältöönsä ja oli 78 px "11-50":llä — rivi näytti
   ryppyiseltä tekstikentän (320 px) vieressä. Mitta on sisällön eikä
   kontrollin: sanaston pisin arvo mahtuu, lyhyin ei kutistu. */
.ilme .kv .sel { min-width: 180px; }
.ilme .kv .inp[type="number"] { max-width: 7em; }

/* LATAUTUVA RIVI ON `.kv`, EI KOPIO SIITÄ.
   `confirm.css` kalibroi luurangon kahdesti käsin (ensin 49 px, sitten
   60 px) koska geometria oli kirjoitettu kahteen paikkaan. Korkeus tulee
   nyt samasta `--touch-target-min`ista kuin `.edit`illä, joten luuranko
   ja valmis rivi ovat saman säännön kaksi tilaa eivätkä voi ajautua
   erilleen. Lataus on hiusviivoja, ei shimmeriä (§13.3); viivojen
   leveydet ja rytmi ovat pinnan omaa sanastoa eivätkä kuulu tänne. */
/* RIVI KANTAA SIVUN MARGINAALIN ITSE.
   Kaksi eri emoa: kausimallin sivuilla rivi on `.ilme`n sisalla ja saa
   marginaalin silta, mutta V3:n sivuilla se on `console-main`in suora
   lapsi. Ilman tata ensimmainen valilehti oli mobiilissa kiinni ruudun
   vasemmassa reunassa (mitattu 375 px: ikoni x=2). Sisennys kumotaan
   siella missa emo jo antaa sen — muuten se kaksinkertaistuisi. */
/* Tarkkuus on `.sub-tab-rail.smp-tabs` eika `.smp-tabs`: jaettu
   `sub-tab-rail.css` asettaa `padding: 0` samalla tarkkuudella ja voittaa
   kaskadissa (se ladataan myohemmin). Mitattu: saanto oli ladattu mutta
   laskettu pehmuste oli 0. */
.sub-tab-rail.smp-tabs {
    max-width: var(--page-max);
    margin-inline: auto;
    padding-inline: var(--page-gutter);
}
.ilme > .sub-tab-rail.smp-tabs {
    max-width: none;
    padding-inline: 0;
}

/* V3:n sivut: rivi on `console-main`in suora lapsi, ja sen alla oleva
   sisalto on `.s3-page`ssa jonka sisennys on 24 px eika `.ilme`n 52 px.
   Rivi asettuu SEN sivun sisaltoon jolla se on — mitattu 1440 px:lla:
   sisalto alkoi 244 px:sta ja rivi 272 px:sta, eli 28 px sisempaa.
   Ero katoaa cutoverissa kun V3:n sivut siirtyvat `.ilme`en. */
.console-main > .sub-tab-rail.smp-tabs { padding-inline: 24px; }

@media (max-width: 760px) {
    .sub-tab-rail.smp-tabs {
        padding-inline: var(--console-page-gutter-mobile);
    }
    .ilme > .sub-tab-rail.smp-tabs { padding-inline: 0; }
}

.ilme .kv--wait > i {
    display: flex;
    align-items: center;
    min-height: var(--touch-target-min, 32px);
}
.ilme .kv--wait > i::before {
    content: "";
    display: block;
    width: 100%;
    height: 1px;
    background: var(--line-2);
}

/* ── Strategia-osion välilehtirivi ────────────────────────────────────
   Kaksi pintaa käyttää samaa riviä: kausimallin seitsemän sivua ja yhden
   strategian sivu, joka renderöityy V3:n assettien kanssa. Säännöt asuvat
   täällä koska tämä on ainoa tiedosto jonka MOLEMMAT lataavat — kausimalli
   suoraan, V3 bundlen ensimmäisenä lähteenä. Perustelut mitoille ovat
   sääntöjen omissa kommenteissa. */
.smp-tabs {
    margin-bottom: var(--space-8);
}

/* SEITSEMÄN VÄLILEHTEÄ, EI YHTÄÄN KATKAISTUA SANAA.

   "Muisti ja päätökset" kutistui flexissä 138 px:iin ja katkesi kahdelle
   riville, jolloin koko rivi kasvoi 37 px:stä 51 px:iin ja perusviiva
   siirtyi. Yksi kaksirivinen välilehti kuudesta yksirivisestä näyttää
   virheeltä, ja se on virhe.

   Mitattu 800 px:n ikkunassa: nimet 700 px + kuusi 28 px:n väliä = 868 px
   kun tilaa on 844. Nimeä ei lyhennetä (termi on päätetty), joten väli
   kapenee siellä missä se ei mahdu. Alle 640 px rivi vierii jo
   `sub-tab-rail`in omalla säännöllä. */
.smp-tabs .sub-tab-rail__tab { white-space: nowrap; }

/* Väli on 24 px eikä 28 px: seitsemän välilehteä ylitti rivin 14 px:llä
   ja viimeinen ("Organisaatio") leikkautui. Kuusi väliä × 4 px = 24 px,
   eli ylitys katoaa eikä rytmi muutu silmälle. */
.smp-tabs { gap: var(--space-6); }

@media (max-width: 1180px) {
    .smp-tabs { gap: var(--space-4); }
}

/* Viimeinen turvaverkko: jos nimet joskus kasvavat (18 kieltä), rivi
   vierii sen sijaan että leikkaisi. Leikattu välilehti on näkymätön;
   vierivä on löydettävissä. */
.smp-tabs {
    overflow-x: auto;
    scrollbar-width: none;
}

.smp-tabs::-webkit-scrollbar { display: none; }

/* Rakentamaton välilehti: näkyvä mutta ei kutsu klikkaamaan. Ei kursoria,
   ei hoveria, ei fokusta — se on rakenteen kuva, ei toiminto. */
.smp-tabs__pending {
    opacity: 0.4;
    cursor: default;
    pointer-events: none;
}

/* Marginaalin sanasto toimii myös rivillä, ei vain lohkossa. Sama
   sääntö, ei kopiota: kaksi määrittelyä ajautuisi erilleen. */
.ilme :is(.blk, .kv) > .lbl { padding-top: var(--space-1); }
.ilme :is(.blk, .kv) > .lbl .mono { display: block; }

/* Tilamerkki arvosarakkeessa. `.mk.q` (ei geometriaa) ohitetulle,
   `.mk.neu` (rengas) kysymättä jääneelle — ohitettu on VASTAUS eikä
   aukko, ja vain aukko saa merkin. */
.ilme .kv .mk { vertical-align: baseline; }

.ilme .blk h2 {
    margin: 0 0 18px;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.015em;
}

/* Lohkon kappale: oletusväri on --ink-2, mutta se EI saa voittaa
   elementtitason tahtoa. Ennen tämä oli yhtenä sääntönä, jolloin
   `.ilme .blk p` (0,2,1) voitti jokaisen `.ilme .<luokka>` (0,2,0)
   -säännön: strategialause pyysi mustetta ja sai harmaan, ja sama koski
   jokaista kappaletta jolle joku oli antanut oman värin. Ilmeen sääntö 6
   sanoo kolme tekstitasoa; käytössä oli kaksi.

   `:where()` on nollaspesifisyyksinen, joten oletus säilyy ja mikä tahansa
   luokka voittaa sen. Marginaali ja riviväli jäävät omaan sääntöönsä,
   koska ne EIVÄT ole tahdonalaisia — ne ovat lohkon rytmiä. */
.ilme .blk p { margin: 0; line-height: 1.55; }
:where(.ilme .blk) p { color: var(--ink-2); }

/* Display-teksti on rytmin ulkopuolella.

   Yllä oleva perustelu pitää — riviväli ON lohkon rytmiä — mutta se koskee
   lohkon KAPPALEITA. Strategialause ja oppi ovat display-tekstiä, ja ne
   asettavat oman rivivälinsä. Se ei ole mennyt koskaan läpi: `.ilme .blk p`
   (0,2,1) voittaa `.ilme .statement`in (0,2,0), joten §6.1:n lupaama 1.22
   oli kuollutta koodia ja lause piirtyi 1.55:llä. Mitattu 28.8.2026: lyhyt
   lause 32 px oli 149 px kun sen olisi pitänyt olla 117 px. Sama koski
   `.oppi`a. Oire oli petollinen, koska mikään ei näyttänyt rikkinäiseltä —
   lause vain luki kappaleena eikä väitteenä.

   Ensimmäinen valitsin kummassakin parissa on 0,2,2 ja voittaa
   järjestyksestä riippumatta; toinen kattaa `.blk`in ulkopuolisen
   esiintymän (esim. `.ilme .view .statement` toteutuspinnalla). */
.ilme .blk p.statement, .ilme p.statement,
.ilme .blk p.oppi,      .ilme p.oppi {
    line-height: var(--lh-snug);
}

.ilme .blk p.big {
    font-size: 17px;
    color: var(--ink);
    max-width: 60ch;
    line-height: 1.45;
}

/* Painotettu kappale: 2 px sääntö vasemmalla, väri = merkitys. Ainoa
   nostolaite koko osiossa — ei laatikoita, ei taustoja. */
.ilme .rule { border-left: 2px solid var(--rust); padding-left: 18px; }
.ilme .rule.g { border-color: var(--green); }

/* Toiminto säännön sisällä. `.rule` isännöi jo painikkeita muualla
   (`_integrations_automation.html`), mutta väli tuli sielläkin kääreen
   omasta luokasta. Sääntö on tässä, jotta jokainen `.rule`in toiminto saa
   saman raon eikä yksikään sivu keksi omaansa. Sama 12 px kuin `.who`lla. */
.ilme .rule form { margin-top: var(--space-3); }

.ilme .rule .who {
    margin-top: 12px;
    display: flex;
    gap: 14px;
    align-items: center;
    font-size: var(--fs-meta);
    color: var(--ink-3);
    flex-wrap: wrap;
}

.ilme .rule .who b { color: var(--ink-2); font-weight: 500; }

/* Strategialause ja oppi: ainoat serif-kursiivin paikat (P6). */
.ilme .statement {
    /* Koko tulee tokenista, ei literaalista: token oli olemassa (myös omalla
       mobiiliarvollaan) mutta komponentti kovakoodasi 38 px, joten ne olivat
       ajautuneet erilleen ilman että kumpikaan oli väärin yksin. */
    /* Riviväli omana ilmoituksenaan eikä `font`-lyhenteessä: lyhenne
       nollaisi sen `normal`iksi, ja arvo kuuluu tokeniin (--lh-snug 1.32).
       Kare valitsi 1.32:n mitatusta kuudesta yhdistelmästä 28.8.2026
       (`_statement_style_harness.html`): 1.55 luki kappaleena, 1.22 oli
       kuudella rivillä ahdas. */
    font: italic var(--serif-weight) var(--fs-statement) var(--serif);
    line-height: var(--lh-snug);
    letter-spacing: -.008em;
    color: var(--ink);
    margin: 0;
    max-width: 34ch;
    /* Optinen koko seuraa pistekokoa: Newsreader piirtää 36 pisteen kirjaimet
       ohuemmilla päätteillä kuin 32 pisteen. Väärä opsz ei näy virheenä vaan
       laimeana lauseena. */
    font-variation-settings: "opsz" 32;
}

/* Pitkä lause: pistekoko pienenee JA mitta kasvaa merkkeinä, niin että
   palstan pikselileveys pysyy samana (~635 px) ja vain rivitiheys muuttuu.
   Pelkkä pistekoon pienennys ei auttaisi: `ch` skaalautuu pistekoon mukana,
   joten rivimäärä pysyisi vakiona ja lohko vain kapenisi.

   Mitattu 25.8.2026 (1440 px, Newsreader): 353 merkin tuotantolause oli
   32 px:llä 8 riviä ja 397 px korkea — kolme kertaa ilmekirjan referenssin
   (109 merkkiä, 149 px). Portaan rajat ja perustelu:
   app/utils/statement_scale.py; vartija tests/unit/ui/test_statement_scale.py. */
/* Portaat pienentävät pistekokoa, EIVÄT vaihda tyyliä.

   28.8.2026 nämä olivat hetken pystyä: kuusi riviä kursiivia luki
   tekstuurina eikä väitteenä, ja pysty korjasi sen. Korjasi väärän asian.
   Todellinen syy oli riviväli — `.ilme .blk p` voitti lauseen oman arvon,
   joten lause ladottiin display-koossa leipätekstin rytmillä (ks. sääntö
   `.ilme p.statement` ylempänä). Kun riviväli on 1.32, kursiivi lukee
   kappaleenakin, ja Kare valitsi sen mitatusta kuudesta yhdistelmästä
   (`app/static/_statement_style_harness.html`).

   Oppi joka kannattaa säilyttää: kursiivin ja pystyn välillä ei ole
   korkeuseroa (kaikki viisi mitattua pituutta antoivat 0 px), mutta pysty
   on ~5 % leveämpi merkkiä kohti (22 px: 405.82 vs 387.47 px samalle
   merkkijonolle). Jos portaat joskus käännetään pystyyn, `fonts.css`iin on
   lisättävä Newsreaderin pystyleikkaus — ilman sitä `font-style: normal` on
   tyhjä käsky, koska CSS:n kirjasinhaku tarjoilee kursiivin vaieten.
   Yhden komennon työ: `python3 scripts/ui/fetch_fonts.py`. */
.ilme .statement--l {
    font-size: var(--fs-statement-long);
    max-width: 42ch;
    font-variation-settings: "opsz" 26;
}

.ilme .statement--xl {
    font-size: var(--fs-statement-xlong);
    max-width: 50ch;
    font-variation-settings: "opsz" 22;
}

.ilme .oppi {
    font: italic var(--serif-weight) 27px/1.32 var(--serif);
    color: var(--ink);
    margin: 0;
    max-width: 40ch;
    font-variation-settings: "opsz" 28;
}

/* ── Kausiviivain · kuukausiruudut, ei jatkuvaa palkkia ──────────────── */

.ilme .ruler {
    padding: 30px 0 22px;
    border-top: 1px solid var(--line);
    display: grid;
    grid-template-columns: 168px 1fr;
    gap: 0 32px;
}

.ilme .ruler .lbl { padding-top: 18px; }
.ilme .rul { position: relative; }

.ilme .rul .yrs {
    display: grid;
    grid-template-columns: repeat(var(--cols, 36), 1fr);
    gap: 3px;
    margin-bottom: 6px;
}

.ilme .rul .yrs span {
    font: 500 var(--fs-mono) var(--mono);
    color: var(--ink-3);
    letter-spacing: .04em;
    border-left: 1px solid var(--line);
    padding-left: 6px;
    line-height: 1;
}

.ilme .rul .cells {
    display: grid;
    grid-template-columns: repeat(var(--cols, 36), 1fr);
    gap: 3px;
    height: 18px;
}

.ilme .rul .c {
    background: var(--line-2);
    border-radius: 1.5px;
    position: relative;
    animation: ilme-cell .3s var(--ease) both;
    animation-delay: calc(var(--i) * 16ms);
}

@keyframes ilme-cell {
    from { opacity: 0; transform: scaleY(.4); }
    to   { opacity: 1; transform: none; }
}

.ilme .rul .c.past { background: var(--past); }
.ilme .rul .c.now { background: var(--green); }
.ilme .rul .c.rev { box-shadow: inset 0 0 0 1.5px var(--ink); background: transparent; }
.ilme .rul .c.past.rev { background: var(--past); }
.ilme .rul .c.end { box-shadow: inset 0 0 0 1.5px var(--ink-3); background: transparent; }

.ilme .rul .c.ev::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -10px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--ink);
    transform: translateX(-50%);
}

.ilme .rul .c.ev.evg::after { background: var(--green); }

.ilme .rul .tags {
    display: grid;
    grid-template-columns: repeat(var(--cols, 36), 1fr);
    gap: 3px;
    margin-top: 14px;
}

.ilme .rul .tags span {
    font: 400 var(--fs-mono) var(--mono);
    color: var(--ink-3);
    white-space: nowrap;
    letter-spacing: .02em;
    position: relative;
    line-height: 1;
}

.ilme .rul .tags span.now { color: var(--green-deep); font-weight: 500; }
.ilme .rul .tags span.r { text-align: right; }

.ilme .rul .sum {
    margin-top: 22px;
    display: flex;
    gap: 22px;
    font-size: 13px;
    color: var(--ink-3);
    flex-wrap: wrap;
}

.ilme .rul .sum b { color: var(--ink); font-weight: 500; }

/* ── Tilamerkit · merkki + sana, ei pillereitä (P4) ──────────────────── */

.ilme .mk {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-weight: 500;
    font-size: 13px;
    white-space: nowrap;
}

.ilme .mk::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
}

/* Pallo = liike, rengas = avoin, neliö = lukittu myönteinen,
   vinoneliö = lukittu kielteinen. */
.ilme .mk.ok { color: var(--green-deep); }
.ilme .mk.ok::before { background: var(--green); }
.ilme .mk.warn { color: var(--rust-deep); }
.ilme .mk.warn::before { background: var(--rust); }
.ilme .mk.test { color: var(--rust-deep); }
.ilme .mk.test::before { box-shadow: inset 0 0 0 1.5px var(--rust); background: transparent; }
.ilme .mk.neu { color: var(--ink-2); }
.ilme .mk.neu::before { box-shadow: inset 0 0 0 1.5px var(--ink-4); background: transparent; }
.ilme .mk.done { color: var(--green-deep); }
/* HUOM · .done on sanastossa (ilmekirja §11.5: neliö, vihreä) mutta se ei
   ole oletus vahvistukselle. Terve rivi on hiljainen (P11): "Piti
   paikkansa", "Valmis", "Toimi" ja "Rakennettu" saavat sanan ilman väriä
   (.mk.q). Käytä .done vain kun vahvistus ITSE on se poikkeama, joka
   listasta pitää löytää — esimerkiksi kun kaikki muu on kesken. Muuten
   vihreä täyttää listan eikä erota mitään. */
.ilme .mk.done::before { background: var(--green); border-radius: 1px; }
.ilme .mk.no { color: var(--rust-deep); }
.ilme .mk.no::before { background: var(--rust); border-radius: 1px; transform: rotate(45deg); }
.ilme .mk.q { font-weight: 400; color: var(--ink-3); }
.ilme .mk.q::before { display: none; }

.ilme .legend {
    display: flex;
    gap: 20px;
    margin-top: 14px;
    font: 400 var(--fs-mono) var(--mono);
    color: var(--ink-3);
    letter-spacing: .02em;
    align-items: center;
    flex-wrap: wrap;
}

.ilme .legend i {
    display: inline-block;
    width: 14px;
    height: 3px;
    background: var(--green);
    border-radius: 1px;
    margin-right: 7px;
    vertical-align: middle;
}

.ilme .legend i.t { width: 1.5px; height: 10px; background: var(--ink); }
.ilme .legend i.w { background: var(--rust); }

/* ── Responsiivisuus ─────────────────────────────────────────────────── */

@media (max-width: 1000px) {
    /* minmax(0, 1fr) eikä 1fr: pelkkä 1fr on minmax(auto, 1fr), jonka
       automaattinen minimi on sisällön min-content. Yksikin liian leveä
       lapsi (esim. kolmisarakkeinen .area) kasvattaa silloin koko lohkon
       viewportin yli sen sijaan että kutistuisi. Mitattu 390 px:ssä:
       .blk oli 338 px mutta sen ainoa sarake 438 px. */
    .ilme .blk,
    .ilme .ph,
    .ilme .ruler { grid-template-columns: minmax(0, 1fr); gap: 10px; }
    .ilme .ph .acts { order: 3; padding-top: 0; }
}

@media (max-width: 760px) {
    .ilme { padding-top: 10px; }
    .ilme .sub-tab-rail {
        position: static;
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        background: transparent;
        gap: 20px;
    }
    .ilme .sub-tab-rail::-webkit-scrollbar { display: none; }
    .ilme .sub-tab-rail__tab { white-space: nowrap; }

    /* Sivugutteri tulee jaetusta tokenista, jotta mobiilin vasen linja on
       sama kaikilla pinnoilla. Alapehmuste on 24 px eikä 60: .console-main
       varaa jo alanavigaation tilan (--mobile-nav-clearance), joten 60 px
       teki sivun loppuun 132 px tyhjää. */
    .ilme {
        padding: 6px var(--console-page-gutter-mobile) var(--space-6);
    }
}

@media (max-width: 600px) {
    .ilme .rul .tags span.r { display: none; }

    /* TIETORIVI TAITTUU MYÖHEMMIN KUIN LOHKO.
       `.blk` taittuu 1000 px:ssä, koska sen marginaali on osion otsikko.
       Rivin avain on eri asia: se kuuluu arvon viereen niin kauan kuin
       arvolle jää tilaa, ja taitto 1000 px:ssä hukkaisi pystytilaa
       tabletilla turhaan.

       Mitattu 375 px:ssä ennen tätä: avain vei 168 px 331:stä, arvolle jäi
       131 px, ja pisin tuotantoarvo venyi 298 px korkeaksi. Raja on siinä
       missä arvo lakkaa mahtumasta, ei siinä missä lohko taittuu. */
    .ilme .kv {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--space-1);
        padding: var(--space-3) 0 var(--space-4);
    }
    /* Avain ja provenienssi samalle riville: pinottuna ne veisivät kaksi
       riviä ennen kuin arvo alkaa, ja rivi olisi korkeampi kuin sen
       sisältö. */
    .ilme .kv > .lbl {
        padding-top: 0;
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 0 var(--space-2);
    }
    .ilme .kv > .lbl .n { margin-top: 0; }
    /* Negatiivinen marginaali kumoutuu taitettuna: arvon vasen reuna on
       sama kuin avaimen, eikä rivi näytä sisennetyltä. */
    .ilme .kv .edit { margin-left: -6px; }
    .ilme .kv .inp,
    .ilme .kv .sel { max-width: 100%; }
}

/* Käännösmerkki otsikon alla (MONIKIELINEN-MUISTI §3): mono-rivi, kolmas
   tekstitaso. `.mono` antaa kirjasimen ja välistyksen; tässä vain paikka
   ja väri. Käännös on poikkeama, joten se saa merkin, mutta ei väriä.
   Jaettu komponentti: sama merkki Strategiassa, Tilanteessa, Muistissa,
   Toteutuksessa, Studiossa ja Organisaatiossa. */
.ph .translation-note {
    margin: var(--space-1) 0 0;
    color: var(--ink-3);
}

/* Kielivalitsin: sama rakenne kuin dokumentin yleisövalitsin (`.aud`).
   Valinta on sivun tila (?lang=), ei asetus; nykyinen on mustetta,
   muut kolmatta tasoa. Ei pillereitä, ei taustaa. */
.ph .lang-switch {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin: var(--space-2) 0 0;
    font: 500 12px var(--mono);
    letter-spacing: var(--tr-mono);
    text-transform: uppercase;
    color: var(--ink-3);
}
.ph .lang-switch a { color: var(--ink-3); text-decoration: none; }
.ph .lang-switch a:hover { color: var(--ink); }
.ph .lang-switch a[aria-current="true"] { color: var(--ink); }

/* Tavoite-editorin huomautus: lukija muokkaa alkuperäistä. Sama sävy kuin
   käännösmerkillä; ei väriä, koska se ei ole virhe. */
[data-goal-kv] .kv-original {
    margin: 0 0 var(--space-2);
    color: var(--ink-3);
}

@media (prefers-reduced-motion: reduce) {
    .ilme *, .ilme .view, .ilme .rul .c { animation: none !important; transition: none !important; }
}
