/* ==========================================================================
   KOW Admin - shared tokens, app shell and components.
   Values mirror lib/core/app_colors.dart + theme.dart from the Flutter admin.
   Light-mode sidebar is the team's "Navy Anchor" panel from the Padali branch.
   ========================================================================== */

:root {
    --primary: #1f6feb;
    --accent: #0ea5a4;
    --tertiary: #f59e0b;
    --success: #16a34a;
    --warning: #d97706;
    --error: #dc2626;
    --info: #2563eb;
    --bg: #f2f5fa;
    --surface: #ffffff;
    --elevated: #f7f9fd;
    --sidebar: #0f2050;
    --text: #102138;
    --text-2: #4a5d78;
    --text-3: #7a8ba4;
    --line: rgba(16, 33, 56, 0.13);
    --line-soft: rgba(16, 33, 56, 0.08);
    --line-strong: rgba(16, 33, 56, 0.24);
    --field-fill: #ffffff;
    --field-line: rgba(16, 33, 56, 0.28);
    --head-fill: color-mix(in srgb, var(--primary) 7%, transparent);
    --head-solid: #eaf1fd;
    --shadow: 0 10px 30px -12px rgba(16, 33, 56, 0.18);
    --card-bg: var(--surface);
    --card-shadow: 0 1px 2px rgba(16, 33, 56, 0.04), 0 8px 24px -16px rgba(16, 33, 56, 0.22);
    --inverse: #162238;
    --on-inverse: #e9f1ff;
    /* Sidebar ("Navy Anchor" in light mode). */
    /* Royal blue, two steps lighter than the dark-mode navy so the themes read apart.
       White text on the darkest stop (#1C4AA8) is 7.6:1; muted text stays above 4.5:1. */
    --nav-bg: radial-gradient( 130% 34% at 50% 0%, rgba(255, 255, 255, 0.14), transparent 70% ), linear-gradient(180deg, #2a62d0 0%, #1c4aa8 100%);
    --nav-line: rgba(255, 255, 255, 0.16);
    --nav-text: #e6eeff;
    --nav-text-hover: #ffffff;
    --nav-hover: rgba(255, 255, 255, 0.12);
    --nav-icon: #c3d5ff;
    --nav-active-bg: #ffffff;
    --nav-active-line: transparent;
    --nav-active-text: #163e96;
    --nav-active-icon: var(--primary);
    --nav-mark: var(--tertiary);
    --nav-muted: #d2dfff;
    --nav-card: rgba(255, 255, 255, 0.12);
    --nav-card-line: rgba(255, 255, 255, 0.22);
    --nav-shadow: 4px 0 20px rgba(28, 74, 168, 0.22);
    --font-body: "Manrope", system-ui, sans-serif;
    --font-head: "Space Grotesk", "Manrope", system-ui, sans-serif;
    --radius-card: 18px;
    --radius-ctl: 12px;
    /* Dropdown standard: change these to resize every dropdown in the site. */
    --dd-h: 54px;
    --dd-w: 220px;
    --dd-pad-l: 16px;
    --dd-caret-gap: 14px;
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --sidebar-w: 272px;
    color-scheme: light;
}

    :root[data-theme="dark"] {
        --bg: #0f172a;
        --surface: #162238;
        --elevated: #1c2b44;
        --sidebar: #0b1322;
        --text: #e9f1ff;
        --text-2: #9fb2cf;
        --text-3: #7387a6;
        --line: rgba(233, 241, 255, 0.22);
        --line-soft: rgba(233, 241, 255, 0.09);
        --line-strong: rgba(233, 241, 255, 0.34);
        --field-fill: #1a2740;
        --field-line: rgba(233, 241, 255, 0.36);
        --head-fill: color-mix(in srgb, var(--primary) 20%, transparent);
        --head-solid: #1d3358;
        --shadow: 0 12px 34px -14px rgba(0, 0, 0, 0.55);
        --card-bg: linear-gradient( 135deg, var(--surface), color-mix(in srgb, var(--elevated) 95%, transparent) );
        --card-shadow: none;
        --inverse: #e9f1ff;
        --on-inverse: #102138;
        --field-fill-solid: #1a2740;
        /* Sidebar: a shade deeper than the page, with a faint glow behind the logo. */
        --nav-bg: radial-gradient( 130% 34% at 50% 0%, rgba(31, 111, 235, 0.16), transparent 70% ), linear-gradient(180deg, #0c1527 0%, #091020 100%);
        --nav-line: rgba(255, 255, 255, 0.07);
        --nav-text: #a7b6cf;
        --nav-text-hover: #eef4ff;
        --nav-hover: rgba(255, 255, 255, 0.05);
        --nav-icon: #7d92b4;
        --nav-active-bg: linear-gradient( 90deg, rgba(31, 111, 235, 0.26), rgba(31, 111, 235, 0.08) );
        --nav-active-line: rgba(126, 178, 255, 0.22);
        --nav-active-text: #8dbbff;
        --nav-active-icon: #8dbbff;
        --nav-mark: var(--accent);
        --nav-muted: #7387a6;
        --nav-card: rgba(255, 255, 255, 0.04);
        --nav-card-line: rgba(255, 255, 255, 0.08);
        --nav-shadow: 10px 0 30px -18px rgba(0, 0, 0, 0.7);
        color-scheme: dark;
    }

/* ---------- Learning taxonomy colours ----------
   One colour per grade level, subject and difficulty, used the same way in
   every table, chip and pop-up. Each dimension also has its own shape, so
   shared hues (Binhi / Mathematics / Easy are all green) never read as the
   same thing:
     level      .tax       filled pill + icon       (strongest)
     subject    .tax-label coloured icon + label
     difficulty .tax-dot   coloured dot + label     (lightest)
   Binhi/Punla match the green/amber Learners cards. */
:root {
    --tax-binhi: #16A34A;
    --tax-punla: #D97706;
    --tax-math: #16A34A;
    --tax-science: #EA580C;
    --tax-filipino: #E11D48;
    --tax-english: #2563EB;
    --tax-writing: #7C3AED;
    --tax-easy: #16A34A;
    --tax-average: #D97706;
    --tax-hard: #DC2626;
}
:root[data-theme="dark"] {
    --tax-binhi: #4ADE80;
    --tax-punla: #FBBF24;
    --tax-math: #4ADE80;
    --tax-science: #FB923C;
    --tax-filipino: #FB7185;
    --tax-english: #60A5FA;
    --tax-writing: #A78BFA;
    --tax-easy: #4ADE80;
    --tax-average: #FBBF24;
    --tax-hard: #F87171;
}
.t-binhi { --t: var(--tax-binhi); }
.t-punla { --t: var(--tax-punla); }
.t-math { --t: var(--tax-math); }
.t-science { --t: var(--tax-science); }
.t-filipino { --t: var(--tax-filipino); }
.t-english { --t: var(--tax-english); }
.t-writing { --t: var(--tax-writing); }
.t-easy { --t: var(--tax-easy); }
.t-average { --t: var(--tax-average); }
.t-hard { --t: var(--tax-hard); }

.tax {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px 3px 7px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--t, var(--text-2)) 32%, transparent);
    background: color-mix(in srgb, var(--t, var(--text-2)) 13%, transparent);
    /* Mixed toward the text colour so amber/orange labels keep 4.5:1 on white. */
    color: color-mix(in srgb, var(--t, var(--text-2)) 72%, var(--text));
    font-size: 12px;
    font-weight: 700;
    line-height: 1.4;
    white-space: nowrap;
}
.tax .ms { font-size: 15px; color: var(--t, var(--text-2)); }
.tax-label {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-weight: 600;
    white-space: nowrap;
}
.tax-label .ms { font-size: 16px; color: var(--t, var(--text-2)); }
.tax-dot {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: color-mix(in srgb, var(--t, var(--text-2)) 72%, var(--text));
    font-weight: 700;
    white-space: nowrap;
}
.tax-dot::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--t, var(--text-2));
    flex: none;
}

/* Chart bars and other --tone readers can use the taxonomy colours directly. */
.tone-binhi { --tone: var(--tax-binhi); }
.tone-punla { --tone: var(--tax-punla); }
.tone-math { --tone: var(--tax-math); }
.tone-science { --tone: var(--tax-science); }
.tone-filipino { --tone: var(--tax-filipino); }
.tone-english { --tone: var(--tax-english); }
.tone-writing { --tone: var(--tax-writing); }

/* Level + subject + difficulty in one line (pool titles). */
.tax-row { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }

/* Tone helpers: any component reads --tone. */
.tone-primary {
    --tone: var(--primary);
}

.tone-accent {
    --tone: var(--accent);
}

.tone-tertiary {
    --tone: var(--tertiary);
}

.tone-success {
    --tone: var(--success);
}

.tone-warning {
    --tone: var(--warning);
}

.tone-error {
    --tone: var(--error);
}

.tone-info {
    --tone: var(--info);
}

/* ---------- Base ---------- */
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

[hidden] {
    display: none !important;
}

body {
    /* One layout for every screen: see the --ui-scale note in _Head.cshtml and kow-consistency.css. */
    zoom: var(--ui-scale, 1);
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 500;
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
    font-family: var(--font-head);
    margin: 0;
    letter-spacing: -0.01em;
}

p {
    margin: 0;
}

a {
    color: inherit;
}

button,
input,
select {
    font: inherit;
    color: inherit;
}

::selection {
    background: color-mix(in srgb, var(--primary) 32%, transparent);
    color: var(--text);
}

:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: 8px;
}

input {
    caret-color: var(--primary);
}

* {
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--text-3) 55%, transparent) transparent;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--text-3) 45%, transparent);
    border-radius: 99px;
    border: 3px solid transparent;
    background-clip: content-box;
}

::-webkit-scrollbar-track {
    background: transparent;
}

.ms {
    font-family: "Material Symbols Outlined";
    font-weight: 400;
    font-style: normal;
    font-size: 20px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    direction: ltr;
    font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24;
    -webkit-font-smoothing: antialiased;
    user-select: none;
    flex-shrink: 0;
    overflow: hidden;
    width: 1em;
}

.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* ---------- App shell ---------- */
.skip-link {
    position: fixed;
    z-index: 10000;
    top: 12px;
    left: 12px;
    padding: 12px 16px;
    transform: translateY(calc(-100% - 16px));
    border-radius: var(--radius-ctl);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow);
}

.skip-link:focus {
    transform: translateY(0);
}

.app {
    display: grid;
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
    min-height: calc(100vh / var(--ui-scale, 1));
}

.sidebar {
    position: sticky;
    top: 0;
    z-index: 2;
    height: calc(100vh / var(--ui-scale, 1));
    display: flex;
    flex-direction: column;
    background: var(--nav-bg);
    color: var(--nav-text);
    border-right: 1px solid var(--nav-line);
    box-shadow: var(--nav-shadow);
    view-transition-name: kow-sidebar;
}

.sidebar__logo {
    display: flex;
    justify-content: center;
    padding: 28px 20px 14px;
}

    .sidebar__logo img {
        width: 200px;
        height: auto;
        aspect-ratio: 720 / 351;
        object-fit: contain;
        filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
        transition: transform 0.4s var(--ease-out);
    }

    .sidebar__logo:hover img {
        transform: scale(1.02);
    }

.nav {
    flex: 1;
    overflow-y: auto;
    padding: 4px 12px;
    scrollbar-width: none;
}

    .nav::-webkit-scrollbar {
        display: none;
    }

.nav__group + .nav__group {
    margin-top: 10px;
}

.nav__group-label {
    padding: 8px 12px 4px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--nav-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nav__item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    height: 42px;
    margin: 2px 0;
    padding: 0 12px;
    border-radius: 12px;
    border: 1px solid transparent;
    color: var(--nav-text);
    text-decoration: none;
    font-weight: 500;
    white-space: nowrap;
    transition: background-color 0.18s ease, color 0.18s ease;
}

    .nav__item .ms {
        position: relative;
        z-index: 1;
        color: var(--nav-icon);
        transition: color 0.18s ease, transform 0.25s var(--ease-out);
    }

    .nav__item > span:not(.ms):not(.nav__pill) {
        position: relative;
        z-index: 1;
        overflow: hidden;
        text-overflow: ellipsis;
    }

a.nav__item:hover {
    background: var(--nav-hover);
    color: var(--nav-text-hover);
}

    a.nav__item:hover .ms {
        transform: translateX(2px);
    }

.nav__item.is-active {
    color: var(--nav-active-text);
    font-weight: 700;
}

    .nav__item.is-active .ms {
        color: var(--nav-active-icon);
        font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 24;
    }

    .nav__item.is-active:hover {
        background: transparent;
    }

/* The selection pill is its own element so it can glide between pages. */
.nav__pill {
    position: absolute;
    inset: -1px;
    border-radius: 12px;
    background: var(--nav-active-bg);
    border: 1px solid var(--nav-active-line);
    box-shadow: 0 6px 16px -10px rgba(0, 0, 0, 0.5);
    view-transition-name: kow-nav-pill;
}
    /* Amber marker on the active page (light mode). */
    .nav__pill::before {
        content: "";
        position: absolute;
        left: -1px;
        top: 10px;
        bottom: 10px;
        width: 4px;
        border-radius: 0 4px 4px 0;
        background: var(--nav-mark);
    }

.nav__item--soon {
    opacity: 0.5;
    cursor: not-allowed;
}

.sidebar__foot {
    padding: 0 12px 12px;
}

.sidebar__divider {
    height: 1px;
    background: var(--nav-line);
    margin: 0 2px;
}

.quick {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 0 6px;
}

.quick__label {
    font-size: 13px;
    color: var(--nav-muted);
}

.quick__btns {
    display: flex;
    gap: 2px;
}

.icon-btn {
    display: inline-grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-2);
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s var(--ease-out);
}

    .icon-btn .ms {
        font-size: 22px;
    }

    .icon-btn:hover {
        background: color-mix(in srgb, var(--text) 8%, transparent);
        color: var(--text);
    }

    .icon-btn:active {
        transform: scale(0.92);
    }

.sidebar .icon-btn {
    color: var(--nav-text);
}

    .sidebar .icon-btn:hover {
        background: var(--nav-hover);
        color: var(--nav-text-hover);
    }

    .sidebar .icon-btn.is-active {
        background: var(--nav-hover);
        color: var(--nav-text-hover);
    }

/* Theme icon swaps with a quarter turn. */
.theme-icon {
    position: relative;
    width: 22px;
    height: 22px;
}

    .theme-icon .ms {
        position: absolute;
        inset: 0;
        transition: transform 0.45s var(--ease-out), opacity 0.25s ease;
    }

    .theme-icon .is-sun {
        opacity: 0;
        transform: rotate(-90deg) scale(0.6);
    }

:root[data-theme="dark"] .theme-icon .is-sun {
    opacity: 1;
    transform: none;
}

:root[data-theme="dark"] .theme-icon .is-moon {
    opacity: 0;
    transform: rotate(90deg) scale(0.6);
}

:root:not([data-theme="dark"]) .sidebar [data-theme-toggle] {
    color: #fcd34d;
}

.account {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px;
    border-radius: 12px;
    background: var(--nav-card);
    border: 1px solid var(--nav-card-line);
    color: var(--nav-text-hover);
}

.account__text {
    flex: 1;
    min-width: 0;
}

.account__label {
    font-size: 13px;
    color: var(--nav-muted);
}

.account__value {
    font-weight: 800;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.main {
    min-width: 0;
    view-transition-name: kow-main;
}

.page {
    container-type: inline-size;
    padding: 20px 24px 28px;
}

.page--fill {
    display: flex;
    flex-direction: column;
    height: calc(100vh / var(--ui-scale, 1));
    padding-bottom: 24px;
}

/* Mobile bottom navigation (shown under 960px, like the Flutter shell). */
.bottom-nav {
    display: none;
}

.theme-fab {
    display: none;
}

@media (max-width: 1239px) {
    :root {
        --sidebar-w: 92px;
    }

    .sidebar__logo {
        padding: 20px 8px 10px;
    }

        .sidebar__logo img {
            width: 56px;
            height: 56px;
            aspect-ratio: auto;
            object-fit: cover;
            object-position: left center;
        }

    .nav__group-label {
        display: none;
    }

    .nav__group + .nav__group {
        margin-top: 8px;
        padding-top: 8px;
        border-top: 1px solid var(--nav-line);
    }

    .nav__item {
        justify-content: center;
        padding: 0;
    }

        .nav__item > span:not(.ms):not(.nav__pill) {
            display: none;
        }

    .quick {
        justify-content: center;
    }

    .quick__label,
    .account__text {
        display: none;
    }

    .quick__btns {
        flex-direction: column;
    }

    .account {
        justify-content: center;
        padding: 6px;
    }
}

@media (max-width: 959px) {
    .app {
        grid-template-columns: minmax(0, 1fr);
    }

    .sidebar {
        display: none;
    }

    .page {
        padding: 16px 16px 96px;
    }

    .page--fill {
        height: auto;
        min-height: calc(100vh / var(--ui-scale, 1));
    }

    .bottom-nav {
        display: flex;
        gap: 8px;
        overflow-x: auto;
        scrollbar-width: none;
        position: fixed;
        inset: auto 0 0 0;
        z-index: 40;
        padding: 8px 10px 10px;
        background: var(--nav-bg);
        border-top: 1px solid var(--nav-line);
        view-transition-name: kow-bottom-nav;
    }

    .bottom-nav__item {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 8px 10px;
        border-radius: 999px;
        border: 1px solid var(--nav-line);
        color: var(--nav-text);
        font-size: 11px;
        font-weight: 600;
        text-decoration: none;
        flex-shrink: 0;
    }

        .bottom-nav__item .ms {
            font-size: 16px;
        }

        .bottom-nav__item.is-active {
            color: var(--nav-active-text);
            font-weight: 700;
            background: var(--nav-active-bg);
            border-color: var(--nav-active-line);
        }

        .bottom-nav__item.nav__item--soon {
            opacity: 0.5;
        }

    .theme-fab {
        display: grid;
        position: fixed;
        right: 16px;
        bottom: 76px;
        z-index: 41;
        width: 44px;
        height: 44px;
        border-radius: 14px;
        background: color-mix(in srgb, var(--primary) 18%, var(--surface));
        color: var(--primary);
        box-shadow: var(--shadow);
    }
}

/* ---------- Page header ---------- */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    min-height: 72px;
    margin-bottom: 16px;
}

    .page-header + * {
        margin-top: 0 !important;
    }

.page-header__text {
    flex: 1 1 280px;
    min-width: 0;
    max-width: 740px;
}

.page-header h1 {
    margin: 0;
    font-size: 24px;
    font-weight: 700;
    line-height: 1.2;
}

.page-header p {
    display: -webkit-box;
    margin: 6px 0 0;
    overflow: hidden;
    font-size: 13px;
    line-height: 1.4;
    color: var(--text-2);
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.page-header__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-end;
}

@container (max-width: 719px) {
    .page-header {
        flex-direction: column;
    }

        .page-header h1 {
            font-size: 19px;
            font-weight: 800;
        }

        .page-header p {
            font-size: 12px;
        }

    .page-header__actions {
        justify-content: flex-start;
    }
}

/* ---------- Surfaces ---------- */
.card {
    position: relative;
    border-radius: var(--radius-card);
    border: 1px solid var(--line);
    background: var(--card-bg);
    box-shadow: var(--card-shadow);
    padding: 16px;
}

.section-title h2 {
    font-size: 16px;
    font-weight: 700;
}

.section-title p {
    margin-top: 4px;
    font-size: 13px;
    color: var(--text-2);
}

.empty-state {
    display: grid;
    place-items: center;
    padding: 16px;
    font-size: 13px;
    color: var(--text-2);
}

/* ---------- Buttons ---------- */
.btn {
    --tone: var(--primary);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 42px;
    padding: 0 20px;
    border-radius: var(--radius-ctl);
    border: 1px solid transparent;
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    overflow: hidden;
    isolation: isolate;
    transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.2s ease, transform 0.15s var(--ease-out), opacity 0.15s ease;
}

    .btn .ms {
        font-size: 18px;
    }

    .btn:active:not(:disabled) {
        transform: scale(0.97);
    }

.btn--filled {
    background: var(--tone);
    color: #fff;
}

    .btn--filled:hover:not(:disabled) {
        box-shadow: 0 6px 16px -8px var(--tone);
        background: color-mix(in srgb, var(--tone) 90%, #fff);
    }

.btn--tonal {
    --tone: var(--accent);
    background: var(--accent);
    color: #fff;
}

    .btn--tonal:hover:not(:disabled) {
        box-shadow: 0 6px 16px -8px var(--accent);
        background: color-mix(in srgb, var(--accent) 90%, #fff);
    }

.btn--outline {
    background: transparent;
    color: var(--primary);
    border-color: color-mix(in srgb, var(--line) 120%, transparent);
    min-height: 38px;
    padding: 0 18px;
}

    .btn--outline:hover:not(:disabled) {
        background: color-mix(in srgb, var(--primary) 8%, transparent);
    }

.btn:disabled,
.btn[aria-disabled="true"] {
    cursor: default;
    color: color-mix(in srgb, var(--text) 38%, transparent);
    pointer-events: none;
}

.btn--filled:disabled,
.btn--tonal:disabled {
    background: color-mix(in srgb, var(--text) 12%, transparent);
}

/* Press ripple, spawned by kow-shell.js. */
.ripple {
    position: absolute;
    z-index: -1;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.22;
    transform: scale(0);
    animation: ripple 0.55s var(--ease-out) forwards;
    pointer-events: none;
}

@keyframes ripple {
    to {
        transform: scale(1);
        opacity: 0;
    }
}

.btn.is-busy .spin-on-busy {
    animation: spin 0.8s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ---------- Pills & chips ---------- */
.pill {
    display: inline-flex;
    align-items: center;
    padding: 6px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--tone, var(--info)) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--tone, var(--info)) 28%, transparent);
    color: var(--tone, var(--info));
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
}

/* ---------- Form fields (Material outlined) ---------- */
.field {
    position: relative;
    display: flex;
    align-items: center;
    min-height: 56px;
    border-radius: var(--radius-ctl);
    background: var(--field-fill);
    --field-ring: inset 0 0 0 1px var(--field-line);
}
    /* The outline is drawn on top of the field's children, so an autofilled or
   full-width input can never paint over the right-hand border. */
    .field::after {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 1;
        border-radius: inherit;
        box-shadow: var(--field-ring);
        pointer-events: none;
        transition: box-shadow 0.18s ease;
    }

    .field:hover {
        --field-ring: inset 0 0 0 1px color-mix(in srgb, var(--text) 55%, transparent);
    }

    .field:focus-within {
        --field-ring: inset 0 0 0 1.6px var(--primary);
    }

    .field.is-invalid {
        --field-ring: inset 0 0 0 1.4px var(--error);
    }

.field__icon {
    margin-left: 14px;
    color: var(--text-2);
    font-size: 22px;
    transition: color 0.18s ease;
}

.field:focus-within .field__icon {
    color: var(--primary);
}

.field input {
    flex: 1;
    min-width: 0;
    height: 54px;
    padding: 0 14px 0 12px;
    border: 0;
    outline: 0;
    background: transparent;
    font-size: 16px;
}

    .field input::placeholder {
        color: var(--text-2);
        opacity: 1;
    }
    /* Browser autofill keeps the field colours instead of a blue box. */
    .field input:-webkit-autofill,
    .field input:-webkit-autofill:hover,
    .field input:-webkit-autofill:focus {
        -webkit-text-fill-color: var(--text);
        -webkit-box-shadow: 0 0 0 1000px var(--field-fill-solid, var(--surface)) inset;
        caret-color: var(--primary);
        transition: background-color 9999s ease-out;
    }

.field__label {
    position: absolute;
    left: 48px;
    top: 50%;
    padding: 0 4px;
    color: var(--text-2);
    font-size: 16px;
    pointer-events: none;
    transform: translateY(-50%);
    transform-origin: left center;
    transition: transform 0.2s var(--ease-out), color 0.2s ease, left 0.2s var(--ease-out);
    border-radius: 4px;
    z-index: 2;
}

    .field__label::before {
        content: "";
        position: absolute;
        inset: 35% -2px auto;
        height: 30%;
        background: var(--label-gap, var(--surface));
        z-index: -1;
        opacity: 0;
        transition: opacity 0.1s ease;
    }

    .field--float input:not(:placeholder-shown) ~ .field__label,
    .field--float:focus-within .field__label,
    .field__label.is-pinned {
        left: 10px;
        /* Centre the label on the top border so its backing strip hides the line. */
        transform: translateY(calc(-50% - 28px)) scale(0.75);
    }

        .field--float input:not(:placeholder-shown) ~ .field__label::before,
        .field--float:focus-within .field__label::before,
        .field__label.is-pinned::before {
            opacity: 1;
        }

.field--float:focus-within .field__label {
    color: var(--primary);
}

.field--float input::placeholder {
    color: transparent;
}

.field__error {
    margin: 6px 0 0 14px;
    font-size: 12px;
    color: var(--error);
}

.field__trail {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin-right: 6px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-2);
    cursor: pointer;
}

    .field__trail:hover {
        background: color-mix(in srgb, var(--text) 8%, transparent);
    }

    .field__trail .ms {
        font-size: 24px;
    }

/* Custom select (progressive enhancement over <select>). */
.select {
    position: relative;
    min-height: 54px;
}

    .select select {
        position: absolute;
        inset: 0;
        opacity: 0;
        width: 100%;
        cursor: pointer;
    }

    .select .field {
        height: var(--dd-h);
        min-height: var(--dd-h);
        cursor: pointer;
    }

.select__value {
    flex: 1;
    padding: 0 12px 0 var(--dd-pad-l);
    font-weight: 600;
    font-size: 15px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.select__caret {
    margin-right: var(--dd-caret-gap);
    color: var(--text-2);
    transition: transform 0.25s var(--ease-out);
    font-size: 24px;
}

.select.is-open .select__caret {
    transform: rotate(180deg);
}

.select.is-open .field {
    --field-ring: inset 0 0 0 1.6px var(--primary);
}

.select.is-open .field__label {
    color: var(--primary);
}

.select__menu {
    position: absolute;
    z-index: 60;
    top: calc(100% + 6px);
    left: 0;
    width: 100%;
    max-height: 320px;
    overflow-y: auto;
    padding: 6px 0;
    margin: 0;
    list-style: none;
    border-radius: 8px;
    background: var(--elevated);
    box-shadow: 0 18px 40px -16px rgba(0, 0, 0, 0.45), 0 0 0 1px var(--line-soft);
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
    transform-origin: top center;
    pointer-events: none;
    transition: opacity 0.16s ease, transform 0.22s var(--ease-out);
}

.select.is-open .select__menu,
.is-open > .select__menu {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

.select__option {
    padding: 14px var(--dd-pad-l);
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

    .select__option:hover,
    .select__option.is-focus {
        background: color-mix(in srgb, var(--text) 8%, transparent);
    }

    .select__option[aria-selected="true"] {
        background: color-mix(in srgb, var(--text) 12%, transparent);
    }

/* ---------- Pager ---------- */
.pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

.pager--center {
    justify-content: center;
}

/* ---------- Toast / snackbar ---------- */
.toast-host {
    position: fixed;
    left: 50%;
    bottom: 24px;
    z-index: 100;
    display: grid;
    gap: 8px;
    transform: translateX(-50%);
    width: min(560px, calc(100vw - 32px));
    pointer-events: none;
}

.toast {
    padding: 14px 18px;
    border-radius: 10px;
    background: var(--inverse);
    color: var(--on-inverse);
    font-size: 14px;
    box-shadow: 0 14px 30px -12px rgba(0, 0, 0, 0.5);
    animation: toast-in 0.32s var(--ease-out) both;
    pointer-events: auto;
}

    .toast.is-leaving {
        animation: toast-out 0.2s ease-in both;
    }

@keyframes toast-in {
    from {
        opacity: 0;
        transform: translateY(14px) scale(0.98);
    }
}

@keyframes toast-out {
    to {
        opacity: 0;
        transform: translateY(8px);
    }
}

@media (max-width: 959px) {
    .toast-host {
        bottom: 80px;
    }
}

/* In the top layer (Popover API) the toast sits above every open pop-up and dialog. */
.toast-host[popover] {
    inset: auto auto 24px 50%;
    height: auto;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    overflow: visible;
    background: transparent;
    color: inherit;
}

.toast-host[popover]:not(:popover-open) {
    display: none;
}

@media (max-width: 959px) {
    .toast-host[popover] {
        inset: auto auto 80px 50%;
    }
}

/* Shared popup controls use theme tokens on every page, including sign-in and embedded Settings. */
button.popup-close[aria-label] {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 5;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    padding: 0;
    margin: 0;
    flex: none;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    animation: none;
    transition: none;
    transform: none;
    color: var(--text-2);
    cursor: pointer;
}
button.popup-close[aria-label] .ms { font-size: 18px; line-height: 1; }
button.popup-close[aria-label]:hover { color: var(--text); background: transparent; box-shadow: none; }
button.popup-close[aria-label]:disabled { opacity: .5; cursor: default; }
.amap:not(.is-modal) button.popup-close { display: none; }
.amap.is-modal .amap__head { padding-inline-end: 48px; }
.has-popup-close .popup-title { padding-inline-end: 48px; overflow-wrap: anywhere; }
dialog.has-popup-close .popup-heading { padding-inline-end: 48px; }
.has-popup-close .popup-heading .popup-title { padding-inline-end: 0; }
dialog.has-popup-close { max-height: calc(100dvh / var(--ui-scale, 1) - 24px); }
button.popup-close[aria-label]:focus-visible, [data-password-toggle]:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}
.password-toggle[data-password-toggle] {
    width: 44px;
    height: 44px;
    flex: none;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-2);
    cursor: pointer;
    display: grid;
    place-items: center;
}
.password-toggle[data-password-toggle] .ms { font-size: 24px; }
.password-toggle[data-password-toggle]:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }
.password-toggle[data-password-toggle]:disabled { opacity: .5; cursor: default; }
.password-control { display: inline-flex; position: relative; width: 100%; min-width: 0; }
.password-control > input { width: 100%; min-width: 0; padding-inline-end: 52px; }
.password-control > .password-toggle { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); }
input[data-password-input]::-ms-reveal { display: none; }

/* ---------- Dialog ---------- */
.dialog {
    width: min(400px, calc(100vw - 32px));
    padding: 24px;
    border: 0;
    border-radius: 24px;
    background: var(--elevated);
    color: var(--text);
    box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.55);
}

.dialog--wide {
    width: min(880px, calc(100vw - 32px));
}

.dialog::backdrop {
    background: rgba(0, 0, 0, 0.45);
}

.dialog[open] {
    animation: dialog-in 0.28s var(--ease-out);
}

    .dialog[open]::backdrop {
        animation: fade-in 0.2s ease;
    }

.dialog.is-closing {
    animation: dialog-out 0.16s ease-in forwards;
}

@keyframes dialog-in {
    from {
        opacity: 0;
        transform: translateY(8px) scale(0.96);
    }
}

@keyframes dialog-out {
    to {
        opacity: 0;
        transform: scale(0.97);
    }
}

@keyframes fade-in {
    from {
        opacity: 0;
    }
}

.dialog h2 {
    font-size: 22px;
    font-weight: 700;
}

.dialog__body {
    margin-top: 14px;
    color: var(--text-2);
    font-size: 14px;
}

.dialog__actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 24px;
}

.btn--text {
    background: transparent;
    color: var(--primary);
    padding: 0 14px;
}

    .btn--text:hover {
        background: color-mix(in srgb, var(--primary) 8%, transparent);
    }

/* ---------- Navigation progress ---------- */
.nav-progress {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 200;
    height: 3px;
    background: linear-gradient(90deg, var(--primary), var(--accent));
    transform: scaleX(0);
    transform-origin: left;
    opacity: 0;
    pointer-events: none;
}

    .nav-progress.is-active {
        opacity: 1;
        animation: progress 1.6s var(--ease-out) 0.15s both;
    }

@keyframes progress {
    0% {
        transform: scaleX(0);
    }

    60% {
        transform: scaleX(0.7);
    }

    100% {
        transform: scaleX(0.92);
    }
}

/* ---------- Entrance ----------
   Budget: a page switch must read as instant. Blocks settle within ~330ms:
   240ms per block, 24ms stagger capped at 4 steps. Opacity + a 6px lift only
   (no blur, no scale), so the browser composites it without repainting.
   "backwards" fill leaves no transform behind, so sticky headers keep working.
   The richer blur entrance stays on the login card, where it is the first impression. */
.js .rise {
    animation: rise 0.24s var(--ease-out) backwards;
    animation-delay: calc(min(var(--i, 0), 8) * 18ms + 40ms);
}

@keyframes rise {
    from {
        opacity: 0;
        transform: translateY(6px);
    }
}

/* ---------- Page and theme transitions ---------- */
@view-transition {
    navigation: none;
}
/* Old page gets out of the way fast; the new page plays its own entrance. */
::view-transition-old(kow-main) {
    animation: vt-out 0.09s linear both;
}

::view-transition-new(kow-main) {
    animation: none;
}

::view-transition-group(kow-nav-pill) {
    animation-duration: 0.3s;
    animation-timing-function: var(--ease-out);
}

@keyframes vt-out {
    to {
        opacity: 0;
    }
}

/* Theme switch: new theme expands as a circle from the toggle. */
:root.theme-switching::view-transition-old(root),
:root.theme-switching::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
}

:root.theme-switching * {
    view-transition-name: none !important;
}

:root.theme-fallback,
:root.theme-fallback * {
    transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease !important;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        animation-delay: 0ms !important;
        transition-duration: 0.12s !important;
    }

    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none !important;
    }
}

/* ---------- Sign-in / sign-out notification (top-right) ----------
   Non-blocking: the page is usable at once. The notice slides in from the
   right edge in 220ms, stays 3s (paused while hovered or focused) and leaves
   in 160ms. On the login page it sits under the theme toggle. */
.notice {
    --notice-tone: var(--success);
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: 120;
    display: flex;
    align-items: center;
    gap: 12px;
    width: min(340px, calc(100vw - 32px));
    padding: 10px 8px 12px 12px;
    overflow: hidden;
    border-radius: 14px;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 2px 4px rgba(16, 33, 56, 0.06), 0 12px 28px -10px rgba(12, 26, 64, 0.32);
    animation: notice-in .22s var(--ease-out) both;
    will-change: transform, opacity;
}
.notice--out { --notice-tone: var(--primary); }
.login-body .notice { top: 66px; }
:root[data-theme="dark"] .notice {
    background: var(--elevated);
    border-color: var(--line-soft);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3), 0 14px 32px -12px rgba(0, 0, 0, 0.75);
}

.notice__icon {
    display: grid;
    place-items: center;
    flex: none;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--notice-tone);
    color: #fff;
    box-shadow: 0 4px 10px -4px var(--notice-tone);
}
.notice__icon .ms { font-size: 19px; font-variation-settings: "FILL" 0, "wght" 600, "GRAD" 0, "opsz" 20; }
.notice--in .notice__icon .ms { animation: notice-check .32s var(--ease-out) .12s backwards; }

.notice__text { flex: 1; min-width: 0; display: grid; gap: 2px; }
.notice__text strong { font-size: 14px; font-weight: 700; line-height: 1.25; }
.notice__text span { font-size: 13px; line-height: 1.3; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.notice__close {
    display: grid;
    place-items: center;
    flex: none;
    align-self: flex-start;
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--text-3);
    cursor: pointer;
    transition: background-color .12s ease, color .12s ease;
}
.notice__close:hover { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); }
.notice__close .ms { font-size: 18px; }

/* Countdown line along the bottom edge. */
.notice__timer {
    position: absolute;
    inset: auto 0 0 0;
    height: 3px;
    background: var(--notice-tone);
    opacity: .55;
    transform-origin: left;
    animation: notice-timer 3s linear .22s forwards;
}
.notice:hover .notice__timer, .notice:focus-within .notice__timer { animation-play-state: paused; }

.notice.is-leaving { animation: notice-out .16s ease-in forwards; }

@keyframes notice-in { from { opacity: 0; transform: translateX(16px) scale(.98); } }
@keyframes notice-out { to { opacity: 0; transform: translateX(16px) scale(.98); } }
@keyframes notice-timer { to { transform: scaleX(0); } }
@keyframes notice-check { from { opacity: 0; transform: scale(.4) rotate(-20deg); } }

@media (max-width: 959px) {
    .notice { top: 12px; right: 12px; width: calc(100vw - 24px); }
}
@media (prefers-reduced-motion: reduce) {
    .notice, .notice.is-leaving, .notice--in .notice__icon .ms { animation-duration: .01ms; }
}