/* ===========================================================================
   VARAUSKIRJA · AIKATAULU
   Kirjoitettu nollasta 10.8.2026. Ei jaa yhtään riviä vanhan kanssa.

   TEESI. Tämä ei ole kalenteri jossa kortit kelluvat tyhjän päällä. Tämä on
   AIKATAULU joka on painettu ruudukkoon: lentokentän lähtötaulu, junan
   aikataulu, tilikirjan viivoitettu sivu. Varaus ei ole kortti taustan
   päällä vaan solu joka on täytetty.

   Roope 9.8.2026: "varaukset tuntuvat leijuvilta." Kolme mekanismia
   vastaa siihen, ja jokainen on rakenteellinen eikä koristeellinen:

     1. VARAUS TÄYTTÄÄ SARAKKEEN reunasta reunaan. Ei sivumarginaalia, ei
        pyöristystä, ei varjoa. Kortilla on ilmaa ympärillään; solulla ei.
     2. RUUDUKKO ON MATERIAALIA. Joka toinen tunti on eri sävyinen kaista,
        kuten viivoitetussa paperissa. Tyhjä ruutu ei ole tyhjä vaan
        viivoitettu. Kelluminen vaatii tyhjyyttä ympärille; tässä ei ole.
     3. VARAUS ANKKUROI AIKAAN. Ylä- ja alareuna ovat vahvempia kuin
        ruudukon omat viivat ja osuvat tarkalleen aikariviin, ja aikakisko
        saa saman merkin varauksen kohdalle. Silmä näkee mihin se kiinnittyy.

   Simo 10.8.2026: "rivit ja ajat erottuvat selkeästi." Aikakisko on oma
   pinta omalla taustallaan, tunnit ovat isoja ja mono-numeroisia, ja
   tuntiviiva on ainoa viiva joka kulkee koko leveyden yli.

   TYPOGRAFIA. Geist ja Geist Mono. Ne ovat Hohtokeilan oman verkkosivuston
   kirjasimet, eli sama typografia tiskillä ja asiakkaan sivulla. Ei Inter
   eikä Space Grotesk: molemmat ovat tekoälytyökalujen konvergenssivalintoja.
   Kellonajat ja kaikki numerot ovat Geist Monoa, jotta sarakkeet ovat
   pystysuunnassa kohdakkain eivätkä tanssi.
   =========================================================================== */

@font-face {
  font-family: 'Geist';
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/Geist-variable-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2122, U+2212;
}
@font-face {
  font-family: 'Geist';
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/Geist-variable-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF;
}
@font-face {
  font-family: 'Geist Mono';
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/GeistMono-variable-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2122, U+2212;
}
@font-face {
  font-family: 'Geist Mono';
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/GeistMono-variable-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF;
}

/* ---------------------------------------------------------------------------
   TOKENIT
   Pohja on Hohtokeilan brändistä (output/hohtokeila/DESIGN.md): hallin katto,
   seinä ja UV-valo. Käyttö on kuitenkin täysin eri kuin edellisessä
   versiossa: siellä väri oli veili taustassa, tässä se on materiaalin sävy.
   --------------------------------------------------------------------------- */
:root {
  /* Materiaali. Neljä pintaa, ei enempää. Jokaisella on tehtävä. */
  --a-syva:    #08070E;   /* sivun pohja, syvin */
  --a-kisko:   #0E0D16;   /* aikakisko ja otsikkorivi: oma pinta */
  --a-arkki-0: #12111C;   /* ruudukon pariton tunti */
  --a-arkki-1: #1B1A2C;   /* ruudukon parillinen tunti: viivoitus */
  /* Simo 10.8.2026: "voit lisata viela varausten opacitya joka tekisi
     sivusta viela selkeamman." Mitattu syy: solu erottui parittomasta
     tunnista L* 7,4 mutta PARILLISESTA vain 2,8, eli joka toisella
     tunnilla varaus lahes sulautui viivoituskaistaan. Nyt erot ovat
     13,4 ja 8,7, eli varattu ja vapaa eroavat yhta selvasti kummallakin
     kaistalla. Metamuste nostettiin samalla, koska vaaleampi solu vei
     sen alle 4,5:1. */
  --a-solu:    #2D2950;   /* varattu solu */
  --a-solu-hi: #383363;   /* varattu solu, osoitin päällä */

  /* Muste. Kolme tasoa. */
  --a-ink:   #F4F3FA;
  --a-ink-2: #B4B0C8;
  --a-ink-3: #9A98B2;

  /* Viivat. Tuntiviiva on ainoa vahva. */
  --a-viiva-tunti: rgba(196,193,222,0.46);
  --a-viiva-puoli: rgba(196,193,222,0.09);
  --a-viiva-rata:  rgba(196,193,222,0.13);
  --a-viiva-reuna: rgba(196,193,222,0.24);

  /* Tila. Väri kertoo mitä pitää tehdä, ei mikä varaus on. */
  --a-toimi:      #FF6A33;   /* maksamaton, vaatii teon. Hohtokeilan keilaraita */
  --a-toimi-ink:  #14100C;
  --a-kunnossa:   #4ED2A8;   /* maksettu */
  /* LASKUTUKSEEN, kolmas maksutila (Roope 3.9.2026, ks. design/BRIEF_
     maksutila_kolme_vaihtoehtoa.md): "nappi laskutukseen ja se menis eri
     väriseks." Sininen, koska mikään palikan täytevärei (--a-solu tumman-
     punainen, --a-kunnossa lähes musta) ei ole sinisen sävyinen - erottuu
     molemmista sekä sävyltään että vaaleudeltaan. Selvästi tummempi/
     kylläisempi kuin --a-nyt (#8B7BF0, vain ohut reunaviiva/nykyhetki),
     jottei sekoitu siihen. */
  --a-laskutus:   #3A6FD1;
  --a-nyt:        #8B7BF0;   /* käynnissä nyt ja nykyhetken viiva */
  --a-rikki:      #FF5C5C;   /* päällekkäisyys */

  --a-mitta-rata: 132px;     /* sarakkeen vähimmäisleveys */
  --a-mitta-kisko: 76px;     /* aikakiskon leveys */
  /* HUOM: rivikorkeus tulee varauskirja.js:sta muuttujassa --vk-row-h, ja se
     asetetaan #vkSheet-elementtiin EIKA juureen. Siksi sita ei voi aliasoida
     taalla: :root ei nae sita. Kaytetaan var(--vk-row-h, 34px) suoraan
     siella missa se on nakyvissa. Mitattu 10.8.2026: JS antaa 38px, ja
     juuritason alias jai varapolkuun 34px, jolloin tuntikaistat eivat
     osuneet riveihin. */

  --a-nopea: 120ms;
  --a-normi: 180ms;
  --a-kaari: cubic-bezier(0.32, 0.72, 0, 1);

  /* VaraaVuoro-klooni 2.9.2026: uudet pinnat topbarille, sarakeotsikoille
     ja aikasarakkeelle. Nama tarvitaan koska VaraaVuoron rakenteessa nama
     neljä pintaa ovat kukin oma varinsa, eivät saman --a-kisko-pinnan
     sävyjä. Tumma teema saa saman logiikan tummina vastineina, jotta
     teemavaihto ei jaa rikki - VaraaVuoro itse ei nayta tumman teeman
     versiota, joten nama ovat meidan sovituksemme eivatka mitattuja. */
  --a-topbar:         #14131C;
  --a-topbar-ink:     #F4F3FA;
  --a-head-rata:      #23314F;
  --a-head-biljardi:  #223018;
  --a-head-kabinetti: #12262B;
  --a-head-ink:       #F4F3FA;
  --a-aika-tunti:     #1B1A2C;
  --a-aika-puoli:     #12111C;
  --a-grid-line:      rgba(196,193,222,0.24);

  /* SOLUJEN OMAT RUUDUKKOVIIVAT. KIERROS 3 (2.9.2026), brief kohta 4:
     "selkeät pysty- ja poikkiviivat", erotuttava myös värillisten solujen
     päällä. --a-grid-line (yllä) EI kelpaa tähän: se on tarkoitettu kromille
     (otsikkorivin reunat, aikakiskon raja) joka on aina neutraalin pinnan
     päällä. Vapaat solut sen sijaan ovat kirkkaan keltaisia/vihreitä, joten
     viiva piirretään suoraan .vk-cell:iin (ks. alempana) omilla, vahvemmilla
     muuttujilla. Tumma teema: valkoinen peite, koska solut ovat samat
     kirkkaat värit molemmissa teemoissa (ks. --a-vapaa-*, teemariippumaton). */
  --a-grid-puoli: rgba(255,255,255,0.16);
  --a-grid-tunti: rgba(255,255,255,0.38);
  --a-grid-ryhma: rgba(255,255,255,0.52);

  /* VAPAAN SOLUN VARIT. VaraaVuoro-klooni 2.9.2026, brief kohta 1, mitattu
     suoraan lähteestä (design/varaavuoro-kalenteri.png). Tarkoituksella
     TEEMARIIPPUMATTOMAT eli samat molemmissa teemoissa: nämä ovat kirkkaita
     tilavärejä jotka lukevat sekä vaalealla että tummalla pohjalla, eikä
     lähteestä ole tummaa versiota mitattavaksi (VaraaVuoro itse on vain
     vaalea) - kaksi eri sävyä olisi arvaus, ei mittaus.
       korostettu = rata ennen hohtoaikaa, tumma = Biljardi, vaalea =
       Kabinetti, hohto = rata klo 16 alkaen (ks. HOHTO_ALKAA_MIN, js). */
  --a-vapaa-korostettu:     rgb(178, 239, 57);
  --a-vapaa-korostettu-hi:  rgb(206, 255, 107);
  --a-vapaa-vaalea:         rgb(205, 230, 155);
  --a-vapaa-vaalea-hi:      rgb(218, 255, 144);
  --a-vapaa-tumma:          rgb(125, 188, 53);
  --a-vapaa-hohto:          rgb(246, 253, 0);
  --a-vapaa-ink:            rgba(0, 0, 0, 0.87);   /* brief: "musta 87% läpinäkyvyydellä" */

  /* SELITTEEN VARATUT TILAT joilla ei ole omaa .vk-block-varitystä (brief
     kohta 1, "Neljälle viimeiselle ei ole vastinetta Markin tietomallissa.
     Määrittele ne silti CSS:ään..."). Varaus/Maksettu/Vakiovuoro käyttävät
     jo olemassa olevia --a-solu/--a-kunnossa/--a-toimi -muuttujia, jotka
     täsmäävät brief-taulukkoon jo ilman muutosta. */
  --a-tila-vahvistamaton:     rgb(226, 231, 226);
  --a-tila-vahvistamaton-ink: #202124;
  --a-tila-kilpailu:          rgb(100, 205, 229);
  --a-tila-kilpailu-ink:      #FFFFFF;
  --a-tila-paikanpitaja:      rgb(61, 63, 65);
  --a-tila-paikanpitaja-ink:  #FFFFFF;

  color-scheme: dark;
}

/* ---------------------------------------------------------------------------
   VAALEA TEEMA = VARAAVUORO-KLOONI (2.9.2026)
   Roope Kemisen tilaus Simon kautta: "kloonaa varaavuoron layout täysin...
   varaavuoron väreineen." Unohda vanha design, tama ei ole sen sävytys
   vaan uusi paletti VaraaVuorosta mitattuna.

   LÄHDE: BRIEF_varauskirja_varaavuoro_klooni.md. Osa arvoista on
   devtools-mitattu suoraan elävästä VaraaVuorosta (rakenteen värit:
   topbar, sarakeotsikot, aikasarake). Osa oli inline-tyyleissä eikä
   niita saanut ulos tyylisäännöistä - ne on POIMITTU pikselistä
   design/varaavuoro-kalenteri.png:sta (ks. brief kohta 3, "poimi
   kuvasta"): --a-solu (varaus, tummanpunainen), --a-kunnossa (maksettu
   varaus, musta), --a-toimi (vakiovuoro, oranssi).

   Vaalea on nyt OLETUS (ks. varauskirja.html data-theme="light"), koska
   VaraaVuoro itse on vaalea eika Roopelle näytetä tummaa versiota
   ensimmäisenä. Tumma teema säilyy valintana teemanapista, ei poistettu. */
:root[data-theme="light"] {
  --a-syva:    #FAFAFA;   /* sivun pohja, sama sävy jonka VaraaVuoro käyttää kortin ympärillä */
  --a-kisko:   #FFFFFF;   /* työkalurivi ja kortti */
  --a-arkki-0: #FFFFFF;   /* ruudukon pohja */
  --a-arkki-1: #EEEEEE;   /* ei enää sävytys - katso --a-aika-tunti/puoli aikasarakkeelle */

  --a-solu:    rgb(122, 40, 40);   /* varaus. Poimittu kuvasta: legendin ja ruudukon "17:00" solun ylareuna, kaksi riippumatonta mittausta tayspiin (122,40,40) / (124,41,41) */
  --a-solu-hi: rgb(150, 56, 56);

  --a-ink:   #202124;
  --a-ink-2: #5F6368;
  --a-ink-3: #80868B;

  --a-viiva-tunti: rgba(0,0,0,0.22);
  --a-viiva-puoli: rgba(0,0,0,0.09);
  --a-viiva-rata:  rgba(0,0,0,0.12);
  --a-viiva-reuna: rgba(0,0,0,0.16);

  --a-toimi:     rgb(244, 143, 27);  /* vakiovuoro, oranssi. Poimittu kuvasta (legenda, tasainen alue y847-858) */
  --a-toimi-ink: #FFFFFF;
  --a-kunnossa:  rgb(19, 19, 19);    /* maksettu varaus, lähes musta. Mitattu suoraan lähteestä (brief antaa tämän valmiina, ei "poimi kuvasta") */
  /* LASKUTUKSEEN, kolmas maksutila (Roope 3.9.2026, ks. design/BRIEF_
     maksutila_kolme_vaihtoehtoa.md). Ei VaraaVuoro-lähteessä, ei siis
     "poimi kuvasta" vaan valittu: erottuu sekä --a-solusta (122,40,40,
     tummanpunainen) että --a-kunnossasta (19,19,19, lähes musta) omalla
     sinisellä sävyllä, ja on tummempi/kylläisempi kuin --a-nyt (rata-
     sarakeotsikon sininen) ettei sekoitu siihen. */
  --a-laskutus:  rgb(30, 82, 173);
  --a-nyt:       rgb(74, 144, 226);  /* sama sininen kuin rata-sarakeotsikko: mitattu suoraan lähteestä */
  --a-rikki:     #C42B2B;

  /* VaraaVuoron neljä rakenteen pintaa. Mitattu suoraan lähteestä (ei
     "poimi kuvasta" -kohtia), ks. brief kohta 3 "Rakenne"-taulukko. */
  --a-topbar:         rgb(63, 81, 181);   /* indigo yläpalkki */
  --a-topbar-ink:     #FFFFFF;
  --a-head-rata:      rgb(74, 144, 226);  /* sininen: rata-sarakkeet */
  --a-head-biljardi:  rgb(66, 103, 35);   /* tummanvihreä: Biljardi */
  --a-head-kabinetti: rgb(28, 80, 102);   /* tumma petrooli: Kabinetti */
  --a-head-ink:       #FFFFFF;
  --a-aika-tunti:     rgb(238, 238, 238); /* aikasarake, tasatunti */
  --a-aika-puoli:     #FFFFFF;            /* aikasarake, puolitunti */
  --a-grid-line:      #DDDDDD;            /* border-collapse-taulukon viiva */

  /* KIERROS 3 (2.9.2026), brief kohta 4: solun oma ruudukkoviiva, mustaa
     eikä --a-grid-linen vaaleaa harmaata, koska Simo mittasi nimenomaan
     etta vaalea harmaa katoaa keltaisen (rgb 246,253,0) ja kirkkaan vihreän
     (rgb 178,239,57) päälle. Musta 0,16/0,38/0,52-läpinäkyvyydellä pysyy
     näkyvänä kaikilla kolmella pinnalla (valkoinen, keltainen, vihreä) eikä
     tarvitse eri arvoa per solutyyppi - yksi rivi vasemmalle silmälle,
     ei kolmea. Tasatunti selvästi vahvempi kuin puolitunti (brief:
     "antaa ruudukolle rytmin"), ryhmäraja vahvin (Rata|Pöytä/Kabinetti). */
  --a-grid-puoli: rgba(0,0,0,0.14);
  --a-grid-tunti: rgba(0,0,0,0.40);
  --a-grid-ryhma: rgba(0,0,0,0.55);

  color-scheme: light;
}

/* ---------------------------------------------------------------------------
   RUNKO
   --------------------------------------------------------------------------- */
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  background: var(--a-syva);
  color: var(--a-ink-2);
  font-family: 'Geist', ui-sans-serif, system-ui, sans-serif;
  font-size: 14px;
  font-feature-settings: 'ss01', 'cv01';
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  padding: 10px 16px; background: var(--a-toimi); color: var(--a-toimi-ink);
  font-weight: 600;
}
.skip-link:focus { left: 12px; top: 12px; }

#vkApp { height: 100vh; display: grid; grid-template-rows: auto auto 1fr; }

/* ---------------------------------------------------------------------------
   YLÄPALKKI. VaraaVuoro-klooni 2.9.2026: indigo topbar rgb(63,81,181),
   64 px korkea, valkoinen teksti (brief kohta 3 "Rakenne" + kohta 4.1).
   --------------------------------------------------------------------------- */
.a-brand {
  display: flex; align-items: center; gap: 14px;
  height: 64px; padding: 0 18px;
  background: var(--a-topbar);
  border-bottom: none;
}
.a-brand-nimi {
  font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
  text-transform: none; color: var(--a-topbar-ink);
}
.a-brand-oikea { margin-left: auto; display: flex; align-items: center; gap: 4px; }
/* Topbarin omat napit: läpinäkyvä tausta ei erotu indigosta, joten
   .a-nappi saa täällä oman, kevyemmän tilan. */
.a-brand .a-nappi { color: var(--a-topbar-ink); border-color: rgba(255,255,255,0.35); }
.a-brand .a-nappi:hover { color: var(--a-topbar-ink); border-color: rgba(255,255,255,0.6); background: rgba(255,255,255,0.12); }

/* Kapea ikkuna (tiskin pieni nayttö, testattu 480px). MITATTU 11.8.2026:
   #vkSarjatMaara taytyy tekstilla vasta kun Vakiovuorot-paneeli on avattu
   kerran ("N voimassa · M paatettya"), ja kayttoontotetulla tilillä tuo
   luku kasvaa ajan myota. Kun yhdistetty painikkeen teksti ("Vakiovuorot
   3 voimassa · 12 paatettya") ei enaa mahtunut 480px levylle, .a-nappi
   rivittyi sisaisesti mutta pysyi kiinteassa 32px-korkeudessa (height,
   ei min-height), joten ylivuotava teksti valahti nakyviin paallekkain
   yrityksen nimen ja paivarivin kanssa. Tyhjalla testitililla tata ei
   nahnyt, koska badge oli viela tyhja. Korjaus: rivi ei enaa rivity
   moneen riviin - yrityksen nimi ja badge typistyvat kolmella pisteella
   ennemmin kuin rikkovat ylareunan, ja "Hallintapaneeli" (ainoa tie pois
   naytolta) sailyy aina kokonaan luettavana koska se typistyy viimeisena. */
@media (max-width: 560px) {
  /* min-width:0 PAKOLLINEN rivilla itsellaan, ei vain lapsilla: flex-lapsen
     oletus min-width on "auto" eli sisallon max-content-leveys, ja tama
     periytyy myos flex-KONTTIIN jos sen omaa min-widthia ei nollata. Ilman
     tata rivi tyontyi 480px:n ikkunassa 559px:n levyiseksi (mitattu
     11.8.2026) vaikka jokaiselle yksittaiselle lapselle oli jo annettu
     max-width - lapsen max-width ei riita, koska flexbox-algoritmi laskee
     rivin oman koon lapsen SISALLON minimileveydesta, ei sen maaritellysta
     max-widthista, ellei min-width:0 kerro etta saa mennae sen alle. */
  .a-brand, .a-paiva { min-width: 0; overflow: hidden; }
  .a-brand-nimi {
    min-width: 0; max-width: 34vw;
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
  .a-brand-oikea { min-width: 0; flex-shrink: 1; }
  #vkSarjatBtn { min-width: 0; }
  /* Vain KASVAVA osa typistyy, ei koko nappi: "Vakiovuorot" on aina
     kokonaan luettavissa (lyhyt, kiinteä), ja lukema ("3 voimassa · 12
     paatettya") typistyy kolmella pisteella kun tili on ollut kaytossa
     pitkaan. text-overflow ei toimi suoraan flex-napin sisalla (nappi on
     inline-flex, ei muodosta yhtenaista tekstirivia), joten se kohdistuu
     TASSA nimenomaan span-elementtiin. */
  #vkSarjatMaara {
    display: inline-block; max-width: 30vw; vertical-align: bottom;
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
}

.a-paiva {
  display: flex; align-items: center; gap: 10px;
  height: 60px; padding: 0 18px;
  background: var(--a-kisko);
  border-bottom: 1px solid var(--a-viiva-reuna);
}
/* Päivämäärä on näkymän tärkein yksittäinen tieto: se kertoo mitä katsot.
   Siksi se on ainoa iso typografinen ele koko näkymässä. */
.a-paiva-nimi {
  font-size: 22px; font-weight: 600; letter-spacing: -0.02em; color: var(--a-ink);
  text-transform: lowercase;
}
.a-paiva-pvm {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 13px; font-weight: 400; color: var(--a-ink-3);
  font-variant-numeric: tabular-nums;
}
.a-paiva-oikea { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.a-nappi {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 32px; padding: 0 12px;
  font-family: inherit; font-size: 12.5px; font-weight: 500;
  color: var(--a-ink-2);
  background: transparent;
  border: 1px solid var(--a-viiva-rata);
  border-radius: 3px;
  cursor: pointer;
  transition: color var(--a-nopea) var(--a-kaari), border-color var(--a-nopea) var(--a-kaari), background var(--a-nopea) var(--a-kaari), transform var(--a-nopea) var(--a-kaari);
}
.a-nappi:hover { color: var(--a-ink); border-color: var(--a-viiva-reuna); background: var(--a-arkki-1); }
.a-nappi:focus-visible { outline: 2px solid var(--a-nyt); outline-offset: 2px; }
/* Kosketuspalaute. Ilman tätä tiskin kosketusnäytöllä napin painallus ei
   näyttänyt mitään ennen kuin toiminto oli jo valmis: :hover ei laukea
   kosketuksesta, ja tämä oli ainoa .a-nappi-luokan tilamuutos. Sama
   0.97-kutistus kuin muualla käytössä olevilla .vk-danger/.vk-ghost-
   napeilla (ks. alempana), jotta kaikki napit tuntuvat samalta. */
.a-nappi:active { transform: scale(0.97); }
.a-nappi-ikoni { width: 32px; padding: 0; }
.a-nappi-vahva { color: var(--a-toimi-ink); background: var(--a-toimi); border-color: var(--a-toimi); font-weight: 600; }
.a-nappi-vahva:hover { color: var(--a-toimi-ink); background: var(--a-toimi); border-color: var(--a-toimi); filter: brightness(1.1); }
.a-nappi[disabled] { opacity: .4; cursor: default; }
.a-nappi[disabled]:active { transform: none; }

/* [hidden] EI TOIMI ITSESTAAN kun elementilla on display-arvon asettava
   luokka. `[hidden]` ja `.a-nappi` ovat samaa tarkkuutta (0,1,0), ja
   .a-nappi on maaritelty myohemmin - siis se voittaa, ja `display:
   inline-flex` jaa voimaan.

   MITATTU 10.8.2026: Simo avasi nakyman yrityksella jolla ei ole ratoja.
   varauskirja.js asetti `vkClosedBtn.hidden = true` oikein, mutta nappi
   jai nakyviin TYHJANA ORANSSINA LAATIKKONA tyhjan tilan alle. Se nayrtti
   rikkinaiselta juuri siina nakymassa jonka tehtava on selittaa ettei
   mitaan ole vialla.

   Tama saanto koskee kaikkia elementteja eika vain sita yhta nappia,
   koska sama ansa odottaa jokaista tulevaa luokkaa jolla on display. */
/* :not(.auki) ON PAKOLLINEN, EI VAROTOIMI.
   varauskirja.js avaa varauspaneelin luokalla `.auki` MUTTA EI POISTA
   `hidden`-attribuuttia (rivi 1510: vkPanel.classList.add('auki')).
   Markupissa aside on `hidden`, joten pelkka `[hidden]{display:none
   !important}` teki paneelin avaamisen mahdottomaksi - varauksen
   klikkaus lakkasi avaamasta tietoja. Se oli minun aiheuttamani
   regressio, ja se syntyi kun korjasin oranssin tyhjan napin.
   Mitattu: Simo 10.8. "kun klikkaan varauksesta, se ei avaa varauksen
   tietoja kuten ennen". */
[hidden]:not(.auki) { display: none !important; }

/* KIERROS 3 (2.9.2026), brief KIERROS 3 kohta 2, tilanhakujärjestyksen
   kohta 4: "Työkalurivi ja aukiolorivi yhdeksi riviksi." .a-tila oli oma
   30 px korkea koko leveyden rivi tummalla pohjalla (varauskirja.html
   "Rivi 3"); se on nyt varauskirja.htmlissa siirretty .a-paiva-DIVIN
   SISÄLLE (päivämäärän ja Tänään-napin väliin), joten se ei enää tarvitse
   omaa korkeuttaan, taustaansa eikä reunaviivaansa - ne perii .a-paiva.
   flex:1 1 auto + min-width:0 antaa sille jäljelle jäävän tilan ja
   sallii kutistumisen; #vkStatusMain typistyy kolmella pisteella jos
   viesti ("Auki 16.00-22.00 · ei vielä varauksia...") ei mahdu, jotta
   Tänään-nappi ei koskaan työnny ruudun ulkopuolelle. */
.a-tila {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 auto; min-width: 0;
  padding-left: 14px; margin-left: 2px;
  border-left: 1px solid var(--a-viiva-puoli);
  font-size: 12px; color: var(--a-ink-3);
}
.a-tila.on-virhe { color: var(--a-rikki); }
#vkStatusMain { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.a-tila[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   RUUDUKKO. Kaksi saraketta: aikakisko ja arkki.
   --------------------------------------------------------------------------- */
/* min-width: 0 ON PAKOLLINEN, EI VAROTOIMI.
   .a-main on gridin (#vkApp) lapsi, ja grid-elementin oletus on
   `min-width: auto` = "ala kutistu sisaltoa pienemmaksi". Ruudukko on
   leveampi kuin ikkuna (12 rataa), joten .a-main venyi sisallon mukaan
   ja vei paneelin ruudun ulkopuolelle.

   MITATTU 10.8.2026 selaimessa: ikkuna 1532px, .a-main 1867px,
   #vkScroll 1507px ja #vkPanel alkoi kohdasta x=1507 - eli paneelista
   nakyi 25 pikselia. Varauksen tiedot aukesivat oikein mutta niita ei
   voinut lukea.

   #vkScroll:lla oli jo min-width: 0. Se ei riita jos VANHEMPI ei
   kutistu: kutistuminen pysahtyy ensimmaiseen elementtiin joka
   kieltaytyy. */
.a-main { position: relative; min-height: 0; min-width: 0; display: flex; }

/* ---------------------------------------------------------------------------
   KORTTI. VaraaVuoro-klooni 2.9.2026, brief kohta 3: taulukko on valkoisen
   kortin sisällä, otsikko yllä, ohje ja selite alla. #vkKortti on flex-
   sarake (otsikko - vierivä ruudukko - ohje - selite), #vkPanel pysyy
   erillisenä flex-sisaruksena entisellään (ei kosketa sen asemointiin).
   Marginaali on KORTISSA ITSESSÄÄN eikä .a-mainissa, koska .a-main on
   yhteinen myös #vkPanelille - jos marginaali olisi siellä, paneeli
   irtoaisi oikeasta reunasta jota se ei saa tehdä. --------------------- */
#vkKortti {
  flex: 1; min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  margin: 20px;
  background: var(--a-kisko);
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.06), 0 4px 16px -4px rgba(0,0,0,0.14);
  overflow: hidden;   /* rajaa pyöristetyt kulmat ruudukon valkoisen taustan yli */
}
#vkKortti[hidden] { display: none; }
@media (max-width: 560px) {
  #vkKortti { margin: 10px; border-radius: 6px; }
}

/* POISTETTU NÄKYVISTÄ KIERROS 3:lla (2.9.2026), brief KIERROS 3 kohta 2,
   tilanhakujärjestyksen kohta 3: "harkitse otsikon poistoa, koska
   päivämäärä lukee jo työkalurivissä." 58 px säästö oli suurin yksittäinen
   siirto koko rivikorkeuslaskussa (ks. varauskirja.js RIVI_H-kommentti).
   Elementti ja sen textContent-päivitys (varauskirja.js) jätetty ennalleen
   - vain näkyvyys pois, jotta JS ei tarvitse omaa erikoistapaustaan. */
#vkKorttiOtsikko { display: none; }

#vkScroll {
  flex: 1; min-width: 0; min-height: 0;
  overflow: auto;
  background: var(--a-kisko);
  scrollbar-color: var(--a-viiva-reuna) transparent;
}

/* KIERROS 3 (2.9.2026), brief KIERROS 3 kohta 2, tilanhakujärjestyksen
   kohdat 1-2: "Selite yhdelle riville kahden sijaan, laatikot
   kapeammiksi" + "Ohjerivi ja selite samalle riville, ohje vasemmalle,
   laatikot oikealle." #vkOhje ja #vkSelite olivat kaksi erillistä täyden
   leveyden riviä (12+84 px + omat paddingit = 125 px yhteensä); ne ovat
   nyt saman #vkAlaosa-flex-rivin kaksi lasta (varauskirja.html), yhteensä
   n. 36-40 px. Aiempi KAHDEN rivin perustelu ("kahdeksan laatikkoa mahtuu
   yhdelle riville 1536 px kortissa") oli oikea mittaus mutta VÄÄRÄ
   johtopäätös tälle kierrokselle - Simo pyytää nyt nimenomaan yhtä riviä,
   ja tila riittää siihen mainiosti. */
#vkAlaosa {
  flex: none;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  padding: 8px 20px;
  border-top: 1px solid var(--a-viiva-puoli);
}
@media (max-width: 560px) {
  #vkAlaosa { flex-wrap: wrap; gap: 8px; }
}
#vkOhje {
  flex: 1 1 auto; min-width: 0;
  font-size: 11px; color: var(--a-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#vkSelite {
  flex: none;
  display: flex; align-items: center; flex-wrap: nowrap;
  gap: 6px;
}
@media (max-width: 560px) {
  /* Kapealla ruudulla ohje ja selite eivät voi olla vierekkäin - selite
     saa rivittyä, mutta pysyy silti yhtenä TIIVIINÄ ryhmänä eikä 4x2
     -ruudukkona kuten ennen kierrosta 3. */
  #vkSelite { flex-wrap: wrap; row-gap: 6px; }
}
.vk-selite-laatikko {
  display: inline-flex; align-items: center; justify-content: center;
  height: 20px;
  border-radius: 3px;
  font-size: 10px; font-weight: 500; text-align: center; white-space: nowrap;
  padding: 0 7px;
}
.vk-selite-laatikko[data-vapaa="korostettu"] { background: var(--a-vapaa-korostettu); color: var(--a-vapaa-ink); }
.vk-selite-laatikko[data-vapaa="hohto"]      { background: var(--a-vapaa-hohto);      color: var(--a-vapaa-ink); }
.vk-selite-laatikko[data-tila="vahvistamaton"] { background: var(--a-tila-vahvistamaton); color: var(--a-tila-vahvistamaton-ink); }
.vk-selite-laatikko[data-tila="varaus"]        { background: var(--a-solu);               color: #FFFFFF; }
.vk-selite-laatikko[data-tila="maksettu"]      { background: var(--a-kunnossa);            color: #FFFFFF; }
.vk-selite-laatikko[data-tila="laskutukseen"]  { background: var(--a-laskutus);            color: #FFFFFF; }
.vk-selite-laatikko[data-tila="kilpailu"]      { background: var(--a-tila-kilpailu);        color: var(--a-tila-kilpailu-ink); }
.vk-selite-laatikko[data-tila="paikanpitaja"]  { background: var(--a-tila-paikanpitaja);    color: var(--a-tila-paikanpitaja-ink); }
.vk-selite-laatikko[data-tila="vakiovuoro"]    { background: var(--a-toimi);                color: var(--a-toimi-ink); }

#vkSheet {
  display: grid;
  grid-template-columns: var(--a-mitta-kisko) 1fr;
  /* NELJÄ RIVIÄ, EI KOLME (13.9.2026, ryhmäotsikkorivi). Rivi 1 on uusi
     #vkGroupsCorner/#vkGroupsHead-pari (Niemi/Messilä-tyyppinen otsikko
     tyyppien YLÄPUOLELLE). Se on TYHJÄ (hidden) kun resurssityyppejä on
     yksi, ja tyhjä/hidden auto-rivi romahtaa 0 px:iin ilman että mikään
     muu rivi tai sen sticky-tarttuma siirtyy - siksi tätä ei tarvinnut
     tehdä ehdolliseksi grid-template-rows-tasolla. Rivit 2-4 ovat entiset
     otsikko/arkki/jalkiotsikko, vain numero kasvoi yhdellä (ks. #vkCorner,
     #vkColsHead, #vkTimes, #vkCanvas, #vkCornerFoot, #vkColsFoot). */
  grid-template-rows: auto auto 1fr auto;
  /* LEVEYS ON EKSPLISIITTINEN, EI max-content. MITATTU 10.8.2026.
     `min-width: max-content` sai jokaisen 1fr-sarakkeen paisumaan koko
     leveyteen: mittapiste sivulla nayrtti
       canvas.gridTemplateColumns = 1532px 1532px 1532px ...
     kun sarakemalli oli oikein (minmax(116px,1fr) x 15) ja otsikoita 15.
     Ruudulla nakyi siis yksi rata kolmentoista sijasta, vaikka data,
     JS ja sarakemalli olivat kaikki kunnossa.

     Syy on grid-mitoituksen kehays: max-content-kokoisessa saeiliossa
     1fr ratkeaa raidan max-content-osuudesta eika jaettavasta tilasta,
     jolloin jokainen rata vie taydet leveydet. Vanha varauskirja.css
     kaytti tasmalleen tata kaavaa - se ei ollut sattumaa vaan se on
     ainoa tapa saada vaakavieritys ilman etta 1fr karkaa.

     --vk-inner-min tulee JS:sta (geo.ryhmat.minLeveys) ja --vk-gutter
     on aikakiskon leveys. */
  width: max(100%, calc(var(--vk-gutter) + var(--vk-inner-min, 0px)));
}

/* RYHMÄOTSIKKORIVI (13.9.2026, Waveriders: "Niemi"/"Messilä",
   "Flyboard"/"Sup lauta" resurssityypin nimenä sarakkeiden yläpuolella).
   Rivi 1 #vkSheet:ssä, aina ennen #vkCorner/#vkColsHead:ia. Piiloutuu
   [hidden]:lla kun resurssityyppejä on yksi (piirraRyhmaOtsikot,
   varauskirja.js) - tyhjä/hidden auto-rivi vie 0 px, joten #vkCorner ja
   #vkColsHead pysyvät tasan nykyisissä kohdissaan (top:0) sillä yritys.

   STICKY-KAKSIKKO: kun rivi ON näkyvissä, #vkCorner/#vkColsHead saavat
   `.vk-ryhmat`-luokan kautta top-arvon RYHMÄRIVIN KORKEUDEKSI (24px, sama
   luku molemmissa säännöissä alla), jotta ne tarttuvat AINA ryhmäotsikon
   ALAPUOLELLE eivätkä sen päälle - kaksi sticky-pintaa pinossa, ei yksi.
   Kun rivi ei ole näkyvissä, top pysyy 0:ssa kuten ennen tätä muutosta. */
#vkGroupsCorner {
  grid-column: 1; grid-row: 1;
  position: sticky; top: 0; left: 0; z-index: 41;
  height: 24px;
  background: var(--a-kisko);
  border-right: 1px solid var(--a-grid-line);
  border-bottom: 2px solid var(--a-grid-line);
}
#vkGroupsHead {
  grid-column: 2; grid-row: 1;
  position: sticky; top: 0; z-index: 31;
  height: 24px;
  display: grid; grid-template-columns: var(--vk-tpl);
  background: var(--a-kisko);
  /* Alaviiva TÄSSÄ, ei .vk-ryhmaotsikossa (design-katselmus 13.9.2026,
     portti 10, web designer): kolot (tyhjät gap-sarakkeet ryhmien välissä)
     eivät kuulu mihinkään .vk-ryhmaotsikko-soluun, joten solukohtainen
     border-bottom jätti viivan katkonaiseksi jokaisen kolon ja vasemman
     kulman (#vkGroupsCorner) kohdalla - mitattu pikselistä (screenshot
     a-hohtokeila-demo-desktop-1440.png, x=1200 y=166 oli "ffffff" kun
     vieressä x=645 oli "dddddd"). Reunaviiva säiliön tasolla kattaa koko
     leveyden kerralla, sama kaava kuin #vkColsHead:in 1px reunalla. */
  border-bottom: 2px solid var(--a-grid-line);
}
/* Yksi ryhmän otsikko. Samat raidat kuin --vk-tpl (JS laskee span-arvon
   geo.ryhmat.raita:sta, kolot mukaan lukien - ks. varauskirja.js
   ryhmita()/piirraRyhmaOtsikot()), joten reunat osuvat tasan sarakkeiden
   reunoihin eikä pikselillekkään viereen. Hieman painavampi kuin
   sarakeotsikko (600 vs. 400) mutta sama perhe/koko - "hillitty
   typografia" (brief), ei oma tyylinsä. overflow:hidden TÄSSÄ elementissä
   (ei vain lapsessa) on pakollinen: grid-solun oletus min-width on auto
   eli sisällön leveys, ja ilman overflow:hiddenia pitkä tyypin nimi
   ("Kattilahalli") työntäisi sarakkeen leveämmäksi kapealla ruudulla -
   sama ansa joka on jo kirjattu MEMORY.md:n mobiilivuoto-oppiin. */
.vk-ryhmaotsikko {
  display: flex; align-items: center; justify-content: center;
  height: 24px; padding: 0 4px;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12px; font-weight: 600; letter-spacing: 0.01em;
  color: var(--a-ink);
  /* Alaviiva siirretty #vkGroupsHead/#vkGroupsCorner-säiliöihin
     13.9.2026 (design-katselmus, portti 10): ks. perustelu niiden
     kohdalla. Tässä ei enää omaa reunaa, ettei viiva kaksinkertaistu. */
}
/* Kulma sitoo aikakiskon ja sarakeotsikot yhteen. Ilman sitä kellonaika
   irtoaa ruudukosta, ja se oli yksi syy leijumisen tuntuun.
   VaraaVuoro-klooni 2.9.2026: kulmassa lukee "alkaa" (brief kohta 4.4,
   sarakeotsikkorivi VaraaVuorossa). Teksti CSS:n content-arvona, ei DOM-
   muutosta: kulmassa ei ollut mitään sisältöä ennenkään. */
#vkCorner {
  grid-column: 1; grid-row: 2;
  position: sticky; top: 0; left: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center;
  background: var(--a-kisko);
  border-right: 1px solid var(--a-grid-line);
  border-bottom: 1px solid var(--a-grid-line);
}
#vkSheet.vk-ryhmat #vkCorner { top: 24px; }
#vkCorner::after {
  content: "alkaa";
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12px; font-weight: 400; color: var(--a-ink-3);
}

#vkColsHead {
  grid-column: 2; grid-row: 2;
  position: sticky; top: 0; z-index: 30;
  display: grid; grid-template-columns: var(--vk-tpl);
  background: var(--a-kisko);
  border-bottom: 1px solid var(--a-grid-line);
}
#vkSheet.vk-ryhmat #vkColsHead { top: 24px; }
/* Sarakeotsikko. VaraaVuoro-klooni 2.9.2026: 28 px korkea, 12 px fontti,
   1 px sisennys, ei lihavoitu (brief kohta 1 "Avainluvut"). Tausta on
   AINA jokin tyyppivari - rata (sininen) on oletus, biljardi/kabinetti
   ohittavat sen alla (data-tyyppi luetaan JS:sta, ks. varauskirja.js
   piirraOtsikot). Ei enaa hiljainen/neutraali otsikko: VaraaVuorossa
   JOKA sarakeotsikko on varillinen pinta, ei vain teksti. */
.vk-col {
  display: flex; align-items: center; justify-content: center;
  height: 28px; padding: 0 1px;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12px; font-weight: 400; letter-spacing: 0.01em;
  background: var(--a-head-rata);
  color: var(--a-head-ink);
  font-variant-numeric: tabular-nums;
  overflow: hidden; white-space: nowrap;
}
.vk-col[data-tyyppi="biljardi"]  { background: var(--a-head-biljardi); }
.vk-col[data-tyyppi="kabinetti"] { background: var(--a-head-kabinetti); }
.vk-col span { overflow: hidden; text-overflow: ellipsis; }
.vk-col + .vk-col { box-shadow: inset 1px 0 0 rgba(255,255,255,0.28); }
.vk-col.ryhma-alku { box-shadow: none; }
.vk-gaphead { justify-self: center; width: 1px; background: var(--a-grid-line); }

/* Toistettu otsikkorivi taulukon alareunassa. VaraaVuoro-klooni 2.9.2026,
   brief kohta 4.4. Sama ulkoasu kuin #vkColsHead/#vkCorner mutta EI
   sticky (rivi on jo kiinni taulukon alareunassa) eika interaktiivinen:
   pointer-events: none varmistaa ettei kopio voi koskaan nayttaa
   klikattavalta vaikka .vk-col-luokka on sama. */
#vkCornerFoot {
  grid-column: 1; grid-row: 4;
  display: flex; align-items: center; justify-content: center;
  background: var(--a-kisko);
  border-right: 1px solid var(--a-grid-line);
  border-top: 1px solid var(--a-grid-line);
}
#vkCornerFoot::after {
  content: "alkaa";
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12px; font-weight: 400; color: var(--a-ink-3);
}
#vkColsFoot {
  grid-column: 2; grid-row: 4;
  display: grid; grid-template-columns: var(--vk-tpl);
  background: var(--a-kisko);
  border-top: 1px solid var(--a-grid-line);
  pointer-events: none;
}

/* AIKAKISKO. Oma pinta, oma tausta, oma reuna. Tämä on se mihin varaukset
   ankkuroituvat, joten se ei saa olla läpinäkyvä eikä sulautua arkkiin. */
#vkTimes {
  grid-column: 1; grid-row: 3;
  position: sticky; left: 0; z-index: 20;
  background: var(--a-kisko);
  border-right: 1px solid var(--a-grid-line);
}
/* Tasatunti/puolitunti. VaraaVuoro-klooni 2.9.2026: aikasarake vuorottelee
   kahden taustan välillä (brief kohta 3 "Rakenne": tasatunti rgb(238,238,238),
   puolitunti valkoinen). KORJATTU 2.9.2026: aiempi versio kirjoitti
   `.vk-t.on-tunti`/`.on-puoli`, mutta JS merkitsee tasatunnin luokalla
   `.hour` (rivi ~753, `t.className = 'vk-t' + (min%60===0 ? ' hour' : '')`)
   eikä puolitunnille mitään omaa luokkaa lainkaan - `.on-tunti`/`.on-puoli`
   ei koskaan täsmännyt mihinkään, sääntö oli kuollutta CSS:ää jo ennen
   tätä kloonia. Puolitunti on nyt PERUSSÄÄNTÖ .vk-t:ssä, tasatunti
   ohittaa sen .hour-luokalla.

   KIERROS 3 (2.9.2026), brief kohta 3: "monospace-numerot näyttävät
   raa'oilta". Syy oli etta font-family oli 'Geist Mono' - oikea
   MONOSPACE-KIRJASIN, ei vain tabular-nums. Kelloissa (ja koko sivun
   muissa numeroissa, ks. .vk-col/.a-paiva-pvm) haluttu keino on
   font-variant-numeric: tabular-nums SUHTEELLISELLA kirjasimella (Geist),
   joka pitää numerot tasalevyisina mutta sailyttaa kirjasimen oman
   muodon - monospace-kirjasin tekee jokaisesta merkista (myos pisteesta)
   saman levyisen, mika lukee koneellisena. .vk-t-tunti/.vk-t-puoli
   (vanhat, kaytatta olevat position:absolute;top:-8px -saannot) POISTETTU:
   ne eivat tasmanneet mihinkaan elementtiin (JS luo vain .aika-spanin),
   joten ne olivat kuollutta koodia joka nayrtti aktiiviselta. */
.vk-t {
  position: relative;
  height: var(--vk-row-h, 26px);
  font-family: 'Geist', ui-sans-serif, system-ui, sans-serif;
  font-variant-numeric: tabular-nums;
  background: var(--a-aika-puoli);
  border-top: 1px solid var(--a-grid-line);
}
.vk-t.hour { background: var(--a-aika-tunti); }
/* .aika: puolitunti on PERUSSÄÄNTÖ (kevyt, harmaa), tasatunti korostuu
   .hour-luokan kautta (tummempi, hieman paksumpi) - brief kohta 3
   "tasatunnit korostettuina..., puolitunnit vaaleampina ja kevyempinä.
   Se antaa silmälle rytmin ilman viivoja." line-height = rivikorkeus
   keskittää numeron pystysuunnassa ilman flexiä; padding-right on
   "pieni sisennys numeron ja ruudukon välissä" (sama kohta). */
.aika {
  display: block;
  padding-right: 8px;
  text-align: right;
  font-size: 12px; font-weight: 400;
  color: var(--a-ink-3);
  line-height: var(--vk-row-h, 26px);
  white-space: nowrap;
}
/* KIERROS 3 JATKO (2.9.2026 ilta): Simo palautti rivikorkeuden ja fontin
   VaraaVuoron omiin mittoihin (26 px / 12 px, ks. varauskirja.js RIVI_H).
   Fonttikoko on siis nyt SAMA molemmilla - paino ja väri (ei enää koko)
   erottavat tasatunnin puolitunnista, "kellonajat tyylikkäämmiksi"
   -vaatimus (KIERROS 3 kohta 3) pysyy voimassa vaikka koko yhtenäistyi. */
.vk-t.hour .aika { font-weight: 700; color: var(--a-ink); }

/* ARKKI. Tähän kaikki kerrokset piirtyvät. VaraaVuoro-klooni 2.9.2026:
   POISTETTU vanha tuntikaistan zebra-raidoitus (repeating-linear-gradient).
   Se oli vanhan tumman designin vastaus "leijumiseen"; VaraaVuoron arkki
   on tasainen valkoinen, ja rivien erot tulevat border-collapse-viivoista
   (ks. #vkRows alla), ei taustasävyistä. */
#vkCanvas {
  grid-column: 2; grid-row: 3;
  position: relative;
  display: grid; grid-template-columns: var(--vk-tpl);
  background: var(--a-arkki-0);
}

/* Kerros 1: tuntiviivoitus. Joka toinen tunti on eri sävyinen kaista.
   TÄMÄ ON SE JOKA POISTAA LEIJUMISEN: tyhjä ruutu ei ole tyhjä vaan
   viivoitettua paperia, eikä varauksella ole tyhjyyttä johon kellua. */
#vkZones {
  position: absolute; inset: 0; z-index: 0;
  display: grid; grid-template-columns: var(--vk-tpl);
  pointer-events: none;
}
/* position: absolute ON PAKOLLINEN, ei koristetta.
   JS sijoittaa jokaisen kaistan `style.top`-arvolla (piirraVyohykkeet).
   Portauksessa jai pelkka `display: block`, jolloin `top` oli merkitykseton
   ja kaista latautui gridin virtaan ruudukon ylareunaan. Mitattu 10.8.2026:
   ILTA-vyohykkeen kaista sai top: 608px mutta piirtyi kohtaan -425px, eli
   kokonaan ruudun ulkopuolelle. Vyohykkeet olivat siis nakymattomia. */
#vkZones i { display: block; position: absolute; left: 0; right: 0; }

/* Hintavyohykkeen savy. Sama kaksi askelta kuin viivoitetussa paperissa,
   jotta vyohyke on materiaalia eika uusi vari: taso 0 on arkki itse eika
   sita piirreta lainkaan. `--vk-zone-*` jai portauksessa maarittelematta,
   joten taustaa ei ollut lainkaan - kaista oli lapinakyva. */
/* Arvot suoraan, ei omaa muuttujaa. Ensimmainen versio kaytti nimia
   --a-vyo-1 ja --a-vyo-2 joita ei maaritelty missaan; fallback pelasti
   deklaraation, mutta maarittelematon nimi on ansa: jos joku poistaa
   fallbackin, koko saanto mitatoityy hiljaa. */
#vkZones i.lv1 { background: rgba(255,255,255,0.022); }
#vkZones i.lv2 { background: rgba(255,255,255,0.045); }
:root[data-theme="light"] #vkZones i.lv1 { background: rgba(20,19,28,0.028); }
:root[data-theme="light"] #vkZones i.lv2 { background: rgba(20,19,28,0.055); }

/* AUKIOLON ULKOPUOLINEN ALUE. Ruudukko on joka paiva 8.00-23.30, joten
   arkena yli puolet siita on aukiolon ulkopuolella. Viivoitus kertoo sen
   yhdella silmayksella.

   VIIVOITUS EIKA TUMMENNUS: tummennus on jo menneen ajan merkki (#vkPast),
   ja maanantaiaamu on molempia. Kaksi eri asiaa ei saa nayttaa samalta.
   Kuvio on myos varista riippumaton (WCAG 1.4.1) ja selviaa tulosteessa. */
#vkZones i.suljettu {
  background: repeating-linear-gradient(
    -45deg,
    rgba(255,255,255,0.030) 0 1px,
    transparent 1px 9px);
}
:root[data-theme="light"] #vkZones i.suljettu {
  background: repeating-linear-gradient(
    -45deg,
    rgba(20,19,28,0.055) 0 1px,
    transparent 1px 9px);
}

/* Kuilun oma merkki samasta asiasta: katkoviiva vasemmassa reunassa ja
   kursivoitu kellonaika. Sailyy vanhasta designista, koska se toimii myos
   silloin kun ruudukko on vieritetty sivusuunnassa pois viivoituksen alta. */
.vk-t.ulkopuoli::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: repeating-linear-gradient(
    180deg, var(--a-ink-3) 0 3px, transparent 3px 6px);
  opacity: .5;
}
.vk-t.ulkopuoli .aika { font-style: italic; }


/* Kerros 2: rivit. Tuntiviiva on ainoa joka kulkee koko leveyden yli. */
#vkRows { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
/* VaraaVuoro-klooni 2.9.2026: border-collapse-nakoinen ruudukko, sama
   viivavari joka rivilla (brief kohta 1: border-collapse: collapse). */
.vk-r { height: var(--vk-row-h, 26px); border-top: 1px solid var(--a-grid-line); }
.vk-r.hour, .vk-r.zone { border-top-color: var(--a-grid-line); }

/* Kerros 3: mennyt aika. Ei uutta väriä, vain kylläisyyden lasku. */
#vkPast {
  position: absolute; left: 0; right: 0; top: 0; z-index: 2;
  background: rgba(8,7,14,0.42);
  pointer-events: none;
}
:root[data-theme="light"] #vkPast { background: rgba(20,19,28,0.05); }

/* Kerros 4: ratojen pystyviivat. Roope: erottele radat pystysuunnassa. */
#vkLanes {
  position: absolute; inset: 0; z-index: 3;
  display: grid; grid-template-columns: var(--vk-tpl);
  pointer-events: none;
}
#vkLanes i { display: block; }
#vkLanes i + i { box-shadow: inset 1px 0 0 var(--a-grid-line); }

#vkHoverRow {
  position: absolute; left: 0; right: 0; top: 0; z-index: 4;
  height: var(--vk-row-h, 26px);
  background: rgba(74,144,226,0.08);
  pointer-events: none; will-change: transform;
}
.vk-gapline { grid-row: 1; align-self: stretch; justify-self: center; width: 1px; background: var(--a-viiva-reuna); z-index: 5; }

/* ---------------------------------------------------------------------------
   VARAUS. Solu, ei kortti.

   Ei sivumarginaalia, ei pyöristystä, ei varjoa, ei skaalausta. Solu
   täyttää sarakkeen reunasta reunaan ja sen ylä- ja alareuna ovat
   vahvempia kuin ruudukon omat viivat, joten se lukee ruudukkoon
   leikattuna alueena eikä sen päälle asetettuna esineenä.
   --------------------------------------------------------------------------- */
/* VaraaVuoro-klooni 2.9.2026: tiiviimpi sisennys (brief kohta 1, datasolun
   sisennys 6 px) - 26 px korkealle riville vanha 5/9/13 px oli liikaa. */
.vk-block {
  grid-row: 1;
  position: relative; z-index: 6;
  align-self: start;
  margin: 0;
  overflow: hidden;
  background: var(--a-solu);
  border-top: 1px solid var(--a-grid-line);
  border-bottom: 1px solid var(--a-grid-line);
  border-radius: 0;
  padding: 3px 6px 3px 10px;
  text-align: left;
  cursor: pointer;
  transition: background var(--a-nopea) var(--a-kaari);
}
.vk-block:hover { background: var(--a-solu-hi); }
.vk-block:focus-visible { outline: 2px solid var(--a-nyt); outline-offset: -2px; }

/* Tilapalkki vasemmassa reunassa. Se on 4 px ja kiinni reunassa, joten se
   lukee solun reunana eikä koristeviivana kortin sisällä. */
.vk-block::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--a-ink-3);
}
.vk-block[data-maksamaton]::before  { background: var(--a-toimi); }
.vk-block[data-maksettu]::before    { background: var(--a-kunnossa); }
.vk-block[data-laskutukseen]::before { background: var(--a-laskutus); }
.vk-block[data-rikki]::before       { background: var(--a-rikki); }

/* ============================================================
   VARAUKSEN TILA. Nama luokat JS kirjoittaa jokaiseen palikkaan
   (`tilaLuokat()`, varauskirja.js), mutta uudessa designissa niille ei
   ollut yhtaan saantoa: menneet, saapumatta jattaneet, kaynnissa olevat
   ja huomiota vaativat varaukset nayttivat tasmalleen samalta kuin
   tavalliset. Loysi 10.8.2026 automaattinen sopimustarkistin, ei ihminen.

   Tulevat TARKOITUKSELLA data-attribuuttien jalkeen. Erottelutarkkuus on
   sama, joten jarjestys ratkaisee, ja se on oikea suunta: "vaatii teon"
   voittaa "maksettu". Maksettu varaus jonka asiakas jatti saapumatta on
   rahaa hallille, eika se saa nayttaa hoidetulta.

   Vari ei ole yhdessakaan naista ainoa erotin (WCAG 1.4.1): mennyt on
   lapinakyvyys, saapumatta jaanyt on yliviivaus, kaynnissa oleva on
   reunaviiva. Ne selviavat myos harmaasavysta.
   ============================================================ */

/* KAYNNISSA NYT. --a-nyt oli designissa valmiina ("kaynnissa nyt ja
   nykyhetken viiva") mutta jai kytkematta. */
.vk-block.nyt::before { background: var(--a-nyt); }
.vk-block.nyt {
  border-top: 2px solid var(--a-nyt);
  padding-top: 2px;
}

/* VAATII TEON. Sama savy kuin maksamattomassa, koska merkitys on sama:
   ihminen, tee jotain. */
.vk-block.attn::before { background: var(--a-toimi); }

/* EI SAAPUNUT. Yliviivaus kertoo etta vuoro jai pelaamatta; palkki pysyy
   toimi-savyisena koska raha on yha auki. */
.vk-block.eisaapunut::before { background: var(--a-toimi); }
.vk-block.eisaapunut .nimi {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

/* MENNYT. Ei uutta varia vaan kyllaisyyden lasku, sama keino kuin
   menneen ajan peitteella (#vkPast). */
.vk-block.mennyt { opacity: 0.45; }
.vk-block.mennyt .nimi { color: var(--a-ink-2); }

/* MARKIN TEKEMA VARAUS. Orb on oikeassa ylakulmassa; jos varauksessa on
   MYOS lisatieto, sen piste osuisi orbin paalle. Tama siirtaa pisteen
   alemmas. Pelkka orb tai pelkka piste ei tarvitse tata. */
.vk-block.mark .piste { top: 17px; }

/* VALITTU VARAUS. Uudessa designissa ei ollut valinnalle mitaan merkkia:
   palikan napsautus avasi paneelin, mutta ruudukossa ei nakynyt MISTA
   varauksesta paneeli kertoo. Kymmenella radalla ja tiheassa illassa se
   on arvausta. Reunan paksuuntuessa sisennys pienenee saman verran,
   jottei teksti hyppaa valinnan mukana. */
.vk-block.valittu {
  background: color-mix(in srgb, var(--a-nyt) 18%, var(--a-solu));
  /* border-style: solid on PAKOLLINEN. Palikan perussaanto asettaa vain
     `border-top`, joten muiden sivujen tyyli on `none` ja niiden LEVEYS
     pakottuu nollaan riippumatta siita mita tassa pyytaa. Mitattu
     selaimesta: pelkka border-color + border-width antoi computed-arvon
     "0.8px 0px" eli kehys nakyi vain ylareunassa. */
  border-style: solid;
  border-color: var(--a-nyt);
  border-width: 1.5px;
  padding: 2.5px 6.5px 2.5px 9.5px;
}
.vk-block.valittu.nyt { padding-top: 1.5px; }

/* Teksti on AINA valkoinen varauspalikan sisalla, riippumatta --a-ink-
   muuttujan yleisesta arvosta: varauskirjan yleisteksti on nyt tumma
   (vaalea teema), mutta palikan tausta on tummanpunainen/musta/oranssi
   ja tarvitsee oman, palikkakohtaisen kontrastinsa. VaraaVuoro-klooni
   2.9.2026, brief kohta 3 "Teksti"-sarake. */
.vk-block .nimi {
  display: block;
  font-size: 12px; font-weight: 550; line-height: 1.25;
  color: #FFFFFF;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vk-block .meta {
  display: block; margin-top: 2px;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 11px; font-weight: 400; line-height: 1.3;
  color: rgba(255,255,255,0.78);
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Alle 52 px korkea solu: kaksi riviä ei mahdu, joten meta piiloon ja nimi
   keskitetään. Fonttia ei pienennetä, koska pieni fontti hämärässä hallissa
   on huonompi kuin puuttuva metarivi. */
.vk-block.vk-matala { padding-top: 0; padding-bottom: 0; display: flex; align-items: center; }
.vk-block.vk-matala .meta { display: none; }

/* Monelle radalle jatkuva varaus: kaistaviiva näyttää rajan, mutta solu
   pysyy yhtenä. */
.vk-block .kaista {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: rgba(196,193,222,0.16);
}
.vk-block .orb {
  position: absolute; right: 8px; top: 8px; width: 6px; height: 6px;
  border-radius: 50%; background: var(--a-nyt);
}
.vk-block .piste {
  position: absolute; right: 8px; bottom: 8px; width: 5px; height: 5px;
  border-radius: 50%; background: var(--a-ink-3);
}
.vk-block[data-tila="peruttu"] { opacity: .45; }
.vk-block.on {
  background: var(--a-solu-hi);
  border-top-color: var(--a-nyt); border-bottom-color: var(--a-nyt);
  box-shadow: inset 0 0 0 1px var(--a-nyt);
}

/* Nykyhetki. Violetti eikä punainen: punainen olisi ruudulla 100 % ajasta
   ja veisi terän päällekkäisvaraukselta, joka on ainoa oikea hälytys. */
#vkNow {
  position: absolute; left: 0; right: 0; z-index: 8;
  height: 2px; background: var(--a-nyt);
  pointer-events: none;
}
/* KIERROS 3 (2.9.2026): siirretty #vkCanvasin SISÄLLE HTML:ssä (ennen
   #vkCanvasin ULKOPUOLINEN sisarus #vkSheet-gridissä, ilman omaa
   grid-column/row-sijoitusta - containing block putosi ylös asti
   .a-mainiin, ainoaan position:relative-esivanhempaan, ja rivi piirtyi
   kortin ylälaidan tienoille väärällä leveydellä: mitattu Playwrightilla
   x:0,y:232,w:1536,h:19 kun kortti itse alkoi x:20:sta - "22."-tekstin
   katkeaminen kortin reunaan oli seuraus, ei oma bugi. #vkCanvas on
   position:relative kuten #vkNow, joten containing block ja leveys ovat
   nyt oikein ilmaiseksi.) z-index 7->9: pitää dashed-viivan #vkCellsin
   (z 8, kirkkaat vapaa-solut) YLÄPUOLELLA, sama periaate kuin #vkNow. */
#vkEndMark {
  position: absolute; left: 0; right: 0; z-index: 9;
  border-top: 1px dashed var(--a-viiva-reuna);
  pointer-events: none;
}
/* KIERROS 3 JATKO (2.9.2026): kun elementti sai vihdoin OIKEAN sijainnin
   (ks. varauskirja.js piirraKuilu), sen textContent piirtyi raakana,
   tyylittelemattomana tekstina suoraan varatun/vapaan solun paalle -
   mitattu heti paikallisella esikatselulla: sama "irrallinen teksti"
   -vaikutelma jonka piti poistua, vain oikeassa kohdassa. ::after +
   attr(data-teksti) antaa sille oman pienen, kortin pintavarisen
   taustalapun (sama --a-kisko kuin aikakisko), jotta se pysyy luettavana
   riippumatta siita mika solu sattuu olemaan viivan alla. */
#vkEndMark::after {
  content: attr(data-teksti);
  position: absolute; left: 6px; top: 2px;
  font-size: 10px; font-weight: 600; color: var(--a-ink-2);
  background: var(--a-kisko);
  padding: 1px 6px;
  border-radius: 3px;
  white-space: nowrap;
  text-transform: lowercase;
}

/* ---------------------------------------------------------------------------
   PANEELI. Liukuu oikealta, ruudukko jää näkyviin. Ei modaalia joka
   peittää päivän: tiskillä pitää nähdä sekä varaus että sen ympäristö.
   --------------------------------------------------------------------------- */
#vkPanel {
  position: relative; z-index: 50;
  width: 360px; flex: none;
  display: flex; flex-direction: column;
  background: var(--a-kisko);
  border-left: 1px solid var(--a-viiva-reuna);
  overflow-y: auto;
}
/* Paneelin avaa varauskirja.js luokalla .auki, EI hidden-attribuutilla
   (varauskirja.js rivit 1480, 1668, 1818). Jos tama sidotaan hiddeniin,
   paneeli saa datan mutta ei nay koskaan. Mitattu 10.8.2026. */
#vkPanel { transform: translateX(100%); width: 0; border-left: 0; overflow: hidden; transition: transform var(--a-normi) var(--a-kaari); }
#vkPanel.auki { transform: none; width: 360px; border-left: 1px solid var(--a-viiva-reuna); overflow-y: auto; }

.a-panel-head {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 18px 18px 14px;
  border-bottom: 1px solid var(--a-viiva-puoli);
}
#vkPanelTag {
  display: inline-block; margin-bottom: 7px;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 10.5px; font-weight: 500; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--a-ink-3);
}
#vkPanelName { font-size: 17px; font-weight: 600; color: var(--a-ink); letter-spacing: -0.01em; }
#vkPanelWhen {
  display: block; margin-top: 3px;
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12.5px; color: var(--a-ink-2); font-variant-numeric: tabular-nums;
}
#vkPanelSarja { display: block; margin-top: 5px; font-size: 12px; color: var(--a-ink-3); }
#vkPanelClose { margin-left: auto; }

.a-panel-body { padding: 16px 18px; display: flex; flex-direction: column; gap: 16px; }

/* varauskirja.js lisaa <dt> ja <dd> suoraan #vkFacts-elementtiin, ei
   kaarittyna. Siksi ruudukko on dl:ssa itsessaan. Mitattu 10.8.2026:
   kaarityta odottava saanto renderoi faktat pystylistaksi. */
#vkFacts {
  display: grid; grid-template-columns: 92px 1fr;
  align-items: baseline;
  font-size: 13px;
}
#vkFacts dt {
  padding: 9px 12px 9px 0;
  color: var(--a-ink-3);
  border-top: 1px solid var(--a-viiva-puoli);
}
#vkFacts dd {
  padding: 9px 0;
  color: var(--a-ink);
  border-top: 1px solid var(--a-viiva-puoli);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
#vkFacts dt:first-of-type, #vkFacts dt:first-of-type + dd { border-top: 0; }

#vkMaksu { padding: 13px 14px; background: var(--a-arkki-1); border-left: 3px solid var(--a-toimi); }
#vkMaksu[data-tila="maksettu"] { border-left-color: var(--a-kunnossa); }
#vkMaksu[data-tila="laskutukseen"] { border-left-color: var(--a-laskutus); }
#vkMaksuTila { display: block; margin-bottom: 9px; font-size: 13px; color: var(--a-ink); }

/* Kolme maksutilaa yhtenä nappiryhmänä (Roope 3.9.2026, ks. design/BRIEF_
   maksutila_kolme_vaihtoehtoa.md): korvaa entisen yhden kuittausnapin.
   Valittu tila erottuu täytevärillä; napit ovat muuten samaa .a-nappi-
   perhettä kuin muualla paneelissa. */
#vkMaksuValinta { display: flex; flex-wrap: wrap; gap: 6px; }
.vk-maksu-nappi { flex: 1 1 auto; }
.vk-maksu-nappi[aria-pressed="true"] {
  font-weight: 600;
  color: #FFFFFF;
  border-color: transparent;
}
.vk-maksu-nappi[data-maksutila="maksamaton"][aria-pressed="true"] { background: var(--a-toimi); border-color: var(--a-toimi); color: var(--a-toimi-ink); }
.vk-maksu-nappi[data-maksutila="maksettu"][aria-pressed="true"]   { background: var(--a-kunnossa); border-color: var(--a-kunnossa); }
.vk-maksu-nappi[data-maksutila="laskutukseen"][aria-pressed="true"] { background: var(--a-laskutus); border-color: var(--a-laskutus); }
.vk-maksu-nappi:disabled { opacity: 0.6; cursor: default; }

.a-kentta { display: flex; flex-direction: column; gap: 5px; }
.a-kentta label { font-size: 12px; color: var(--a-ink-3); }
.a-kentta input, .a-kentta textarea, .a-kentta select {
  font-family: inherit; font-size: 13.5px; color: var(--a-ink);
  padding: 9px 10px;
  background: var(--a-arkki-0);
  border: 1px solid var(--a-viiva-rata);
  border-radius: 3px;
}
.a-kentta input:focus, .a-kentta textarea:focus, .a-kentta select:focus {
  outline: none; border-color: var(--a-nyt); box-shadow: inset 0 0 0 1px var(--a-nyt);
}
.a-kentta-pari { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.a-panel-toiminnot { margin-top: auto; padding: 14px 18px; border-top: 1px solid var(--a-viiva-puoli); display: flex; gap: 8px; }

/* Siirtolomakkeen nuolirivi (jono #144): kaksi olemassa olevaa
   .a-nappi-ikoni-nappia vierekkain, saman parin alla jota ne siirtavat.
   Ei uusia vareja eika fontteja - vain rivitys, samat napit kuin muualla
   paneelissa (esim. vkPanelClose). */
.vk-siirto-nuolet { display: flex; gap: 8px; margin-top: -6px; }
#vkSiirtoTila { display: block; font-size: 12.5px; color: var(--a-ink-3); }
#vkSiirtoTila:empty { display: none; }

/* Asiakastiedon muokkaus (14.9.2026): virhe suoraan kentän alla, ei uusi
   väri - sama --a-rikki jota .a-tila.on-virhe jo käyttää. #vkAsiakasHuomio
   käyttää samaa harmaata kuin muut paneelin sivuhuomautukset (esim.
   #vkSiirtoTila). Kentät eivät voi ylileveydä 360 px:n ruudulla, koska
   .a-kentta input perii jo 100 % leveyden ja * { box-sizing: border-box }
   on globaali (rivi 260) - ei tarvinnut min-width:0:aa lisätä. */
.vk-kentta-virhe { display: block; font-size: 12px; color: var(--a-rikki); }
.vk-kentta-virhe:empty { display: none; }
#vkAsiakasVirhe { display: block; font-size: 12.5px; color: var(--a-rikki); }
#vkAsiakasVirhe:empty { display: none; }
#vkAsiakasHuomio { display: block; font-size: 12.5px; color: var(--a-ink-3); }
#vkAsiakasHuomio:empty { display: none; }

/* Virhereuna suoraan kentässä (web designer 15.9.2026): pelkkä teksti
   kentän alla huomataan kiireessä liian hitaasti, fokusreuna jää siniseksi
   eikä erotu virheestä. Sama --a-rikki kuin virheteksti yllä - yksi väri,
   ei kaksi eri punaista. Poistetaan JS:stä (poistaKenttaInvalid) kun
   kenttää muokataan tai virheet nollataan. */
/* Spesifisyys .a-kentta input(.vk-kentta-invalid):focus asti, muuten
   .a-kentta input:focus (rivi ~1088, kolme selektoria) voittaisi tämän
   kahden selektorin säännön eikä virhereuna näkyisi fokuksessa. */
.a-kentta input.vk-kentta-invalid,
.a-kentta input.vk-kentta-invalid:focus {
  border-color: var(--a-rikki); box-shadow: inset 0 0 0 1px var(--a-rikki);
}

/* ---------------------------------------------------------------------------
   TYHJÄ, SULJETTU, LATAUS
   Rakenne piirretään aina. Tyhjä ruudukko ei saa koskaan olla tyhjä sivu.
   --------------------------------------------------------------------------- */
#vkClosed {
  position: absolute; inset: 0; z-index: 45;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  background: rgba(8,7,14,0.86);
  text-align: center; padding: 24px;
}
#vkClosed[hidden] { display: none; }
#vkClosedTitle { font-size: 19px; font-weight: 600; color: var(--a-ink); }
#vkClosedText { font-size: 13.5px; color: var(--a-ink-2); max-width: 40ch; }

/* ---------------------------------------------------------------------------
   KALENTERI JA VAKIOVUOROT: kelluvia pintoja, ainoat varjolliset.
   --------------------------------------------------------------------------- */
#vkCal, #vkSarjat {
  position: absolute; z-index: 60;
  background: var(--a-kisko);
  border: 1px solid var(--a-viiva-reuna);
  border-radius: 4px;
  box-shadow: 0 24px 60px -20px rgba(0,0,0,0.7);
}
#vkCal[hidden], #vkSarjat[hidden] { display: none; }
#vkCal { top: 96px; left: 18px; width: 280px; padding: 12px; }
#vkSarjat { top: 96px; right: 18px; width: 420px; max-height: 70vh; overflow-y: auto; padding: 16px; }
.a-cal-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
#vkCalLabel { flex: 1; text-align: center; font-size: 13px; font-weight: 600; color: var(--a-ink); }
.a-cal-wd { display: grid; grid-template-columns: repeat(7,1fr); gap: 2px; margin-bottom: 4px; }
.a-cal-wd span {
  text-align: center; font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 10px; color: var(--a-ink-3);
}
#vkCalGrid { display: grid; grid-template-columns: repeat(7,1fr); gap: 2px; }
#vkCalGrid button {
  aspect-ratio: 1; font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12px; color: var(--a-ink-2);
  background: transparent; border: 1px solid transparent; border-radius: 2px; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
#vkCalGrid button:hover { background: var(--a-arkki-1); color: var(--a-ink); }
#vkCalGrid button.on { background: var(--a-toimi); color: var(--a-toimi-ink); font-weight: 600; }
#vkCalGrid button.tanaan { border-color: var(--a-nyt); }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
/* ============================================================
   SILTA: vanhat --vk-* -tunnukset uuden designin --a-* -paletista.

   MIKSI TAMA ON OLEMASSA (10.8.2026)
   varauskirja.js luo ajossa 35 luokkaa. Uusi aikataulu.css tyylitteli
   niista 12. Loput 23 - solut joista varaus luodaan, maksumerkinta,
   koko raahaustoiminto, kalenterin paivat, paneelin napit ja
   vakiovuorot - jaivat kokonaan ilman tyyleja. Se on se "todella
   paljon bugeja" jonka Simo naki.

   Puuttuvat saannot poimittiin tuotannon varauskirja.css:sta
   (68 saantoa) sen sijaan etta ne olisi kirjoitettu uusiksi: ne ovat
   jo todennettuja ja ne vastaavat tasmalleen sita mita JS odottaa.
   Ne kayttavat --vk-* -tunnuksia, joita uusi design ei maarittele.

   Siksi tama silta. Yksi kartta on parempi kuin 68 uudelleen
   kirjoitettua saantoa: uusi paletti nakyy lapi, eika kumpikaan
   tiedosto tarvitse toisen sisaltoa.
   ============================================================ */
:root {
  /* ---- RAKENNEMUUTTUJAT: JS-SOPIMUKSEN OLETUKSET ----
     varauskirja.js asettaa nama ajossa #vkSheet-elementtiin:
       --vk-tpl        sarakemalli, esim. "minmax(var(--vk-col-min),1fr) 12px ..."
       --vk-col-min    sarakkeen vahimmaisleveys
       --vk-inner-min  arkin vahimmaisleveys
       --vk-row-h      rivikorkeus
     ja LUKEE taman:
       --vk-gutter     aikakiskon leveys (JS laskee silla sarakeleveyden)

     MIKSI OLETUKSET OVAT PAKOLLISIA. CSS mitatoi koko deklaraation jos
     var() ei ratkea. `grid-template-columns: var(--vk-tpl)` ilman arvoa
     ei siis tarkoita "yksi sarake" vaan "ei sarakemallia" - ja silloin
     grid pinoaa kaiken YHTEEN sarakkeeseen.

     MITATTU 10.8.2026: Simo naki 13 radan sijasta yhden. Sarakeotsikot
     pinoutuivat paallekkain (nakyi vain "Rata 1") ja varaukset venyivat
     koko leveydelle. Vanha varauskirja.css maaritteli --vk-gutter:96px;
     uusi ei maaritellyt naista yhtaan. Siltakerros kartoitti VARIT
     muttei rakennetta - se oli minun aukkoni.

     --vk-gutter on 76px eika 96px, koska uuden designin aikakisko on
     --a-mitta-kisko: 76px. Vaara arvo ei kaada mitaan mutta laskee
     sarakeleveyden 20 pikselia vaarin joka piirrossa. */
  --vk-tpl: repeat(auto-fit, minmax(55px, 1fr));
  --vk-col-min: 55px;
  --vk-inner-min: 0px;
  --vk-row-h: 26px;
  --vk-gutter: var(--a-mitta-kisko, 76px);

  --vk-ink-1: var(--a-ink);
  --vk-ink-2: var(--a-ink-2);
  --vk-ink-3: var(--a-ink-3);

  --vk-line-1: var(--a-viiva-puoli);
  --vk-line-2: var(--a-viiva-reuna);

  --vk-block:       var(--a-solu);
  --vk-block-hover: var(--a-solu-hi);

  --vk-accent:      var(--a-kunnossa);
  --vk-accent-hi:   var(--a-kunnossa);
  --vk-accent-line: var(--a-kunnossa);
  --vk-accent-soft: color-mix(in srgb, var(--a-kunnossa) 16%, transparent);
  --vk-on-accent:   var(--a-toimi-ink);

  --vk-alert:      var(--a-rikki);
  --vk-alert-hi:   var(--a-rikki);
  --vk-alert-soft: color-mix(in srgb, var(--a-rikki) 14%, transparent);

  --vk-attn:      var(--a-toimi);
  --vk-attn-soft: color-mix(in srgb, var(--a-toimi) 14%, transparent);

  --vk-zone-1: var(--a-arkki-1);
  --vk-focus:  var(--a-nyt);

  --vk-r: 6px;
  --vk-t-hover: var(--a-nopea);
  --vk-ease: var(--a-kaari);
}
/* Jokainen kellonaika, hinta, henkilömäärä ja ratanumero on tasarivissä.
   Tämä on yhden rivin ero ammattitaulukon ja Excelin välillä. */
.vk-num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
.vk-cal-day {
  height: 32px; padding: 0;
  border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--vk-ink-2); cursor: pointer;
  font-size: 12.5px; font-weight: 470;
  font-variant-numeric: tabular-nums;
}
.vk-cal-day:hover { color: var(--vk-ink-1); border-color: var(--vk-line-2); }
.vk-cal-day.out { color: var(--vk-ink-3); opacity: 0.45; }
.vk-cal-day.today { color: var(--vk-accent-hi); font-weight: 590; }
.vk-cal-day.sel {
  background: var(--vk-accent-soft); border-color: var(--vk-accent-line);
  color: var(--vk-ink-1); font-weight: 590;
}
/* Kohdistetun varauksen alku- ja loppuaika. Korostus on GRAFIIKKAA eikä
   tekstin painoa: tasatunti on jo ink-1 ja 590, joten pelkkä musteen
   nosto ei näkyisi lainkaan juuri niillä riveillä joilla varaukset
   useimmin alkavat. Hakanen kuilussa (ks. .vk-span) kantaa korostuksen. */
.vk-t.paat .aika { color: var(--vk-ink-1); }
/* Vyöhykkeen merkintä: nimi versaalina ja hinta sen alle. Hinta luetaan
   TEKSTINÄ, järjestys vaaleutena ja palkin voimakkuutena. Yksikään
   ulottuvuus ei ole värin varassa (WCAG 1.4.1). */
.vk-zonetag { display: block; margin-top: 2px; text-align: right; max-width: 100%; overflow: hidden; }
/* 10 px on koko sovelluksen pienin sallittu koko, ja sallittu vain
   versaalilabelissa jossa harveike on vähintään .08em. Kuilun leveys 96 px
   on mitattu tästä: "PÄIVÄSAIKA" mahtuu, pidempi katkeaa ja koko nimi jää
   title-attribuuttiin. */
.vk-zonetag b {
  display: block;
  font-size: 10px; line-height: 13px; font-weight: 540; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--vk-ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.vk-zonetag i {
  display: block; font-style: normal;
  font-size: 10.5px; line-height: 13px; font-weight: 540; color: var(--vk-ink-2);
  font-variant-numeric: tabular-nums;
}
/* Kuilun vasen reuna: 2 px palkki jonka VOIMAKKUUS kertoo vyöhyketason.
   Ei sävyä, ei väriä, ei neljättä ulottuvuutta. */
.vk-zonebar { position: absolute; left: 0; width: 2px; }
.vk-zonebar.lv0 { background: var(--vk-ink-3); opacity: 0.45; }
.vk-zonebar.lv1 { background: var(--vk-ink-2); }
.vk-zonebar.lv2 { background: var(--vk-ink-1); }
/* Kohdistetun varauksen aikaväli kuilun OIKEASSA reunassa: 2 px palkki
   varauksen alusta loppuun ja 7 px poikkiviiva kummassakin päässä.
   Vyöhykepalkki on kuilun vasemmassa reunassa, joten ne eivät voi mennä
   sekaisin. Tämä on vastaus siihen että varaus tuntui leijuvan: silmän
   ei tarvitse laskea riviä vaan kaksi päätä osoittavat kellonaikoihin. */
.vk-span {
  position: absolute; right: 0; width: 2px;
  color: var(--vk-ink-2); background: currentColor;
  pointer-events: none;
}
.vk-span.on { color: var(--vk-accent); }
.vk-span::before, .vk-span::after {
  content: ""; position: absolute; right: 0;
  width: 7px; height: 2px; background: currentColor;
}
.vk-span::before { top: 0; }
.vk-span::after { bottom: 0; }
/* Varoitusglyfi on oma elementtinsä eikä nimen perässä: pitkä nimi
   katkeaa kolmeen pisteeseen, ja silloin katkeaisi myös glyfi. Juuri se
   kaksoiskoodaus jonka värisokea käyttäjä tarvitsee katoaisi ensimmäisenä
   pitkänimisestä varauksesta. */
.vk-block.rikki .varoitus {
  position: absolute; top: 4px; right: 6px;
  font-style: normal; font-size: 12px; line-height: 1;
  color: var(--vk-alert-hi);
}
/* S1-brief (9.8.2026), vika 3: "MAKSAMATON tulee suoraan nimen ja
   kellonajan päälle". Mitattu selaimessa: sana renderöityy n. 73 px
   leveäksi (620-paino, iso koko), mutta nimelle oli varattu vain 62 px
   tilaa — 11 px vajaus, jonka verran merkki piirtyi jo LEVEÄSSÄ palikassa
   nimen viimeisten kirjainten päälle. Kapealla radalla (alle n. 80 px)
   73 px leveä position:absolute-lippu peitti nimen lähes kokonaan, koska
   absoluuttinen sijoitus ei välitä mitä sen alla on.

   Korjaus: merkki ei enää ole irrallinen kulmalippu vaan istuu SAMALLA
   gridrivillä kuin kellonaika (ks. .vk-block yllä: nimi omalla rivillään,
   aika ja lippu jakavat toisen rivin, lippu oikeassa reunassa). Aika
   kutistuu tarvittaessa lipun tieltä (grid-sarakkeet minmax(0,..)) — ei
   päällekkäisyyttä, koska molemmat ovat oman gridsolunsa sisällä eivätkä
   voi enää piirtyä toistensa päälle. Tämä on ainoa tapa jolla nimi,
   kellonaika JA maksutila mahtuvat kaikki näkyviin jo 30 minuutin
   varauksen 38 pikselissä (DOM-järjestystä nimi/aika/lippu ei saanut
   muuttaa, koska JS luo lipun aina viimeisenä sisarena — grid-rivi/sarake
   -sijoitus ratkaisee sen ilman DOM-muutosta). Kapealla radalla lippu
   itse typistyy kolmella pisteellä ennen kuin se söisi kellonajalta
   kaiken tilan. VÄRI EI OLE AINOA MERKKI missään näistä tapauksista
   (WCAG 1.4.1): sana on aina läsnä, vain sen leveys joustaa. */
/* ---- KORJAUS 9.8.2026 ILLALLA: lippu sai OMAN RIVINSA ----

   Ylla kuvattu kahden rivin ratkaisu poisti paallekkaisyyden, mutta ei
   luettavuutta. Mitattu tuotannosta (markai.fi, lauantai 8.8., 10 varausta):
   sana "Maksamaton" vaatii 73 px, ja yhdeksalle kymmenesta jai 20 px.
   Nayttoon tuli "M…", jolloin maksutilan kertoi kaytannossa enaa punainen
   vari — juuri se mika WCAG 1.4.1 kieltaa.

   Perustelu "fyysinen pikselirajoite" ei pitanyt: tavallinen yhden radan
   tunnin varaus on 97 px LEVEA mutta 114-228 px KORKEA. Niukkuus oli
   vaakasuuntaista ja ratkaisu haettiin vaakasuunnasta. Pystysuuntaa oli
   koko ajan 3-6 kertaa tarpeeksi.

   Nyt: nimi rivilla 1, kellonaika rivilla 2, maksumerkinta rivilla 3 koko
   leveydelta. Mikaan ei kilpaile tilasta, joten mikaan ei typisty. */
.vk-block .maksulippu {
  display: block; grid-column: 1 / -1; grid-row: 3;
  justify-self: start; min-width: 0; max-width: 100%;
  margin-top: 1px;
  font-style: normal; font-size: 9.5px; line-height: 12px;
  font-weight: 620; letter-spacing: 0.02em; text-transform: uppercase;
  color: var(--vk-alert-hi);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  pointer-events: none;
}
/* MATALA PALIKKA (30 min = 38 px): kolmatta rivia ei ole mihin mahduttaa,
   ja leikkautuva rivi olisi huonompi kuin lyhennetty sana — silloin
   maksutila katoaisi kokonaan. Naissa merkki palaa kellonajan viereen,
   mutta EI typistettyna sanana vaan yliviivattuna eurona: 11 px levea
   glyfi mahtuu aina, ja se erottuu MUODOLLA eika pelkalla varilla.
   Sana "Maksamaton" jaa DOMiin (font-size: 0 ei poista sita
   saavutettavuuspuusta), joten ruudunlukija lukee sen yha. */
.vk-block.vk-matala .maksulippu {
  grid-column: 2; grid-row: 2;
  align-self: center; justify-self: end;
  margin-top: 0;
  font-size: 0;
}
.vk-block.vk-matala .maksulippu::before {
  content: "€";
  display: inline-block;
  font-size: 11px; line-height: 12px; font-weight: 700; letter-spacing: 0;
  text-decoration: line-through; text-decoration-thickness: 1.5px;
}
/* ============================================================
   VARAUKSEN SIIRTO (raahaus ja näppäimistön siirtotila)

   Kolme tilaa, kolme eri viesti:
     .vk-raahaa   — tämä on nyt kädessäsi
     .vk-esto     — tähän ei voi pudottaa
     .vk-siirtyy  — palvelin miettii

   Estotila ei nojaa väriin: mukana on 45 asteen viivoitus, sama
   kaksoiskoodaus kuin päällekkäisyydessä (.vk-block.rikki). Noin
   1/12 mieskäyttäjästä ei erota punaista taustastaan, ja tiskillä
   se on juuri se hetki jolloin tieto tarvitaan heti.
   ============================================================ */
.vk-block.vk-raahaa {
  z-index: 30;
  cursor: grabbing;
  border-color: var(--vk-accent);
  border-width: 1.5px;
  padding: 2.5px 6.5px 2.5px 9.5px;
  /* Varjo on tässä perusteltu vaikka muualla ruudukossa ei ole varjoja:
     nostettu palikka on ainoa asia joka on ruudukon YLÄPUOLELLA, ja se
     on koko raahauksen ydinviesti. */
  box-shadow: 0 6px 20px rgba(0,0,0,0.35);
  /* Ei siirtymää raahauksen aikana: palikan on oltava siellä missä
     osoitin on, ei siellä missä se oli 120 ms sitten. */
  transition: none;
}
.vk-block.vk-raahaa::before { background: var(--vk-accent); }
.vk-block.vk-esto {
  border-color: var(--vk-alert);
  background-color: var(--vk-alert-soft);
  background-image: repeating-linear-gradient(45deg,
    transparent 0 6px, var(--vk-alert-soft) 6px 12px);
  cursor: not-allowed;
}
.vk-block.vk-esto::before { background: var(--vk-alert); }
.vk-block.vk-siirtyy { opacity: 0.6; }

/* ALUEEN MAALAUS (jono #145, Roope 3.9.2026). OMA PÄÄLLYSTASO, EI SOLUN
   TAUSTAVÄRI: kolme vapaan solun rgb-arvoa (yllä muuttujina) eivät saa
   muuttua maalauksen aikana (Seppo 3.9.2026). Sama asemointikaava kuin
   .vk-block:lla (marginTop + gridColumn, ks. raahausAsemoi
   varauskirja.js:ssä) — elementti on siis aina täsmälleen samojen
   ruutujen päällä, koskematta niihin. pointer-events:none koska osoitin
   luetaan koko ajan canvasin koordinaateista, ei tästä kerroksesta. */
.vk-maalaus {
  grid-row: 1;
  position: relative;
  z-index: 20;
  align-self: start;
  pointer-events: none;
  border: 2px solid var(--vk-accent);
  background: color-mix(in srgb, var(--vk-accent) 16%, transparent);
  border-radius: 4px;
  box-sizing: border-box;
}
/* Raahauksen ajan koko ruudukko lakkaa reagoimasta osoittimeen: ilman
   tätä hover-korostus ja tekstin maalaus taistelevat raahauksen kanssa. */
.vk-canvas.vk-raahataan { cursor: grabbing; user-select: none; }
.vk-canvas.vk-raahataan .vk-block:not(.vk-raahaa) { pointer-events: none; }
.vk-maksu-btn {
  font: inherit; font-size: 12.5px; font-weight: 590;
  padding: 7px 12px;
  color: var(--vk-ink-1);
  background: var(--vk-block);
  border: 1px solid var(--vk-line-2);
  border-radius: var(--vk-r);
  cursor: pointer;
}
.vk-maksu-btn:hover { background: var(--vk-block-hover); }
.vk-maksu-btn:disabled { opacity: 0.55; cursor: default; }
.vk-maksu-btn:focus-visible {
  outline: 2px solid var(--vk-accent); outline-offset: 2px;
}
/* SOLUKERROKSEN SAILIO. Puuttui uudesta tyylista kokonaan, ja se rikkoi
   kaksi asiaa kerralla: nappaimistoruudukko ei ollut missaan, ja RAAHAUS
   paatteli sarakkeen naiden solujen mitoista - jotka olivat kaikki
   nollan levyisia, joten lahin sarake oli aina ensimmainen ja varaus
   hyppasi Radalle 1 heti kun sita alkoi vetaa (Simo 10.8. klo 20.15).
   #vkCells kaytetaan id:lla JS:ssa mutta tyylitellaan luokalla vanhassa;
   molemmat tassa, jottei sama aukko synny uudelleen kumpaakaan kautta. */
#vkCells, .vk-cells { position: absolute; inset: 0; z-index: 8; pointer-events: none; }

.vk-cellrow {
  display: grid; grid-template-columns: var(--vk-tpl);
  height: var(--vk-row-h);
}
/* SOLUN RUUDUKKOVIIVAT. KIERROS 3 (2.9.2026), brief kohta 4: "jokaisen
   solun ympärillä näkyvä viiva, sekä pysty- että vaakasuunnassa",
   border-collapse: collapse -henkinen mutta box-shadow'lla, ei borderilla,
   koska border kasvattaisi solun kokoa (box-sizing ei riitä gridin fr-
   sarakkeille millipikselintarkasti) ja rikkoisi rivikorkeuden.

   NELJÄ CUSTOM PROPERTYÄ, EI NELJÄÄ SÄÄNTÖÄ: --vk-b-t/-b-r/-b-b/-b-l ovat
   oletuksena tyhjät (top/left) tai puolitunnin väri (right/bottom), ja
   .hour/.ryhma-alku vain YLIKIRJOITTAVAT yhden muuttujan. Ilman tätä
   jokainen luokkayhdistelmä (esim. hour+ryhma-alku, joka syntyy aina kun
   tasatunti sattuu ryhmän ensimmäiseen sarakkeeseen) olisi tarvinnut oman
   box-shadow-rivinsä, koska box-shadow ei yhdisty periytymällä vaan
   korvautuu kokonaan - neljä muuttujaa laskee sen automaattisesti eikä
   yhdistelmiä unohdu. Top ei ole oletuksena puolitunnin väriä: edellisen
   rivin BOTTOM-viiva piirtää jo sen saman rajan, kaksinkertainen viiva
   samassa kohdassa vain sumentaisi sen. */
.vk-cell {
  pointer-events: none;
  --vk-b-t: transparent;
  --vk-b-r: var(--a-grid-puoli);
  --vk-b-b: var(--a-grid-puoli);
  --vk-b-l: transparent;
  box-shadow:
    inset 0  1px 0 0 var(--vk-b-t),
    inset -1px 0 0 0 var(--vk-b-r),
    inset 0 -1px 0 0 var(--vk-b-b),
    inset 1px 0 0 0 var(--vk-b-l);
}
/* Tasatunti: vahvempi YLÄreuna (brief: "tasatunnin viiva vahvempi kuin
   puolituntien... antaa ruudukolle rytmin"). rivikorkeus.hour-luokka
   tulee JS:stä samalla kaavalla kuin aikakiskon .vk-t.hour (piirraSolut). */
.vk-cellrow.hour .vk-cell { --vk-b-t: var(--a-grid-tunti); }
/* Ryhmäraja: vahvempi VASEN reuna siinä sarakkeessa jossa Pöytä/Kabinetti
   alkaa (brief kohta 4, viimeinen luetelmakohta). Sama .ryhma-alku-lippu
   kuin sarakeotsikoissa (ks. piirraOtsikot), nyt myös piirraSolut asettaa
   sen soluriville. */
.vk-cell.ryhma-alku { --vk-b-l: var(--a-grid-ryhma); }
.vk-cell:focus { outline: none; }
.vk-cell:focus-visible {
  outline: 2px solid var(--vk-focus);
  outline-offset: -2px;
  border-radius: 3px;
}

/* SULJETTU AIKA - KORJATTU POIS (2.9.2026 ilta). Tässä oli harmaa
   haalistus + klikkausesto aukiolon ulkopuoliselle solulle. Se perustui
   briefiin joka oli VÄÄRIN LUETTU lähteestä: Simo lähetti kuvan oikeasta
   VaraaVuorosta, jossa aukiolon ulkopuolinen "Vapaa"-solu on ihan
   tavallinen vihreä solu (vaalein sävy, sama kuin Kabinetti), ei harmaa
   eikä klikkaamaton. Väri tulee nyt suoraan .vk-cell[data-vapaa="vaalea"]
   -säännöstä (ks. alempana) - varauskirja.js valitsee sen aukiolon
   ulkopuolella (piirraSolut, muuttuja "suljettu"), joten erillistä
   data-suljettu-attribuuttia tai omaa taustasääntöä ei enää tarvita. */

/* VAPAAN SOLUN TÄYTTÖ. VaraaVuoro-klooni 2.9.2026, brief kohta 1.
   .vk-cell on CSS-grid-solu (.vk-cellrow { display:grid }), joten se
   venyy oletuksena reunasta reunaan ilman lisämäärittelyä - sama "täyttää
   sarakkeen" -periaate kuin .vk-blockilla (ks. yllä "VARAUS. Solu, ei
   kortti").

   pointer-events: auto VAIN data-vapaa-soluille, EI KAIKILLE .vk-cell:
   klikkauskäsittelijä (varauskirja.js, sidoPaneeli) laskee rivin/sarakkeen
   e.clientX/clientY-koordinaateista eikä e.targetista (ks. sen oma kommentti
   "SOLU LASKETAAN KOORDINAATEISTA, EI OSUMATESTISTA" - 10.8.2026 bugi jonka
   se korjasi), ja se erikseen ohittaa vain `.vk-block`-osumat. Koska
   e.target kupliutuu aina #vkCanvasiin asti riippumatta pointer-eventsistä,
   tämä ei voi rikkoa klikkausta eikä palikoiden raahausta (jotka kohdistuvat
   ainoastaan .vk-block-elementteihin, eivät koskaan tähän kerrokseen).

   font-size PALAUTETTU 12px:aan (2.9.2026 ilta): rivikorkeus palasi
   26px:aan Simon paatoksella ("kayta VaraaVuoron mittoja sellaisenaan"),
   joten myos fontti palasi lahteen omaan 12px:aan, ei enaa 14px-rivin
   vaatimaa 10px:aa. */
.vk-cell[data-vapaa] {
  pointer-events: auto;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Geist', ui-sans-serif, system-ui, sans-serif;
  font-size: 12px; font-weight: 500;
  color: var(--a-vapaa-ink);
  user-select: none;
  transition: background var(--a-nopea) var(--a-kaari), filter var(--a-nopea) var(--a-kaari);
}
.vk-cell[data-vapaa="korostettu"] { background: var(--a-vapaa-korostettu); }
.vk-cell[data-vapaa="korostettu"]:hover { background: var(--a-vapaa-korostettu-hi); }
.vk-cell[data-vapaa="vaalea"]     { background: var(--a-vapaa-vaalea); }
.vk-cell[data-vapaa="vaalea"]:hover { background: var(--a-vapaa-vaalea-hi); }
/* tumma/hohto: brief ei anna mitattua hover-arvoa naille kahdelle (vain
   korostetulle ja vaalealle oli), joten "hover vaalentaa" toteutetaan
   suodattimella eika arvatulla rgb-arvolla. */
.vk-cell[data-vapaa="tumma"]      { background: var(--a-vapaa-tumma); }
.vk-cell[data-vapaa="tumma"]:hover { filter: brightness(1.12); }
.vk-cell[data-vapaa="hohto"]      { background: var(--a-vapaa-hohto); }
.vk-cell[data-vapaa="hohto"]:hover { filter: brightness(1.06); }
/* KIERROS 3 (2.9.2026), brief kohta 3: musta kellonaikakupla peitti
   allaan olevan kellonajan, koska se ja aikasarakkeen oma numero elivat
   samassa 76 px:n kiskossa samalla oikeaan reunaan tasatulla kohdalla.
   Kupla siirtyi RUUDUKON PUOLELLE (varauskirja.js naytaNowTag appendaa nyt
   el.vkCanvasiin, ei el.vkTimesiin) - vasemmalle reunalle, kiinni
   #vkNow-viivan alkuun, missä se ei voi enää osua aikasarakkeen tekstiin.
   Väri vaihdettu --vk-accentista (joka resolvi --a-kunnossaksi, "maksettu
   varaus" eli lähes musta - väärä muuttuja, ei tarkoitettu väri) suoraan
   --a-nyt:hyn, sama väri kuin itse nyt-viivalla. */
.vk-nowtag {
  position: absolute; left: 6px; top: 0; z-index: 9;
  padding: 2px 7px 3px;
  border-radius: 999px;
  background: var(--a-nyt); color: #FFFFFF;
  font-size: 11px; font-weight: 590;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1;
  box-shadow: 0 1px 3px rgba(0,0,0,0.28);
  pointer-events: none; will-change: transform;
}
.vk-danger, .vk-danger-solid, .vk-ghost {
  min-height: 44px; padding: 11px 16px 12px;
  font-size: 13px; font-weight: 540;
  border-radius: 10px; cursor: pointer;
  background: transparent;
  transition: opacity var(--vk-t-hover) var(--vk-ease),
              transform var(--vk-t-hover) var(--vk-ease);
}
.vk-danger:active, .vk-danger-solid:active, .vk-ghost:active { transform: scale(0.98); }
.vk-confirm-row { display: flex; gap: 8px; }
.vk-danger-solid { flex: 1; color: var(--vk-alert-hi); border: 1px solid var(--vk-alert); }
.vk-danger-solid[disabled] { opacity: 0.5; cursor: default; }
.vk-ghost { color: var(--vk-ink-2); border: 1px solid var(--vk-line-2); }
.vk-ghost:hover { color: var(--vk-ink-1); }
/* Toimintonappi. Vihrea, koska tama on ainoa kohta jossa henkilokunta
   luo jotain: peruutus on punainen, luonti vihrea, eika niita voi sekoittaa. */
.vk-primary {
  width: 100%; padding: 12px 18px; border-radius: 999px; border: none;
  background: var(--vk-accent, #12A594); color: #06201C;
  font: inherit; font-size: 15px; font-weight: 640; cursor: pointer;
  transition: transform .16s cubic-bezier(.2,.8,.2,1), opacity .16s linear;
}
.vk-primary:hover { transform: translateY(-1px); }
.vk-primary:disabled { opacity: .55; cursor: default; transform: none; }
/* ---- Yksi vakiovuoro ---- */
.vk-sarja {
  padding: 13px 14px 14px;
  margin-bottom: 10px;
  border: 1px solid var(--vk-line-1);
  border-radius: var(--vk-r, 10px);
  background: var(--vk-zone-1);
}
.vk-sarja[data-paatetty="1"] { opacity: .62; }
.vk-sarja h3 {
  font-size: 14.5px; line-height: 19px; font-weight: 590;
  color: var(--vk-ink-1); margin: 0 0 3px;
  overflow-wrap: anywhere;
}
.vk-sarja .rivi {
  font-size: 12.5px; font-weight: 470; line-height: 1.5;
  color: var(--vk-ink-2);
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1;
}
.vk-sarja .rivi b { font-weight: 590; color: var(--vk-ink-1); }
.vk-sarja .paatetty-merkki {
  display: inline-block; margin-left: 6px;
  font-size: 10px; font-weight: 620; letter-spacing: .07em; text-transform: uppercase;
  color: var(--vk-ink-3);
}
/* Generointi ja paattaminen samassa rivissa: molemmat koskevat kautta,
   eivat yhta paivaa. Paivamaara on generoinnin VIERESSA, jottei kukaan
   paina "Generoi" tietamatta mihin asti. */
.vk-sarja-toiminnot {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end;
  margin-top: 11px; padding-top: 11px;
  border-top: 1px solid var(--vk-line-1);
}
.vk-sarja-toiminnot .kentta { display: flex; flex-direction: column; gap: 4px; }
.vk-sarja-toiminnot .kentta span {
  font-size: 10.5px; font-weight: 590; letter-spacing: .08em;
  text-transform: uppercase; color: var(--vk-ink-3);
}
.vk-sarja-toiminnot input[type="date"] {
  min-height: 36px; padding: 6px 9px; margin: 0;
  font: 470 12.5px/1.3 'InterVariable', system-ui, sans-serif;
  color: var(--vk-ink-1); background: transparent;
  border: 1px solid var(--vk-line-2); border-radius: 8px;
}
.vk-sarja-toiminnot .vk-maksu-btn { min-height: 36px; }
/* Generoinnin tulos. Epaonnistuneet viikot ovat tassa nakyvissa: kausi
   jossa kaksi viikkoa puuttuu EI saa nayttaa onnistuneelta. */
.vk-sarja-tulos {
  margin-top: 10px; padding: 9px 11px 10px;
  border-radius: 8px;
  font-size: 12.5px; font-weight: 470; line-height: 1.5;
  background: var(--vk-accent-soft); color: var(--vk-ink-1);
  border-left: 3px solid var(--vk-accent);
}
.vk-sarja-tulos[data-vika="1"] {
  background: var(--vk-attn-soft); border-left-color: var(--vk-attn);
}
.vk-sarja-tulos[data-vika="virhe"] {
  background: var(--vk-alert-soft); border-left-color: var(--vk-alert);
}
.vk-sarja-tulos ul { list-style: none; margin: 7px 0 0; padding: 0; }
.vk-sarja-tulos li {
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1;
  padding: 2px 0; color: var(--vk-ink-2);
}
.vk-sarja-tulos li b { font-weight: 590; color: var(--vk-ink-1); }
.vk-sarja-form .vk-confirm-row { margin-top: 2px; }
/* ---- Sarjamerkinta ruudukossa ja varauspaneelissa ----
   Vakiovuoron varaus ei saa nayttaa tavalliselta varaukselta. Merkinta on
   sanoin (sarjan nimi) eika pelkalla symbolilla: symboli yksin ei kerro
   MIKA vakiovuoro, ja juuri se on se tieto jota tiskin takana tarvitaan. */
.vk-block .sarjalippu {
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--vk-accent); opacity: .75;
  pointer-events: none;
}

/* ============================================================
   PALAUTETEKSTIEN SAVYT JA PIKKUOSAT
   Nama luokat JS kirjoittaa, mutta uudesta designista puuttuivat
   saannot. Vaikutus ei ollut rikkinainen ulkoasu vaan MYKKA ulkoasu:
   virhe luki samanvarisena kuin tavallinen tila, kuittaus ei
   vihertanyt, ja tyhja tieto naytti annetulta tiedolta.
   Loysi 10.8.2026 automaattinen sopimustarkistin.
   ============================================================ */

/* Virhe tilarivilla. Vari EI ole ainoa erotin: teksti itse sanoo mika
   meni vikaan, tama vain nostaa sen silmaan. */
#vkStatus.is-error #vkStatusMain { color: var(--a-rikki); }

/* Onnistunut kuittaus. Sama savy kuin maksetulla varauksella, koska
   merkitys on sama: tama on kunnossa, sinun ei tarvitse tehda mitaan. */
#vkStatusMain.on-ok { color: var(--a-kunnossa); }
.vk-panel-note.on-ok { color: var(--a-kunnossa); }

/* Tyhja tieto varauspaneelissa. Ilman tata "ei tiedossa" nayttaa
   samalta kuin annettu arvo, ja tiskilla se on eri asia. */
.vk-facts .tyhja { color: var(--a-ink-3); }

/* Resurssityypin otsikko uuden varauksen lomakkeessa. */
.vk-resgrid .tyyppi {
  width: 100%; margin: 4px 0 0;
  font-size: 11px; font-weight: 590; letter-spacing: .06em;
  text-transform: uppercase; color: var(--a-ink-3);
}

/* Osoittimen alla oleva rivi aikakiskossa. Kirkastus kertoo mihin
   kellonaikaan hiiri osuu, kun ruudukossa on 32 rivia. */
.vk-t.hot .aika { color: var(--a-ink); }

/* ---------------------------------------------------------------
   MAKSETTU NAKYY YHTA VAHVASTI KUIN MAKSAMATON.

   Roope merkitsi 11.8.2026 varauksen maksetuksi eika mikaan nakyvasti
   muuttunut. Data kulki oikein: kanta, ruudukko, attribuutti ja vari olivat
   kaikki kunnossa. Vika oli siina etta "vihrea" oli 4 pikselin pystyviiva
   palikan reunassa, ja samalla katosi "Maksamaton"-sana. Nakyva elementti
   siis korvautui nakymattomalla erolla.

   Maksamattomalla oli sana ja maksetulla pelkka vari. Rahan saapuminen on
   tiskilla paivan tarkein tilamuutos ja se oli visuaalisesti heikoin.

   Palikka saa nyt myos vihrean savyn taustaan. Se ei ole koristelu vaan
   ainoa muutos joka nakyy silmankulmasta ruudukkoa selatessa: yksittaisen
   sanan lukeminen vaatii katseen kohdistamisen.
   --------------------------------------------------------------- */
/* VaraaVuoro-klooni 2.9.2026: "maksettu varaus" on OMA kiinteä väri
   rgb(19,19,19), ei tummanpunaisen sävytys (brief kohta 3, mitattu
   suoraan lähteestä). Vanha gradientti sävytti --a-kunnossa:lla
   varauksen taustaa; --a-kunnossa on nyt lähes musta eikä enää vihreä,
   joten koko palikka vaihtaa väriä eikä vain sävyä. Teksti pysyy
   vaaleana koska palikan tausta on nyt tumma. */
.vk-block .maksulippu.maksettu { color: #8FE3C0; }
.vk-block[data-maksettu] {
  background: var(--a-kunnossa);
  background-image: none;
}
/* LASKUTUKSEEN (Roope 3.9.2026, ks. design/BRIEF_maksutila_kolme_
   vaihtoehtoa.md): sama mekanismi kuin maksetulla - koko palikka vaihtaa
   väriä, ei vain sävyä, jotta ero näkyy silmänkulmasta ruudukkoa
   selatessa eikä vaadi yksittäisen sanan lukemista. */
.vk-block .maksulippu.laskutukseen { color: #C9DBFF; }
.vk-block[data-laskutukseen] {
  background: var(--a-laskutus);
  background-image: none;
}
/* Peruttu voittaa maksetun/laskutukseen menneen: peruttua varausta ei
   esiteta hoidettuna vaikka raha olisi jo liikkeellä. Sama periaate kuin
   tilaluokissa yllä. */
.vk-block.peruttu[data-maksettu],
.vk-block.peruttu[data-laskutukseen] { background: var(--a-solu); }