/* Show it is fixed to the top */
body {
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 14px;
    line-height: 1.42857143;
    color: #555;
}

a {
    text-decoration: none;
    color: #337ab7;
}

a:hover {
    color: #23527c;
    text-decoration: underline;
}

:root {
    --navbar-height: 56px; /* approx height of the sticky top navbar; single source of truth */
    /* Desktop sidebar rail: full width, and the icon-only width it folds to
       (static/js/sidebar-collapse.js toggles .sidebar-collapsed on <html>). */
    --sidebar-width: 210px;
    --sidebar-collapsed-width: 58px;
    /* Brand color: one hex drives the navbar accent line and the sidebar
       active states in both themes (dark derivations in dark-mode.css).
       Overridable later per organisation by injecting a :root override. */
    --app-brand: #337ab7;
    --app-primary: var(--app-brand);
    --app-primary-hover: color-mix(in srgb, var(--app-brand) 75%, #000);
    --app-primary-subtle: color-mix(in srgb, var(--app-brand) 12%, transparent);
    --bs-focus-ring-color: color-mix(in srgb, var(--app-primary) 25%, transparent);
}

/* Brand accent line at the bottom edge of the top bar. Inset box-shadow
   instead of border so the navbar height stays exactly --navbar-height
   (the sidebar rail is positioned against it). */
.navbar.bg-dark {
    box-shadow: inset 0 -3px 0 var(--app-primary);
}

/*
 * Sidebar
 *
 * Rendered as a Bootstrap responsive offcanvas (`offcanvas-md offcanvas-start`):
 * a normal in-flow rail at >=768px, a slide-in drawer below 768px. Bootstrap
 * handles the show/hide, backdrop and focus trapping — no custom JS or
 * per-breakpoint width syncing required.
 */

.sidebar {
    /* Mobile: slide-in offcanvas drawer. The visible surface comes from the
       .bg-light on .offcanvas-header / .sidebar-inner (dark-mode.css remaps
       it for the dark theme); the offcanvas bg is matched to it so a short
       menu doesn't leave a differently-colored strip below .sidebar-inner. */
    --bs-offcanvas-width: 260px;
    --bs-offcanvas-bg: #e9ecef;
    /* Light theme: darken the rail below the page default (#f8f9fa) so it
       reads as its own surface against the white content. Scoped here so
       content-area .bg-light panels keep Bootstrap's default. */
    --bs-light-rgb: 233, 236, 239;
    /* The sub-navigation's connector line. A variable rather than a value in
       the rule, so dark-mode.css can re-tint it without entering a
       specificity fight with .nav-link.active over border-left-color. */
    --sidebar-rail: rgba(0, 0, 0, .14);
}

@media (min-width: 768px) {
    /* Desktop: fixed-width rail that sticks just below the navbar */
    #sidebarMenu {
        flex: 0 0 var(--sidebar-width);
        align-self: flex-start;
        position: sticky;
        top: var(--navbar-height);
        height: calc(100vh - var(--navbar-height));
        overflow-y: auto;
    }

    /*
     * offcanvas-md forces `background: transparent !important` on both
     * .offcanvas-md and .offcanvas-body at >=768px and sets the body to
     * display:flex. Restore the body to a normal block and let .sidebar-inner
     * carry the background so the rail stays filled on desktop.
     */
    #sidebarMenu .offcanvas-body {
        display: block;
        height: 100%;
    }

    #sidebarMenu .sidebar-inner {
        min-height: 100%;
    }

    /* Subtle right-edge separator (dark-mode.css overrides it for the dark theme) */
    .sidebar {
        box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
    }
}

.sidebar .nav-link {
    font-weight: 500;
    color: #333;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* left padding compensates the reserved accent border so text keeps
       its original alignment */
    padding: 1rem 1.5rem 1rem calc(1.75rem - 4px);
    border-left: 4px solid transparent; /* reserved so .active doesn't shift the text */
}

.sidebar .nav-link.disabled {
    padding-bottom: 0.5rem;
}

/*
 * Sub-navigation: the pages of the section that is open — Hallinta, and
 * kalenterin suunnittelu (templates/nav/org_sidebar.html).
 *
 * Depth used to be 0.5rem of extra indentation and nothing else, which did
 * not read as nesting: the rows looked like ordinary menu items that happened
 * to sit closer together. The group now carries three signals at once — the
 * parent becomes a heading (.section-open), the rows start past the parent's
 * icon, and their own left borders stack into one continuous rail down the
 * whole group.
 *
 * The rail is those borders rather than one border on the <ul> precisely so
 * that .active below lights up the current row's segment of it: the eye gets
 * both the group's extent and its position inside the group from the same
 * line.
 */
.sidebar .nav-link.section-open {
    font-weight: 700;
    color: #212529;
    padding-bottom: 0.6rem;
}

.sidebar .sidebar-subnav {
    margin-bottom: 0.75rem;
}

.sidebar .nav-link.sidebar-sub {
    /* Puts the rail under the middle of the parent item's icon: the item's
       text box starts at 28px (1.75rem padding, less the 4px accent border,
       plus the border), and the icon in it is about 14px wide. */
    margin-left: 2.1rem;
    padding: 0.4rem 1rem 0.4rem 0.85rem;
    /* Narrower than the 4px accent the top-level items reserve, so an active
       sub-item reads as a thinner mark one level in */
    border-left: 3px solid var(--sidebar-rail);
    font-size: 0.9rem;
    color: #495057;
}

.sidebar .nav-link.active {
    color: var(--app-primary);
    background-color: var(--app-primary-subtle);
    border-left-color: var(--app-primary);
    font-weight: 600;
}

.sidebar .nav-link:hover {
    background-color: rgba(0, 0, 0, .05);
}

/*
 * Collapsed rail (desktop only)
 *
 * The toggle at the foot of the menu folds the 210px rail into an icon strip,
 * giving wide content — the planning table above all — back its width on a
 * laptop screen. Labels are hidden by shrinking the text to nothing rather
 * than by display:none: the words stay in the accessibility tree, and
 * static/js/sidebar-collapse.js copies them into a title so hovering an icon
 * still names it.
 */
.sidebar-collapse-toggle {
    align-items: center;
    gap: .5rem;
    width: 100%;
    padding: .6rem 1.5rem .6rem calc(1.75rem - 4px);
    border: 0;
    border-top: 1px solid rgba(0, 0, 0, .1);
    background: transparent;
    color: #6c757d;
    font-size: .85rem;
    white-space: nowrap;
    overflow: hidden;
}

.sidebar-collapse-toggle:hover {
    background-color: rgba(0, 0, 0, .05);
    color: #333;
}

@media (min-width: 768px) {
    html.sidebar-collapsed #sidebarMenu {
        flex-basis: var(--sidebar-collapsed-width);
    }

    html.sidebar-collapsed .sidebar .nav-link,
    html.sidebar-collapsed .sidebar-collapse-toggle {
        position: relative;
        padding-left: 0;
        padding-right: 0;
        text-align: center;
        justify-content: center;
        gap: 0;
        /* Hides the label without removing it from the DOM (see above) */
        font-size: 0;
    }

    html.sidebar-collapsed .sidebar .nav-link i,
    html.sidebar-collapsed .sidebar-collapse-toggle i {
        font-size: 1rem;
    }

    /* Counts don't fit a 58px rail, so the badge becomes a plain "something
       is waiting" dot; the number is back as soon as the rail is opened. */
    html.sidebar-collapsed .sidebar .nav-link .badge {
        position: absolute;
        top: .5rem;
        right: .75rem;
        width: 8px;
        height: 8px;
        min-width: 0;
        padding: 0;
        margin: 0;
        border-radius: 50%;
        font-size: 0;
    }

    /* The open section's sub-items are often titles the user wrote — the
       planning periods — and there is no icon to stand in for them, so the
       whole group waits until the rail is open. Hiding the list rather than
       its links also takes the group's bottom margin with it. */
    html.sidebar-collapsed .sidebar .sidebar-subnav {
        display: none;
    }
}

/*
 * Hallinta -> Asetukset: yksi rivi, yksi kenttä
 *
 * Rivin kaksi puoliskoa — tallennettu arvo ja sen muokkain — ovat molemmat
 * sivulla, ja vain toinen näkyvissä kerrallaan. Vaihto on luokka rivillä
 * (static/js/organisation-settings.js) eikä uusi sivulataus, ja sama luokka
 * on palvelimen keino avata rivi, jonka tallennus hylättiin.
 */
.setting-row .setting-editor,
.setting-row.setting-row-open .setting-display,
.setting-row.setting-row-open .setting-edit {
    display: none;
}

.setting-row.setting-row-open .setting-editor {
    display: block;
}

/* Kynänappi on kosketuskohde ennen kaikkea: 44px on se, mihin sormella osuu.
   Leveys ja korkeus samat, jotta ikoni on keskellä eikä nappi veny tekstin
   mukaan — tekstiä siinä ei ole. */
.setting-edit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
}

/* Tallennuksen kuittaus katoaa itsestään: se kertoo juuri tapahtuneesta eikä
   ole rivin tila, ja jäädessään se olisi minuutin päästä valhe. */
.setting-saved {
    animation: setting-saved-fade 4s ease-out forwards;
}

@keyframes setting-saved-fade {
    0%, 60% {
        opacity: 1;
    }
    100% {
        opacity: 0;
        visibility: hidden;
    }
}

/* Ominaisuuspaneelin ikonisarake: sama leveys joka rivillä, jotta otsikot
   alkavat samasta kohdasta, ja tekstin ensimmäisen rivin tasalla. */
.feature-icon {
    width: 1.75rem;
    padding-top: 0.15rem;
}

/* Flex-lapsi kutistuu vasta tällä, ja ilman sitä pitkä katkeamaton arvo
   (rajapinnan osoite, CORS-lista) leventää rivin yli kortin. */
.min-width-0 {
    min-width: 0;
}

/*
 *  Main view
 */
.main {
    min-width: 0; /* allow the flex child to shrink so .table-responsive can scroll */
}

/*
 * Tab bars: keep the tabs on one row and scroll horizontally on narrow
 * screens instead of wrapping into a ragged multi-row border.
 * NOTE: do NOT use on a nav that contains a dropdown — the overflow clips
 * the open dropdown menu (see event/calendar_tabs.html, which wraps instead).
 */
.nav-scroll {
    flex-wrap: nowrap;
    overflow-x: auto;
}


/*
 * Form
 */

/*
 * The anonymous pages reached from an invitation link. The same column width
 * as the entrance pages, but these carry no <body> class of their own: the
 * registration form has ten fields and is opened on a phone, from a QR code,
 * more often than not, so it starts at the top rather than middled.
 */
.public-panel {
    width: 100%;
    max-width: 32rem;
    margin: auto;
}

.normal-link {
    text-decoration: none;
    color: #337ab7;
}

/*Kalenterin fontin väri*/
#cal-slide-content a.event-item {
    font-weight: normal;
    line-height: 22px;
}

.data-left {
    width: 150px;
    float: left;
    overflow-wrap: break-word;
    font-weight: bold;
}

.data-right {
    overflow-wrap: break-word;
    width: calc(100% - 150px);
    float: left;
    padding-bottom: 3px;
}

.data.row {
    margin-bottom: 10px;
}

.small_text {
    color: #6c6a6a;
    font-size: 90%;
}

.indent {
    margin-left: 40px;
}


.error-text {
    color: #a94442;
}

.list-group {
    margin-bottom: 0;
}

.rounded-block {
    margin: 20px;
}

.custom-file-label {
    width: 100%;
}

.custom-file-border {
    line-height: 1.5;
    padding: .375rem .75rem;
    color: #495057;
    background-color: #ffffff;
    border: 1px solid #ced4da;
}

.custom-file-ext-border {
    margin-left: -.5rem;
    padding: .5rem 1rem .8rem .7rem;
    line-height: 1.5;
    color: #495057;
    background-color: #e9ecef;
    border: 1px solid #ced4da;
}

.custom-modal-title {
    display: inline;
}

.table-responsive .dt-buttons {
    margin-bottom: 0.5rem;
}

/* Event table toolbar: buttons + length/search on one row, so no per-item bottom margin. */
.table-responsive .dt-top-row .dt-buttons {
    margin-bottom: 0;
}

.table-responsive {
    margin-bottom: 3rem;
}

.margin_top_1 {
    margin-top: 0.5rem;
}

.dt-left {
    text-align: left !important;
}

#calendar {
    margin-top: 0.5rem;
}

.draft {
    font-style: italic;
    color: #000000; /* #a9a9a9 was too light for datatables view*/
}

.draft a {
    color: #000000; /* #b0c4de was too light for datatables view*/
}

.loader-box {
    text-align: center;
    text-align: -webkit-center;
    padding: 6rem;
}

.loader {
    border: 16px solid #f3f3f3; /* Light grey */
    border-top: 16px solid #337ab7; /* Blue */
    border-radius: 50%;
    width: 120px;
    height: 120px;
    -webkit-animation: spin 2s linear infinite; /* Safari */
    animation: spin 2s linear infinite;
}

.text-white {
    color: #d3d3d3;
}

.mb-2 {
    margin-bottom: 2rem;
}

/* Safari */
@-webkit-keyframes spin {
    0% {
        -webkit-transform: rotate(0deg);
    }
    100% {
        -webkit-transform: rotate(360deg);
    }
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}


/*
 * Event state indicator colors.
 *
 * Nämä ovat samat värit jotka kalenterisyöte antaa tapahtumille
 * (erp/views/event_calendar.py), ja siksi samat molemmissa teemoissa: syöte on
 * palvelinpuolella eikä tiedä teemasta, joten jos selite tummenisi tummassa
 * teemassa, se ei enää vastaisi kalenterin laatikoita. Tekstiväri on siitä
 * syystä myös kiinteä — kalenterissa sen valitsee taustan kirkkaudesta
 * BaseCalendar.getContrastTextColor.
 */
.event-state-ready {
    background-color: #99d4f4;
}

.event-state-draft {
    background-color: #ffb6b6;
    /* Kalenterissa luonnoksen teksti on punainen (syötteen textColor). */
    color: #dc3545;
}

.event-state-reservation {
    background-color: #def499;
}

/*
 * =========================================================================
 * Kalenterin suunnittelu — yhteinen muotoilukieli
 * =========================================================================
 *
 * Suunnittelun välilehdet (tapahtumasuunnittelu, puhujien toiveet, puhujien
 * työvuorot, työvuorotyypit, kopiointivaihe ja katselulinkki) piirtyvät samalla
 * kielellä: paperinvärinen otsikkorivi, mustat kuukausi- ja harmaat
 * viikko-otsikot, keltaiset luonnosrivit, pyöristetyt pillerit tyypeille ja
 * yksi työkalupalkki taulukon yllä. Kallen suunnitelma 8.9.2026, ks.
 * notes/design/tapahtumien-suunnittelutyokalu.md.
 *
 * Sävyt ovat muuttujina, ja dark-mode.css vaihtaa vain ne: säännöt alla eivät
 * tiedä teemasta mitään. Paperi on lämmin eikä harmaa, koska seurakalenteri on
 * painotuote ja taulukko on sen työversio — sama väri kertoo mistä on kyse.
 */
:root {
    --planning-paper: #f6efdc;
    --planning-paper-deep: #efe5c8;
    --planning-ink: #1f1c17;
    --planning-ink-soft: #625a51;
    --planning-draft: #fbf3d5;
    --planning-final: #fdfaf1;
    --planning-line: #e4dac0;
    --planning-accent: #b7860b;
}

/* Otsikkorivi: jakson ajanjakso pillerinä ja mahdollinen "Suljettu". */
.planning-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.planning-range {
    display: inline-block;
    padding: 0.35rem 0.8rem;
    border: 1px solid var(--planning-line);
    border-radius: 0.5rem;
    background-color: var(--planning-paper-deep);
    color: var(--planning-ink);
    font-weight: 700;
    white-space: nowrap;
}

/*
 * Tilaisuustyypit pillereinä, jotka ovat samalla suodatin.
 *
 * Päällä oleva on tumma ja pois oleva ääriviiva: rivi kertoo yhdellä
 * silmäyksellä mitä jaksossa on ja mikä siitä on näkyvissä. Valintaruutu on
 * dokumentissa (.btn-check piilottaa sen), joten näppäimistö ja testit
 * toimivat kuten rasteilla ennen.
 */
.planning-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.45rem;
    margin-bottom: 0.75rem;
}

.planning-chip {
    display: inline-block;
    padding: 0.3rem 0.9rem;
    border: 1px solid var(--planning-line);
    border-radius: 999px;
    background-color: var(--bs-body-bg);
    color: var(--planning-ink-soft);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.25;
    cursor: pointer;
    user-select: none;
}

.planning-chip:hover {
    border-color: var(--planning-ink-soft);
}

.btn-check:checked + .planning-chip,
.planning-chip--static {
    background-color: var(--planning-ink);
    border-color: var(--planning-ink);
    color: var(--bs-body-bg);
}

.planning-chip--static {
    cursor: default;
}

.btn-check:focus-visible + .planning-chip {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

/* "Kaikki" ja "Ei mitään": linkkejä pillerien perässä, eivät pillereitä. */
.planning-chip-link {
    padding: 0.3rem 0.4rem;
    border: 0;
    background: none;
    color: var(--bs-link-color);
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
}

.planning-chip-link:hover {
    text-decoration: underline;
}

/*
 * Työkalupalkki: haku vasemmalla, toiminnot keskellä, näkymäasetukset oikealla.
 * Pystyviivat erottavat ryhmät, koska "Poista jakso" ja "Merkitse rivit
 * lopullisiksi" vierekkäin ilman rajaa lukevat yhtenä sarjana.
 */
.planning-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.planning-toolbar__divider {
    align-self: stretch;
    width: 1px;
    margin: 0 0.25rem;
    background-color: var(--planning-line);
}

.planning-toolbar__end {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-left: auto;
}

.planning-search {
    width: 18rem;
    max-width: 100%;
    border-radius: 0.6rem;
    border-color: var(--planning-line);
}

/*
 * Palkin painike. Oma luokka eikä .btn-outline-*, koska Bootstrapin
 * ääriviivapainikkeet ovat teemavärisiä ja tumma reunus tummalla teemalla
 * katoaa; tämä lukee reunansa ja taustansa samoista muuttujista kuin
 * taulukko. Väriversiot kertovat painikkeen painon: tumma on rivin päämäärä,
 * keltainen ja punainen ovat ne joita ei paineta vahingossa.
 */
.planning-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.8rem;
    border: 1px solid var(--planning-line);
    border-radius: 0.6rem;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.25;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

.planning-btn:hover {
    background-color: var(--planning-paper);
    border-color: var(--planning-ink-soft);
    color: var(--bs-body-color);
}

.planning-btn:disabled {
    opacity: 0.45;
    cursor: default;
    pointer-events: none;
}

.planning-btn--primary {
    background-color: var(--planning-ink);
    border-color: var(--planning-ink);
    color: var(--bs-body-bg);
}

.planning-btn--primary:hover {
    background-color: var(--planning-ink-soft);
    border-color: var(--planning-ink-soft);
    color: var(--bs-body-bg);
}

.planning-btn--warning {
    color: var(--bs-warning-text-emphasis);
    border-color: color-mix(in srgb, var(--bs-warning) 45%, var(--planning-line));
}

.planning-btn--danger {
    color: var(--bs-danger-text-emphasis);
    border-color: color-mix(in srgb, var(--bs-danger) 35%, var(--planning-line));
}

.planning-btn--success {
    color: var(--bs-success-text-emphasis);
    border-color: color-mix(in srgb, var(--bs-success) 45%, var(--planning-line));
}

/*
 * Ohje (i)-painikkeen takana. Rengas on korostusvärinen, jotta se löytyy
 * palkin oikeasta reunasta ilman että se kilpailee toimintopainikkeiden
 * kanssa; sisältö tulee popoverissa (planning_toolbar.js).
 */
.planning-help-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 2px solid var(--planning-accent);
    border-radius: 50%;
    background-color: var(--bs-body-bg);
    color: var(--planning-accent);
    font-size: 0.85rem;
    font-weight: 700;
}

.planning-help-popover {
    --bs-popover-max-width: 26rem;
    --bs-popover-border-color: var(--planning-line);
}

.planning-help p {
    margin-bottom: 0.6rem;
}

.planning-help__title {
    color: var(--planning-ink-soft);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Rivimäärä ja yhteenveto taulukon yllä. */
.planning-count,
.planning-summary {
    font-size: 0.9rem;
}

/* Tilamerkit. Bootstrapin -subtle-taustat ovat teemakohtaisia valmiiksi. */
.planning-badge {
    border-radius: 0.4rem;
    font-weight: 600;
}

.planning-badge--ready {
    background-color: var(--bs-success-bg-subtle);
    color: var(--bs-success-text-emphasis);
}

.planning-badge--draft {
    background-color: var(--bs-warning-bg-subtle);
    color: var(--bs-warning-text-emphasis);
}

.planning-badge--closed {
    background-color: var(--planning-ink);
    color: var(--bs-body-bg);
}

/*
 * Taulukko.
 *
 * Otsikkorivi on paperinvärinen ja versaalein harvennettuna, jotta se erottuu
 * riveistä tekstin muodolla eikä vain viivalla. Rivit lukevat taustansa
 * --bs-table-bg-muuttujasta: Bootstrap 5.3:n taulukkosolut lukevat sen, ja
 * hover-korostus tulee erillisestä --bs-table-bg-statesta, joka voittaa yhä.
 * Suoraan asetettu tausta söisi hoverin.
 *
 * Luonnos on keltainen ja lopullinen paperinvaalea. Väri on koko rivillä eikä
 * tilasarakkeessa, koska rivejä on satoja ja rivin värin lukee ilman että
 * sarakkeeseen asti ehtii katsoa. Keltainen tarkoittaa "tähän pitää vielä
 * palata".
 */
.planning-grid {
    --bs-table-border-color: var(--planning-line);
}

.planning-grid > thead > tr > th {
    background-color: var(--planning-paper);
    color: var(--planning-ink-soft);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}

.planning-grid > tbody > tr {
    --bs-table-bg: var(--planning-final);
}

.planning-grid > tbody > tr.planning-row--draft {
    --bs-table-bg: var(--planning-draft);
}

/* Tapahtuman nimi on rivin otsikko ja lihavoitu kuten painetussa kalenterissa. */
.planning-grid td.planning-cell--name {
    font-weight: 700;
}

.planning-grid td.planning-cell--date,
.planning-grid td.planning-cell--time {
    white-space: nowrap;
}

/*
 * Tiivis: pienempi riviväli ja fontti, jolloin ruudulle mahtuu kuukausi
 * kerrallaan. Kytkin työkalupalkissa, tila selaimen muistissa
 * (planning_toolbar.js).
 */
.planning-grid--compact > tbody > tr > td,
.planning-grid--compact > thead > tr > th {
    padding-top: 0.1rem;
    padding-bottom: 0.1rem;
    font-size: 0.85rem;
    line-height: 1.25;
}

.planning-grid--compact .planning-band > td {
    padding-top: 0.15rem;
    padding-bottom: 0.15rem;
}

/*
 * Sarakeotsikot pysyvät näkyvissä vieritettäessä.
 *
 * Jakso on satoja rivejä ja toistakymmentä saraketta, ja otsikkorivin
 * vieritettyä ohi ei enää tiedä kumpi nimisarake on kumpi (palaute 7.9.2026).
 *
 * **Kääre lakkaa olemasta vierityssäiliö.** Bootstrapin `.table-responsive` on
 * `overflow-x: auto`, ja koska toinen akseli ei silloin voi jäädä
 * `visible`iksi, myös `overflow-y` laskeutuu `auto`ksi — kääre on siis
 * vierityssäiliö molempiin suuntiin, ja sticky tarttuisi sen omaan yläreunaan
 * eikä ruudun. Kääre ei kuitenkaan vierry pystyyn (sen korkeus on sisällön
 * korkeus), joten otsikko ei tarttuisi mihinkään.
 *
 * Vaihtoehto olisi ollut antaa käärelle ruudun korkuinen katto ja jättää se
 * vierityssäiliöksi. Se hylättiin: solun editorin valikko (Choices) on
 * absoluuttisesti asemoitu solun sisään, ja korkeudeltaan rajattu säiliö
 * leikkaisi sen taulukon alareunassa. Nyt leikkaavaa säiliötä ei ole.
 *
 * Hinta on, että alle noin 1200px leveydellä taulukko on käärettään leveämpi
 * ja vierittää sivua vaakaan sen sijaan että vierittäisi kääreen sisällä.
 * Otsikko pysyy silti sarakkeidensa kohdalla, koska se liikkuu vaakaan
 * taulukon mukana.
 *
 * Alle 768px sääntöä ei ole: siellä taulukko on korttilista eikä otsikkoriviä
 * ole lainkaan (.table-stack), ja katselulinkin taulukko tarvitsee kääreensä
 * vaakavierityksen.
 */
@media (min-width: 768px) {
    .planning-scroll {
        overflow: visible;
    }

    .planning-scroll > table > thead > tr > th {
        position: sticky;
        /* Navipalkin alle, ei ruudun ylälaitaan: navipalkki on itsekin sticky. */
        top: var(--navbar-height);
        /* Taulukon rivit ovat asemoimattomia, joten kaksi riittää niiden yli.
           Selvästi alle Choicesin 1000:n, jottei auki oleva solun valikko jää
           otsikon taakse — ja alle navipalkin 1030:n. */
        z-index: 2;
        /* Reunaviiva ei kulje mukana sticky-solussa, koska taulukon reunat
           piirtyvät soluväleihin; varjo on se joka erottaa otsikon riveistä. */
        box-shadow: inset 0 -1px 0 var(--planning-line);
    }
}

/*
 * Kuukauden ja viikon otsikkorivit suunnittelutaulukossa.
 *
 * Puolen vuoden jakso on satoja rivejä, ja vieritettäessä katoaa se mistä
 * kohtaa kalenteria luetaan. Vk-sarake kertoo saman numerona joka rivillä,
 * mutta numero rivin reunassa ei erotu — vaihtumiskohta on se mitä silmä hakee.
 *
 * Kaksi tasoa erottuvat tummuudella eivätkä sävyllä: kuukausi on musta ja
 * viikko harmaa, jolloin kumpi on kumman sisällä näkyy ilman että väri
 * kilpailee rivien oman tilavärin kanssa (.planning-row--draft).
 *
 * box-shadow eikä background-color: Bootstrap 5.3 maalaa solun taustan
 * inset-varjolla, joka voittaisi tähän soluun asetetun taustan. Sama syy kuin
 * korostetun rivin välähdyksessä.
 */
.planning-band > td {
    box-shadow: inset 0 0 0 9999px var(--planning-band-bg);
    color: var(--planning-band-fg);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    /* Kuukauden nimi tulee palvelimelta pienellä ("tammikuu 2027"); versaalit
       ovat esitystapa eivätkä sisältöä, joten ne tehdään täällä. */
}

.planning-band--month > td {
    --planning-band-bg: var(--planning-ink);
    --planning-band-fg: var(--bs-body-bg);
    font-size: 0.95rem;
    padding-top: 0.45rem;
    padding-bottom: 0.45rem;
}

.planning-band--week > td {
    --planning-band-bg: var(--planning-ink-soft);
    --planning-band-fg: var(--bs-body-bg);
    font-size: 0.8rem;
    padding-left: 1.25rem;
}

/* Otsikkorivi ei ole kortti. Alle 768px .table-stack tekee jokaisesta rivistä
   reunustetun kortin, mutta osion otsikko on nimenomaan se mikä erottaa kortit
   toisistaan — reunus ja pyöristys tekisivät siitä yhden kortin lisää. */
@media (max-width: 767.98px) {
    .table-stack > tbody > tr.planning-band {
        display: block;
        margin: 0.75rem 0 0.35rem;
        padding: 0;
        border: 0;
        border-radius: 0;
    }

    .table-stack > tbody > tr.planning-band > td {
        display: block;
        padding: 0.2rem 0.6rem;
        border-radius: 0.25rem;
        /* Korttiasettelu nollaa solun inset-varjon (ks. .table-stack), jolla
           palkki muuten maalataan — ilman tätä otsikko olisi valkoista tekstiä
           valkoisella. Tavallinen tausta riittää, koska korttina solu ei ole
           enää Bootstrapin taulukkosolu. */
        background-color: var(--planning-band-bg);
    }
}

/*
 * Juhlapyhä viikonpäivän kohdalla, nimi suluissa perässä: "pe (Uudenvuodenpäivä)".
 *
 * Seurakalenterissa juhlapyhä on se päivä jonka ympärille loput järjestetään,
 * ja sheetissä se luettiin ihmisen muistista. Väri on viikonpäiväsolussa eikä
 * koko rivillä, koska rivin väri on jo varattu luonnos/valmis-tilalle
 * (.planning-row--draft) — kaksi merkitystä samassa värissä ei kerro kumpaakaan.
 *
 * Ei text-mutedia rinnalle: sävy tulee tästä, ja Bootstrapin --bs-danger-text
 * -emphasis on luettava molemmilla teemoilla toisin kuin kirkas punainen.
 */
.planning-holiday {
    color: var(--bs-danger-text-emphasis);
    font-weight: 600;
    white-space: nowrap;
}

.planning-holiday-name {
    font-weight: 400;
}

/*
 * "Muuta huomioitavaa" punaisella.
 *
 * Muistiinpano kertoo mitä rivillä on vielä sopimatta, ja sadan rivin jaksossa
 * juuri ne muutamat rivit ovat se mitä haetaan. Väri on solun tekstissä, joten
 * tyhjä muistiinpano ei värjää mitään — eikä rivin oma tilaväri katoa alta.
 */
.planning-note {
    color: var(--bs-danger-text-emphasis);
}

/*
 * Rivi, joka juuri syntyi tai siirtyi, välähtää hetken.
 *
 * Kopio menee päivänsä alle jonnekin taulukon keskelle, ja päivämäärän vaihto
 * siirtää rivin toisen viikon alle — ilman merkkiä klikkauksesta ei näe muuta
 * kuin että jotain tapahtui jossain (palaute 7.9.2026). Animaatio eikä pysyvä
 * väri, koska korostus on vastaus yhteen klikkaukseen eikä rivin ominaisuus.
 *
 * box-shadow eikä --bs-table-bg: Bootstrap 5.3 maalaa solun taustan juuri
 * inset-varjolla, ja mukautuvat ominaisuudet eivät interpoloi — animoitava on
 * siis se sama varjo. Ilman fill-modea rivi palaa animaation jälkeen omaan
 * taustaansa itsestään.
 */
@keyframes planning-row-flash {
    from {
        box-shadow: inset 0 0 0 9999px color-mix(in srgb, var(--bs-info) 55%, transparent);
    }
    to {
        box-shadow: inset 0 0 0 9999px transparent;
    }
}

.planning-row--flash > td {
    animation: planning-row-flash 4s ease-out 1;
}

/* Liikkeen sijaan pelkkä väri niille, jotka ovat pyytäneet vähemmän liikettä:
 * korostus on yhä se mitä pyydettiin, eikä välkkyminen ole sen ydin. */
@media (prefers-reduced-motion: reduce) {
    .planning-row--flash > td {
        animation: none;
        box-shadow: inset 0 0 0 9999px color-mix(in srgb, var(--bs-info) 35%, transparent);
    }
}

/* Katselulinkin osoitekenttä jakson ylälaidassa: täysi leveys puhelimessa,
 * muuten linkin mittainen eikä koko rivin. */
.planning-share-group {
    max-width: 34rem;
}

/*
 * Muokattava solu näyttää muokattavalta.
 *
 * Taulukko näytti pelkältä listalta, ja käyttäjät eivät huomanneet että soluja
 * voi klikata. Merkki on katkoviiva arvon alla — vakiintunut merkki paikallaan
 * muokattavasta arvosta — ja se näkyy myös tyhjässä solussa, joka on juuri se
 * solu jota ei muuten huomaa lainkaan.
 *
 * Valitsin on [data-field], eli täsmälleen se attribuutti jonka palvelin jättää
 * pois lukitusta solusta. Lopulliset rivit, väärän tyypin rivit ja suljettu
 * jakso eivät siis saa merkkiä, eikä tämä tiedosto päättele oikeuksia.
 *
 * Hover-korostus asetetaan --bs-table-bg-stateen: Bootstrap 5.3 maalaa rivin
 * hoverin samasta muuttujasta, joten suoraan asetettu background-color jäisi
 * sen alle.
 */
.planning-grid td[data-field] {
    cursor: pointer;
    border-bottom: 1px dashed color-mix(in srgb, var(--bs-emphasis-color) 35%, transparent);
}

.planning-grid td[data-field]:hover {
    --bs-table-bg-state: color-mix(in srgb, var(--bs-emphasis-color) 10%, transparent);
}

/*
 * Kynä katkoviivan lisäksi.
 *
 * Pelkkä katkoviiva jäi huomaamatta: taulukossa on muitakin viivoja, ja ohje
 * sen yläpuolella luetaan vasta kun tietää etsivänsä jotain. Kynä on
 * yksiselitteinen eikä tarvitse selitystä — ja se on haalea, koska sivulla on
 * satoja rivejä ja täysi kontrasti tekisi taulukosta lukukelvottoman.
 * Kursorin alla se kirkastuu, jolloin merkki vahvistaa juuri sen solun jota
 * ollaan klikkaamassa.
 *
 * Erillinen ::after eikä ikonielementti soluun: merkki ei ole sisältöä vaan
 * sen ominaisuus, eikä se saa päätyä solun tekstiin — editori lukee solun
 * nykyisen arvon textContentista.
 */
.planning-grid td[data-field]::after {
    content: "\f304"; /* fa-pen */
    font-family: "Font Awesome 7 Free";
    font-weight: 900;
    font-size: 0.7em;
    margin-left: 0.35rem;
    opacity: 0.25;
}

.planning-grid td[data-field]:hover::after {
    opacity: 0.8;
}

/*
 * "Lisää…" tyhjässä muokattavassa solussa.
 *
 * Tyhjä solu katkoviivalla luki yhä tyhjänä; sana kertoo että siihen voi
 * kirjoittaa. Teksti tulee CSS-muuttujasta, jonka planning_grid.js asettaa
 * taulukon data-placeholder-attribuutista käännettynä — sama sana on
 * sadoissa soluissa, eikä sitä kanneta joka solun attribuuttina. Ilman
 * skriptiä muuttujaa ei ole, content on epäkelpo ja solu jää tyhjäksi, mikä
 * on täsmälleen entinen käyttäytyminen.
 *
 * :empty on tarkka: templaatti ei jätä muokattavan solun sisään rivinvaihtoja
 * eikä välilyöntejä (planning/_grid_rows.html), ja editori kirjoittaa
 * tyhjennetyn solun textContentiksi tyhjän merkkijonon.
 */
.planning-grid td[data-field]:empty::before {
    content: var(--planning-placeholder);
    color: color-mix(in srgb, currentcolor 45%, transparent);
    font-style: italic;
}

/*
 * Työpöydällä kynä on solun oikeassa ylänurkassa eikä tekstin perässä.
 *
 * Rivin osana se katkesi omalle rivilleen aina kun solun teksti täytti
 * sarakkeen leveyden — tilaisuustyyppi on pisin ja osui siihen useimmin — ja
 * koko taulukon rivi kasvoi kaksinkertaiseksi yhden merkin takia. Absoluuttinen
 * ei osallistu rivitykseen lainkaan, ja solu varaa sille tilan oikeasta
 * reunastaan.
 *
 * Valikkosolu (tilaisuustyyppi, paikka) saa lisäksi nuolen kynän viereen:
 * se kertoo että klikkaus avaa listan eikä kenttää. Taustakuvana eikä
 * pseudoelementtinä, koska ::before on varattu tyhjän solun vihjeelle.
 *
 * Vain työpöydällä: korttiasettelussa solu on "otsikko ..... arvo" -flexiä,
 * jossa kynä asettuu kolmanneksi palaksi rivin loppuun eikä katkea mihinkään.
 */
@media (min-width: 768px) {
    .planning-grid td[data-field] {
        position: relative;
        padding-right: 1.1rem;
    }

    .planning-grid td[data-field]::after {
        position: absolute;
        top: 0.25rem;
        right: 0.3rem;
        margin-left: 0;
    }

    .planning-grid td.planning-cell--select[data-field] {
        padding-right: 2.3rem;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%237a7268' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M3 6l5 5 5-5'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 1.2rem center;
        background-size: 0.65rem;
    }
}

/*
 * Työvuorosolun tekijät: yksi nimi per rivi, eikä nimen sisällä katkota.
 *
 * Sarake on kapea, koska sarakkeita on monta, joten "Matti Meikäläinen" katkesi
 * etunimen jälkeen — ja kahden vuoron solussa kaksi nimeä valui yhdeksi
 * pötköksi, josta ei erottanut mistä kukin alkaa. Rivi per tekijä on sekä
 * luettavampi että ennustettavan korkuinen: kaksi vuoroa on kaksi riviä eikä
 * neljä.
 */
.planning-name-list {
    display: flex;
    flex-direction: column;
}

.planning-name {
    white-space: nowrap;
}

/* Avattu solu on kenttä eikä enää klikattava arvo, joten merkit pois —
 * kentällä on oma reunansa, ja kaksi viivaa päällekkäin näyttää rikkinäiseltä. */
.planning-grid td[data-field]:focus-within {
    border-bottom-color: transparent;
    background-image: none;
}

.planning-grid td[data-field]:focus-within::after,
.planning-grid td[data-field]:focus-within::before,
/* Puuttuvan vuoron plussa on jo kehotus klikata, joten kynä sen vieressä olisi
   kaksi merkkiä samasta asiasta. */
.planning-grid td[data-field]:has(> [data-add-turn])::after {
    content: none;
}

/*
 * Tila-sarake ei kuristu.
 *
 * Solussa on kytkin ja sen nimiö ("Valmis" tai "Luonnos"). Kapealla näytöllä
 * taulukko jakaa leveyden sarakkeille sisällön mukaan, ja nimiö katkesi
 * kytkimen alle omalle rivilleen. Korttiasettelussa (alle 768px) kytkin on
 * otsikkonsa oikealla puolella eikä kilpaile sarakeleveydestä, joten sääntö
 * rajataan taulukkonäkymään.
 */
@media (min-width: 768px) {
    .planning-grid td[data-state-cell] {
        white-space: nowrap;
    }
}

/*
 * Työvuorosolun editori: yksi rivi per työvuoro.
 *
 * Vuoron nimi kentän edessä, koska samalla tilaisuudella on säännöllisesti
 * "ensimmäinen puhe" ja "toinen puhe" — ilman nimeä kaksi valikkoa päällekkäin
 * ei kerro kumpi on kumpi. min-width kentälle, ettei valikko kuristu sarakkeen
 * leveyteen: solu on kapea siksi että siinä on tavallisesti pari nimeä.
 */
.planning-turn-editor {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 14rem;
    padding: 0.25rem;
}

.planning-turn-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.planning-turn-label {
    flex: 0 0 6rem;
    font-size: 0.75rem;
    text-align: right;
    overflow-wrap: anywhere;
}

.planning-turn-row > select,
.planning-turn-row > input {
    flex: 1 1 auto;
}

/* Editorin alarivi: uusi vuoro vasemmalla, Valmis oikealla. */
.planning-turn-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.25rem;
}

.planning-turn-done {
    margin-left: auto;
    padding: 0.2rem 0.7rem;
    font-size: 0.8rem;
}

/* Puhelimessa työkalupalkin haku vie koko rivin ja näkymäasetukset putoavat
   omalle rivilleen, jotta painikkeet eivät jää yhden kirjaimen levyisiksi. */
@media (max-width: 767.98px) {
    .planning-search {
        width: 100%;
    }

    .planning-toolbar__end {
        width: 100%;
        margin-left: 0;
    }
}

/*
 * Taulukko, joka leveytyy sisältönsä eikä ruudun mukaan.
 *
 * Bootstrapin `.table` on `width: 100%`, mikä on oikein silloin kun sarakkeissa
 * on tekstiä. Kapeista luvuista koostuva taulukko sen sijaan levitetään
 * täysleveällä näytöllä puolityhjäksi: rivin ensimmäinen ja viimeinen solu
 * päätyvät toistensa ääripäihin, ja silmä joutuu kulkemaan puoli metriä
 * yhdellä rivillä pysyäkseen. Juuri se tekee lukemisesta työlästä.
 *
 * max-width pitää tämän yhteensopivana `.table-responsive`-käärön kanssa:
 * kapealla näytöllä taulukko ei kasva sen yli vaan vierittyy kuten ennenkin.
 *
 * Vain työpöydällä: alle 768px `.table-stack` muuttaa taulukon korttilistaksi,
 * jolla ei ole sarakkeita joiden leveyttä tämä koskisi.
 */
@media (min-width: 768px) {
    .table-fit {
        width: auto;
        max-width: 100%;
    }
}

/*
 * Puhujan oma lomake: kapea palsta myös työpöydällä.
 *
 * Bootstrapin `.container` on isolla näytöllä 1320px, ja koko sen levyinen
 * tekstikenttä on vaikeampi täyttää kuin kapea — silmä ei löydä kentän alkua
 * takaisin. Lomake on pystysuora kysymyslista, joten sama muoto kelpaa
 * puhelimeen ja työpöydälle; se on samalla ainoa muoto joka on testattu.
 */
.speaker-form {
    max-width: 36rem;
}

/*
 * Puhujan tietojen kuittaus.
 *
 * Kaksi väriä samalle ruudulle, koska kuittaus voi tulla kahdelta suunnalta ja
 * ero on koordinaattorille merkitsevä: vihreä tarkoittaa että puhuja itse kävi
 * linkin kautta katsomassa tietonsa, oletussininen että koordinaattori merkitsi
 * ne tarkistetuiksi puhelun jälkeen. Sama tieto on ruudun title-tekstissä
 * sanoina — väri on nopea silmäys eikä ainoa kanava, koska se ei erotu
 * kaikille.
 *
 * background-color ja border-color eikä accent-color: Bootstrapin
 * .form-check-input on `appearance: none` ja piirtää ruudun itse, joten
 * accent-color ei osu siihen lainkaan. Se näytti oikealta laskettuna arvona ja
 * ruudulla ei miltään.
 */
.speaker-check {
    cursor: pointer;
}

.speaker-check--self:checked {
    background-color: var(--bs-success);
    border-color: var(--bs-success);
}

/* Kalenterin selitelaatikot "Tilaisuuksien tilat" -rivillä */
.calendar-legend {
    display: inline-block;
    min-width: 8rem;
    padding: 0.25rem 0.75rem;
    text-align: center;
    border-radius: 0.25rem;
    color: #000;
}

.scroll-menu{
   min-width: 220px;
   max-height: 90vh;
   overflow: auto;
 }

.org-search-container {
   position: sticky;
   top: 0;
   background: inherit;
   z-index: 1;
   padding-top: 0.25rem;
 }

/*
 * Detail views (tilaisuus, paikka, ...)
 * ------------------------------------
 * A label/value listing that survives a phone screen. The old pattern was
 * either `.data-left` (a 150px float, which leaves a 360px phone 200px for the
 * value) or `col-md-3` pairs (which stack into unseparated label/value blocks).
 * Here the desktop keeps the familiar two-pairs-per-row look, and below 768px
 * each field becomes label-above-value with a hairline separator.
 */

/* Flex/grid children need this before they will shrink below their content
   width — without it a long title pushes the action buttons off screen. */
.min-w-0 {
    min-width: 0;
}

/* base.html gives the content row 20px of top margin, and Bootstrap gives the
   breadcrumb 1rem below itself: together some 36px before the title, which is
   a lot of a small laptop's screen spent on a single line of navigation. */
.detail-breadcrumb {
    --bs-breadcrumb-margin-bottom: 0.25rem;
    margin-top: -0.5rem;
}

.detail-title {
    font-size: 1.5rem;
    margin-bottom: 0.25rem;
}

.detail-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    margin-bottom: 0;
}

.detail-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.05rem 1rem;
    padding: 0.3rem 0.25rem;
    border-top: 1px solid var(--bs-border-color);
    min-width: 0;
}

.detail-item > dt {
    font-weight: 600;
    color: var(--bs-secondary-color);
}

.detail-item > dd {
    margin-bottom: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Paikan osat yhdelle riville pilkuilla eroteltuna. Flex-kontti hylkää
   elementtien välisen tyhjän, joten templatessa saa rivittää vapaasti ilman
   että pilkun eteen jää välilyönti. */
.detail-place {
    display: flex;
    flex-wrap: wrap;
    column-gap: 0.35rem;
}

.detail-place > span:not(:last-child)::after {
    content: ",";
}

/* Paikan nimi ja osoite erotetaan viivalla, osoitteen osat pilkuilla:
   "toimitalo – Professorinväylä 7, 90100 Oulu" */
.detail-place > .detail-place-name:not(:last-child)::after {
    content: " \2013";
}

/* Section with its own heading and free-form content (työvuorot, muuta, ...):
   heading in the label column on desktop, above the content on a phone. */
.detail-block {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.35rem 1rem;
    margin-top: 1.5rem;
}

.detail-block > .detail-block-title {
    font-weight: 600;
    color: var(--bs-secondary-color);
    font-size: 1rem;
    margin-bottom: 0;
}

.detail-block > .detail-block-body {
    min-width: 0;
}

/* The global .table-responsive reserves 3rem below itself for the DataTables
   controls; inside a detail block the next thing is usually a button that
   belongs with the table. */
.detail-block .table-responsive {
    margin-bottom: 0.75rem;
}

/*
 * Choices.js: monivalinnat ja pitkät valintalistat.
 *
 * Kirjasto tarjoaa versiosta 11 lähtien kaikki värit ja mitat
 * --choices-*-muuttujina, ja niitä käytetään täällä valitsinten sijaan. Syy on
 * konkreettinen: kirjaston oma sääntö on
 * `.choices__list--dropdown, .choices__list[aria-expanded]`, jonka
 * jälkimmäinen osa on painoarvoltaan 0-2-0 — täsmälleen sama kuin
 * `[data-bs-theme="dark"] .choices__list--dropdown`. Tasapelin ratkaisee
 * järjestys, ja choices.min.css ladataan base_site_form.html:n formstyle-lohkossa
 * dark-mode.css:n jälkeen, joten kirjasto voitti ja pudotusvalikko jäi valkoiseksi
 * tummassa teemassa. Muuttuja periytyy eikä kilpaile painoarvosta lainkaan.
 */
.choices {
    /* Kirjaston oletus on 1, jolloin auki oleva valikko jää lomakkeen
       myöhempien positioitujen elementtien (esim. CKEditorin työkalurivi) alle.
       1000 on Bootstrapin dropdown-taso, navbarin (1030) ja modaalin alla. */
    --choices-z-index: 1000;
}

/*
 * Monivalinnan hakukenttä.
 *
 * Choices mitoittaa kloonatun syötekentän sisältönsä mukaan. Ilman
 * placeholderValue-asetusta se on tyhjänä 1ch eli 8 pikseliä leveä: kenttään voi
 * kirjoittaa ja lista suodattuu, mutta mitään ei näy eikä kentän olemassaoloa voi
 * arvata. Paikkamerkki (ks. form/multiselect_script.html) nostaa sen 5ch:hon, mikä
 * riittää vain paikkamerkille itselleen.
 *
 * !important siksi, että kirjasto kirjoittaa leveyden inline-tyylinä
 * (`min-width: 5ch; width: 1ch`), ja inline voittaa tyylitiedoston ilman sitä.
 * Tämä on se tapaus jota varten !important on olemassa.
 */
.choices__input--cloned {
    min-width: 12rem !important;
}

/*
 * Käyttäjän lisäoikeuksien hierarkia (user/user_form.html, PermissionSelectMultiple
 * erp/forms/user.py:ssä). Sisennys näyttää minkä oikeuden sisällä toinen jo on
 * (ks. erp/lib/permissions.py: ORGANISATION_PERMISSION_LEVELS). Vain
 * pudotusvalikon riveillä (.choices__item--choice) — valituissa tageissa
 * sisennys ei kertoisi mitään, ne ovat jo yksi litteä rivi.
 */
.choices__item--choice .perm-depth-1 {
    margin-left: 1.25rem;
}

.choices__item--choice .perm-depth-2 {
    margin-left: 2.5rem;
}

.choices__item--choice .perm-depth-3 {
    margin-left: 3.75rem;
}

@media (min-width: 768px) {
    .detail-title {
        font-size: 2rem;
    }

    .detail-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 2rem;
    }

    .detail-item {
        grid-template-columns: 10rem minmax(0, 1fr);
        align-items: baseline;
    }

    /* Long free text (lisätiedot, kommentti) gets the whole row */
    .detail-item--wide {
        grid-column: 1 / -1;
    }

    .detail-item--wide > dd {
        max-width: 60rem;
    }

    .detail-block {
        grid-template-columns: 10rem minmax(0, 1fr);
    }
}

/*
 * Tables that become cards on a phone
 * -----------------------------------
 * `table-responsive` only moves the overflow into a sideways scroll, which on a
 * phone hides the last columns (and with them the row actions). A `.table-stack`
 * table keeps one markup for both layouts: below 768px every row becomes a card
 * where the cells are laid out by role instead of by column —
 *
 *   .stack-title    the row's name; first line, together with
 *   .stack-actions  the row's buttons, pushed to the right of that same line
 *   .stack-people   ) and then whatever the row is about, in this order
 *   .stack-time     )
 *   .stack-fill     )
 *   .stack-pair     "label ....... value", for a cell that means nothing
 *                   without its column heading. The label comes from the
 *                   cell's own data-stack-label, because the heading row is
 *                   what a card layout throws away — and a lone "4" in a
 *                   column of numbers is not information.
 *   .stack-chips    a row of toggle buttons, given a thumb-sized hit area
 *   .stack-hide     cell that carries nothing worth a line on a card
 *
 * Anything without one of these classes gets a line of its own.
 */

@media (max-width: 767.98px) {
    .table-stack > thead {
        display: none;
    }

    .table-stack,
    .table-stack > tbody {
        display: block;
        width: auto;
    }

    .table-stack > tbody > tr {
        /* Two columns: the content, and a narrow one for what belongs on the
           right edge (the row's buttons, the fill rate). */
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: 0.75rem;
        align-items: start;
        margin-bottom: 0.5rem;
        padding: 0.3rem 0.6rem 0.35rem;
        border: 1px solid var(--bs-border-color);
        border-radius: 0.5rem;
        /* The row variant classes (.table-success, .table-warning) set these
           variables on the row; on desktop the cells consume them. */
        background-color: var(--bs-table-bg);
        color: var(--bs-table-color);
    }

    /* The name filter hides rows with the `hidden` attribute, whose `display:
       none` comes from the browser's own stylesheet — and an author rule beats
       that, so without this every filtered-out row stays on screen the moment
       the table turns into cards. */
    .table-stack > tbody > tr[hidden] {
        display: none;
    }

    .table-stack > tbody > tr > td,
    .table-stack > tbody > tr > th {
        /* A cell with no role of its own gets a line to itself */
        grid-column: 1 / -1;
        padding: 0.1rem 0;
        border: 0;
        /* Bootstrap paints the cell background with a 9999px inset shadow, which
           would spill over the card's rounded corners. */
        box-shadow: none;
        /* The card is painted once, by the row. A cell that painted its own
           background would double a translucent row variant (.planning-row--draft
           is a color-mix against transparent), and the gaps the grid leaves
           between cells would then read as a paler block — which is exactly how
           it looked before this line. */
        background-color: transparent;
        text-align: left;
        overflow-wrap: anywhere;
    }

    /* The two things worth reading first on a phone: what the turn is, and who
       is on it. The times and the fill rate stay at body size below them. */
    .table-stack .stack-title {
        grid-row: 1;
        grid-column: 1;
        font-weight: 600;
        font-size: 1.15rem;
    }

    .table-stack .stack-actions {
        grid-row: 1;
        grid-column: 2;
        justify-self: end;
        padding: 0;
    }

    .table-stack .stack-people {
        grid-row: 2;
        font-size: 1.15rem;
        line-height: 1.35;
    }

    /* Last line: the times on the left, the fill rate against the right edge */
    .table-stack .stack-time {
        grid-row: 3;
        grid-column: 1;
        white-space: nowrap;
        /* Slightly recessed against the title and the names. Not opacity: that
           would also dim the .time-differs highlight nested inside. */
        color: color-mix(in srgb, currentcolor 80%, transparent);
    }

    .table-stack .stack-fill {
        grid-row: 3;
        grid-column: 2;
        justify-self: end;
        text-align: right;
        color: color-mix(in srgb, currentcolor 80%, transparent);
    }

    /*
     * The line straight under the title: when a row happened, where it is.
     *
     * Deliberately not .stack-time, which is pinned to the card's third row for
     * the event page's fixed three-line shape. These cards have a variable
     * number of lines, so everything below the title is auto-placed and follows
     * document order — one rule fewer to keep in step with the markup.
     */
    .table-stack .stack-sub {
        white-space: nowrap;
        color: color-mix(in srgb, currentcolor 80%, transparent);
    }

    /*
     * A number that only means something next to its column heading.
     *
     * The heading row is the first thing a card layout throws away, so the
     * label travels with the cell instead. ::before rather than markup: the
     * same cell is edited in place by planning_speakers.js, which replaces the
     * cell's text with an input — a real element in there would be wiped on the
     * first click, and a label that disappears when you edit the value is worse
     * than no label at all.
     */
    .table-stack .stack-pair {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 0.75rem;
        text-align: right;
    }

    .table-stack .stack-pair::before {
        content: attr(data-stack-label);
        flex: 0 1 auto;
        text-align: left;
        font-weight: 400;
        color: color-mix(in srgb, currentcolor 65%, transparent);
        /* The cell breaks long values anywhere it has to; a heading broken
           mid-word ("Tilaisuustyyp / pi") just reads as damage. The value gets
           the leftover width instead. */
        overflow-wrap: normal;
    }

    /* The editor that opens inside such a cell keeps the label company instead
       of pushing it off the line. */
    .table-stack .stack-pair .form-control,
    .table-stack .stack-pair .form-select {
        width: auto;
        flex: 1 1 6rem;
    }

    /* Toggles are tapped, not clicked: the desktop chip is a couple of
       millimetres tall, which is a miss on a phone. */
    .table-stack .stack-chips {
        padding-top: 0.35rem;
    }

    .table-stack .stack-chips .btn {
        --bs-btn-padding-y: 0.3rem;
        --bs-btn-padding-x: 0.6rem;
        margin-bottom: 0.25rem;
    }

    .table-stack .stack-hide {
        display: none;
    }

    /* Thumb-sized icon buttons */
    .table-stack .stack-actions .btn {
        --bs-btn-padding-y: 0.4rem;
        --bs-btn-padding-x: 0.7rem;
        --bs-btn-font-size: 1rem;
    }
}

/*
 * A time that differs from the one the event itself has: work turns default to
 * the event's own start and end, so one that begins earlier or ends later is
 * the exception and has to be visible at a glance. The colour is fixed because
 * these rows are always the pale .table-success / .table-warning variants,
 * which keep their dark text in the dark theme too.
 */
.time-differs {
    font-weight: 700;
    color: #b02a37;
    white-space: nowrap;
}

@media print {
    /* Hide navigation elements */
    .navbar { display: none !important; }
    .sidebar { display: none !important; }

    /* Main content uses full page width once the sidebar is hidden */
    .main {
        width: 100% !important;
    }

    /* Hide UI-only elements */
    .dropdown,
    .breadcrumb,
    .murupolku,
    .pagination,
    .ryhman_kommentit,
    #sidebar,
    .feedback-widget-container
    {
        display: none !important;
    }

    /* Let content use full width since sidebar is hidden */
    .left_site {
        width: 100% !important;
        max-width: 100% !important;
        flex: 0 0 100% !important;
    }

    /* Clean page setup */
    body {
        font-size: 12pt;
        color: #000 !important;
    }

    a { color: #000 !important; }

    /* Force light mode for print */
    html[data-bs-theme="dark"] { color-scheme: light !important; }
}
/* Lomakesivun luettava mittasuhde. Organisaation muokkaus piilottaa sivupalkin
   (hide_sidebar), jolloin lomake venyisi koko ikkunan levyiseksi ja kahden
   sarakkeen kentistä tulisi metrin mittaisia. Kapeampi keskitetty palsta on
   sama ratkaisu kuin suunnitelmassa; ota käyttöön muillakin täysleveillä
   lomakesivuilla sen sijaan että kirjoittaisit max-widthin uudestaan. */
.form-page {
    max-width: 1080px;
}

/* Lomakkeen tarttuva toimintopalkki (Peruuta / Tallenna). Oikeaan reunaan
   jätetään tilaa palautewidgetille (.feedback-widget-btn), joka on fixed
   ikkunan oikeassa alakulmassa ja peittäisi Tallenna-napin aina kun
   lomakepalstan oikea reuna sattuu widgetin kohdalle — kapealla näytöllä
   käytännössä joka kerta. */
.form-actions {
    padding-right: 5rem;
}

/* Tilaisuuden kanavaesikatselu (event_preview_panel.html). Mockit jäljittelevät
   oikeita ulostuloja: infonäyttö on mustavalkoinen molemmissa teemoissa koska
   oikea näyttökin on, lehtirivi on antiikvaa kuten painettu palsta, ja
   tekstiviesti on viestikupla. Valitsemattomat kanavat jäävät kokonaan pois
   (erp/views/event_preview.py), joten himmennys jää sille tapaukselle jossa
   kanava on valittu mutta julkaisu ei silti tapahdu: luonnos, sammutettu
   julkinen API, tekstiviestit pois organisaatiolta. */
.event-preview-off .event-preview-mock {
    opacity: 0.45;
}

.event-preview-screen {
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    color: #000;
    overflow: hidden;
}

.event-preview-screen-title {
    background: #000;
    color: #fff;
    font-weight: 600;
    padding: 0.25rem 0.75rem;
}

.event-preview-screen-row {
    display: flex;
    gap: 1rem;
    padding: 0.5rem 0.75rem;
}

.event-preview-screen-time {
    flex-shrink: 0;
    white-space: nowrap;
}

.event-preview-paper {
    background: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    font-family: Georgia, 'Times New Roman', serif;
    padding: 0.5rem 0.75rem;
}

.event-preview-sms {
    background: var(--bs-success-bg-subtle);
    border-radius: 1rem;
    max-width: 90%;
    padding: 0.5rem 0.75rem;
}

/* Esikatselulaatikko (event_preview_box.html). Laatikko seuraa vieritystä,
   jotta paneeli pysyy pitkällä lomakkeella sen kentän vieressä jota ollaan
   muokkaamassa. Otsikkopalkkia klikkaamalla laatikko painuu oikeaan reunaan
   pystyotsikoksi (.event-preview-rail) ja pystyotsikkoa klikkaamalla auki;
   valinta muistetaan selaimessa. Sisältö on oma sävynsä lomakkeen taustaa
   vasten, jotta esikatselut eroavat muokattavista kentistä. */
.event-preview-box {
    position: sticky;
    /* Navipalkin alle, ja korkeus sen mukaan: pelkkä 100vh jättäisi laatikon
       alareunan navipalkin verran ruudun alapuolelle, jolloin viimeiseen
       korttiin ei pääse vierittämään. */
    top: calc(var(--navbar-height) + 1rem);
}

.event-preview-panel {
    background: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - var(--navbar-height) - 2rem);
    overflow: hidden;
}

.event-preview-panel-header,
.event-preview-rail {
    background: var(--bs-secondary-bg);
    border: 0;
    color: inherit;
}

.event-preview-panel-header:hover,
.event-preview-panel-header:focus-visible,
.event-preview-rail:hover,
.event-preview-rail:focus-visible {
    background: color-mix(in srgb, var(--bs-secondary-bg) 85%, var(--bs-emphasis-color));
}

.event-preview-panel-header {
    align-items: center;
    border-bottom: 1px solid var(--bs-border-color);
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
    padding: 0.5rem 0.75rem;
    text-align: left;
    width: 100%;
}

.event-preview-panel-hide {
    color: var(--bs-secondary-color);
}

.event-preview-panel-body {
    overflow-y: auto;
    padding: 0.75rem 0.75rem 0;
}

.event-preview-rail {
    align-items: center;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    display: flex;
    gap: 0.5rem;
    justify-content: center;
    padding: 0.75rem 0.5rem;
    width: 100%;
}

.event-preview-rail-title {
    font-weight: 600;
}

/* Kapea pystyotsikko vain leveällä näytöllä: pinotussa mobiililayoutissa
   palsta on koko sivun leveä, joten otsikko on tavallinen palkki. */
@media (min-width: 1200px) {
    /* Pystyotsikko on yksi rivi: nuoli ja teksti latautuvat saman kapean
       kaistan pituussuuntaan, eivät vierekkäisiksi palstoiksi. */
    .event-preview-rail {
        flex-direction: column;
        padding: 0.75rem 0.25rem;
        width: 2.25rem;
    }

    .event-preview-rail-title {
        letter-spacing: 0.05em;
        writing-mode: vertical-rl;
    }

    /* Kokoon painetussa tilassa esikatselupalsta kapenee pystyotsikon
       leveyteen ja pääpalsta ottaa vapautuneen tilan. */
    .event-preview-collapsed > .event-preview-col {
        flex: 0 0 auto;
        width: auto;
    }

    /* Sama kuin Bootstrapin .col: flex-basis 0, jotta leveä sisältö (esim.
       työvuorotaulukko) ei kasvata palstaa niin että pystyotsikko rivittyy
       sen alle, vaan kapenee jäljelle jäävään tilaan. */
    .event-preview-collapsed > [data-event-preview-main] {
        flex: 1 0 0%;
        max-width: 100%;
        min-width: 0;
    }
}

/* Ohjeteksti jonka lukija voi panna pois: sulkunappi sisällön oikeaan
   ylänurkkaan, ja tilalle jäävä "Näytä ohje" oletuksena piilossa. Kumpi näkyy,
   ratkeaa selaimessa (static/js/help_box.js). */
.help-box {
    position: relative;
}

.help-box-hide {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 2;
}

/* Nappi on sisällön oikeassa ylänurkassa, joten sisältö kapenee sen verran.
   Sama ratkaisu kuin Bootstrapin omassa .alert-dismissiblessa, ja samasta
   syystä: teksti ei saa kulkea napin alta. Laatikkomuotoinen ohje saa tilan
   omaan padingiinsa, muu sisältö (esim. pelkkä kappale) kapenee itse. */
.help-box > .alert {
    padding-inline-end: 2.5rem;
}

.help-box > :not(.alert) {
    padding-inline-end: 2rem;
}

[data-help-reveal] {
    display: none;
}

/*
 * Event table (the Taulukko tab, templates/event/calendar_datatable.html).
 *
 * One card: action row, result row with the filter pills, the table. The
 * colours come from the theme variables so the dark theme needs no second set
 * of values — --app-primary is the brand colour, and --app-primary-subtle and
 * --app-primary-hover are its derivatives (dark-mode.css lightens them).
 *
 * A filtered column shows in three places at once — the header button, the
 * column tint and the pill row — and all three read the same state
 * (static/js/event-table-filters.js). The header cell carries the state as
 * .event-col-filtered; the button and the cells are styled off it.
 */
.event-table-card {
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
}

.event-table-toolbar {
    position: relative; /* the mass-action menu is positioned against this */
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    flex-wrap: wrap;
}

.event-table-actions,
.event-table-tools {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.event-table-tools {
    gap: 8px;
    margin-left: auto;
}

/* DataTables' Buttons container ends up holding the export menu and the
   mass-action menu, spaced like the rest of the row. */
.event-table-actions div.dt-buttons {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 0;
}

.event-table-tools div.dt-search {
    width: 260px;
    max-width: 100%;
}

/* The placeholder does the labelling; the label DataTables renders is empty. */
.event-table-tools div.dt-search label:empty {
    display: none;
}

.event-table-tools div.dt-search input {
    width: 100%;
}

.event-table-help {
    min-width: 34px;
}

/* The "View" menu: grouped settings with small uppercase headings. */
.dropdown-menu.event-table-view-menu {
    min-width: 260px;
    padding: 12px;
}

.dropdown-menu.event-table-view-menu.show {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.event-table-view-group {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 5px;
}

.event-table-view-heading {
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bs-secondary-color);
}

.event-table-view-group div.dt-length {
    width: 100%;
}

.event-table-view-group div.dt-length label {
    display: none;
}

.event-table-view-switch {
    margin: 0;
    font-size: 13px;
}

/* Narrow screens: one row of buttons — "New" and the mass actions on the left,
   the View menu and the help on the right — and the search box on a full-width
   row of its own below. The two groups become transparent (display: contents)
   so their controls take part in the toolbar's flex layout directly; the JS
   still finds the groups by id, since the DOM is unchanged. */
@media (max-width: 767.98px) {
    .event-table-toolbar {
        gap: 8px;
        padding: 10px 12px;
    }

    .event-table-actions,
    .event-table-tools {
        display: contents;
    }

    /* Buttons' stylesheet makes its container full-width and centred under
       768px; here it is one button in a row of buttons. */
    .event-table-actions div.dt-buttons {
        width: auto;
        float: none;
        margin: 0;
        text-align: left;
    }

    .event-table-tools > .dropdown {
        margin-left: auto;
    }

    .event-table-tools div.dt-search {
        order: 10;
        flex: 1 0 100%;
        width: auto;
    }

    .event-table-filters {
        padding: 0 12px 10px;
    }
}

/* Result row: "7 / 214 events", a separator, the pills, "Clear filters". */
.event-table-filters {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 16px 12px;
    flex-wrap: wrap;
    font-size: 13px;
}

.event-table-count {
    font-weight: 500;
}

.event-table-count-total {
    color: var(--bs-secondary-color);
    font-weight: 400;
}

.event-table-filter-separator {
    width: 1px;
    height: 20px;
    background: var(--bs-border-color);
    margin: 0 2px;
}

/* The pills take part in the row's own flex layout. */
.event-table-pills {
    display: contents;
}

.event-filter-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.2;
    color: var(--app-primary-hover);
    background: var(--app-primary-subtle);
    border: 1px solid color-mix(in srgb, var(--app-primary) 35%, transparent);
}

.event-filter-pill .btn-close {
    /* Bootstrap's default is 1em, meant for a modal's corner. */
    padding: 0;
    width: 0.5rem;
    height: 0.5rem;
    background-size: 0.5rem;
}

.event-table-clear {
    padding: 0 4px;
    font-size: 13px;
}

/* The table. Only the table scrolls sideways; the rows above stay put so the
   active filters are readable however far the table has been scrolled. */
.event-table-scroll {
    position: relative; /* so ColumnControl accounts for this element's scroll offset */
    overflow-x: auto;
}

.event-table-body div.dt-container {
    padding: 0;
}

table.event-table {
    margin: 0;
    font-size: 13px;
    min-width: 1060px;
    --bs-table-bg: transparent;
}

table.event-table thead th {
    padding: 8px 12px;
    font-weight: 600;
    white-space: nowrap;
    background: var(--bs-tertiary-bg);
    border-bottom: 1px solid var(--bs-border-color);
}

/* Marker 2: the filtered column's header and cells. An inset shadow rather than
   a border so the row height does not change with the state. */
table.event-table thead th.event-col-filtered {
    background: var(--app-primary-subtle);
    box-shadow: inset 0 -2px 0 var(--app-primary);
}

table.event-table tbody td {
    padding: 9px 12px;
}

table.event-table tbody td.event-col-filtered {
    background-color: color-mix(in srgb, var(--app-primary) 6%, transparent);
}

table.event-table div.dt-column-header {
    align-items: center;
    gap: 6px;
}

/* ColumnControl's header buttons: a quiet sort arrow and an outline funnel,
   both darkening on hover. Focus rings are the browser's own and are kept. */
table.event-table span.dtcc {
    gap: 2px;
    --dtcc-button-icon_color: currentColor;
}

table.event-table span.dtcc button.dtcc-button {
    padding: 2px 4px;
    border: 1px solid transparent;
    border-radius: var(--bs-border-radius-sm);
    background: transparent;
    color: var(--bs-secondary-color);
    opacity: 1;
    line-height: 1;
    align-items: center;
}

table.event-table span.dtcc button.dtcc-button:hover {
    border-color: transparent;
    background: transparent;
    color: var(--bs-body-color);
}

table.event-table span.dtcc button.dtcc-button_order.dtcc-button_active {
    color: var(--app-primary);
}

table.event-table span.dtcc button.dtcc-button_order.dtcc-button_active:hover {
    color: var(--app-primary-hover);
}

/* Marker 1: the filter button of a filtered column, filled and carrying the value. */
table.event-table thead th.event-col-filtered span.dtcc button.dtcc-button_dropdown {
    padding: 2px 8px;
    background: var(--app-primary);
    border-color: var(--app-primary);
    /* The page background as text: white on the brand blue in the light theme,
       near-black on the lightened blue the dark theme uses. */
    color: var(--bs-body-bg);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.4;
}

table.event-table thead th.event-col-filtered span.dtcc button.dtcc-button_dropdown:hover {
    background: var(--app-primary-hover);
    border-color: var(--app-primary-hover);
    color: var(--bs-body-bg);
}

table.event-table span.dtcc .event-filter-value {
    margin-left: 5px;
    white-space: nowrap;
}

table.event-table span.dtcc .event-filter-value:empty {
    display: none;
}

/* The start column's date pickers, above its text box in the filter panel. */
div.dtcc-dropdown .event-date-range {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding-bottom: 8px;
}

div.dtcc-dropdown .event-date-range label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin: 0;
    font-size: 13px;
}

div.dtcc-dropdown .event-date-range input[type="date"] {
    width: 10.5em;
}

div.dtcc-dropdown .event-date-range-warning {
    font-size: 12px;
    color: var(--bs-danger);
}

/* Filters that leave nothing: the message and a way out, inside the body. */
.event-table-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 24px 12px;
    color: var(--bs-secondary-color);
    font-size: 13px;
}

/* Row count and paging under the table. */
.event-table-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 16px;
    border-top: 1px solid var(--bs-border-color);
    font-size: 13px;
}

.event-table-footer div.dt-paging {
    margin: 0;
}

.event-table-footer div.dt-paging .pagination {
    margin: 0;
}
