/* Accessibility layer on top of the artifact's own stylesheet. Loaded after it and unlayered,
   so equal-specificity rules here win. Reuses the artifact's tokens; it does not restyle the app. */

/* ── Contrast: light-mode colours nudged to at least 4.6:1, also on their 10–16% tints.
   Dark mode already passes and keeps the artifact's values (its selectors are more specific). */
:root {
    --c-dc: #377234;
    --c-gc: #985518;
    --ok: #297346;
    --warn: #965600;
}

/* ── Focus: keep it visible inside scroll containers and above sticky bars */
html {
    scroll-padding-block: 88px 120px;
}

.picker button:focus-visible,
.tablewrap :focus-visible {
    outline-offset: -3px;
}

:focus-visible {
    outline-width: 3px;
}

/* ── Skip link */
.skip-link {
    background: var(--accent);
    border-radius: 0 0 8px 8px;
    color: var(--accent-fg);
    font-weight: 700;
    inset-block-start: 0;
    inset-inline-start: 16px;
    padding: 10px 16px;
    position: fixed;
    text-decoration: none;
    transform: translateY(-120%);
    z-index: 20;

    &:focus {
        transform: none;
    }
}

.visually-hidden {
    block-size: 1px;
    clip-path: inset(50%);
    inline-size: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
}

/* ── Messages: not colour alone. Success and errors get a tinted box and an icon. */
.msg.ok,
.msg.bad,
.notice.bad,
.notice--ok {
    --tone: var(--ok);

    align-items: flex-start;
    background: color-mix(in srgb, var(--tone) 12%, var(--surface));
    border: 1px solid var(--tone);
    border-inline-start-width: 4px;
    border-radius: 8px;
    color: var(--fg);
    display: flex;
    font-weight: 600;
    gap: 8px;
    padding: 8px 12px;

    &::before {
        background: var(--tone);
        border-radius: 50%;
        color: var(--surface);
        content: "✓";
        content: "✓" / "";
        flex: none;
        font-size: .8rem;
        font-weight: 700;
        inline-size: 1.3em;
        line-height: 1.3em;
        margin-block-start: .15em;
        text-align: center;
    }
}

.msg.bad,
.notice.bad,
.comp-error {
    --tone: var(--bad);

    &::before {
        content: "!";
        content: "!" / "";
    }
}

/* Error per competency after a save attempt with missing answers */
.comp[data-invalid] {
    border-color: var(--bad);
    box-shadow: 0 0 0 2px var(--bad);
}

.comp-error {
    align-items: flex-start;
    background: color-mix(in srgb, var(--bad) 10%, var(--surface));
    border: 1px solid var(--bad);
    border-inline-start-width: 4px;
    border-radius: 8px;
    display: flex;
    font-weight: 600;
    gap: 8px;
    margin: 0;
    padding: 8px 12px;

    &::before {
        background: var(--bad);
        border-radius: 50%;
        color: var(--surface);
        flex: none;
        font-size: .8rem;
        font-weight: 700;
        inline-size: 1.3em;
        line-height: 1.3em;
        margin-block-start: .15em;
        text-align: center;
    }
}

.dim[data-invalid] .q b {
    color: var(--bad);
}

.dim[data-invalid] .seg button:not([aria-pressed="true"]) {
    border-color: var(--bad);
}

/* ── Progress: also as text, not only coloured segments */
.progress-count {
    color: var(--muted);
    font-size: .86rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ── Connection status, shown when the server cannot be reached */
.connection-status {
    margin-block-end: 16px;
}

/* ── Target size: at least 24×24 px (WCAG 2.5.8) */
.chips label,
.cview .lvls span {
    min-block-size: 28px;
}

.checks input,
.chips input {
    block-size: 18px;
    flex: none;
    inline-size: 18px;
}

/* ── Wide tables: keep the OLOD name in view while scrolling sideways */
.tablewrap {
    overscroll-behavior-inline: contain;
}

table.heat th:first-child,
table.heat td:first-child {
    background: var(--surface);
    inset-inline-start: 0;
    position: sticky;
    z-index: 1;
}

table.heat thead th:first-child {
    z-index: 2;
}

/* ── Small screens: give the form the room. The header scrolls away and the save bar stays
   compact; it stops sticking once it holds a longer result message (errors also show per competency). */
@media (max-width: 640px) {
    html {
        scroll-padding-block: 16px 96px;
    }

    .top {
        position: static;
    }

    .panel {
        padding: 16px 14px;
    }

    .savebar {
        gap: 8px 12px;
        padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));

        .progress {
            display: none;
        }

        .progress-count {
            flex: 1 1 0;
            font-size: .82rem;
            white-space: normal;
        }

        .msg {
            flex-basis: 100%;
            font-size: .88rem;
            order: 3;
        }

        /* Only the short neutral status ("Niet-opgeslagen wijzigingen.") stays pinned. */
        &:has(.msg.bad),
        &:has(.msg.ok) {
            position: static;
        }
    }

    .kpis {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .kpi b {
        font-size: 1.3rem;
    }

    table.heat th:first-child,
    table.heat td:first-child {
        max-inline-size: 42vw;
        min-inline-size: 9.5rem;
    }

    .filters .btn {
        flex: 1 1 100%;
    }
}

/* ── Windows high-contrast / forced colours: pressed state must not rely on fills */
@media (forced-colors: active) {
    [aria-pressed="true"],
    .tabs button[aria-selected="true"] {
        outline: 3px solid Highlight;
        outline-offset: -3px;
    }

    .progress i.on {
        background: Highlight;
    }

    .msg.ok::before,
    .msg.bad::before,
    .notice.bad::before {
        forced-color-adjust: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    * {
        scroll-behavior: auto !important;
        transition-duration: 0ms !important;
    }
}
