/* ===================================================================
   KALENTERISIVUJEN TYYLISTÖ
   Lähde: prototypes/assets/kalenteri.css (kanoninen). Ladataan vain
   sivuilla, joilla on ort/kalenteri-lohko (ks. ort-kalenteri-lisäosa).

   Erot prototyyppiin:
   1. Sivukehys (topbar, header, navigaatio, footer, .wrap) on jätetty
      pois: teeman theme.css hoitaa sen jo. Mukaan on otettu vain se,
      mitä teemassa ei ole: .page-head, .breadcrumb, .skip-link.
   2. Selaimet, joissa teemalla on samanniminen luokka (.filters, .chip,
      .badge, .btn-line), on rajattu .cal-juuren sisään, jottei
      kalenterisivun tyyli vuoda etusivun komponentteihin.
   3. Kuukausiruudukon viikonpäivä (.mc-weekday) piilotetaan työpöydällä
      ruudunlukijalta näkymättä (clip) eikä display:none:lla, jotta
      päiväsolulla on aina saavutettava nimi ("lauantai 8.").

   Rakenne:
     1  Kompakti ylätunniste ja murupolku
     2  Rekisterimuuttujat (tumma / vaalea)
     3  Viikkonauha
     4  Työkalupalkki
     5  Suodattimet
     6  Listanäkymä
     7  Kuukausinäkymä
     8  Tilauslaatikko ja pyhäkkölista
     9  Mobiili (≤860px)
    10  Tulostus
   =================================================================== */

/* Kalenteri täyttää sivun leveyden: post-content-kääreen 72ch-rajaus
   koskee vain tavallista sisältöä. */
.cal-page-content { max-width: none; }

/* Sivun oma teksti kalenterin yläpuolella. Kalenteri ON sivun sisältöä
   (lohko post-contentissa), joten koko post-contentia ei voi kääriä .wrapiin:
   se kaventaisi kalenterin. Rajaus koskee siksi vain muita lapsia kuin
   kalenteria.

   Sääntö syntyi, kun kieliversioiden johdantokappale levisi reunasta reunaan.
   Kappaleet poistettiin 9.9.2026 — kalenterisivulla ei ole kuvaheroa juuri
   siksi, ettei kalenteri jäisi taitteen alle, eikä vaalea tekstikaista kahden
   tumman välissä kuulu samaan sivuun — ja niiden ainoa oma tieto on nyt
   ylätunnisteen page-head-notessa. Sääntö jää silti: kalenterisivun sisältö
   on ylläpitäjän muokattavissa, ja seuraava sinne kirjoitettu kappale
   asettuu nyt oikeaan leveyteen ilman että vika tarvitsee löytää uudelleen.
   Suomenkielisellä sivulla sisältöä ei ole, joten sääntö ei näy siellä. */
.cal-page-content > *:not(.cal) {
  max-width: 72ch;
  /* Vasen reuna samaan linjaan kalenterin kanssa: .wrapin oma sisennys, kun
     ikkuna on kapeampi kuin 1180px, muuten sen lisäksi keskityksen jäännös. */
  margin-inline: max(var(--sp-5), calc((100% - 1180px) / 2 + var(--sp-5))) auto;
}
.cal-page-content > *:not(.cal):first-child { padding-top: var(--sp-6); }
.cal-page-content > .cal { margin-top: 0; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--c-candle); color: var(--c-midnight);
  padding: 12px 20px; font-weight: 600; text-decoration: none;
}
.skip-link:focus { left: 0; }

/* ===================================================================
   1  KOMPAKTI YLÄTUNNISTE JA MURUPOLKU

   Kuvahero poistettu 29.7.2026. Se vei työpöydällä ~400 px ja mobiilissa
   yli puoli ruutua, jolloin kalenteri — sivun ainoa syy olla olemassa —
   jäi taitteen alle. Ylätunniste on nyt tekstikaista: murupolku, otsikko
   ja yksi asialause. Otsikko on tarkoituksella pienempi kuin --fs-h1:
   työkalusivun otsikon tehtävä on paikantaa, ei tehdä vaikutusta.
   =================================================================== */
.page-head { padding: var(--sp-4) 0 var(--sp-6); }
.page-head h1 { font-family: var(--font-display); font-weight: 500;
  font-size: clamp(1.75rem, 3.2vw, 2.5rem); line-height: var(--lh-tight);
  letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--c-cream); }
.page-head .page-head-note { color: var(--c-mist); font-size: var(--fs-body);
  max-width: 68ch; margin-top: var(--sp-3); }
.page-head .page-head-note a { color: var(--c-gold-l); }
.page-head .page-head-note a:hover { color: var(--c-candle); }

.breadcrumb { padding: 0 0 var(--sp-3); }
.breadcrumb ol { list-style: none; display: flex; flex-wrap: wrap; gap: var(--sp-2); font-size: var(--fs-meta); color: var(--c-mist); margin: 0; padding: 0; }
.breadcrumb a { color: var(--c-gold-l); text-decoration: none; }
.breadcrumb a:hover { color: var(--c-candle); text-decoration: underline; }
.breadcrumb .sep { color: var(--c-gold); }
.breadcrumb [aria-current] { color: var(--c-mist); }

/* ===================================================================
   2  REKISTERIMUUTTUJAT
   Sama komponenttijoukko piirtyy tummana (palveluskalenteri) tai
   vaaleana (tapahtumakalenteri). Kaikki värit tulevat näistä
   muuttujista — komponenttisäännöissä ei ole kiinteitä värejä.
   Kontrastit (mitattu tokens.css:n arvoilla):
     tumma:  kerma/vigilia 17,82:1 · usva/vigilia 9,08:1 · kynttilä/vigilia 11,98:1
             (tumma rekisteri jäi 15.8.2026 lämpimälle mustalle; sinisellä
             keskiyöllä luvut olisivat 15,85 · 8,07 · 10,65)
     vaalea: muste/pergamentti 14,8:1 · smoke/pergamentti 7,4:1 · ember/kerma 7,3:1
   =================================================================== */
.cal { --cal-radius: var(--radius-ui); display: block; }

/* Tumma rekisteri on lämmintä vigilia-mustaa, ei sinistä keskiyötä
   (päätös 15.8.2026): jumalanpalveluskalenteri kuuluu samaan hartaaseen
   joukkoon kuin sitaattikaista ja kirkkokalenteri, ei selailtaviin
   sinisiin kaistoihin. Ks. theme.css, .vigil-band. */
.cal--dark {
  --cal-bg:        var(--c-vigil);
  --cal-fg:        var(--c-cream);
  --cal-fg-soft:   var(--c-mist);
  --cal-accent:    var(--c-candle);
  --cal-accent-2:  var(--c-gold-l);
  --cal-line:      rgba(250, 244, 232, .22);
  --cal-line-soft: rgba(250, 244, 232, .12);
  --cal-surface:   rgba(250, 244, 232, .035);
  --cal-surface-2: rgba(250, 244, 232, .07);
  --cal-on-bg:     var(--c-candle);
  --cal-on-fg:     var(--c-vigil);
  --cal-focus:     var(--c-candle);
  --cal-badge-fg:  var(--c-gold-l);
  --cal-badge-bd:  var(--border-gold);
  background: var(--c-vigil); color: var(--c-cream);
}
.cal--light {
  --cal-bg:        var(--c-parchment);
  --cal-fg:        var(--c-ink);
  --cal-fg-soft:   var(--c-smoke);
  --cal-accent:    var(--c-ember);
  --cal-accent-2:  var(--c-gold-d);
  --cal-line:      rgba(28, 26, 23, .20);
  --cal-line-soft: rgba(28, 26, 23, .10);
  --cal-surface:   var(--c-cream);
  --cal-surface-2: #F7EFDF;
  --cal-on-bg:     var(--c-gold-d);
  --cal-on-fg:     var(--c-cream);
  --cal-focus:     var(--c-gold-d);
  /* Oli oma syvä kultansa #7A5A1E; yhdistetty --c-gold-d:hen, jotta
     vaalealla pinnalla on vain yksi kulta. */
  --cal-badge-fg:  var(--c-gold-d);
  --cal-badge-bd:  rgba(138, 101, 33, .50);
  background: var(--c-parchment); color: var(--c-ink);
}
.cal a { color: var(--cal-accent-2); }
.cal a:hover { color: var(--cal-accent); }
.cal a:focus-visible, .cal button:focus-visible, .cal summary:focus-visible {
  outline: 2px solid var(--cal-focus); outline-offset: 2px;
}

/* [hidden] on ohjelmallinen piilotus: sen pitää voittaa komponenttien
   omat display-arvot (esim. .tool-row { display:flex }), muuten JS:n
   asettama hidden ei tee mitään. */
.cal [hidden] { display: none !important; }

.cal .sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Listasivun rytmi on tiiviimpi kuin kerronnallisen sisältösivun: osioväli
   sp-5, ei sp-7. Ilmavuus palvelee lukemista, ei selaamista. */
.cal section { padding: var(--sp-5) 0; }
.cal section:first-of-type { padding-top: var(--sp-5); }
.cal section:last-of-type { padding-bottom: var(--sp-7); }

/* Yhteinen sektio-otsikko kalenterisivuilla */
.cal h2.cal-h2 { font-family: var(--font-display); font-weight: 500; font-size: var(--fs-h2);
  text-transform: uppercase; letter-spacing: var(--tracking-caps); line-height: 1.1; color: var(--cal-fg); }
.cal .cal-eyebrow { display: block; font-size: var(--fs-eyebrow); font-weight: 600; text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow); color: var(--cal-accent); margin-bottom: var(--sp-2); }

/* Painikkeet kalenterialueella */
.cal .btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 48px; padding: 12px 24px; border-radius: var(--radius-ui); border: 1px solid transparent;
  font: inherit; font-weight: 600; font-size: var(--fs-body); text-decoration: none; cursor: pointer;
  transition: background-color var(--dur-fade) var(--ease-calm), color var(--dur-fade) var(--ease-calm),
              border-color var(--dur-fade) var(--ease-calm); }
.cal .btn-primary { background: var(--cal-on-bg); color: var(--cal-on-fg); border-color: var(--cal-on-bg); }
.cal .btn-primary:hover { background: var(--cal-accent-2); border-color: var(--cal-accent-2); color: var(--cal-on-fg); }
.cal--dark .btn-primary:hover { color: var(--c-vigil); }
.cal .btn-line { background: none; color: var(--cal-fg); border-color: var(--cal-line); }
.cal .btn-line:hover { border-color: var(--cal-accent); color: var(--cal-accent); background: none; }
.cal .btn-sm { min-height: 44px; padding: 9px 16px; font-size: var(--fs-meta); }

/* ===================================================================
   3  VIIKKONAUHA

   Korvaa entisen ajanjaksovalitsimen (Tämä viikko / Tämä kuukausi /
   Kaikki tulevat). Nauha tekee kaksi asiaa, jotka valitsin ei tehnyt:
   näyttää yhdellä silmäyksellä MINÄ PÄIVINÄ palveluksia on, ja vie
   listassa suoraan haluttuun päivään. Lista pysyy koko ajan täytenä
   ("kaikki tulevat"), joten nauha on kulkuväline eikä rajaus — mikään
   ei katoa näkyvistä sitä käyttämällä.
   =================================================================== */
/* Nauha on pystypino: leima ylhäällä, nuolirivi (.wb-row) alla. Pinon
   leveyden määrää nuolirivi, jolloin keskitetty leima on täsmälleen
   rivin keskellä — flex-wrap-rivityksessä leiman 100 %:n perusleveys
   venytti nauhan leimaa ja riviä leveämmäksi ja keskitys valui sivuun. */
.cal .weekbar { display: flex; flex-direction: column; gap: var(--sp-2); }
.cal .weekbar .wb-row { display: flex; align-items: center; gap: var(--sp-2); }
.cal .weekbar .wb-nav { min-width: 40px; min-height: 48px; border: 1px solid var(--cal-line);
  background: none; color: var(--cal-fg); font: inherit; font-size: 1.25rem; line-height: 1;
  cursor: pointer; border-radius: var(--radius-ui); }
.cal .weekbar .wb-nav:hover:not(:disabled) { border-color: var(--cal-accent); color: var(--cal-accent); }
.cal .weekbar .wb-nav:disabled { opacity: .35; cursor: default; }

.cal .weekbar .wb-days { display: flex; gap: 2px; }

/* Viikkonumero ja päiväväli nauhan yläpuolella omalla rivillään
   (flex-basis 100 % rivittää; elementti on ryhmän ensimmäinen).
   Viikkonumero on korostettu, jotta nuolilla selattaessa näkyy heti,
   että liike on nimenomaan viikko kerrallaan. */
.cal .weekbar .wb-label { display: flex; align-items: baseline;
  justify-content: center; gap: var(--sp-2); font-size: var(--fs-meta); color: var(--cal-fg-soft); }
/* Sama korostuskulta kuin sivulla muutenkin ja eyebrow-tekstien paino:
   numeron erottaa väri ja vaihtumisanimaatio, ei lihavuus. */
.cal .weekbar .wb-week { display: inline-block; color: var(--cal-accent);
  font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
@media (prefers-reduced-motion: no-preference) {
  /* Pieni pudotus viikon vaihtuessa. Luokka tulee aina uuteen
     elementtiin (ks. kalenteri.js renderWeekbar), joten animaatio
     käynnistyy joka kerta alusta. */
  .cal .weekbar .wb-week.is-vaihtui { animation: wb-week-vaihtui 420ms var(--ease-calm); }
  @keyframes wb-week-vaihtui {
    0%   { transform: translateY(-7px) scale(1.15); opacity: 0; }
    55%  { opacity: 1; }
    100% { transform: none; }
  }
}

/* Päiväsolu. Palveluksettomat päivät ovat <span>, joten näppäimistö
   hyppää suoraan päiviin joissa on jotain. Leveys on KIINTEÄ eikä
   sisällön mukainen: muuten rivi eläisi päivänumeroiden leveyden
   mukana ja seuraava-nuoli vaihtaisi paikkaa viikkoa vaihdettaessa. */
.cal .weekbar .wb-day { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; flex: 0 0 52px; width: 52px; min-height: 48px; padding: 4px 2px; border: 1px solid transparent;
  border-radius: var(--radius-ui); background: none; font: inherit; color: var(--cal-fg-soft); }
/* nowrap on varmistus: solu on kapea, ja jos tila loppuu kesken, teksti
   saa mieluummin valua reunan yli kuin rivittyä merkki kerrallaan
   pystyriviksi ("m / a / 1 / 7 / ."), kuten kävi mobiilissa 17.8.2026. */
.cal .weekbar .wb-wd { font-size: .68rem; font-weight: 600; text-transform: uppercase; letter-spacing: .1em;
  white-space: nowrap; }
.cal .weekbar .wb-num { font-family: var(--font-display); font-size: 1.16rem; font-weight: 600; line-height: 1;
  white-space: nowrap; }
/* Merkintöjen olemassaolon kertoo päivän valittavuus: nappi ja kehys.
   Erillinen merkkipiste poistettu turhana toistona (11.8.2026). */
.cal .weekbar button.wb-day { cursor: pointer; color: var(--cal-fg); border-color: var(--cal-line); }
.cal .weekbar button.wb-day:hover { border-color: var(--cal-accent); color: var(--cal-accent); }
.cal .weekbar button.wb-day:focus-visible { outline: 2px solid var(--cal-focus); outline-offset: 2px; }
.cal .weekbar .wb-day.is-today { border-color: var(--cal-accent); }
.cal .weekbar .wb-day.is-today .wb-num { color: var(--cal-accent); }
/* Listassa juuri näkyvä päivä */
.cal .weekbar .wb-day.is-current { background: var(--cal-on-bg); border-color: var(--cal-on-bg); color: var(--cal-on-fg); }
.cal .weekbar .wb-day.is-current .wb-num,
.cal .weekbar .wb-day.is-current .wb-wd { color: var(--cal-on-fg); }

/* ===================================================================
   4  TYÖKALUPALKKI

   Palkki tarttuu työpöydällä headerin alle (29.7.2026): näkymän vaihto ja
   rajaus ovat käytettävissä keskeltäkin listaa, jolloin suodattimien ei
   tarvitse viedä tilaa sivun kärjestä. Tarttuminen edellyttää, että palkki
   ja lista ovat SAMASSA <section>-elementissä — sticky liikkuu vain
   vanhempansa laatikon sisällä, ja oma osio olisi vain palkin korkuinen.
   Mobiilissa ei tartuta: pystysuunnassa pinoutuva palkki söisi liian ison
   osan ruudusta.
   =================================================================== */
.cal .cal-tools { border: 1px solid var(--cal-line); border-bottom: 0;
  padding: var(--sp-4) var(--sp-5);
  display: grid; gap: var(--sp-4);
  /* Kaksi taustakerrosta: läpikuultava pinta opaakin pohjavärin päällä.
     Pelkkä --cal-surface on rgba, jolloin alle vierivä lista näkyisi läpi. */
  background-color: var(--cal-bg);
  background-image: linear-gradient(var(--cal-surface), var(--cal-surface)); }

@media (min-width: 861px) {
  /* --header-h asettaa theme.js (mitattu headerin korkeus); 78px on
     varmuusarvo, jos JS ei ole ehtinyt ajaa. z-index jää headerin (60)
     alle, jotta header peittää palkin eikä toisin päin. */
  .cal .cal-tools { position: sticky; top: var(--header-h, 78px); z-index: 40; }
  body.admin-bar .cal .cal-tools { top: calc(var(--header-h, 78px) + 32px); }
}
@media (prefers-reduced-motion: no-preference) {
  .cal .cal-tools { transition: box-shadow var(--dur-fade) var(--ease-calm); }
}
/* Varjo vasta kun palkki on tarttunut: JS lisää luokan. Ensimmäinen
   kerros on hiusviiva palkin ja listan väliin — se on box-shadow eikä
   border-bottom, koska reunus kasvattaisi palkin korkeutta ja siirtäisi
   listaa pikselin verran juuri tarttumishetkellä. Palkin alareuna on muuten
   avoin, jotta se lukee ylhäällä yhtenä paneelina rajausten kanssa. */
.cal .cal-tools.is-stuck {
  box-shadow: 0 1px 0 var(--cal-line), 0 8px 24px rgb(var(--c-midnight-rgb) / .28);
}
/* Rajaussirut EIVÄT ole palkin sisällä (muutos 15.8.2026, ks. render.php):
   ne ovat sisaruselementti, joka jää normaaliin virtaan ja vierii pois
   niin kuin mikä tahansa sisältö. Näin tarttuva palkki on työpöydällä
   vain 128 px (ennen 261 px) eikä listan sisältö hyppää mihinkään.
   Ensimmäinen yritys — sirujen piilotus tarttuessa — kutisti sticky-
   elementtiä, joka on yhä normaalissa virrassa: koko lista nytkähti
   ylöspäin sirujen korkeuden verran kesken vierityksen. */

.cal .tool-row { display: flex; gap: var(--sp-4); flex-wrap: wrap; align-items: center; }
/* "Tänään" on markupissa heti näkymävalitsimen jälkeen, jotta se pysyy
   mobiilissa samalla rivillä sen kanssa; työpöydällä se siirretään
   viikkonauhan perään, seuraava viikko -nuolen viereen — se on
   ajassa liikkumisen nappi siinä missä nuoletkin. */
@media (min-width: 861px) {
  .cal .tool-row > #today-btn { order: 3; }
  /* Tilausnappi työntyy rivin oikeaan laitaan, erilleen ajassa
     liikkumisen napeista — se ei kuulu samaan ryhmään. */
  .cal .tool-row > #subscribe-open { order: 4; margin-left: auto; }
  /* Kaikki napit samalle korkeudelle: viikkonumeroleima korottaa
     nauhaa ylöspäin, joten rivi tasataan alareunaan — näkymä- ja
     Tänään-napit asettuvat viikkonappien tasalle. */
  .cal .tool-row { align-items: flex-end; }
  /* Pystyjakaja näkymävalinnan ja ajassa liikkumisen välissä. Täyte on
     nauhasäiliössä, jotta se siirtää leimaa ja nappiriviä saman verran
     eikä leiman keskitys karkaa; itse viiva piirretään alareunasta ylös
     vain vähän nappirivin yläpuolelle — ei leimariville asti. Kuukausi-
     näkymässä nauhan paikalla on kuukausivalitsin, jolle sama jakaja. */
  .cal .tool-row > .weekbar,
  .cal .tool-row > .monthnav { position: relative; padding-left: var(--sp-4); }
  .cal .tool-row > .weekbar::before,
  .cal .tool-row > .monthnav::before { content: ''; position: absolute; left: 0; bottom: 0;
    width: 1px; height: calc(100% - 26px); background: var(--cal-line); }
  .cal .tool-row > .monthnav::before { height: 100%; }
}
.cal .tool-group { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: center; }
.cal .tool-group > .tg-label { font-size: var(--fs-eyebrow); font-weight: 600; text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow); color: var(--cal-fg-soft); }

/* Segmentoitu valitsin (näkymä, ajanjakso) */
.cal .segmented { display: flex; flex-wrap: wrap; gap: 0; border: 1px solid var(--cal-line); border-radius: var(--radius-ui); overflow: hidden; }
.cal .segmented button { min-height: 48px; padding: 10px 18px; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: var(--fs-meta); font-weight: 600; color: var(--cal-fg);
  border-right: 1px solid var(--cal-line); }
.cal .segmented button:last-child { border-right: 0; }
.cal .segmented button[aria-pressed="true"] { background: var(--cal-on-bg); color: var(--cal-on-fg); }
.cal .segmented button:hover:not([aria-pressed="true"]) { background: var(--cal-surface-2); }
.cal .segmented button:focus-visible { outline: 2px solid var(--cal-focus); outline-offset: -2px; }

/* Kuukausiaskellus */
.cal .monthnav { display: flex; align-items: center; gap: var(--sp-2); }
.cal .monthnav button { min-width: 48px; min-height: 48px; border: 1px solid var(--cal-line); background: none;
  color: var(--cal-fg); font: inherit; font-size: 1.25rem; line-height: 1; cursor: pointer; border-radius: var(--radius-ui); }
.cal .monthnav button:hover { border-color: var(--cal-accent); color: var(--cal-accent); }
.cal .monthnav .mn-label { min-width: 11ch; text-align: center; font-family: var(--font-display); font-weight: 600;
  font-size: 1.3rem; letter-spacing: .03em; color: var(--cal-fg); }

/* ===================================================================
   5  SUODATTIMET

   Paikkakunta ja kieli ovat näkyvissä ilman avaamista (päätös 29.7.2026):
   ryhmiä on kaksi ja ne mahtuvat yhdelle riville, jolloin paneelin
   avaaminen olisi maksanut klikkauksen säästämättä juuri tilaa. Napit ovat
   <button aria-pressed> — useampi päällä yhtä aikaa, eli monivalinta
   ryhmän sisällä.
   =================================================================== */
/* margin-bottom: 0 kumoaa teeman samannimisen .filters-luokan (etusivun
   paikkakuntasuodatin) marginaalin — muuten palkkiin jää 24 px tyhjää. */
/* Kaksi saraketta: rajausryhmät allekkain vasemmalle, tyhjennysnappi
   oikeaan yläkulmaan ensimmäisen rivin tasalle (muutos 15.8.2026). Ennen
   rivi oli flex + margin-left:auto, jolloin nappi rivittyi omalle
   rivilleen heti kun sirut täyttivät leveyden — eli käytännössä aina.
   Rivi 1 on 8.9.2026 alkaen hakukenttä, sitä ennen paikkakuntasirut. */
.cal .filters { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: start; column-gap: var(--sp-5); row-gap: var(--sp-3);
  margin-bottom: 0;
  /* Oma paneelinsa työkalupalkin alla, mutta reunat sovitettu niin että ne
     lukevat yhtenä laatikkona: palkilta puuttuu alareuna, rajauksilta
     yläreuna, ja väliin jää vain vaalea erotinviiva. Taustat ovat samat
     (opaakki pohja + läpikuultava pinta), koska palkki liukuu tarttuessaan
     rajausten päälle eikä lista saa näkyä läpi. */
  border: 1px solid var(--cal-line); border-top: 1px solid var(--cal-line-soft);
  padding: var(--sp-4) var(--sp-5);
  background-color: var(--cal-bg);
  background-image: linear-gradient(var(--cal-surface), var(--cal-surface)); }
.cal .filters .filter-set { grid-column: 1; }
.cal .filters #clear-filters { grid-column: 2; grid-row: 1; }
/* Tyhjennysnappi on samaa nappiperhettä kuin työkalurivin Tilaa kalenteri,
   mutta kullatuin reunoin: se erottuu siruista toimintona, joka koskee
   koko rajausriviä. [hidden]-pari tarvitaan, koska .btn asettaa oman
   display-arvon (ks. huomio §1:ssä). */
.cal .filters #clear-filters { border-color: var(--cal-accent); color: var(--cal-accent); }
.cal .filters #clear-filters:hover { background: var(--cal-surface-2); }
.cal .filters #clear-filters[hidden] { display: none; }
.cal .filter-set { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; min-width: 0; }
/* Sirut nimiön riville myös silloin, kun ne eivät mahdu yhdelle riville
   (muutos 15.8.2026). Ilman flex-basis: 0 selain vertaa siruryhmän
   rivittämätöntä leveyttä jäljellä olevaan tilaan ja siirtää KOKO ryhmän
   omalle rivilleen — niin kävi kielisiruille, vaikka ne olisivat mahtuneet
   nimiön viereen rivitettyinä. Nollaperustalla ryhmä jää riville ja
   rivittyy sisältään. Nimiö kohdistuu ensimmäisen sirurivin tekstiin
   (align-items: baseline), joten se ei valu monirivisen ryhmän keskelle. */
.cal .filter-set > .chips { flex: 1 1 0; }
/* Nimiö on <span> eikä <legend>: legend ei asetu luotettavasti samalle
   riville sirujen kanssa. Saavutettavuus tulee role="group" +
   aria-labelledby -parista, jota työkalupalkki käyttää muutenkin. */
.cal .filter-set .fs-label { font-size: var(--fs-eyebrow); font-weight: 600; text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow); color: var(--cal-fg-soft); }
.cal .chips { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.cal .chip { display: inline-flex; align-items: center; min-height: 44px; padding: 8px 18px;
  border: 1px solid var(--cal-line); border-radius: var(--radius-pill); background: none;
  font: inherit; font-size: var(--fs-meta); color: var(--cal-fg); cursor: pointer;
  transition: background-color var(--dur-fade) var(--ease-calm), border-color var(--dur-fade) var(--ease-calm),
              color var(--dur-fade) var(--ease-calm); }
.cal .chip:hover { border-color: var(--cal-accent); }
/* Valittu siru erottuu täytöllä, ei väkäsellä: täytetty pinta vs.
   ääriviiva on muukin ero kuin väri (WCAG 1.4.1), ja poistettu "✓ "
   -etuliite lopettaa samalla sirun leveyden nykimisen klikatessa. */
.cal .chip[aria-pressed="true"] { background: var(--cal-on-bg); border-color: var(--cal-on-bg);
  color: var(--cal-on-fg); font-weight: 600; }
.cal .chip:focus-visible { outline: 2px solid var(--cal-focus); outline-offset: 2px; }


/* ---------- Hakukenttä (§5.1) ----------
   Kenttä on rajauspaneelin VIIMEISENÄ, sirujen alapuolella (päätös
   8.9.2026). Sirut vastaavat kysymykseen "missä ja millä kielellä", kenttä
   kysymykseen "mikä" — ja sirut riittävät useimmiten. Kenttä on siruja
   painavampi elementti, joten ylimmäisenä se veti katseen pois niistä.

   Kenttä EI ole työkalupalkissa, vaikka palkki tarttuu ja paneeli ei:
   palkissa on jo näkymävalitsin, Tänään, viikkonauha ja Tilaa kalenteri,
   eikä kenttä mahdu sinne rikkomatta riviä. Palkissa oli 8.9.2026 asti
   pilleri, joka näytti voimassa olevan hakusanan vieritettäessäkin; se
   poistettiin tarpeettomana (kenttä kertoo saman) ja samalla palkki
   lakkasi kasvamasta 127 → 187 px:iin haun ajaksi. */
.cal .fs-haku { align-items: center; }
/* Nimiö samaan pystylinjaan sirurivien nimiöiden kanssa: sirujen .fs-label
   on baseline-kohdistettu, kentän nimiö keskitetään 44 px:n kenttään. */
.cal .haku { display: flex; align-items: center; gap: var(--sp-3);
  flex: 1 1 0; min-width: 0; flex-wrap: wrap; }
/* Kehys on oma elementtinsä, jotta tyhjennysristi voi asettua kentän
   sisään absoluuttisesti. Yläraja 40ch: pidempi kenttä lupaisi pidempiä
   kyselyitä kuin haku palkitsee (sanat ovat JA-ehtoja, joten kolme sanaa
   on jo tiukka rajaus). */
.cal .haku__kehys { position: relative; display: flex; flex: 1 1 22ch;
  min-width: 0; max-width: 40ch; }
.cal .haku__kentta { flex: 1 1 auto; min-width: 0; min-height: 44px;
  padding: 8px 44px 8px 14px; border: 1px solid var(--cal-line);
  border-radius: var(--radius-ui); background: var(--cal-surface-2);
  font: inherit; font-size: var(--fs-body); color: var(--cal-fg);
  transition: border-color var(--dur-fade) var(--ease-calm); }
.cal .haku__kentta::placeholder { color: var(--cal-fg-soft); opacity: 1; }
.cal .haku__kentta:hover { border-color: var(--cal-accent); }
.cal .haku__kentta:focus-visible { border-color: var(--cal-accent);
  outline: 2px solid var(--cal-focus); outline-offset: 2px; }
/* Selaimen oma tyhjennysristi pois: se on vain WebKitissä, sijaitsee eri
   kohdassa ja olisi kaksi ristiä samassa kentässä muualla kuin siellä. */
.cal .haku__kentta::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.cal .haku__tyhjenna { position: absolute; right: 2px; top: 50%;
  transform: translateY(-50%); width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--radius-ui); background: none;
  font: inherit; font-size: 1.25rem; line-height: 1;
  color: var(--cal-fg-soft); cursor: pointer; }
.cal .haku__tyhjenna:hover { color: var(--cal-accent); }
.cal .haku__tulos { font-size: var(--fs-meta); color: var(--cal-fg-soft); margin: 0; }
/* Tyhjänä osumaluku ei vie tilaa mutta pysyy DOMissa: aria-live-alue, joka
   on välillä display:none, voi jäädä ruudunlukijalta huomaamatta
   (sama peruste kuin .cal-status). */
.cal .haku__tulos:empty { width: 0; overflow: hidden; }

/* Tyhjä tulos */
.cal .empty-state { border: 1px dashed var(--cal-line); padding: var(--sp-7) var(--sp-5); text-align: center; }
.cal .empty-state p { color: var(--cal-fg-soft); max-width: 46ch; margin: 0 auto var(--sp-4); }
.cal .empty-state .es-title { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--cal-fg);
  text-transform: uppercase; letter-spacing: var(--tracking-caps); margin-bottom: var(--sp-3); }

/* Ilmoitusalue (rajausten tyhjennys ym.). Tyhjänä se ei varaa korkeutta
   mutta pysyy DOMissa: aria-live-alue, joka on välillä display:none, voi
   jäädä ruudunlukijalta huomaamatta. Ilmoitus on harvinainen ja kasvattaa
   palkkia vain hetkeksi. */
.cal .cal-status { font-size: var(--fs-meta); color: var(--cal-fg-soft); margin: 0; }
.cal .cal-status:empty { height: 0; overflow: hidden; }

/* ===================================================================
   6  LISTANÄKYMÄ
   viikko-/kuukausiotsikko → päiväotsikko → palvelus-/tapahtumarivit
   =================================================================== */
/* Viikkojen väli oli sp-7 (48 px); yhdessä edellisen viikon viimeisen
   päiväryhmän alatäytteen kanssa siitä tuli ~72 px tyhjää, mikä on paljon
   listassa jonka koko tarkoitus on näyttää monta päivää kerralla.
   sp-5 riittää erottamaan viikot (viikko-otsikko on jo iso ja kultainen). */
.cal .weekgroup { margin-top: var(--sp-5); }
/* Ensimmäinen ryhmä on kiinni työkalupalkissa (sama osio), joten se ei
   tarvitse ryhmien välistä isoa väliä. */
.cal #list-view > .weekgroup:first-child { margin-top: var(--sp-4); }
.cal #list-view > .weekgroup:first-child .week-head { margin-bottom: var(--sp-4); }
/* Nuolilla selattaessa vieritetään viikon otsikkoon (ks. kalenteri.js
   vierita), joten myös ryhmä tarvitsee saman vieritysmarginaalin kuin
   päiväryhmä alempana. */
.cal .weekgroup { scroll-margin-top: calc(var(--header-h, 78px) + var(--cal-tools-h, 160px) + var(--sp-4)); }
/* Artikkelityypografian nollaus listan otsikoista. Kalenterilohko
   renderöityy post-contentin sisään, joten teeman sääntö
   `.entry-content h1…h6 { margin-top: var(--sp-6) }` osuu myös viikko- ja
   päiväotsikoihin — 32 px kumpaankin. Kappaleiden väliotsikoille se on
   oikein, listan rakenneotsikoille ei: viikko-otsikko on flex-rivin osa
   ja päiväotsikko on päiväryhmän ensimmäinen solu, jolloin marginaali
   pudotti päivämäärän 32 px oman rivinsä alapuolelle. */
.cal .week-head h3,
.cal .day-head .dh-heading { margin-top: 0; }

.cal .week-head { display: flex; align-items: baseline; gap: var(--sp-4); flex-wrap: wrap;
  border-bottom: 1px solid var(--cal-line); padding-bottom: var(--sp-2); margin-bottom: var(--sp-5); }
/* Viikko-otsikko on listan päänavigointitaso nuolilla selattaessa,
   joten se saa olla selvästi päiväotsikoita kookkaampi. */
.cal .week-head h3 { font-family: var(--font-display); font-weight: 500;
  font-size: clamp(1.35rem, 2.4vw, 1.75rem); line-height: var(--lh-tight); text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow); color: var(--cal-accent); }
.cal .week-head .wh-range { font-family: var(--font-display); font-style: italic;
  font-size: clamp(1.1rem, 1.9vw, 1.4rem); color: var(--cal-fg-soft); }

/* scroll-margin-top: viikkonauhasta hypättäessä päivä ei saa jäädä
   tarttuneen headerin ja työkalupalkin alle. --cal-tools-h asettaa
   kalenteri.js (mitattu palkin korkeus). */
.cal .daygroup { display: grid; grid-template-columns: 148px 1fr; gap: var(--sp-5); padding: var(--sp-4) 0 var(--sp-5);
  border-top: 1px solid var(--cal-line-soft);
  scroll-margin-top: calc(var(--header-h, 78px) + var(--cal-tools-h, 160px) + var(--sp-4)); }
/* Viikon ensimmäinen päiväryhmä ilman yläviivaa: week-headilla on jo oma
   border-bottom, ja kaksi viivaa peräkkäin näytti virheeltä.
   Sisarusvalitsin eikä :first-of-type — jälkimmäinen katsoo elementin
   TYYPPIÄ, ja ryhmän ensimmäinen <div> on .week-head, joten yksikään
   .daygroup ei koskaan täyttänyt ehtoa ja sääntö oli kuollut. */
.cal .week-head + .daygroup { border-top: 0; }
/* Tämän päivän ryhmällä oli vaalea pohja (poistettu 15.8.2026): käytännössä
   se osui listan ensimmäiseen päivään ja näytti siltä kuin ensimmäinen päivä
   olisi jotenkin eri lajia kuin muut. Päivän merkintä on TÄNÄÄN-lipuke
   (.dh-today), joka riittää yksin. */
.cal .day-head { position: relative; }
/* Päiväotsikko on oikea otsikkotaso (h4): viikko h3 → päivä h4 → rivi h5,
   jolloin ruudunlukijan otsikkonavigaatio vie suoraan päivästä toiseen. */
.cal .day-head .dh-heading { display: flex; flex-direction: column; font-weight: 400; }
.cal .day-head .dh-weekday { font-family: var(--font-display); font-style: italic; font-size: 1.32rem; color: var(--cal-fg-soft); }
.cal .day-head .dh-date { font-family: var(--font-display); font-weight: 600; font-size: 2.1rem; line-height: 1.05;
  color: var(--cal-fg); margin-top: 2px; }
.cal .day-head .dh-today { display: inline-block; margin-top: var(--sp-2); padding: 3px 12px; border-radius: var(--radius-pill);
  background: var(--cal-on-bg); color: var(--cal-on-fg); font-size: .75rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; }

/* "Näytä lisää" on vain mobiilin palanappi (ks. §9): työpöydällä lista on
   kokonaan näkyvissä, joten nappia ei ole. Sääntö on .cal .btn:n jälkeen,
   jotta se voittaa sen display-arvon samalla tarkkuudella. */
.cal .lisaa-nappi { display: none; }

.cal .entries { display: grid; gap: var(--sp-3); }

/* Yksittäinen palvelus / tapahtuma */
.cal .entry { border: 1px solid var(--cal-line); border-left: 3px solid var(--cal-accent-2);
  background: var(--cal-surface); padding: var(--sp-4) var(--sp-5);
  transition: border-color var(--dur-fade) var(--ease-calm); }
.cal .entry:hover { border-color: var(--cal-badge-bd); border-left-color: var(--cal-accent); }
/* Jumalanpalveluskalenterissa kultainen vasen reunus on varattu
   seuraavalle palvelukselle (is-next) — muilla riveillä se toistuisi
   joka kortissa eikä korostaisi enää mitään. Leveys säilyy, jotta
   rivit pysyvät samassa linjassa. Tapahtumakalenterin vaalea pinta
   pitää reunuksensa (sama tyyli kuin etusivun tapahtumakorteissa). */
.cal--dark .entry:not(.is-next) { border-left-color: var(--cal-line); }
.cal--dark .entry:not(.is-next):hover { border-left-color: var(--cal-badge-bd); }
.cal .entry.is-past { opacity: .55; }
/* Seuraava tuleva rivi — sama merkintätapa kuin etusivun palvelusnostossa
   (.svc-card.is-next): kultareunus ja lipuke, ei hehkua eikä liikettä.
   Lipukkeen sijainti ja typografia tulevat teeman .next-flag-säännöstä;
   tässä annetaan vain kalenteripinnan värit. */
.cal .entry.is-next { position: relative; border-color: var(--cal-accent); border-left-color: var(--cal-accent); }
.cal .entry.is-next .next-flag { background: var(--cal-bg); color: var(--cal-accent); }
.cal .entry-main { display: grid; grid-template-columns: 92px 1fr; gap: var(--sp-4); align-items: start; }
.cal .entry-time { font-family: var(--font-display); font-weight: 600; font-size: 1.6rem; line-height: 1.1;
  color: var(--cal-accent); white-space: nowrap; }
.cal .entry-time .et-end { display: block; font-family: var(--font-body); font-size: var(--fs-meta);
  font-weight: 400; color: var(--cal-fg-soft); letter-spacing: 0; }
.cal .entry-title { font-weight: 600; font-size: 1.125rem; text-transform: uppercase; letter-spacing: var(--tracking-caps);
  color: var(--cal-fg); line-height: 1.25; margin: 0; }
.cal--light .entry-title { text-transform: none; letter-spacing: 0; font-size: 1.2rem;
  font-family: var(--font-display); font-weight: 600; }
/* Karttaneula kuten etusivun korteissa (theme.css .svc-place). */
.cal .entry-place { display: flex; align-items: flex-start; gap: 6px;
  color: var(--cal-fg-soft); font-size: var(--fs-body); margin-top: var(--sp-2); }
.cal .entry-place .pin { flex: none; width: 13px; height: 13px; margin-top: 5px;
  fill: none; stroke: currentColor; stroke-width: 1.8; opacity: .75; }
/* Katuosoite on ruudulla lisätiedoissa (rivi pysyy lyhyenä), mutta
   tulosteessa se liitetään paikan nimeen — paperilla ei voi klikata auki. */
.cal .ep-addr { display: none; }
/* Kalenterisivuilla vakiopaikan osoite näkyy aina: täällä sille on
   tilaa toisin kuin etusivun korteissa, eikä siistitty nimi enää
   sisällä osoitetta. */
.cal .ep-addr--nayta { display: inline; }
/* Linkki ei saa erottua muista paikkariveistä: karttaneula on vihje,
   alleviivaus ei kuulu tyyliin. Hover ja focus-rengas kertovat linkin. */
.cal .entry-place a { color: inherit; text-decoration: none; }
.cal .entry-place a:hover { color: var(--cal-accent); }
.cal .entry-note { color: var(--cal-fg-soft); font-size: var(--fs-body); margin-top: var(--sp-2); font-style: italic; }

.cal .badges { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-3); }
.cal .badge { display: inline-block; border: 1px solid var(--cal-badge-bd); color: var(--cal-badge-fg);
  border-radius: var(--radius-pill); padding: 3px 12px; font-size: .78rem; font-weight: 600; letter-spacing: .06em; }
.cal .badge--solid { background: var(--cal-on-bg); border-color: var(--cal-on-bg); color: var(--cal-on-fg); }

/* Laajennettava osio (tilauslaatikon "Mitä tilaaminen tekee?").
   Natiivi <details> + <summary>: toimii näppäimistöllä ja ruudunlukijalla
   ilman JS:ää, eikä sisällä piilotettuja eleitä.

   Rivien oma "Lisätiedot"-pudotus poistettiin 29.7.2026: se toisti aika-,
   paikka-, kieli- ja paikkakuntatiedot, jotka näkyvät jo rivillä, eikä
   "Kesto" kertonut mitään mitä kellonaikaväli ei jo kerro. */
.cal details { margin-top: var(--sp-3); border-top: 1px solid var(--cal-line-soft); padding-top: var(--sp-2); }
.cal summary { display: flex; align-items: center; gap: var(--sp-2); min-height: 44px; cursor: pointer;
  font-size: var(--fs-meta); font-weight: 600; color: var(--cal-accent-2); list-style: none; }
.cal summary::-webkit-details-marker { display: none; }
.cal summary::after { content: "＋"; font-size: 1rem; }
.cal details[open] summary::after { content: "－"; }
.cal summary:hover { color: var(--cal-accent); }
/* ===================================================================
   7  KUUKAUSINÄKYMÄ
   Desktop: 7 saraketta. ≤860px: sama DOM muuttuu päivälistaksi
   (tyhjät päivät ja täytesolut piiloon, viikonpäivä soluun mukaan).
   Vaakavieritystä ei sallita missään leveydessä.
   =================================================================== */
.cal .month-wrap { margin-top: var(--sp-6); }
.cal .month-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; margin-bottom: 1px; }
.cal .month-weekdays span { padding: var(--sp-2); text-align: center; font-size: var(--fs-eyebrow); font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em; color: var(--cal-fg-soft); }
.cal .month-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--cal-line-soft);
  border: 1px solid var(--cal-line); }
.cal .mcell { background: var(--cal-bg); min-height: 128px; padding: var(--sp-2); }
.cal .mcell.is-pad { background: var(--cal-surface); }
.cal .mcell.is-today { background: var(--cal-surface-2); box-shadow: inset 0 0 0 2px var(--cal-accent); }
.cal .mcell .mc-date { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; color: var(--cal-fg); }
/* Viikonpäivä on työpöydällä sarakeotsikossa, mutta se jätetään soluun
   ruudunlukijaa varten: näin solun nimi on "lauantai 8." eikä pelkkä "8.". */
.cal .mcell .mc-weekday {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.cal .mcell.is-past .mc-date { color: var(--cal-fg-soft); }
.cal .mc-item { display: block; width: 100%; text-align: left; background: none; border: 0; border-top: 1px solid var(--cal-line-soft);
  padding: 6px 2px; margin-top: 4px; font: inherit; font-size: .8125rem; line-height: 1.35; color: var(--cal-fg); cursor: pointer; }
.cal .mc-item:hover { color: var(--cal-accent); }
.cal .mc-item .mi-time { font-weight: 700; color: var(--cal-accent); }
.cal .mc-item .mi-name { display: block; color: var(--cal-fg); }
.cal .mc-item .mi-place { display: block; color: var(--cal-fg-soft); font-size: .75rem; }
.cal .mcell.is-past .mc-item { opacity: .6; }

/* Valitun päivän tiedot kuukausinäkymän alla */
.cal .month-detail { margin-top: var(--sp-5); border: 1px solid var(--cal-line); background: var(--cal-surface); padding: var(--sp-5); }
.cal .month-detail h4 { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-h3);
  text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--cal-fg); margin-bottom: var(--sp-4); }
.cal .month-detail .entries { gap: var(--sp-3); }

/* ===================================================================
   8  TILAUSLAATIKKO JA PYHÄKKÖLISTA
   =================================================================== */
.cal .subscribe { border: 1px solid var(--cal-line); background: var(--cal-surface); padding: var(--sp-5);
  display: grid; gap: var(--sp-3); }
.cal .subscribe h2 { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-h3);
  text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--cal-fg); }
.cal .subscribe p { color: var(--cal-fg-soft); max-width: 62ch; line-height: 1.7; }
.cal .subscribe code, .cal .sub-note code { display: inline-block; font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: .9375rem; background: var(--cal-surface-2); border: 1px solid var(--cal-line-soft);
  padding: 8px 12px; word-break: break-all; color: var(--cal-fg); }
.cal .subscribe .sub-actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.cal .sub-note { font-size: var(--fs-meta); font-style: italic; color: var(--cal-fg-soft); }

/* Rajausseloste: kertoo, mitä tilaukseen kuuluu. Kun rajauksia on
   valittuna, seloste korostuu — tilaaja huomaa varmasti, ettei osoite
   olekaan koko kalenterin. */
.cal .subscribe .sub-rajaus { font-size: var(--fs-meta); color: var(--cal-fg-soft); }
.cal .subscribe .sub-rajaus.is-rajattu { color: var(--cal-accent); font-weight: 600; }

/* Tilausdialogi: sama .subscribe-lohko kuin alalaidan osiossa. Dialogin
   oma padding on 0 ja lohko tuo omansa — näin dialogiin itseensä osuva
   klikkaus voi tulla vain taustasta, jolloin JS sulkee dialogin. */
.cal .sub-dialog { padding: 0; border: 1px solid var(--cal-line); background: var(--cal-bg); color: var(--cal-fg);
  width: min(680px, calc(100vw - 2 * var(--sp-4))); margin: auto; }
.cal .sub-dialog::backdrop { background: rgba(10, 8, 6, .82); backdrop-filter: blur(3px); }
.cal .sub-dialog .subscribe { border: 0;
  /* rgba-pinta tarvitsee peittävän pohjan alleen (vrt. .cal-tools) */
  background-color: var(--cal-bg); background-image: linear-gradient(var(--cal-surface), var(--cal-surface)); }
/* Otsikolle tilaa sulkunapin alla, ettei pitkä otsikko mene sen alle. */
.cal .sub-dialog .subscribe h2 { padding-right: 44px; }
.cal .dlg-close { position: absolute; top: 4px; right: 4px; z-index: 1; width: 44px; height: 44px;
  border: 0; background: none; color: var(--cal-fg-soft); font-size: 1.6rem; line-height: 1; cursor: pointer; }
.cal .dlg-close:hover { color: var(--cal-accent); }
.cal .dlg-close:focus-visible { outline: 2px solid var(--cal-focus); outline-offset: -2px; }

.cal .places { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-4); }
.cal .place { border: 1px solid var(--cal-line); padding: var(--sp-5); background: var(--cal-surface); }
.cal .place h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.2rem; line-height: 1.25;
  color: var(--cal-fg); margin-bottom: var(--sp-2); }
.cal .place p { font-size: var(--fs-meta); color: var(--cal-fg-soft); line-height: 1.6; }
.cal .place a { display: inline-block; margin-top: var(--sp-3); font-size: var(--fs-meta); font-weight: 600; }

/* ===================================================================
   9  MOBIILI (≤860px)
   =================================================================== */
@media (max-width: 860px) {
  .page-head { padding: var(--sp-2) 0 var(--sp-4); }
  .page-head h1 { font-size: min(1.9rem, 8vw); }
  .page-head .page-head-note { font-size: var(--fs-meta); margin-top: var(--sp-2); }

  /* Kosketuskohteet myös toissijaisissa linkeissä: 44px pystysuunnassa. */
  .breadcrumb a, .cal .place a, .cal .subscribe a, .cal .entry-place a {
    display: inline-flex; align-items: center; min-height: 44px; }
  /* align-items: center, koska linkit ovat 44 px korkeita kosketuskohteita
     (sääntö yllä) mutta erotin › ja nykyinen sivu ovat tavallista tekstiä.
     Oletusarvoisella stretchillä listan kohdat venyivät 44 px:iin ja vain
     linkin teksti keskittyi — muut jäivät laatikon yläreunaan, jolloin
     murupolku näytti rivistä pudonneelta. */
  .breadcrumb ol { gap: 0 var(--sp-2); align-items: center; }

  /* Työkalut ja suodattimet pinoutuvat */
  .cal .cal-tools { padding: var(--sp-4); }

  /* Hakukenttä koko leveydelle: 390 px:n ruudulla 22ch-perusta jättäisi
     osumaluvun samalle riville 60 px:n levyiseksi. Nimiö on jo omalla
     rivillään (.filter-set on tässä leveydessä grid). */
  .cal .haku { gap: var(--sp-2); }
  .cal .haku__kehys { flex: 1 1 100%; max-width: none; }

  /* Näkymävalitsin pois (päätös 14.8.2026). Kuukausiruudukko latistui
     tässä leveydessä joka tapauksessa päivälistaksi, joten valinta oli
     "lista vai lista" — ja huonompi lista: mitatussa elokuussa 39 %
     korkeudesta oli jo menneitä päiviä, merkinnän tiedot vaativat toisen
     napautuksen ja "Seuraavaksi"-lipuke puuttui. kalenteri.js pakottaa
     tilan listaksi, joten piilotus ei jätä näkymää tavoittamattomiin.
     Elementti jää DOMiin: aria-labelledby osoittaa sen nimiöön. */
  .cal .tool-row > .tg-view { display: none; }

  /* Rivi 1: "Tänään" ja "Tilaa kalenteri" jakavat rivin, viikkonauha
     omalle rivilleen. Järjestys annetaan orderilla, koska markupissa
     nauha on nappien välissä (työpöydän rivijärjestys). */
  .cal .tool-row { flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
  .cal .tool-row > #today-btn { order: 1; flex: 1 1 auto; }
  .cal .tool-row > #subscribe-open { order: 2; flex: 1 1 auto; }
  .cal .tool-row > .weekbar { order: 3; flex: 1 1 100%; }
  .cal .tool-group { align-items: stretch; }
  /* Viikkonauha: nuolet leimariville, päivät koko leveydelle
     (korjaus 17.8.2026).

     Ennen nuolet ja seitsemän päivää jakoivat saman rivin. Nuolet veivät
     88 px, joten 390 px:n ruudulla soluun jäi 29,7 px — juuri ja juuri —
     ja 360 px:llä 25,4 px, jolloin "ma 17." rivittyi merkki kerrallaan
     pystyriviksi. Nuolet mahtuvat leimariville, joka on muuten tyhjä, ja
     päivät saavat nauhan koko leveyden: 320 px:n ruudullakin soluun jää
     yli 30 px, eli tilaa on myös selaimen isommalle tekstikoolle.

     .wb-row on display: contents, jotta nuolet ja päivänauha asettuvat
     suoraan nauhan ruudukkoon. Rivielementtiä ei voi poistaa markupista,
     koska työpöydällä se rajaa leiman keskityksen (ks. §3). */
  .cal .weekbar { display: grid; grid-template-columns: auto 1fr auto;
    align-items: center; gap: 4px; }
  .cal .weekbar .wb-row { display: contents; }
  .cal .weekbar .wb-label { grid-row: 1; grid-column: 2; flex-wrap: wrap; }
  /* Nuoli on leimarivin korkuinen: 44 × 40 px on yhä sormelle riittävä
     kohde, ja rivi pysyy matalampana kuin päivärivi. */
  .cal .weekbar .wb-nav { grid-row: 1; min-width: 44px; min-height: 40px; }
  .cal .weekbar #week-prev { grid-column: 1; }
  .cal .weekbar #week-next { grid-column: 3; }
  .cal .weekbar .wb-days { grid-row: 2; grid-column: 1 / -1; min-width: 0; }
  .cal .weekbar .wb-day { flex: 1 1 0; width: auto; min-width: 0; padding: 4px 2px; }
  /* Harvennus vie kapeassa solussa saman verran tilaa kuin yksi merkki. */
  .cal .weekbar .wb-wd { letter-spacing: .04em; }
  /* Rajaussirut vaakanauhaksi (päätös 14.8.2026).

     Pystyyn rivittyneinä ne veivät 390 px:n ruudulla 389 px eli 46 %
     ruudun korkeudesta: paikkakuntia on kahdeksan ja kieliä seitsemän,
     ja kummankin määrä kasvaa. Nauhassa ryhmä vie aina kaksi riviä
     — nimiön ja sirurivin — riippumatta sirujen määrästä.

     Työpöydän päätös 29.7.2026 (sirut näkyvissä, ei paneelin takana) jää
     voimaan: siellä ryhmät mahtuvat yhdelle riville, tässä eivät.
     Nimiöt pysyvät näkyvissä myös mobiilissa — ilman niitä paikkakunnat
     ja kielet valuisivat yhdeksi erittelemättömäksi sirumassaksi. */
  /* Yksi sarake: työpöydän kaksisarakkeinen asettelu (rajaukset vasemmalle,
     tyhjennysnappi oikeaan yläkulmaan) purettaisiin tässä liian kapeaksi. */
  .cal .filters { display: grid; grid-template-columns: 1fr; gap: var(--sp-4); }
  .cal .filters .filter-set { grid-column: auto; }
  .cal .filters #clear-filters { grid-column: auto; grid-row: auto; }
  .cal .filter-set { display: grid; gap: var(--sp-2); min-width: 0; }
  .cal .chips {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    min-width: 0; scrollbar-width: thin;
    /* Pystytäyte, jottei sirun focus-rengas (outline-offset 2px) leikkaudu
       vierityssäiliön reunaan; negatiivinen marginaali palauttaa rytmin. */
    padding: 3px 0; margin: -3px 0;
    /* Näppäimistöllä siirryttäessä selain vierittää sirun näkyviin; täyte
       jättää sen reunaan kiinni menemisen sijaan hieman irti. */
    scroll-padding-inline: var(--sp-4);
  }
  .cal .chip { flex: 0 0 auto; }
  /* Ilmaa nauhan loppuun, jotta viimeinen siru ei jää kiinni reunaan. */
  .cal .chips::after { content: ''; flex: 0 0 var(--sp-2); }
  .cal .filters #clear-filters { justify-self: start; margin-left: 0; }
  /* Ryhmien otsikot ruudunlukijalle: "Lista / Kuukausi" ja "Tämä viikko /
     Kaikki tulevat" kertovat itsensä, ja kaksi otsikkoriviä oli 64 px pois
     listan tilasta. Elementit jäävät DOMiin, koska aria-labelledby
     osoittaa niihin. */
  .cal .tool-group > .tg-label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .cal .segmented { width: 100%; }
  .cal .segmented button { flex: 1 1 0; padding: 10px 8px; }
  .cal .monthnav { justify-content: space-between; width: 100%; }
  .cal .monthnav .mn-label { flex: 1; min-width: 0; font-size: 1.15rem; }

  /* --- Listan pystyrytmi (tiivistys 14.8.2026) ---
     Mitattuna sisältöä oli listan korkeudesta vain 64 %: 7 365 px:stä
     2 625 px oli väliä ja otsikoita. Välit puolitetaan mobiilissa; koko
     rytmi on työpöydällä ennallaan, jossa tilaa on.

     1) .weekgroup on <section>, joten se sai myös yleissäännön
        .cal section { padding: var(--sp-5) 0 } — 48 px jokaista viikkoa
        kohti, mitä sääntö ei tarkoittanut (se on sivutason osioille).
        Valitsimessa on section.weekgroup, jotta se voittaa myös
        .cal section:first-of-type/:last-of-type -säännöt. */
  .cal section.weekgroup { padding: 0; }
  /* 2) Ryhmien ja otsikoiden välit: viikon viimeisestä rivistä seuraavan
        viikon otsikkoon oli 152 px, otsikosta ensimmäiseen riviin 113 px. */
  .cal .weekgroup { margin-top: var(--sp-5); }
  .cal .week-head { margin-bottom: var(--sp-3); }
  /* Ensimmäinen ryhmä tarvitsee enemmän ilmaa kuin sp-3: se ei irtaudu
     edellisestä rivistä vaan reunustetusta työkalupalkista, ja tiukalla
     marginaalilla otsikko liimautui palkin alareunaan (13 px, kun
     viikkojen keskinäinen väli on 41 px). */
  .cal #list-view > .weekgroup:first-child { margin-top: var(--sp-6); }
  .cal #list-view > .weekgroup:first-child .week-head { margin-bottom: var(--sp-3); }
  .cal .entries { gap: var(--sp-2); }

  /* Päiväryhmä pinoon: iso päivämäärä otsikoksi rivien ylle */
  .cal .daygroup { grid-template-columns: 1fr; gap: var(--sp-3); padding: var(--sp-3) 0 var(--sp-4); }
  /* Tämän päivän tummennus pois mobiilista. Kortit käyttävät samaa
     --cal-surface-pintaa, joten yksipalstaisessa pinossa pinnat
     kasautuivat: tämän päivän kortit piirtyivät tummennuksen PÄÄLLE ja
     olivat vaaleampia kuin kaikki muut kortit — ja tausta peitti myös
     ryhmän tyhjän ylätäytteen, jolloin otsikon yläpuolelle jäi irrallisen
     näköinen vaalea palkki. "Tänään"-lipuke merkitsee päivän jo yksin.
     Työpöydällä tummennus on ennallaan: siellä se on kaksipalstaisen
     rivin korostus, ei kortin alle jäävä pinta. */
  .cal .daygroup.is-today { background: none; }
  /* Lipuke keskitetään, ei tasata peruslinjaan: pillerin peruslinja on
     sen tekstin alalaidassa, jolloin rivistä tuli 63 px korkea vaikka
     otsikkoteksti on 29 px. Ero näkyi tyhjänä tilana päiväotsikon ympärillä.
     Otsikon oma sisältö (viikonpäivä + päivämäärä) pysyy peruslinjassa. */
  .cal .day-head { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
  .cal .day-head .dh-heading { flex-direction: row; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
  /* Rivikorkeudet kiinni tekstiin: "keskiviikko 19.8." vei 61 px, vaikka
     kirjaimet ovat ~30 px. Viikonpäivä peri leipätekstin väljän
     rivikorkeuden, ja se määräsi koko peruslinjaan tasatun rivin korkeuden. */
  .cal .day-head .dh-weekday { line-height: 1.15; }
  .cal .day-head .dh-date { font-size: 1.7rem; margin-top: 0; line-height: 1.1; }
  .cal .day-head .dh-today { margin-top: 0; }

  .cal .entry { padding: var(--sp-3) var(--sp-4); }
  .cal .entry-main { grid-template-columns: 1fr; gap: var(--sp-1); }
  .cal .entry-time { font-size: 1.45rem; }
  .cal .entry-time .et-end { display: inline; margin-left: var(--sp-2); }
  /* Vakiopaikan osoite piiloon: se rivittyi joka kortissa kahdelle
     riville (~40 px kortista, jonka keskikorkeus oli 186 px). Paikan
     nimi ja karttalinkki riittävät ruudulla; paperilla osoite tulee
     takaisin, koska siellä linkkiä ei voi klikata (§10). */
  .cal .ep-addr--nayta { display: none; }
  .cal .entry-place { font-size: var(--fs-meta); }

  /* Lista paloissa: JS merkitsee näkyvän rajan yli menevät viikko-/
     kuukausiryhmät (ks. kalenteri.js paloita). Täysi lista oli 390 px:n
     ruudulla 48 000 px eli noin 57 ruudullista.

     Piilotus tehdään VAIN tässä mediakyselyssä, joten ikkunan levetessä
     koko lista palaa itsestään eikä JS:n tarvitse purkaa mitään. Ilman
     JS:ää palvelin renderöi listan kokonaan eikä luokkaa aseteta. */
  .cal .weekgroup.is-katkaistu { display: none; }
  .cal .lisaa-nappi { display: flex; width: 100%; margin-top: var(--sp-5); }

  /* Kuukausiruudukon mobiilisäännöt on poistettu näkymävalitsimen mukana:
     ruudukkoon ei pääse enää tässä leveydessä. Ruudukon oma tyylistö (§7)
     on koskematon, joten näkymä toimii työpöydällä ennallaan. */
}

@media (max-width: 400px) {
  .cal .chip { padding: 8px 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .cal *, .cal *::before, .cal *::after { transition: none !important; animation: none !important; }
}

/* ===================================================================
   10  TULOSTUS
   Mustavalkoinen, yksipalstainen lista. Työkalut, navigaatio ja
   kuukausiruudukko jäävät pois; suodatustila tulostuu tekstinä, jotta
   paperilta näkee mitä on rajattu. Lisätiedot avataan JS:llä
   beforeprint-tapahtumassa (ks. assets/js/kalenteri.js).
   =================================================================== */
@media print {
  @page { margin: 14mm; }
  html, body { background: #fff !important; color: #000 !important; font-size: 11pt; }
  .site-top, .site-header, .topbar, .page-head, .breadcrumb, footer, .skip-link,
  .cal .cal-tools, .cal .month-wrap, .cal .subscribe, .cal #pyhakot, .no-print,
  .cal .next-flag { display: none !important; }
  /* Tulostettaessa listanäkymä tulee aina mukaan, vaikka ruudulla olisi
     kuukausiruudukko — paperilla ruudukko on hyödytön. */
  .cal #list-view[hidden] { display: block !important; }
  .cal section { padding: 0; }
  /* Paperilla riittää aika + nimi + paikka + lisätieto. Osoite tulee
     mukaan .ep-addr-osasta — myös se, jonka mobiilisääntö piilottaa
     ruudulta. Tulostettaessa paperin leveys on tyypillisesti alle 860 px,
     joten §9 on voimassa myös tulosteessa. */
  .cal .ep-addr, .cal .ep-addr--nayta { display: inline; }
  /* Samasta syystä listan katkaisu on purettava: paperille kuuluu koko
     lista. !important, koska §9:n sääntö on tarkempi (.weekgroup.is-katkaistu). */
  .cal .weekgroup.is-katkaistu { display: block !important; }
  .cal, .cal--dark, .cal--light { background: #fff !important; color: #000 !important; }
  .cal * { color: #000 !important; background: transparent !important; box-shadow: none !important; }
  .wrap { max-width: none; padding: 0; }
  .print-head { display: block !important; border-bottom: 1.5pt solid #000; padding-bottom: 6pt; margin-bottom: 12pt; }
  /* Tulosteen otsikko ei ole <h1> vaan <p>: näytöllä sivulla on jo oma h1,
     eikä piilotettu kakkos-h1 kuulu otsikkorakenteeseen. */
  .print-head .ph-title { font-family: var(--font-display); font-size: 20pt; font-weight: 600;
    text-transform: uppercase; letter-spacing: .06em; line-height: 1.15; }
  .print-head p { font-size: 9.5pt; margin-top: 4pt; }
  .cal .weekgroup { margin-top: 10pt; break-inside: avoid; }
  .cal .week-head { border-bottom: .5pt solid #000; margin-bottom: 6pt; }
  .cal .daygroup { grid-template-columns: 110px 1fr; gap: 8pt; padding: 4pt 0; border-top: .5pt solid #999; break-inside: avoid; }
  .cal .day-head .dh-date { font-size: 14pt; }
  .cal .day-head .dh-today { border: .5pt solid #000; }
  .cal .entry { border: 0; border-left: 2pt solid #000; padding: 2pt 0 4pt 8pt; break-inside: avoid; }
  .cal .entry-main { grid-template-columns: 64px 1fr; gap: 8pt; }
  .cal .entry-time { font-size: 12pt; }
  .cal .entry-title { font-size: 11pt; }
  .cal .badge { border: .5pt solid #000; padding: 0 4pt; font-size: 8pt; }
  .cal details { border-top: 0; }
  .cal summary { display: none; }
  .print-foot { display: block !important; margin-top: 14pt; padding-top: 6pt; border-top: .5pt solid #000; font-size: 9pt; }
}
.print-head, .print-foot { display: none; }
