/* =============================================================================
 * components.css — componentlaag voor de nieuwe interface
 * =============================================================================
 *
 * Gebouwd op design-tokens.css. Regels hier gebruiken UITSLUITEND rol-tokens
 * (--text-*, --surface-*, --border-*, --sp-*, ...), nooit het palet of een losse
 * hexwaarde. Wie hier een hex tegenkomt: dat is een fout, geen uitzondering.
 *
 * Alle klassen hebben het prefix `oc-` zodat ze niet botsen met Bootstrap of met
 * de bestaande Site.css. Zolang de oude schermen nog draaien staan beide lagen
 * naast elkaar; dat is bedoeld en tijdelijk.
 *
 * Ruimte komt van flex/grid + gap, niet van marges: marges klappen samen en
 * verdubbelen, gaps niet.
 * ---------------------------------------------------------------------------- */

/* == Shell: 64px icoonbalk + werkgebied ==================================== */
.oc-shell {
    display: flex;
    min-height: 100vh;
    background: var(--surface-app);
}

.oc-rail {
    width: var(--rail-width);
    flex: none;
    background: var(--surface-rail);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--sp-6) 0;
    gap: var(--sp-8);
}

.oc-rail__logo {
    width: 34px;
    height: 34px;
    object-fit: contain;
    display: block;
}

.oc-rail__nav {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    width: 100%;
    align-items: center;
}

.oc-rail__item {
    width: var(--rail-icon-size);
    height: 40px;
    border-radius: var(--rail-icon-radius);
    display: grid;
    place-items: center;
    color: rgba(255, 255, 255, .62);
    transition: background-color .15s ease-in-out, color .15s ease-in-out;
}

    .oc-rail__item:hover,
    .oc-rail__item:focus-visible {
        background: rgba(255, 255, 255, .10);
        color: var(--text-on-dark);
    }

    /* Actief item: accentkleur op een lichte vulling. Niet alleen kleur - het
     * vlak verandert ook, zodat de status niet uitsluitend via kleur leest. */
    .oc-rail__item.is-active {
        background: rgba(255, 255, 255, .14);
        color: var(--brand-accent);
    }

.oc-rail__spacer { flex: 1; }

.oc-rail__avatar {
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .16);
    color: var(--text-on-dark);
    font-family: var(--font-sans);
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    display: grid;
    place-items: center;
    cursor: pointer;
}

    .oc-rail__avatar:hover { background: rgba(255, 255, 255, .26); }

    .oc-rail__avatar:focus-visible {
        outline: var(--focus-outline);
        outline-offset: 2px;
    }

.oc-rail__menu {
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-sm);
    box-shadow: var(--shadow-raised);
    padding: var(--sp-2);
    font-size: var(--fs-body);
}

    .oc-rail__menu .dropdown-item {
        border-radius: var(--r-xs);
        padding: var(--sp-3) var(--sp-5);
        color: var(--text-default);
    }

        .oc-rail__menu .dropdown-item:hover,
        .oc-rail__menu .dropdown-item:focus {
            background: var(--brand-accent-wash);
            color: var(--text-link);
        }

.oc-main {
    flex: 1;
    min-width: 0; /* laat grafieken en tabellen krimpen i.p.v. de pagina rekken */
    display: flex;
    flex-direction: column;
}

/* == Topbalk (62px) ======================================================== */
/* De nieuwe shell heeft geen vaste navbar, dus de body-padding uit Site.css (die
 * ruimte maakte voor de oude fixed navbar) moet hier weg. */
.oc-body {
    padding: 0;
    margin: 0;
    background: var(--surface-app);
    /* De basistypografie hoort hier en stond er niet.
     *
     * P1 hostte de webfonts zelf en zette --font-sans, maar niets legde die op de
     * body. Bootstrap zet body op zijn eigen systeemstack en laadt eerder, dus
     * alles wat geen expliciete font-family had - alinea's, tabelcellen,
     * koppen, knoppen - bleef in Segoe UI staan. De webfonts werden wel
     * gedownload en vrijwel niet gebruikt.
     *
     * Een klasse wint van het element-selector van Bootstrap, dus dit is genoeg;
     * !important is niet nodig. */
    font-family: var(--font-sans);
    color: var(--text-default);
    line-height: var(--lh-normal);
    /* Cijferkolommen recht houden.
     *
     * De cijferrol (--font-mono) draait sinds de huisstijlwissel op Maven Pro,
     * en dat is geen monospace: bij evenredige cijfers verspringt een kolom
     * getallen per regel. tabular-nums vraagt de letter om cijfers van gelijke
     * breedte en herstelt dat. Het staat op de body en niet per cijferveld,
     * omdat het overal onschadelijk is en anders elk nieuw tabel- of
     * grafiekveld het opnieuw moet onthouden. */
    font-variant-numeric: tabular-nums;
}

/* == Koppen dragen het display-font =========================================
 * Comfortaa voor de koppen, Maven Pro voor de rest. De grens ligt bewust bij
 * ongeveer --fs-h4 (16,5px): daaronder - kaartlabels, tabelkoppen, de
 * semibold regelkopjes binnen een kaart - blijft Maven Pro staan, want
 * Comfortaa's ronde vormen lopen op 13-15px dicht en kosten leesbaarheid in
 * precies de schermen die het dichtst bedrukt zijn. Het merk in de topbalk is
 * de uitzondering: dat staat op 14,5px en draagt de letter toch, omdat het een
 * logo is en geen tekst die je leest.
 *
 * De schermspecifieke titels staan er met naam bij; ze zijn geen <h*> in de
 * opmaak maar spelen wel de rol van kop. Zet een nieuwe kop van dat formaat
 * hier ook neer, anders valt hij stil terug op de broodtekstletter. */
.oc-body h1,
.oc-body h2,
.oc-body h3,
.oc-body h4,
.oc-body h5,
.oc-body h6,
.oc-body legend,
.oc-title,
.oc-topbar__wordmark,
.oc-topbar__context-name,
.modal-title,
.inf-kop--groep,
.rp-kop__titel,
.rp-blok__titel,
.sg-title,
.sg-h2,
.sg-t--h1,
.sg-t--h2 {
    font-family: var(--font-display);
}

.oc-topbar {
    height: 62px;
    flex: none;
    display: flex;
    align-items: center;
    gap: var(--sp-7);
    padding: 0 var(--sp-8);
    background: var(--surface-card);
    border-bottom: 1px solid var(--border-subtle);
}

.oc-topbar__wordmark {
    font-size: 14.5px;
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-tight);
    color: var(--brand-primary);
    white-space: nowrap;
    text-decoration: none;
}

.oc-topbar__divider {
    width: 1px;
    height: 26px;
    background: var(--border-default);
    flex: none;
}

.oc-topbar__context {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.oc-topbar__context-name {
    font-size: var(--fs-h4);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-tight);
    color: var(--text-strong);
    white-space: nowrap;
}

.oc-topbar__context-meta {
    font-family: var(--font-mono);
    font-size: var(--fs-label);
    font-weight: var(--fw-medium);
    color: var(--text-subtle);
    white-space: nowrap;
}

.oc-topbar__spacer { flex: 1; }

/* Een datumveld uit de oude schermen in de topbalk.
 *
 * De herbouwde schermen gebruiken <input type="date">, maar de beheerschermen die naar
 * deze schil verhuisd zijn houden hun jQuery UI-datepicker - die zit in een Bootstrap
 * .input-group, en die staat op width:100%. In de flexrij van de topbalk duwt dat al
 * het andere eruit. */
.oc-topbar .input-group {
    width: auto;
    flex: none;
}

    .oc-topbar .input-group .oc-input {
        width: 9rem;
    }

/* == Tabbladen binnen een sectie ===========================================
 *
 * De icoonbalk kent per sectie meerdere bestemmingen, maar linkt er maar één van:
 * de eerste. Alles daarachter was in de nieuwe schil niet aan te klikken. Deze rij
 * onder de topbalk zet ze er weer bij.
 *
 * Bewust een rij tekstlinks en geen tweede balk met vlakken: het is navigatie
 * binnen een scherm dat je al gekozen hebt, en het mag niet concurreren met de
 * icoonbalk ernaast.
 */
.oc-tabs {
    flex: none;
    display: flex;
    align-items: stretch;
    /* Twee regels in plaats van horizontaal schuiven.
     *
     * Dit stond op overflow-x:auto met een verborgen schuifbalk. Beheer heeft
     * achttien tabbladen en die passen op 100% zoom niet op één regel: alles vanaf
     * "LetsGrow schrijven" viel buiten beeld. Schuiven had ook gekund, maar zonder
     * zichtbare schuifbalk was er niets wat vertelde DAT er nog iets achter zat -
     * die tabbladen waren daarmee onvindbaar in plaats van moeilijk bereikbaar.
     *
     * Rijafstand nul: de tabbladen brengen hun eigen verticale ruimte mee, en een gat
     * ertussen zou de onderstreping van een actieve tab op de eerste regel los boven
     * de tweede laten zweven. */
    flex-wrap: wrap;
    column-gap: var(--sp-6);
    row-gap: 0;
    padding: 0 var(--sp-8);
    background: var(--surface-card);
    border-bottom: 1px solid var(--border-subtle);
}

.oc-tabs__item {
    flex: none;
    display: flex;
    align-items: center;
    padding: var(--sp-4) 0;
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    color: var(--text-subtle);
    text-decoration: none;
    white-space: nowrap;
    /* Altijd een rand, ook als hij onzichtbaar is: anders verspringt de rij een
     * pixel zodra je een ander tabblad kiest. */
    border-bottom: 2px solid transparent;
}

    .oc-tabs__item:hover {
        color: var(--text-strong);
    }

    .oc-tabs__item.is-active {
        color: var(--brand-primary);
        font-weight: var(--fw-semibold);
        border-bottom-color: var(--brand-primary);
    }

    .oc-tabs__item:focus-visible {
        outline: var(--focus-outline);
        outline-offset: -2px;
    }

.oc-content {
    flex: 1;
    min-width: 0;
    padding: var(--sp-8);
    overflow-x: auto; /* brede schermen scrollen hier, niet de hele pagina */
}


/* == Kaart ================================================================= */
.oc-card {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-card);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.oc-card__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-5) var(--sp-6) 0;
}

.oc-card__body {
    padding: var(--sp-5) var(--sp-6) var(--sp-6);
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}

.oc-card--rail {
    background: var(--surface-rail);
    color: var(--text-on-dark);
    border-color: transparent;
}


/* == Kaartkop: titel, toelichting, en rechts eventueel een knop ============
 * Gebruikt door elk nieuw scherm dat een kaart een eigen kop geeft. Stond eerst
 * in dashboard.css; toen het analysescherm hem ook nodig had hoorde hij hier. */
.oc-cardtop {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-6);
    flex-wrap: wrap;
}

/* De kop met de toelichting erboven staat ook op kaarten die de volle
   paginabreedte innemen. Zonder grens loopt zo'n zin op een breed scherm door tot
   1700px en moet het oog terug naar links zoeken waar de volgende regel begint.
   Deze grens raakt alleen de tekstkolom - de grafiek eronder blijft zo breed als
   de kaart. */
.oc-cardtop__text {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    max-width: 78ch;

    /* De ondergrens hoort bij de flex-wrap hierboven, en die twee samen zijn de reden
       dat dit werkt op een telefoon.

       Met min-width:0 - wat hier stond - kan de tekstkolom tot nul krimpen, en dat doet
       hij ook: .oc-cardtop__actions staat op flex:none en geeft geen millimeter. Op 375px
       werd de toelichting daardoor een kolom van één woord per regel ("Wat / één / extra
       / kilo") terwijl de knoppen ernaast de kaart uit liepen.

       min(100%, 22rem) betekent: op een brede kaart houdt de tekst minstens 22rem en
       staan de knoppen ernaast; op een smalle kaart eist de tekst de hele regel op en
       wippen de knoppen eronder. Geen breakpoint nodig - het hangt van de KAART af en
       niet van het scherm, en dezelfde kaart is in een kolom van een derde net zo smal
       als op een telefoon. */
    min-width: min(100%, 22rem);
}

.oc-cardtop__actions {
    display: flex;
    align-items: center;
    gap: var(--sp-5);
    flex: none;
}

.oc-title {
    font-size: var(--fs-h4);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-tight);
    color: var(--text-strong);
    margin: 0;
}


/* == Keuzelijst ============================================================
 * Een rij keuzes onder elkaar, elk klikbaar, met de actieve gemarkeerd. De
 * radio-invoer zit erin zodat toetsenbord en schermlezer het als een keuzegroep
 * zien - een rij <div>'s met een klikhandler doet dat niet.
 *
 * Stond eerst in analyse.css; toen de koerskiezer hem ook nodig had hoorde hij
 * hier. */
.oc-choices {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.oc-choice {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-sm);
    background: var(--surface-card);
    font-size: var(--fs-body);
    color: var(--text-default);
    cursor: pointer;
}

    .oc-choice:hover {
        border-color: var(--border-strong);
    }

    .oc-choice:focus-within {
        outline: var(--focus-outline);
        outline-offset: 1px;
    }

    .oc-choice input {
        accent-color: var(--brand-accent-text);
        flex: none;
        margin: 0;
    }

    .oc-choice.is-active {
        border-color: var(--brand-accent-text);
        background: var(--brand-accent-wash);
        color: var(--text-strong);
        font-weight: var(--fw-semibold);
    }

    /* Een uitgeschakelde keuze mag niet als klikbaar ogen. */
    .oc-choice input:disabled {
        cursor: not-allowed;
    }

        .oc-choice:has(input:disabled) {
            cursor: default;
            opacity: .7;
        }


/* == Verticale stapel ======================================================
 * Kaarten onder elkaar met de standaardtussenruimte. Bestaat zodat een scherm
 * daarvoor geen eigen klasse hoeft te verzinnen. */
.oc-stack {
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
    min-width: 0;
}


/* == Labels en tekstrollen ================================================= */
.oc-label {
    font-family: var(--font-mono);
    font-size: var(--fs-label);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--text-subtle);
}

.oc-caption {
    font-size: var(--fs-caption);
    line-height: var(--lh-snug);
    color: var(--text-subtle);
}

.oc-unit {
    font-size: var(--fs-micro);
    color: var(--text-subtle);
}


/* == Metriek: het grote getal ============================================== */
.oc-metric {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
}

.oc-metric__value {
    font-size: var(--fs-metric);
    font-weight: var(--fw-bold);
    line-height: var(--lh-tight);
    color: var(--text-strong);
    font-variant-numeric: tabular-nums;
}

.oc-metric__delta {
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    font-variant-numeric: tabular-nums;
}

.oc-metric__delta--up { color: var(--state-good); }
.oc-metric__delta--down { color: var(--state-warn); }


/* == Badge / pill ==========================================================
 * Status leest via vorm én kleur: elke variant heeft een eigen vulling en rand,
 * zodat de betekenis niet alleen aan de tint hangt. */
.oc-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-family: var(--font-mono);
    font-size: var(--fs-label);
    font-weight: var(--fw-semibold);
    padding: 3px var(--sp-4);
    border-radius: var(--r-xs);
    border: 1px solid transparent;
    white-space: nowrap;
}

.oc-badge--auto {
    background: var(--state-good-wash);
    color: var(--state-good);
    border-color: rgba(167, 193, 66, .45);
}

.oc-badge--hand {
    background: var(--state-warn-wash);
    color: var(--state-warn);
    border-color: rgba(134, 120, 89, .40);
}

.oc-badge--error {
    background: var(--state-error-wash);
    color: var(--state-error);
    border-color: rgba(185, 71, 40, .38);
}

.oc-badge--neutral {
    background: var(--border-hair);
    color: var(--text-default);
    border-color: var(--border-subtle);
}

/* Het stipje voor een status-badge, met een zachte halo eromheen. Neemt de
   tekstkleur van de badge over, dus elke variant klopt vanzelf. */
.oc-badge__dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex: none;
    background: currentColor;
    box-shadow: 0 0 0 3px rgba(167, 193, 66, .28);
}


/* == Knoppen =============================================================== */
.oc-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-3);
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    font-weight: var(--fw-semibold);
    line-height: 1;
    padding: var(--sp-4) var(--sp-5);
    border-radius: var(--r-sm);
    cursor: pointer;
    text-decoration: none;
    transition: background-color .15s ease-in-out, border-color .15s ease-in-out;
    /* De KALE .oc-btn is de secundaire knop, en niet iets onzichtbaars.
     *
     * Eerst stond hier een doorzichtige achtergrond met een doorzichtige rand en
     * geen kleur. Een <button class="oc-btn"> viel dan terug op de knopstijl van
     * de browser en een <a class="oc-btn"> op de linkkleur van Bootstrap - dus
     * blauwe onderstreepte tekst waar een knop hoorde te staan. Alleen wie de
     * variantklasse kende kreeg iets bruikbaars, en dat is precies de valkuil
     * waar het rapportscherm en de dagcheck allebei in liepen.
     *
     * .oc-btn--ghost blijft bestaan en geeft nu hetzelfde; expliciet mag. */
    background: var(--surface-card);
    color: var(--text-default);
    border: 1px solid var(--border-default);
}

    .oc-btn:hover {
        background: var(--brand-accent-wash);
        color: var(--text-link);
    }

    .oc-btn:focus-visible {
        outline: var(--focus-outline);
        outline-offset: 2px;
        box-shadow: var(--focus-ring);
    }

.oc-btn--primary {
    background: var(--brand-primary);
    color: var(--text-on-dark);
    border-color: transparent;
}

    .oc-btn--primary:hover { background: var(--brand-primary-hover); color: var(--text-on-dark); }

/* Let op: inkt op limoen (6,8:1), niet wit (2,03:1 - zou falen). */
.oc-btn--accent {
    background: var(--brand-accent);
    color: var(--text-on-accent);
    border-color: transparent;
}

    .oc-btn--accent:hover { background: var(--p-lime-700); color: var(--text-on-dark); }

.oc-btn--ghost {
    background: transparent;
    color: var(--text-default);
    border-color: var(--border-default);
}

    .oc-btn--ghost:hover { background: var(--brand-accent-wash); color: var(--text-link); }

/* Een knop die iets AAN of UIT zet, moet laten zien wat hij nu is. Zonder deze
   regel zag een ingedrukte toggle er precies zo uit als een uitgedrukte, en moest
   je aan de grafiek ernaast aflezen of je hem net had aangezet. */
.oc-btn[aria-pressed="true"] {
    background: var(--brand-accent-wash);
    color: var(--text-link);
    border-color: var(--brand-accent-text);
}


/* == Segmented control (Vandaag | Week) ==================================== */
.oc-segment {
    display: inline-flex;
    background: var(--border-hair);
    border-radius: var(--r-sm);
    padding: 2px;
    gap: 2px;
}

.oc-segment__option {
    font-size: var(--fs-caption);
    font-weight: var(--fw-semibold);
    padding: var(--sp-3) var(--sp-5);
    border-radius: var(--r-xs);
    border: 0;
    background: transparent;
    color: var(--text-subtle);
    cursor: pointer;
}

    .oc-segment__option.is-active {
        background: var(--surface-card);
        color: var(--text-strong);
        box-shadow: var(--shadow-card);
    }

    .oc-segment__option:focus-visible {
        outline: var(--focus-outline);
        outline-offset: 1px;
    }


/* == Tabel ================================================================= */
.oc-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-body);
}

    .oc-table th {
        text-align: left;
        font-family: var(--font-mono);
        font-size: var(--fs-label);
        font-weight: var(--fw-semibold);
        letter-spacing: var(--tracking-label);
        text-transform: uppercase;
        color: var(--text-subtle);
        background: var(--surface-app);
        padding: var(--sp-4) var(--sp-5);
        border-bottom: 1px solid var(--border-default);
        white-space: nowrap;
    }

    .oc-table td {
        padding: var(--sp-4) var(--sp-5);
        border-bottom: 1px solid var(--border-hair);
        color: var(--text-default);
        vertical-align: top;
    }

    .oc-table tr:last-child td { border-bottom: 0; }

    /* Getalkolommen: rechts uitlijnen met tabular-nums zodat cijfers onder
     * elkaar staan, ook bij wisselende breedtes. */
    .oc-table .oc-num {
        text-align: right;
        font-variant-numeric: tabular-nums;
        font-family: var(--font-mono);
        color: var(--text-strong);
    }

/* Brede tabellen scrollen in hun eigen container; de pagina zelf nooit. */
.oc-tablewrap {
    overflow-x: auto;
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-md);
    background: var(--surface-card);
}


/* == bootstrap-table binnen oc-tablewrap ===================================
 *
 * De indexschermen van het beheer laten bootstrap-table het zoeken, sorteren en
 * pagineren doen. De plugin bouwt daarvoor een eigen wikkel OM de tabel heen: een
 * balk erboven met de knoppen uit #toolbar links en het zoekveld rechts, en een balk
 * eronder met het aantal regels en de paginakeuze.
 *
 * Die twee balken krijgen in bootstrap-table.min.css alleen een marge boven en onder.
 * Voor de zijkant rekent de plugin op een bootstrap-container eromheen, en die is er
 * hier niet: .oc-tablewrap is een rand met een ronde hoek en verder niets. De knop
 * Historie plakte daardoor tegen de linkerrand en het zoekveld tegen de rechter,
 * terwijl de tabel eronder zijn celruimte wel had - op Beperkingen, Bedrijf, Locatie,
 * Abonnementen en de zeven andere schermen met deze tabel.
 *
 * Dezelfde zijruimte als een cel, zodat de knop links precies boven de eerste kolom
 * begint en het zoekveld rechts op de laatste uitkomt. */
.oc-tablewrap .fixed-table-toolbar,
.oc-tablewrap .fixed-table-pagination {
    padding-inline: var(--sp-5);
}

/* De paginabalk staat onder de laatste rij, en die heeft geen onderlijn meer: zonder
   deze streep zweeft "1 tot 25 van 78" los tegen de onderrand van de kaart. */
.oc-tablewrap .fixed-table-pagination {
    border-top: 1px solid var(--border-hair);
}

/* Het zoekveld is een kale bootstrap .form-control en zag er daarmee anders uit dan
   elk ander invoerveld in deze schil - andere rand, andere hoek, blauwe focusring.
   De plugin maakt dat element zelf aan, dus .oc-input meegeven kan niet vanuit de
   view; het moet hier. */
.oc-tablewrap .fixed-table-toolbar .search .form-control {
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    color: var(--text-strong);
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--r-sm);
    padding: var(--sp-4) var(--sp-5);
}

    .oc-tablewrap .fixed-table-toolbar .search .form-control:focus {
        outline: none;
        border-color: var(--brand-accent);
        box-shadow: var(--focus-ring);
    }

/* Het keuzeknopje voor het aantal regels per pagina is een bootstrap .btn-secondary,
   en dat is in deze applicatie donkerleigrijs met witte letters. Zo'n zwarte pil
   naast een regel grijze tekst leest als de belangrijkste knop van het scherm,
   terwijl hij alleen de paginagrootte kiest. Dezelfde vorm als een kale .oc-btn. */
.oc-tablewrap .fixed-table-pagination .page-list .btn {
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    font-weight: var(--fw-semibold);
    line-height: 1;
    padding: var(--sp-4) var(--sp-5);
    border-radius: var(--r-sm);
    background: var(--surface-card);
    color: var(--text-default);
    border: 1px solid var(--border-default);
}

    .oc-tablewrap .fixed-table-pagination .page-list .btn:hover {
        background: var(--brand-accent-wash);
        color: var(--text-link);
    }


/* == Formulier ============================================================= */
.oc-field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

.oc-field__label {
    font-size: var(--fs-caption);
    font-weight: var(--fw-medium);
    color: var(--text-default);
}

/* Een datumveld met het kalendericoon ernaast, in een Bootstrap .input-group.
 *
 * Bootstrap geeft de flexregels die dat op één regel houden UITSLUITEND aan
 * `.input-group > .form-control` en `> .form-select`:
 *
 *     flex: 1 1 auto; width: 1%; min-width: 0;
 *
 * Bij het omzetten van de beheerschermen is form-control .oc-input geworden, en
 * daarmee viel die regel weg. Het veld hield zijn eigen breedte, de regel paste niet
 * meer, en .input-group staat op flex-wrap: wrap - dus het icoon zakte eronder.
 *
 * Alleen binnen .oc-body: de oude schil gebruikt nog gewoon .form-control en heeft
 * deze regels niet nodig. */
.oc-body .input-group > .oc-input {
    position: relative;
    flex: 1 1 auto;
    width: 1%;
    min-width: 0;
}

    /* Naadloos tegen elkaar, zoals bij een .form-control. */
    .oc-body .input-group > .oc-input:not(:last-child) {
        border-top-right-radius: 0;
        border-bottom-right-radius: 0;
    }

.oc-body .input-group > .oc-input ~ .input-group-text {
    border-left: 0;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.oc-input {
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    color: var(--text-strong);
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--r-sm);
    padding: var(--sp-4) var(--sp-5);
}

    .oc-input:focus {
        outline: none;
        border-color: var(--brand-accent);
        box-shadow: var(--focus-ring);
    }

    .oc-input[aria-invalid="true"] {
        border-color: var(--state-error);
    }

/* Getalinvoer rechts uitgelijnd en monospaced - net als in de tabellen. */
.oc-input--num {
    text-align: right;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
}

/* Een kolom invoervelden in een kaart.
 *
 * Gebruikt door de beheerschermen die naar deze schil verhuisd zijn. Zonder
 * breedtegrens rekt een datumveld op een breed scherm mee tot de hele kaart, en staat
 * het label eenzaam links van anderhalve meter leeg vak. .oc-field zelf krijgt die
 * grens niet: die staat ook in stroken en roosters van de herbouwde schermen, waar de
 * omgeving de breedte al bepaalt. */
.oc-form {
    display: flex;
    flex-direction: column;
    gap: var(--sp-5);
    max-width: 28rem;
}

/* Naam-waardeparen op een bevestigingsscherm: wat je op het punt staat te verwijderen.
 *
 * Een kale <dl> zet de waarde onder het label en laat ze na een paar regels niet meer
 * bij elkaar horen; op de Locatie-bevestiging waren dat acht paren op zestien regels.
 * Twee kolommen houdt label en waarde naast elkaar. */
.oc-deflist {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: var(--sp-3) var(--sp-6);
    margin: 0;
    max-width: 44rem;
}

    .oc-deflist dt {
        font-size: var(--fs-caption);
        font-weight: var(--fw-medium);
        color: var(--text-subtle);
    }

    .oc-deflist dd {
        margin: 0;
        color: var(--text-strong);
    }

.oc-field__error {
    font-size: var(--fs-caption);
    color: var(--state-error);
}


/* == Voortgang van een doorrekening ========================================
 *
 * Een doorrekening duurt seconden tot tientallen seconden. Zonder terugkoppeling
 * is dat niet te onderscheiden van een scherm dat vastloopt, en gaat de teler
 * herladen - waarmee de berekening opnieuw begint.
 *
 * Vandaar de fase-tekst NAAST de balk: "waar is de computer mee bezig" is het
 * antwoord dat geruststelt; het percentage alleen niet. Bij het doorrekenen van
 * de dagen staat er "3/7 dagen klaar", want dat is de enige fase die lang genoeg
 * duurt om de voortgang echt te zien lopen.
 *
 * Deze component staat in components.css en niet in dashboard.css: het dashboard
 * en de analyse gebruiken hem allebei, en een tweede kopie loopt uit elkaar.
 */
.oc-progress {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-5) var(--sp-6);
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-md);
}

/* Moet er staan. Het hidden-attribuut krijgt zijn display:none uit de
   browserstylesheet, en die verliest van de display:flex hierboven - de balk zou
   dus altijd zichtbaar zijn, ook als het JavaScript hem verbergt. */
.oc-progress[hidden] {
    display: none;
}

.oc-progress__top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
}

.oc-progress__fase {
    font-size: var(--fs-body);
    color: var(--text-default);
}

.oc-progress__percent {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-caption);
    color: var(--text-subtle);
}

/* De goot. Overflow hidden zodat de vulling de afronding volgt. */
.oc-progress__baan {
    height: 6px;
    border-radius: var(--r-pill);
    background: var(--surface-sunken);
    overflow: hidden;
}

.oc-progress__vulling {
    height: 100%;
    width: 0;
    border-radius: var(--r-pill);
    background: var(--brand-accent);
    transition: width .3s ease-out;
}

/* Zolang de rekenkern nog niets te melden heeft (0%) loopt er een streepje heen
   en weer. Een balk die op nul stilstaat leest als "er gebeurt niets". */
.oc-progress--onbepaald .oc-progress__vulling {
    width: 30%;
    animation: oc-progress-heenweer 1.3s ease-in-out infinite;
}

@keyframes oc-progress-heenweer {
    0% { margin-left: -30%; }
    100% { margin-left: 100%; }
}


/* == Toegankelijkheid ====================================================== */
@media (prefers-reduced-motion: reduce) {
    .oc-rail__item,
    .oc-btn,
    .oc-input {
        transition: none;
    }

    /* Het onbepaalde streepje blijft staan in plaats van heen en weer te lopen;
       de balk zelf springt naar zijn nieuwe breedte zonder te glijden. */
    .oc-progress--onbepaald .oc-progress__vulling {
        animation: none;
    }

    .oc-progress__vulling {
        transition: none;
    }
}


/* == De shell op een telefoon ==============================================
 *
 * Tot P9 had dit bestand geen enkele breakpoint. Op 375px kostte de icoonbalk
 * 64px van de 375, liep de rechterkant van de topbalk buiten beeld, en werd de
 * afdelingsnaam afgekapt onder de knoppen die elk scherm daar zelf neerzet.
 *
 * Onder de md-grens van Bootstrap (768px - dezelfde grens die de rest van de
 * pagina al hanteert, dus geen tweede stelsel) wordt de icoonbalk een
 * ONDERBALK. Dat is de gangbare plek op een telefoon, het geeft de inhoud de
 * volle breedte terug, en de vijf secties blijven allemaal met een duim
 * bereikbaar. Artboard 1o tekent de telefoon dan ook zonder balk aan de zijkant.
 */
@media (max-width: 767.98px) {
    /* Van rij naar blok: de balk staat straks vast onderaan en hoort niet meer
       in de flexstroom mee te tellen. */
    .oc-shell {
        display: block;
    }

    .oc-rail {
        position: fixed;
        inset: auto 0 0 0;
        width: auto;
        height: auto;
        min-height: var(--rail-height-mobile);
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--sp-2);
        padding: var(--sp-2) var(--sp-4);
        /* Onder de home-indicator van een iPhone zou de balk anders half
           onbereikbaar zijn. */
        padding-bottom: calc(var(--sp-2) + env(safe-area-inset-bottom, 0px));
        z-index: 1030; /* boven de sticky elementen van Bootstrap */
        box-shadow: var(--shadow-overlay);
    }

    /* Het merk staat al in de topbalk; twee keer is verspilde hoogte. */
    .oc-rail__logo,
    .oc-rail__spacer {
        display: none;
    }

    .oc-rail__nav {
        flex: 1;
        flex-direction: row;
        justify-content: space-around;
        gap: var(--sp-1);
        width: auto;
    }

    .oc-rail__item {
        width: var(--rail-icon-size);
        height: var(--rail-icon-size);
    }

    /* De topbalk mag afbreken in plaats van zijn inhoud eruit te duwen. */
    .oc-topbar {
        height: auto;
        flex-wrap: wrap;
        gap: var(--sp-2) var(--sp-4);
        padding: var(--sp-3) var(--sp-4);
    }

    /* De streep scheidt niets meer zodra er wordt afgebroken, en de spacer
       heeft niets om weg te duwen. */
    .oc-topbar__divider,
    .oc-topbar__spacer {
        display: none;
    }

    /* Context op een eigen regel, zodat de schermeigen knoppen ernaast niet
       over de afdelingsnaam heen komen te staan. */
    .oc-topbar__context {
        flex: 1 1 100%;
    }

    /* Liever twee regels dan een afgekapte bedrijfsnaam. */
    .oc-topbar__context-name,
    .oc-topbar__context-meta {
        white-space: normal;
    }

    .oc-content {
        padding: var(--sp-5) var(--sp-4);
        /* Ruimte voor de onderbalk, anders ligt de laatste kaart eronder. */
        padding-bottom: calc(var(--rail-height-mobile) + env(safe-area-inset-bottom, 0px) + var(--sp-6));
    }
}
