/*
 * App layer on top of vendored Pico CSS (static/pico.min.css).
 *
 * Pico styles the semantic elements (typography, forms, buttons, tables, links)
 * and provides light/dark via `data-theme` + `--pico-*` variables. This file
 * (1) retunes Pico's design tokens into a distinct identity for the lesson
 * planner — indigo primary, warm-amber accent, editorial heading serif — so we
 * are not shipping Pico's defaults as-is, and (2) adds the app-specific chrome
 * (top bar, nav), card/panel layout, form helpers, and the journal / grade /
 * seating grids — all keyed off Pico variables so they follow the active theme.
 */

/* ---------- Self-hosted fonts (SIL OFL; files in /static/fonts) ---------- */
/*
 * Inter for body/UI, Fraunces for headings. `font-display: swap` shows the
 * system fallback immediately and swaps in the web font once loaded, so first
 * paint is never blocked. Only the latin subset is shipped.
 */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/static/fonts/inter-400.woff2") format("woff2");
}
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("/static/fonts/inter-500.woff2") format("woff2");
}
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/static/fonts/inter-600.woff2") format("woff2");
}
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/static/fonts/inter-700.woff2") format("woff2");
}
@font-face {
    font-family: "Fraunces";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("/static/fonts/fraunces-500.woff2") format("woff2");
}
@font-face {
    font-family: "Fraunces";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/static/fonts/fraunces-600.woff2") format("woff2");
}
@font-face {
    font-family: "Fraunces";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/static/fonts/fraunces-700.woff2") format("woff2");
}

/* ---------- Design tokens: retune Pico for a distinct identity ---------- */
:root {
    /* Typography: crisp UI sans for body, editorial serif for headings. */
    --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    --font-head: "Fraunces", Georgia, "Times New Roman", serif;
    --pico-font-family-sans-serif: var(--font-body);
    --pico-font-family: var(--font-body);

    /* App accent. `--accent` is a bright amber for decorative fills (brand mark,
     * card edges); `--accent-text` is a darker shade that clears WCAG AA contrast
     * (>=4.5:1 on the card background) for accent-coloured *text*. */
    --accent: #e08a1e;
    --accent-text: #b45309;

    /* Slightly softer, more modern rounding and a calmer type scale. */
    --pico-border-radius: 0.6rem;
    --pico-line-height: 1.6;

    /* Indigo primary (light). Overriding Pico's blue with the app's own hue. */
    --pico-primary: #4338ca;
    --pico-primary-background: #4f46e5;
    --pico-primary-hover: #3730a3;
    --pico-primary-hover-background: #4338ca;
    --pico-primary-focus: rgba(79, 70, 229, 0.28);
    --pico-primary-inverse: #ffffff;
    --pico-primary-underline: rgba(67, 56, 202, 0.4);

    /* Cool off-white app canvas so white cards/panels lift off the page. */
    --pico-background-color: #f5f6fb;
    --pico-card-background-color: #ffffff;
    --pico-card-border-color: #e7e8f0;
    --pico-card-sectioning-background-color: #fbfbfe;
    --pico-muted-border-color: #e7e8f0;
    --pico-card-box-shadow: 0 1px 2px rgba(20, 22, 40, 0.04), 0 6px 20px rgba(20, 22, 40, 0.05);
}

[data-theme="dark"] {
    --accent: #f4b458;
    /* On the dark canvas the bright amber already clears AA, so text reuses it. */
    --accent-text: #f4b458;

    /* Indigo primary (dark) — brighter so it reads on the deep canvas. */
    --pico-primary: #a5b4fc;
    --pico-primary-background: #6366f1;
    --pico-primary-hover: #c7d2fe;
    --pico-primary-hover-background: #4f46e5;
    --pico-primary-focus: rgba(129, 140, 248, 0.3);
    --pico-primary-inverse: #0b0d14;
    --pico-primary-underline: rgba(165, 180, 252, 0.4);

    /* Deep, slightly cool slate canvas with lifted card surfaces. */
    --pico-background-color: #0f111a;
    --pico-card-background-color: #191c28;
    --pico-card-border-color: #2a2e3f;
    --pico-card-sectioning-background-color: #1f2331;
    --pico-muted-border-color: #2a2e3f;
    --pico-card-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.28);
}

/* ---------- Design tokens: spacing & type scale ---------- */
/*
 * A single spacing scale (4px base) and a modular type scale (1.2 ratio off a
 * 1rem body) so layout values come from one vocabulary instead of ad-hoc rems.
 * Prefer these vars for new padding/margin/gap and font sizes.
 */
:root {
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-7: 2rem;

    --text-sm: 0.833rem;   /* labels, table cells, dense UI */
    --text-base: 1rem;     /* body / prose */
    --text-lg: 1.2rem;     /* section leads */
    --text-xl: 1.44rem;    /* h2 */
    --text-2xl: 1.728rem;  /* h1 */
}

/* Editorial serif headings with tightened tracking; keep dense UI on the sans. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-head);
    font-weight: 600;
    letter-spacing: -0.01em;
}
h1 { letter-spacing: -0.02em; }
.content > h1:first-child { margin-bottom: var(--space-5); }

/* Page title with an inline control (e.g. the school-year picker) on the right,
 * so a one-select filter doesn't cost a whole panel row above the content. */
.page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
    margin-bottom: var(--space-5);
}
.page-head h1 { margin-bottom: 0; }
.page-head form {
    margin: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 0.9rem;
}
.page-head label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0;
    font-size: 0.9rem;
    color: var(--pico-muted-color);
}
.page-head select { width: auto; margin: 0; }
/* Groups the right-hand controls (a filter/picker form + a "New…" button) into
 * one cluster, so the page-head stays a clean title-left / controls-right split
 * instead of stranding a middle item when there are three. */
.page-head-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 0.9rem;
}

/* ---------- Layout: fixed left sidebar + scrolling content ---------- */
.layout { display: flex; align-items: stretch; min-height: 100vh; }
.content { flex: 1 1 auto; min-width: 0; padding: 1.75rem 2rem 4rem; }

.sidebar {
    flex: 0 0 15rem;
    width: 15rem;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 1rem 0.9rem 1.2rem;
    background: var(--pico-card-background-color);
    border-right: 1px solid var(--pico-muted-border-color);
    /* Stays put while the content column scrolls. Only the link list scrolls
     * (see .mainnav), so the account footer never drops below the fold. */
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
}
.sidebar-body { display: flex; flex-direction: column; gap: 0.4rem; flex: 1 1 auto; min-height: 0; }
/* Brand + collapse button share one row; the divider lives on the wrapper. */
.sidebar-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding-bottom: 0.7rem;
    border-bottom: 1px solid var(--pico-muted-border-color);
}
.brand {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-head);
    font-weight: 700;
    font-size: 1.25rem;
    letter-spacing: -0.02em;
    color: var(--pico-color);
    text-decoration: none;
    white-space: nowrap;
    padding: 0.2rem 0.55rem;
}
.brand:hover { text-decoration: none; }
/* Warm accent mark before the wordmark for a small piece of identity. */
.brand::before {
    content: "";
    width: 0.7rem;
    height: 0.7rem;
    border-radius: 0.2rem;
    background: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.mainnav {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.05rem;
    margin: 0.3rem 0;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Room for the focus outline inside the scroll box. */
    padding: 2px;
}
/* Small section headings: Heute / Planung / Stammdaten / Konto. */
.nav-group {
    margin: 0.7rem 0.7rem 0.15rem;
    color: var(--pico-muted-color);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.nav-group:first-child { margin-top: 0.2rem; }
.mainnav a {
    display: block;
    color: var(--pico-secondary);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
    padding: 0.36rem 0.7rem;
    border-radius: 0.45rem;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.mainnav a:hover {
    color: var(--pico-primary);
    background: color-mix(in srgb, var(--pico-primary) 12%, transparent);
    text-decoration: none;
}
/* Current section (set by nav.js). Filled pill so the location is obvious. */
.mainnav a[aria-current="page"] {
    color: var(--pico-primary-inverse);
    background: var(--pico-primary-background);
    font-weight: 600;
}
/* User + logout pinned to the bottom of the sidebar. */
.sidebar-foot {
    margin-top: auto;
    padding-top: 0.8rem;
    border-top: 1px solid var(--pico-muted-border-color);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.user { color: var(--pico-muted-color); font-size: 0.8rem; word-break: break-all; }
.sidebar-foot .inline { display: block; margin: 0; }
.sidebar-foot button { width: 100%; margin: 0; }
.spacer { flex: 1; }

/* Theme toggle lives in the sidebar footer; full-width like the logout button
 * (the .sidebar-foot button rule sizes it), just a touch smaller. */
.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    font-size: 0.85rem;
    padding-block: 0.4rem;
}
/* The icon previews the mode the click switches to. */
.theme-toggle .icon-sun, .theme-toggle.is-dark .icon-moon { display: none; }
.theme-toggle.is-dark .icon-sun { display: inline; }
/* Phones only (see the media query): opens the nav drawer. `button.` beats
 * Pico's button colours, which would paint the icon white on white. */
button.nav-menu {
    display: none;
    width: auto;
    margin: 0;
    padding: 0.35rem 0.5rem;
    background: transparent;
    border: 1px solid var(--pico-muted-border-color);
    color: var(--pico-h1-color);
    line-height: 0;
}
/* Pico redefines --pico-color inside buttons (white, for filled buttons), so
 * the icon takes the heading colour, which follows the theme. */
button.nav-menu svg { color: var(--pico-h1-color); }

/* ---------- Collapsible sidebar ---------- */
/* A ghost square button whose glyph is a CSS-drawn hamburger (three bars via a
 * bar + box-shadow), so it inherits the current text color in both themes. */
.nav-toggle {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.1rem;
    height: 2.1rem;
    padding: 0;
    color: var(--pico-secondary);
    background: transparent;
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 0.45rem;
    cursor: pointer;
}
.nav-toggle:hover {
    color: var(--pico-primary);
    border-color: var(--pico-primary);
    background: color-mix(in srgb, var(--pico-primary) 12%, transparent);
}
.nav-toggle::before {
    content: "";
    width: 1rem;
    height: 2px;
    background: currentColor;
    box-shadow: 0 -0.32rem 0 currentColor, 0 0.32rem 0 currentColor;
}

/* Reopen tab: hidden until the sidebar is collapsed, then floats top-left. */
.nav-open {
    display: none;
    position: fixed;
    top: 0.7rem;
    left: 0.7rem;
    z-index: 50;
    background: var(--pico-card-background-color);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
}
.nav-collapsed .sidebar { display: none; }
.nav-collapsed .nav-open { display: inline-flex; }
/* Keep page content clear of the floating reopen button while collapsed. */
.nav-collapsed .content { padding-top: 3.5rem; }

/* Narrow screens: the sidebar becomes a slim top bar (brand + menu button);
 * the links and account footer open as a drawer below it (nav.js). */
@media (max-width: 768px) {
    .layout { flex-direction: column; }
    .sidebar {
        flex: none;
        width: auto;
        height: auto;
        padding: 0.6rem 1rem;
        position: sticky;
        top: 0;
        z-index: 20;
        overflow: visible;
        border-right: none;
        border-bottom: 1px solid var(--pico-muted-border-color);
    }
    .sidebar-head { border-bottom: none; padding-bottom: 0; }
    button.nav-menu { display: inline-flex; margin-left: auto; }
    .sidebar-body {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        max-height: calc(100dvh - 3.5rem);
        padding: 0.5rem 1rem 1rem;
        background: var(--pico-card-background-color);
        border-bottom: 1px solid var(--pico-muted-border-color);
        box-shadow: 0 12px 24px rgb(0 0 0 / 0.15);
    }
    .sidebar.is-open .sidebar-body { display: flex; }
    /* In the drawer the whole panel scrolls, not just the link list. */
    .sidebar-body { overflow-y: auto; }
    .mainnav { flex: none; overflow: visible; }
    .mainnav a { padding: 0.55rem 0.7rem; }
    /* The top bar is already compact; the desktop collapse feature doesn't apply. */
    .nav-toggle { display: none; }
    .nav-collapsed .sidebar { display: flex; }
    .nav-collapsed .content { padding-top: 1.25rem; }
    .sidebar-foot {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        padding-top: var(--space-2);
    }
    .sidebar-foot .user { flex-basis: 100%; }
    .sidebar-foot button { width: auto; }
    .content { padding: 1.25rem 1.1rem 3rem; }
}

/* Journal on phones: the time column plus one day (journal.js sets data-day;
 * the switcher above the grid changes it). Wider screens show the week. */
.day-switch { display: none; }
@media (max-width: 768px) {
    .day-switch:not([hidden]) {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--space-3);
        margin-bottom: var(--space-3);
    }
    .day-switch svg { width: 1.1rem; height: 1.1rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
    table.journal tr > :nth-child(n+2) { display: none; }
    table.journal[data-day="0"] tr > :nth-child(2),
    table.journal[data-day="1"] tr > :nth-child(3),
    table.journal[data-day="2"] tr > :nth-child(4),
    table.journal[data-day="3"] tr > :nth-child(5),
    table.journal[data-day="4"] tr > :nth-child(6),
    table.journal[data-day="5"] tr > :nth-child(7),
    table.journal[data-day="6"] tr > :nth-child(8) { display: table-cell; }
    table.journal thead th:first-child { width: 6rem; }
    /* The toolbar wraps onto two rows. */
    .cal-toolbar { flex-wrap: wrap; }
    /* Wide data tables scroll sideways inside their card instead of
     * stretching the page. */
    .content table:not(.journal):not(.seatgrid) { display: block; overflow-x: auto; }
}

/* ---------- Keyboard focus & skip link ---------- */
/* Pico's focus halo is a faint 28% tint; a solid outline is visible on every
 * background (including the filled current-page pill). */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--pico-primary);
    outline-offset: 2px;
}
.mainnav a[aria-current="page"]:focus-visible { outline-color: var(--pico-color); }
.skip-link {
    position: absolute;
    left: 0.75rem;
    top: -3rem;
    z-index: 100;
    padding: 0.5rem 0.9rem;
    border-radius: var(--pico-border-radius);
    background: var(--pico-primary-background);
    color: var(--pico-primary-inverse);
    font-weight: 600;
    text-decoration: none;
}
.skip-link:focus { top: 0.75rem; }

/* ---------- Panels / cards ---------- */
.panel {
    background: var(--pico-card-background-color);
    border: 1px solid var(--pico-card-border-color, var(--pico-muted-border-color));
    border-radius: var(--pico-border-radius);
    padding: 1rem 1.25rem;
    margin-bottom: var(--space-5);
    box-shadow: var(--pico-card-box-shadow);
}
.panel > :last-child { margin-bottom: 0; }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
/* Setup: current-year badges and the override buttons beside the year title. */
.year-status { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-left: auto; }
.year-status button { width: auto; margin: 0; padding: 0.3rem 0.8rem; font-size: 0.85rem; }
/* Editable title: a text input dressed as the panel's h2. It reads as a plain
 * heading and reveals that it is editable only on hover (dashed underline) and
 * focus (the usual focus ring). `form.… input[type="text"]` (0,2,2) must outrank
 * the compact control rule further down (`input:not(…):not(…)`, 0,2,1), or the
 * title shrinks to control size. */
.title-edit { margin: 0; min-width: 0; flex: 1; }
form.title-edit input[type="text"] {
    font-family: var(--font-head);
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--pico-h2-color);
    width: auto;
    max-width: 100%;
    field-sizing: content;
    min-width: 4ch;
    height: auto;
    margin: 0;
    padding: 0.1rem 0.3rem;
    margin-left: -0.3rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--pico-border-radius);
    box-shadow: none;
}
/* Page-level variant: the class page's title replaces its h1. */
.title-edit-h1 { margin-bottom: var(--space-5); }
form.title-edit-h1 input[type="text"] {
    font-size: var(--text-2xl);
    letter-spacing: -0.02em;
    color: var(--pico-h1-color);
}
form.title-edit input[type="text"]:hover { border-bottom: 1px dashed var(--pico-muted-color); }
form.title-edit input[type="text"]:focus-visible {
    border-color: var(--pico-primary-border);
    box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
}
.auth-card {
    max-width: 24rem;
    margin: 3.5rem auto;
    background: var(--pico-card-background-color);
    border: 1px solid var(--pico-card-border-color, var(--pico-muted-border-color));
    border-radius: var(--pico-border-radius);
    padding: 2rem 2rem 1.75rem;
    box-shadow: var(--pico-card-box-shadow);
    /* Warm accent hairline along the top edge for a branded touch. */
    border-top: 3px solid var(--accent);
}
.auth-card h1 { margin-bottom: 0.25rem; }
.auth-card .auth-sub { color: var(--pico-muted-color); margin-bottom: 1.5rem; font-size: 0.95rem; }
.auth-card button[type="submit"] { margin-top: 0.5rem; }
.auth-card > p:last-child { margin-bottom: 0; text-align: center; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; }
.card {
    display: flex; flex-direction: column; gap: 0.2rem;
    background: var(--pico-card-background-color);
    border: 1px solid var(--pico-card-border-color, var(--pico-muted-border-color));
    border-radius: var(--pico-border-radius);
    padding: 1.25rem; color: var(--pico-color); text-decoration: none;
    box-shadow: var(--pico-card-box-shadow);
    transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}
a.card:hover {
    border-color: color-mix(in srgb, var(--pico-primary) 55%, var(--pico-card-border-color));
    transform: translateY(-2px);
    box-shadow: 0 6px 24px rgba(20, 22, 40, 0.1);
    text-decoration: none;
}
.card .stat {
    font-family: var(--font-head);
    font-size: 2.4rem; font-weight: 600; line-height: 1.05;
    color: var(--accent-text);
    font-variant-numeric: tabular-nums;
}
.card .label { color: var(--pico-muted-color); font-weight: 500; }
.card ul { margin: 0.25rem 0 0; padding-left: 1.1rem; }

/* ---------- Werkzeuge: countdown ----------
 * A wide card with a large display, preset chips, Min:Sek entry and the
 * Start/Pause/Weiter toggle. `.done` (time's up) pulses red, shared with the
 * sidebar's .nav-timer. */
@media (min-width: 720px) { .card-wide { grid-column: span 2; } }
.countdown .cd-display { font-size: 3.4rem; }
.countdown.running .cd-display { color: var(--pico-primary); }
.countdown .cd-done-label { display: none; color: #c0392b; font-weight: 600; }
.countdown.done .cd-done-label { display: inline; }
.countdown.done .cd-display, .nav-timer.done { color: #c0392b; animation: timer-pulse 1s ease-in-out infinite; }
@keyframes timer-pulse { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
    .countdown.done .cd-display, .nav-timer.done { animation: none; }
}
.cd-presets { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.cd-presets .cd-preset {
    width: auto;
    margin: 0;
    padding: 0 0.75rem;
    border: var(--pico-border-width) solid var(--pico-muted-border-color);
    border-radius: 999px;
    background: transparent;
    color: var(--pico-primary);
    font-variant-numeric: tabular-nums;
}
.cd-presets .cd-preset:hover { background: color-mix(in srgb, var(--pico-primary) 10%, transparent); }
.cd-entry { display: flex; align-items: flex-end; gap: 0.4rem; margin-top: 0.5rem; }
.cd-entry label { margin: 0; font-size: var(--text-sm); color: var(--pico-muted-color); }
.cd-entry input { width: 6rem; margin: 0.15rem 0 0; font-variant-numeric: tabular-nums; }
.cd-colon { padding-bottom: 0.45rem; font-weight: 600; }
.cd-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.cd-actions button { width: auto; margin: 0; }

/* The sidebar's live countdown and stopwatch pills (see timers.js), side by
 * side; each is hidden while its timer is idle. */
.nav-timers { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.5rem 0.75rem; }
.nav-timers:not(:has(.nav-timer:not([hidden]))) { display: none; }
.nav-timer {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.7rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--pico-primary) 12%, transparent);
    color: var(--pico-primary);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-decoration: none;
}
.nav-timer[hidden] { display: none; }
.nav-timer.paused { opacity: 0.6; }

/* ---------- Form layouts ---------- */
/* An inline row of controls (Pico makes inputs full-width + spaced; undo that). */
.row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.6rem; margin-bottom: 0.5rem; }
.row :is(input, select, textarea) { width: auto; flex: 1; min-width: 11ch; margin-bottom: 0; }
.row button, .row .secondary { width: auto; margin-bottom: 0; }
.row .grow { flex: 4; }
.row .code { flex: 0 0 auto; font-family: var(--pico-font-family-monospace); white-space: nowrap; }
.narrow { flex: 0 0 7ch !important; min-width: 0 !important; }
/* Date and time pickers keep their natural width (it depends on the locale's
 * format, e.g. "02:00 PM" vs "14:00"): squeezed to the generic minimum above
 * they cut the value off ("10/22/2" for 10/22/2026). A row too long for the
 * line wraps instead. */
.row input:is([type="date"], [type="time"]) { flex: 0 0 auto; width: auto; }

/* A responsive label grid for the bigger forms. */
.grid-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 0 1rem; align-items: end; }
.grid-form > label { margin-bottom: 0.6rem; }
.grid-form .wide { grid-column: 1 / -1; }
/* Caption of a rich-text field. It is a <span>, not a <label> (Quill must not
 * sit inside a label), so mirror Pico's label text here. */
.grid-form > .rich-field { margin-bottom: 0.6rem; }
.rich-label {
    display: block;
    margin-bottom: calc(var(--pico-spacing) * 0.375);
    color: var(--pico-color);
    font-weight: var(--pico-form-label-font-weight, var(--pico-font-weight));
}
/* Lesson editor: the period picker with its pencil toggle, and the from/to
 * pair that toggle reveals. The row repeats an input's bottom margin so it
 * lines up with its neighbours; the fieldset is `display: contents`, so Von
 * and Bis become grid cells like every other field. */
.grid-form > .lesson-time { margin-bottom: 0.6rem; }
/* The period choice ("Doppellektion Nachmittag · 13:30–15:05") and its button
 * need two columns' room. Span two only once the grid has two (2 × 210px +
 * gap): spanning in a one-column grid would add an implicit column. */
.lesson-form { container-type: inline-size; }
@container (min-width: 440px) {
    .grid-form > .lesson-time { grid-column: span 2; }
}
.lesson-time-row { display: flex; gap: 0.5rem; margin-bottom: var(--pico-spacing); font-variant-numeric: tabular-nums; }
.lesson-time-row select { flex: 1; min-width: 0; margin: 0; }
.lesson-time-row .icon-button { flex: none; display: inline-flex; align-items: center; justify-content: center; width: auto; margin: 0; padding: 0 0.85rem; }
/* Pressed look while the deviating from/to inputs are open. */
.lesson-time-row .icon-button[aria-expanded="true"] { background: var(--pico-primary-background); border-color: var(--pico-primary-background); color: var(--pico-primary-inverse); }
.grid-form > .time-pair { display: contents; }
.grid-form > .time-pair[hidden] { display: none; }
.time-pair > label { margin-bottom: 0.6rem; }
.grid-form > button, .grid-form .form-actions { grid-column: 1 / -1; justify-self: start; }
.form-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin-top: 0.25rem; }
.form-actions .secondary, .form-actions button { margin-bottom: 0; }

/* Inline single-button forms (delete/save actions in tables). */
.inline { display: inline; margin: 0; }
/* Pico makes `button[type=submit]` full-width; keep action buttons shrink-wrapped. */
.inline button, .actions button { width: auto; margin: 0; }
td.actions, .actions { display: flex; gap: 0.6rem; align-items: center; justify-content: flex-end; }
.actions a { white-space: nowrap; }

/* Compact, uniform sizing for form controls and every button / button-styled
 * link, so inputs and buttons line up at the same height in a row. (Pico's
 * default 1rem / 1.5-line-height control is a touch tall for dense action rows.)
 * Single-line controls get line-height:1 to match the buttons exactly;
 * textarea keeps a readable multi-line height. */
button, [type="submit"], [type="button"], [type="reset"], [role="button"],
a.secondary,
input:not([type="checkbox"]):not([type="radio"]), select {
    font-size: 0.85rem;
    line-height: 1;
    /* Pin every control to the exact same height (box-sizing is border-box):
     * text box (0.85rem) + Pico's shared vertical padding + border, top and
     * bottom. An explicit value avoids the sub-pixel rounding that content-based
     * `height: auto` produces differently for inputs vs buttons. */
    height: calc(0.85rem + var(--pico-form-element-spacing-vertical) * 2
                 + var(--pico-border-width) * 2);
}
textarea { font-size: 0.85rem; }

/* Links styled as secondary buttons (Pico only styles `button.secondary`). */
a.secondary {
    display: inline-block;
    width: auto;
    margin: 0;
    padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
    border: var(--pico-border-width, 1px) solid var(--pico-secondary-border, var(--pico-secondary));
    border-radius: var(--pico-border-radius);
    color: var(--pico-secondary-inverse, #fff);
    background: var(--pico-secondary-background, var(--pico-secondary));
    text-decoration: none;
}
a.secondary:hover { text-decoration: none; filter: brightness(1.05); }

/* External links from an Ort/URL field: long URLs break inside table cells
 * instead of widening them; on a form, the "Open ↗" link sits after the label. */
.ext-link { overflow-wrap: anywhere; }
.label-link { margin-left: 0.5rem; font-size: var(--text-sm); font-weight: 500; }

/* "Von Vorlektion übernehmen" review page: per conflicting field, current
 * and previous content side by side (stacked on narrow screens), then the
 * overwrite / append / keep choice. */
.carry-field { margin-bottom: 1.5rem; }
.carry-field legend { font-weight: 600; }
.carry-compare {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}
.carry-caption { display: block; margin-bottom: 0.25rem; font-size: var(--text-sm); color: var(--pico-muted-color); }
.carry-box {
    padding: 0.5rem 0.75rem;
    border: var(--pico-border-width) solid var(--pico-muted-border-color);
    border-radius: var(--pico-border-radius);
    font-size: var(--text-sm);
    max-height: 16rem;
    overflow-y: auto;
}
.carry-box > :last-child { margin-bottom: 0; }
.carry-phase + .carry-phase { margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px dashed var(--pico-muted-border-color); }
.carry-phase small { display: block; color: var(--pico-muted-color); }
.carry-choices { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; }
.carry-choices label { margin: 0; }
.chip-inline {
    display: inline-block;
    margin: 0 0.25rem 0.25rem 0;
    padding: 0.1rem 0.6rem;
    border-radius: 999px;
    background: var(--pico-card-sectioning-background-color);
    font-size: var(--text-sm);
}

/* Destructive actions (Pico has no red variant). */
button.danger, .danger {
    --pico-background-color: #c0392b;
    --pico-border-color: #c0392b;
    --pico-color: #fff;
}
[data-theme="dark"] button.danger, [data-theme="dark"] .danger {
    --pico-background-color: #e06c5a;
    --pico-border-color: #e06c5a;
    --pico-color: #17110f;
}
/* Journal: the lesson's delete "×" only appears on hover/focus (where hover
 * exists), so it is not a stray target next to every title. */
@media (hover: hover) {
    table.journal .journal-remove { opacity: 0; transition: opacity 0.15s ease; }
    table.journal td:hover .journal-remove,
    table.journal .journal-remove:focus-within { opacity: 1; }
}
button.linkish { width: auto; margin: 0; padding: 0 0.3rem; background: transparent; border: none; color: #c0392b; font-weight: 700; }

/* ---------- Chips & misc ---------- */
.chips { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0; margin: 0.5rem 0; }
.chips li { background: var(--pico-secondary-background, var(--pico-muted-border-color)); color: var(--pico-secondary-inverse, var(--pico-color)); border-radius: 999px; padding: 0.15rem 0.7rem; font-size: 0.85rem; }
.muted { color: var(--pico-muted-color); }
/* Error pages (error.rs): a calm card with a way back. */
.error-page { max-width: 36rem; margin: 2rem auto; }
.error-detail { margin: var(--space-4) 0; color: var(--pico-muted-color); font-size: var(--text-sm); }
.error-page .form-actions button, .error-page .form-actions a { width: auto; margin: 0; }
/* An empty list or missing prerequisite: explanation plus its one action. */
.empty-state { padding: var(--space-5) 0; text-align: center; }
.empty-state p { margin-bottom: var(--space-4); color: var(--pico-muted-color); }
.empty-state [role="button"] { width: auto; }
/* The shown school year is not the one running by semester dates. */
.year-notice { margin: -0.5rem 0 1rem; color: var(--accent-text); font-weight: 500; }
.error { color: #c0392b; font-weight: 500; }

/* Read-only banner shown to users without a valid subscription. */
.view-only-banner {
    margin-bottom: 1rem;
    padding: 0.6rem 1rem;
    border-radius: var(--pico-border-radius);
    background: #fff3cd;
    border: 1px solid #ffe08a;
}
.view-only-banner a { color: #7a5b00; font-weight: 600; text-decoration: none; }

/* Subscription status + admin active/expired markers. */
.status-ok { color: #2e7d32; font-weight: 500; }
.status-warn { color: #c0392b; font-weight: 500; }
.badge { display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.5rem;
    border-radius: 999px; font-size: 0.8em; }
.badge.ok { background: #e6f4ea; color: #2e7d32; }
.badge.warn { background: #fdecea; color: #c0392b; }
label.checkbox { display: inline-flex; align-items: center; gap: 0.35rem; margin: 0; }
/* Pico draws checkboxes at a fixed size; a `width: auto` here would collapse
 * that drawn box to a sliver. */
label.checkbox input[type="checkbox"] { flex: none; width: 1.25em; min-width: 0; height: 1.25em; margin: 0; }
/* Student forms: the class checkboxes wrap as a row of chips-like options. */
.student-classes { display: flex; flex-wrap: wrap; gap: 0.5rem 1.25rem; margin-bottom: var(--pico-spacing); }
.student-classes legend { margin-bottom: 0.4rem; line-height: 1.3; }
/* The hint sits on its own line under the year (it used to overlap it). */
.student-classes legend small { display: block; margin-top: 0.15rem; line-height: 1.3; }

/* ---------- Journal toolbar ----------
 * Calendar-app layout on one row: Today, a segmented prev/next group, the week
 * title (opens the date picker), actions pushed right. Quiet outline buttons so
 * the title carries the visual weight.
 * --cal-text captures the page text colour here, on a plain div: Pico
 * redefines --pico-color on buttons (inverse) and links (primary), so using it
 * inside them would render white-on-white / link-blue text. */
.day-switch, .series-nav { --cal-text: var(--pico-color); }
.cal-toolbar {
    --cal-text: var(--pico-color);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin-bottom: 1rem;
}
.cal-toolbar form { margin: 0; }
.cal-toolbar .cal-btn,
.day-switch .cal-btn,
.series-nav .cal-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: auto;
    /* Same box as every other control (see the global sizing rule, which
     * only reaches button-like elements, not these links). */
    height: calc(0.85rem + var(--pico-form-element-spacing-vertical) * 2
                 + var(--pico-border-width) * 2);
    margin: 0;
    padding: 0 0.85rem;
    border: var(--pico-border-width) solid var(--pico-muted-border-color);
    border-radius: var(--pico-border-radius);
    background: var(--pico-card-background-color);
    color: var(--cal-text);
    font-size: 0.85rem;
    line-height: 1;
    font-weight: 500;
    text-decoration: none;
    box-shadow: none;
}
.cal-toolbar .cal-btn:hover,
.cal-toolbar .cal-btn:focus-visible,
.day-switch .cal-btn:hover,
.series-nav .cal-btn:hover {
    background: var(--pico-card-sectioning-background-color);
    border-color: var(--pico-secondary-border, var(--pico-muted-border-color));
    color: var(--cal-text);
    text-decoration: none;
}
.cal-toolbar svg {
    width: 1.05rem;
    height: 1.05rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
/* Segmented group: shared borders, rounded only at the outer ends. */
.cal-nav { display: inline-flex; }
.cal-nav .cal-btn { padding: 0 0.55rem; border-radius: 0; }
.cal-nav .cal-btn + .cal-btn { margin-left: calc(var(--pico-border-width) * -1); }
.cal-nav .cal-btn:first-child { border-radius: var(--pico-border-radius) 0 0 var(--pico-border-radius); }
.cal-nav .cal-btn:last-child { border-radius: 0 var(--pico-border-radius) var(--pico-border-radius) 0; }
.cal-nav .cal-btn:hover, .cal-nav .cal-btn:focus-visible { position: relative; z-index: 1; }
/* The week title: a ghost button; the hidden date input sits under it so the
 * native picker anchors there. */
.cal-jump { position: relative; }
.cal-toolbar .cal-title {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0.3rem 0.5rem;
    border: 0;
    border-radius: var(--pico-border-radius);
    background: transparent;
    color: var(--cal-text);
    font-size: 1.15rem;
    line-height: 1.2;
    box-shadow: none;
}
.cal-toolbar .cal-title:hover,
.cal-toolbar .cal-title:focus-visible { background: var(--pico-card-sectioning-background-color); }
.cal-week { font-weight: 700; }
.cal-range { color: var(--pico-muted-color); font-variant-numeric: tabular-nums; }
.cal-title svg { align-self: center; color: var(--pico-muted-color); }
.cal-toolbar input.cal-picker {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}
.cal-toolbar .cal-actions { margin-left: auto; }

/* ---------- Journal & seating grids ---------- */
table.journal, table.seatgrid { table-layout: fixed; }
table.journal th, table.journal td,
table.seatgrid td {
    border: 1px solid var(--pico-muted-border-color);
    vertical-align: top;
    padding: 0.4rem;
}
table.journal thead th, table.journal tbody th {
    background: var(--pico-card-sectioning-background-color);
}
table.journal td { height: 3.4rem; }
/* Row headers (period, "Tagesnotizen", ...): wide enough for the German
 * labels, hyphenated rather than broken mid-word. */
table.journal thead th:first-child { width: 7.5rem; }
table.journal tbody th { hyphens: auto; overflow-wrap: normal; word-break: normal; }
/* Drag and drop: the tile being moved fades, free cells show where it can go. */
table.journal td[draggable="true"] { cursor: grab; }
table.journal td.is-dragging { opacity: 0.45; }
table.journal.is-dragging td[data-drop-date] { outline: 1px dashed var(--pico-muted-border-color); outline-offset: -4px; }
table.journal td.is-drop-target { background: color-mix(in srgb, var(--pico-primary) 16%, transparent); outline: 2px dashed var(--pico-primary); outline-offset: -4px; }
/* A lesson tile: title, prepared dot, then the topic as a quiet second line. */
/* Titles hyphenate at syllables (German, from <html lang>) instead of being
 * cut mid-word in the narrow day columns. */
table.journal .cell-title {
    margin-right: 0.25rem;
    font-size: 0.95rem;
    line-height: 1.3;
    overflow-wrap: normal;
    word-break: normal;
    hyphens: auto;
}
/* Sits in the tile's top-right corner, so it never wraps onto its own line. */
.prep-dot {
    float: right;
    margin: 0.35rem 0 0 0.25rem;
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    border: 1.5px solid var(--pico-muted-color);
    vertical-align: middle;
}
.prep-dot.is-prepared { background: var(--pico-ins-color); border-color: var(--pico-ins-color); }
table.journal .cell-topic {
    display: block;
    margin-top: 0.15rem;
    line-height: 1.3;
    font-size: var(--text-sm);
}
/* Weekend columns (Sa, So: children 7–8 after the time column): a faint
 * tint so the working week stays the visual focus. :where() keeps the cell
 * rule at minimal specificity, so lesson tiles, subject colours, hover and
 * holidays below all still win over it. */
table.journal thead th.weekend,
table.journal :where(td:nth-child(n+7)) {
    background: color-mix(in srgb, var(--pico-muted-color) 7%, transparent);
}
/* Today's column header: accent text and a bar on top, as calendar apps mark it. */
table.journal thead th.today {
    color: var(--pico-primary);
    box-shadow: inset 0 3px 0 var(--pico-primary);
}
table.journal thead th.today small { color: var(--pico-primary); font-weight: 600; }
table.journal small { color: var(--pico-muted-color); }
/* Occupied slots (cells containing a lesson link) read as filled tiles with a
 * primary accent edge; empty slots stay quiet until hovered. Needs :has(). */
table.journal td:has(a) {
    background: color-mix(in srgb, var(--pico-primary) 9%, transparent);
    border-left: 3px solid var(--pico-primary-background);
}
table.journal td:has(a) a { font-weight: 500; }
/* When the lesson's subject has a colour, it replaces the generic primary
 * accent (tint + left edge) so the journal is scannable at a glance. Placed
 * after the rule above to win at equal specificity. --subject-color is set
 * inline from a server-validated #RRGGBB value. */
table.journal td.has-subject {
    background: color-mix(in srgb, var(--subject-color) 15%, transparent);
    border-left: 3px solid var(--subject-color);
}
table.journal td:has(.cell-place):hover {
    background: color-mix(in srgb, var(--pico-primary) 5%, transparent);
}
table.seatgrid td { height: 3rem; text-align: center; vertical-align: middle; border-style: dashed; }
/* Empty seats: faint dashed placeholder; occupied seats: solid filled chip. */
table.seatgrid td:empty::before { content: "·"; color: var(--pico-muted-color); }
table.seatgrid td:not(:empty) {
    border-style: solid;
    font-weight: 500;
    background: color-mix(in srgb, var(--pico-primary) 8%, transparent);
}
/* A lesson whose own from/to was edited off its period slot: flag it below
 * the title in the accent colour so the deviation stands out. */
small.alt-time {
    display: block;
    margin-top: 0.1rem;
    color: var(--accent-text);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    cursor: help;
}
.cell-place select { width: 100%; margin: 0; border: none; background: transparent; }
/* The "+" placeholder in empty slots: a subtle, centered add affordance. */
.cell-place select:invalid { color: var(--pico-muted-color); text-align: center; }

/* Day information rows above the lessons (holidays, day notes, absences,
 * birthdays): compact, auto height, and never styled as lesson tiles even
 * when a cell holds links (the absence list links to each student). */
table.journal tr.day-info td {
    height: auto;
    background: none;
    border-left: 1px solid var(--pico-muted-border-color);
    font-size: var(--text-sm);
}
table.journal tr.day-info td a { font-weight: 400; }
table.journal tr.day-info td,
table.journal tr.day-info textarea { hyphens: auto; overflow-wrap: normal; word-break: normal; }
table.journal tr.day-info td:nth-child(n+7) {
    background: color-mix(in srgb, var(--pico-muted-color) 7%, transparent);
}
/* A heavier rule separates the day rows from the lesson grid below. */
/* A heavier rule between the day rows and the lesson grid: on the first
 * lesson row, since which info rows are shown varies from week to week. */
table.journal tr.day-info + tr:not(.day-info) > * { border-top-width: 3px; }
/* The info rows can be folded away (journal.js remembers the choice). */
table.journal.infos-hidden tr.day-info { display: none; }
table.journal tr.day-info td.is-holiday {
    background: color-mix(in srgb, var(--accent-text) 12%, transparent);
}
/* Absenzen cell: the whole cell opens the day's "record an absence" dialog. */
table.journal tr.day-info td.absence-cell:has(dialog) { cursor: pointer; }
table.journal tr.day-info td.absence-cell:has(dialog):hover {
    background: color-mix(in srgb, var(--pico-primary) 5%, transparent);
}
button.absence-add {
    width: 100%;
    height: auto;
    margin: 0;
    padding: 0.15rem 0.3rem;
    border: 1px dashed var(--pico-muted-border-color);
    background: transparent;
    color: var(--pico-muted-color);
    font-size: var(--text-sm);
}
button.absence-add:hover { color: var(--pico-primary); border-color: var(--pico-primary); }
.absence-dialog { cursor: auto; font-size: var(--text-base); }
.absence-dialog article { width: min(28rem, 100%); }
.absence-dialog h3 { margin-bottom: var(--space-5); }
.absence-halves { display: flex; gap: 1.5rem; }
.absence-dialog footer { display: flex; justify-content: flex-end; gap: 0.6rem; }
.absence-dialog footer button { width: auto; margin: 0; }
.day-tag { display: block; font-weight: 600; color: var(--accent-text); }
.day-list { list-style: none; margin: 0 0 0.25rem; padding: 0; }
.day-list li { margin: 0; padding: 0; list-style: none; }
.day-note { margin: 0; }
.day-note textarea {
    margin: 0 0 0.25rem;
    padding: 0.25rem 0.4rem;
    min-height: 2.6rem;
    font-size: var(--text-sm);
    resize: vertical;
}
.day-note button { width: 100%; margin: 0; padding: 0.15rem 0.4rem; font-size: var(--text-sm); }

.phase { border-left: 3px solid var(--pico-muted-border-color); padding-left: 0.75rem; }

/* ---------- Table polish (Pico owns the base; add scannability) ---------- */
/* Uppercase, muted headers read as column labels rather than heavy text. */
:where(.panel, .content) table th {
    font-size: 0.76rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--pico-muted-color);
    font-weight: 600;
}
/* Row hover aids left-to-right tracking in long student/grade lists. */
:where(.panel, .content) tbody tr {
    transition: background-color 0.1s ease;
}
:where(.panel, .content) tbody tr:hover {
    background: color-mix(in srgb, var(--pico-primary) 6%, transparent);
}

/* ---------- Course folders (lesson list, grouped by course) ---------- */
.course-folder {
    border: 1px solid var(--pico-card-border-color, var(--pico-muted-border-color));
    border-radius: var(--pico-border-radius);
    background: var(--pico-card-background-color);
    box-shadow: var(--pico-card-box-shadow);
    margin-bottom: 0.7rem;
    overflow: hidden;
}
.course-folder > summary {
    cursor: pointer;
    padding: 0.65rem 0.95rem;
    font-family: var(--font-head);
    font-weight: 600;
}
.course-folder > summary:hover {
    background: color-mix(in srgb, var(--pico-primary) 6%, transparent);
}
.course-folder[open] > summary {
    border-bottom: 1px solid var(--pico-muted-border-color);
}
/* Lesson count badge, pushed to the right edge of the folder header. */
.folder-count {
    float: right;
    font-family: var(--font-body);
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--pico-muted-color);
    background: color-mix(in srgb, var(--pico-primary) 12%, transparent);
    border-radius: 999px;
    padding: 0.05rem 0.55rem;
}
.course-folder table { margin: 0; }
/* Lesson rows are a flex list (not a table) so every course folder lays out
 * identically: title fills the left, then the date, a small gap, and the
 * edit/delete actions pinned to the right — with the date right-aligned in a
 * fixed slot so dates line up vertically across folders. */
.lesson-list { list-style: none; margin: 0; padding: 0; }
.lesson-list > li { margin: 0; list-style: none; border-top: 1px solid var(--pico-muted-border-color); }
.lesson-list > li:first-child { border-top: none; }
/* Each row is one link: the whole width opens the lesson. */
.lesson-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.95rem;
    color: var(--pico-color);
    text-decoration: none;
}
.lesson-row:hover { background: color-mix(in srgb, var(--pico-primary) 7%, transparent); text-decoration: none; }
.lesson-row .lesson-title { color: var(--pico-primary); font-weight: 500; }
.lesson-row.is-past .lesson-title { color: var(--pico-muted-color); font-weight: 400; }
.lesson-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* While searching: the hit's context under the title, one muted line. */
.lesson-excerpt {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--pico-muted-color);
    font-size: var(--text-sm);
    font-weight: 400;
}
.lesson-date {
    flex: 0 0 auto;
    min-width: 6rem;
    text-align: right;
    white-space: nowrap;
    color: var(--pico-muted-color);
    font-variant-numeric: tabular-nums;
}
/* Lists whose first link opens the row: the whole row reacts to hover. */
table.link-rows tbody tr:hover { background: color-mix(in srgb, var(--pico-primary) 6%, transparent); }
th.select-col, td.select-col { width: 2.5rem; }
td.select-col input, th.select-col input { margin: 0; }
/* Bulk toolbar under the students table, shown while rows are ticked. */
.bulk-bar {
    position: sticky;
    bottom: var(--space-4);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-5);
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--pico-border-radius);
    background: var(--pico-card-background-color);
    border: 1px solid var(--pico-primary-border);
    box-shadow: 0 8px 24px rgb(0 0 0 / 0.12);
}
.bulk-action { display: inline-flex; align-items: center; gap: var(--space-2); }
.bulk-action :is(select, input, button) { width: auto; margin: 0; }
/* Type-to-filter box above a list (filter.js). */
input.list-filter { max-width: 24rem; margin-bottom: var(--space-4); }
/* Numeric cells align on the decimal for tidy grade columns. */
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Small helpers used on the setup page. */
.small { font-size: 0.8rem; }
.empty {
    color: var(--pico-muted-color);
    text-align: center;
    padding: var(--space-5);
    border: 1px dashed var(--pico-muted-border-color);
    border-radius: var(--pico-border-radius);
}

/* ---------- Flash toast (transient success feedback; see flash.js) ---------- */
.toast {
    position: fixed;
    bottom: var(--space-6);
    left: 50%;
    transform: translateX(-50%);
    z-index: 30;
    background: var(--pico-primary-background);
    color: var(--pico-primary-inverse);
    padding: var(--space-2) var(--space-5);
    border-radius: var(--pico-border-radius);
    box-shadow: 0 6px 24px rgba(20, 22, 40, 0.18);
    font-size: var(--text-sm);
    font-weight: 600;
    opacity: 1;
    transition: opacity 0.4s ease;
}
.toast { display: flex; align-items: center; gap: 0.6rem; }
button.toast-close {
    width: auto;
    height: auto;
    margin: 0;
    padding: 0 0.25rem;
    border: none;
    background: transparent;
    color: inherit;
    font-size: 1.1rem;
    line-height: 1;
    opacity: 0.8;
}
button.toast-close:hover { opacity: 1; }
.toast-hide { opacity: 0; }
.toast-error { background: var(--pico-del-color); color: #fff; }

/* ---------- Row autosave (see autosave.js) ---------- */
/* A row with unsaved edits gets a quiet accent bar; one whose save failed a
 * red one, and stays dirty so leaving it again retries. */
form[data-autosave-row] {
    /* The bar sits in the gutter (negative margin), so rows stay aligned with
     * the "add" row below them. */
    border-left: 3px solid transparent;
    padding-left: 0.4rem;
    margin-left: calc(-0.4rem - 3px);
    transition: border-color 0.2s ease;
}
form[data-autosave-row].is-dirty { border-left-color: var(--pico-primary-border); }
form[data-autosave-row].is-error { border-left-color: var(--pico-del-color); }

/* ---------- Student photos ---------- */
/* ---------- Student page: profile header, sidebar, field cards ---------- */
.crumb { margin-bottom: var(--space-3); font-size: var(--text-sm); }
.crumb a { text-decoration: none; }
.profile-head {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    margin-bottom: var(--space-6);
}
.profile-head h1 { margin: 0 0 var(--space-2); }
.profile-id { min-width: 0; }
/* The photo, or the initials in the accent tint when there is none. */
.profile-avatar {
    flex: 0 0 auto;
    width: 5.5rem;
    height: 5.5rem;
    border-radius: 50%;
    object-fit: cover;
    box-shadow: 0 0 0 3px var(--pico-card-background-color), 0 0 0 5px var(--accent);
}
.profile-initials {
    display: grid;
    place-items: center;
    background: color-mix(in srgb, var(--accent) 18%, var(--pico-card-background-color));
    color: var(--accent-text);
    font-family: var(--font-head);
    font-size: 2rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.profile-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin: 0;
    color: var(--pico-muted-color);
    font-size: var(--text-sm);
}
/* The "Heimweg" link (search.ch) at the end of the header facts. */
.profile-meta .profile-link { font-weight: 600; text-decoration: none; }
.profile-meta .profile-link.muted { color: var(--pico-muted-color); font-weight: 400; text-decoration: underline; }
/* Theme-aware status colours (the global .badge ones are tuned for light). */
.profile-meta .badge { margin-left: 0; padding: 0.1rem 0.6rem; font-size: var(--text-sm); }
.profile-meta .badge.ok {
    background: color-mix(in srgb, var(--pico-ins-color) 15%, transparent);
    color: var(--pico-ins-color);
}
.profile-meta .badge.warn {
    background: color-mix(in srgb, var(--pico-del-color) 15%, transparent);
    color: var(--pico-del-color);
}
.profile-meta .badge:not(.ok):not(.warn) {
    background: color-mix(in srgb, var(--pico-muted-color) 15%, transparent);
}
.chip {
    padding: 0.1rem 0.65rem;
    border-radius: 999px;
    background: var(--pico-primary);
    color: var(--pico-primary-inverse);
    font-weight: 600;
}
.chip-quiet {
    background: color-mix(in srgb, var(--pico-primary) 12%, transparent);
    color: var(--pico-primary);
}
/* Sidebar of facts beside the field cards; one column on narrow screens. */
.profile-grid {
    display: grid;
    grid-template-columns: minmax(15rem, 18rem) minmax(0, 1fr);
    gap: var(--space-5);
    align-items: start;
}
@media (max-width: 900px) {
    .profile-grid { grid-template-columns: minmax(0, 1fr); }
    /* On a phone the fields come first; the facts follow below. The contact
     * card would repeat the Kontakt fields right above it. */
    .profile-aside { order: 2; position: static; }
    .profile-aside .contact-card { display: none; }
    .profile-head { gap: var(--space-4); }
    .profile-avatar { width: 4rem; height: 4rem; }
    .profile-initials { font-size: 1.5rem; }
}
.profile-aside { position: sticky; top: var(--space-5); }
.profile-aside h2, .field-card h2 { font-size: var(--text-lg); margin-bottom: var(--space-4); }
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.stat {
    padding: var(--space-3);
    border-radius: var(--pico-border-radius);
    background: color-mix(in srgb, var(--pico-muted-color) 8%, transparent);
}
.stat strong {
    display: block;
    font-family: var(--font-head);
    font-size: 1.75rem;
    line-height: 1.1;
}
.stat span { color: var(--pico-muted-color); font-size: var(--text-sm); }
.stat-alert { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.stat-alert strong { color: var(--accent-text); }
.stat-unit { margin: var(--space-2) 0 var(--space-4); color: var(--pico-muted-color); font-size: var(--text-sm); }
.card-link { font-size: var(--text-sm); font-weight: 600; text-decoration: none; }
.contact-list { margin: 0; }
.contact-list dt { color: var(--pico-muted-color); font-size: var(--text-sm); font-weight: 400; }
.contact-list dd { margin: 0 0 var(--space-3); overflow-wrap: anywhere; }
.contact-list a { text-decoration: none; }
.photo-form { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-2); }
/* `height: auto` undoes the compact control height, which clipped the
 * browser's "choose file" button. */
.photo-form input[type="file"] { height: auto; margin: 0; padding: 0.3rem; font-size: var(--text-sm); }
.photo-form button { width: 100%; margin: 0; }
/* The field cards form one autosave "row"; its gutter bar would run the full
 * height, so the state shows in the hint line instead. */
form.profile-main[data-autosave-row] { border-left: 0; padding-left: 0; margin-left: 0; }
.field-card textarea { margin: 0; }
/* Denser than the default form: three columns where they fit, and small
 * muted labels so the values carry the weight. */
.field-card .grid-form { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.field-card .grid-form > label {
    margin-bottom: var(--space-3);
    color: var(--pico-muted-color);
    font-size: var(--text-sm);
}
.field-card .grid-form > label > input { margin-top: 0.2rem; color: var(--pico-color); }
/* Email addresses need room; only where the card has 3 columns (on a phone
 * a span would add an implicit column). */
@media (min-width: 1100px) {
    .field-card .grid-form > .span-2 { grid-column: span 2; }
}
/* Lesson symbols (Spezialsymbole, src/symbols.rs): inline SVG icons sized to
 * the text around them. */
.symbol-icon { height: 1.15em; width: auto; vertical-align: -0.2em; flex: none; }
.lesson-title-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.lesson-title-row h1 { margin: 0; }
/* The editor's symbol button: a dashed "+ Symbol" until one is chosen. */
button.symbol-pick {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    width: auto;
    margin: 0;
    padding: 0.2rem 0.6rem;
    border: 1px dashed var(--pico-muted-border-color);
    background: transparent;
    color: var(--pico-muted-color);
    font-size: var(--text-sm);
    line-height: 1;
}
button.symbol-pick:hover { border-color: var(--pico-primary); color: var(--pico-primary); }
button.symbol-pick.has-symbol { padding: 0.15rem; border-color: transparent; }
button.symbol-pick .symbol-icon { height: 2rem; vertical-align: middle; }
button.symbol-pick.has-symbol .symbol-placeholder { display: none; }
.symbol-dialog article { width: min(30rem, 100%); }
.symbol-row { display: flex; flex-wrap: wrap; gap: 0.3rem; padding: 0.3rem 0; border-bottom: 1px solid var(--pico-muted-border-color); }
.symbol-row:last-child { border-bottom: 0; }
button.symbol-choice {
    width: auto;
    margin: 0;
    padding: 0.2rem;
    border: 2px solid transparent;
    border-radius: 0.4rem;
    background: transparent;
    line-height: 0;
}
button.symbol-choice:hover { background: color-mix(in srgb, var(--pico-primary) 10%, transparent); }
button.symbol-choice[aria-pressed="true"] { border-color: var(--pico-primary); }
button.symbol-choice .symbol-icon { height: 1.6rem; }
.symbol-dialog footer { margin-top: var(--space-4); }
.cell-symbol { margin-left: 0.25rem; white-space: nowrap; }
.row-symbol { margin-right: 0.4rem; }

/* Lesson editor: homework from earlier lessons that is due today, on top. */
.due-homework {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-left: 3px solid var(--accent);
    border-radius: 0.4rem;
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.due-homework h2 { margin: 0 0 var(--space-2); font-size: var(--text-base); }
.due-homework ul { margin: 0; padding: 0; list-style: none; }
.due-homework li { margin: 0; padding: 0; list-style: none; }
.due-homework li + li { margin-top: var(--space-2); }
.due-homework-text { margin: 0; white-space: pre-line; }
.due-homework-from { color: var(--pico-muted-color); font-size: var(--text-sm); }
.homework-due small { display: block; margin-top: 0.2rem; color: var(--pico-muted-color); }
.autosave-hint { margin: 0 0 var(--space-3); color: var(--pico-muted-color); font-size: var(--text-sm); }
.autosave-hint .hint-error { display: none; }
.profile-main.is-error .autosave-hint { color: var(--pico-del-color); font-weight: 600; }
.profile-main.is-error .hint-ok { display: none; }
.profile-main.is-error .hint-error { display: inline; }
/* Subject page: colour swatch before the name; the form is the main column
 * and the class links sit in the sidebar on the right. */
.subject-swatch {
    display: inline-block;
    width: 0.8em;
    height: 0.8em;
    margin-right: 0.4em;
    border-radius: 0.2em;
    background: var(--subject-color);
    vertical-align: 0.05em;
}
.profile-grid-end { grid-template-columns: minmax(0, 1fr) minmax(15rem, 18rem); }
@media (max-width: 900px) { .profile-grid-end { grid-template-columns: minmax(0, 1fr); } }
.chip-list li { display: inline-flex; align-items: center; gap: 0.2rem; }
.chip-list form { margin: 0; }
button.chip-remove {
    width: auto;
    height: auto;
    margin: 0;
    padding: 0 0.15rem;
    border: none;
    background: transparent;
    color: inherit;
    line-height: 1;
    opacity: 0.6;
}
button.chip-remove:hover { opacity: 1; color: var(--pico-del-color); }
/* Absences: one autosave form per row on a shared column grid. */
.abs-row {
    display: grid;
    grid-template-columns: 9.5rem 3.5rem 3.5rem minmax(8rem, 1fr) 6rem 4rem 2rem;
    align-items: center;
    gap: var(--space-3);
    padding: 0.35rem 0;
    border-top: 1px solid var(--pico-muted-border-color);
}
.abs-row > * { margin: 0; }
.abs-row input[type="checkbox"] { justify-self: center; }
.abs-head { border-top: none; color: var(--pico-muted-color); font-size: var(--text-sm); font-weight: 600; }
.abs-head span:nth-child(n+2):not(:nth-child(4)) { text-align: center; }
form.abs-row[data-autosave-row] { margin-left: 0; padding-left: 0; border-left: 0; }
form.abs-row.is-error { background: color-mix(in srgb, var(--pico-del-color) 8%, transparent); }
.stat span::first-letter { text-transform: uppercase; }
.abs-summary .stats { max-width: 22rem; }
@media (max-width: 700px) {
    .abs-head { display: none; }
    .abs-row { grid-template-columns: 1fr auto auto auto; }
    .abs-row input[type="text"] { grid-column: 1 / -1; }
}
/* ---------- Kontrollen (checklists.html, student_checklists.html) ---------- */
.checklist-grid {
    display: grid;
    grid-template-columns: minmax(15rem, 19rem) minmax(0, 1fr);
    gap: var(--space-5);
    align-items: start;
}
@media (max-width: 900px) { .checklist-grid { grid-template-columns: minmax(0, 1fr); } }
.checklist-list { list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.checklist-list li { margin: 0; padding: 0; list-style: none; }
.checklist-link {
    display: grid;
    gap: 0.05rem;
    padding: 0.45rem 0.6rem;
    border-radius: 0.4rem;
    color: var(--pico-color);
    text-decoration: none;
}
.checklist-link:hover { background: color-mix(in srgb, var(--pico-primary) 7%, transparent); text-decoration: none; }
.checklist-link.is-selected { background: color-mix(in srgb, var(--pico-primary) 14%, transparent); }
.checklist-subject { color: var(--pico-muted-color); font-size: var(--text-sm); }
.checklist-title { font-weight: 600; }
.checklist-meta { color: var(--pico-muted-color); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.checklist-marked { color: var(--accent-text); font-weight: 600; }
.checklist-overdue { color: var(--pico-del-color); font-weight: 600; }
/* Journal: a Kontrolle due that day; muted once everyone is recorded. */
.due-check:not(.is-complete) a { font-weight: 600; }
.due-check:not(.is-complete) small { color: var(--accent-text); font-weight: 600; }
.due-check.is-complete, .due-check.is-complete a { color: var(--pico-muted-color); }
.checklist-new summary { color: var(--pico-primary); font-weight: 600; cursor: pointer; }
.checklist-new form { margin-top: var(--space-3); }
.checklist-new button { width: auto; }
.checklist-head { grid-template-columns: minmax(0, 2fr) minmax(10rem, 1fr) minmax(9rem, 1fr); }
@media (max-width: 760px) { .checklist-head { grid-template-columns: minmax(0, 1fr); } }
.checklist-fill { align-items: center; }
.checklist-fill label { flex: none; margin: 0; color: var(--pico-muted-color); font-size: var(--text-sm); }
form.checklist-fill input[type="text"] { flex: 0 1 14rem; }

/* One autosaving form per row, on a shared grid. The layout follows the
 * table's own width (a container query): one line per student where there is
 * room, else name + Markieren above Inhalt + Bemerkung, and on a phone three
 * lines. */
.check-table { display: grid; container-type: inline-size; }
.check-row {
    display: grid;
    grid-template-columns: 2rem minmax(0, 1fr) auto;
    grid-template-areas: "num name mark" "num content content" "num note note";
    gap: 0.35rem 0.5rem;
    align-items: center;
    margin: 0;
    padding: 0.35rem 0.4rem;
    border-bottom: 1px solid var(--pico-muted-border-color);
}
.check-row.student-check-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name mark" "content content" "note note";
}
.check-num { grid-area: num; align-self: start; color: var(--pico-muted-color); text-align: right; font-variant-numeric: tabular-nums; }
.check-name { grid-area: name; min-width: 0; overflow-wrap: anywhere; }
.check-content { grid-area: content; display: flex; align-items: center; gap: 0.35rem; min-width: 0; }
form.check-row input[type="checkbox"] { grid-area: mark; margin: 0 auto; }
form.check-row > input[name="note"] { grid-area: note; }
.check-head { display: none; color: var(--pico-muted-color); font-size: var(--text-sm); font-weight: 600; }
@container (min-width: 520px) {
    .check-row {
        grid-template-columns: 2rem minmax(0, 1.7fr) minmax(0, 1fr) auto;
        grid-template-areas: "num name name mark" "num content note note";
    }
    .check-row.student-check-row {
        grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) auto;
        grid-template-areas: "name name mark" "content note note";
    }
}
@container (min-width: 760px) {
    .check-row {
        grid-template-columns: 2rem minmax(8rem, 1fr) minmax(17rem, 1.8fr) 5.5rem minmax(8rem, 1.2fr);
        grid-template-areas: "num name content mark note";
    }
    .check-row.student-check-row {
        grid-template-columns: minmax(11rem, 1.4fr) minmax(17rem, 1.8fr) 5.5rem minmax(8rem, 1.2fr);
        grid-template-areas: "name content mark note";
    }
    .check-head { display: grid; }
    .check-head > span { grid-area: auto; }
}
/* Marked for follow-up: an accent tint, like the old planner's yellow rows. */
.check-row.is-marked { background: color-mix(in srgb, var(--accent) 22%, transparent); }
form.check-row input[type="text"] { margin: 0; padding: 0.3rem 0.5rem; }
.check-meta { display: block; color: var(--pico-muted-color); }
form.check-row .check-content input[type="text"] { flex: 1 1 5rem; min-width: 4rem; }
.check-quick { display: inline-flex; flex: none; gap: 0.2rem; }
/* Pico gives a button its own --pico-color (white on the primary fill), so
 * the unpressed pills take the row's text colour instead. */
.check-quick button {
    width: auto;
    margin: 0;
    padding: 0.15rem 0.5rem;
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 999px;
    background: transparent;
    color: inherit;
    font-size: var(--text-sm);
}
.check-quick button[aria-pressed="true"] {
    border-color: var(--pico-primary-background);
    background: var(--pico-primary-background);
    color: var(--pico-primary-inverse);
}

/* ---------- Live link pickers (lesson editor: Lernziele, Lehrplan 21) ---------- */
.picker-search { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-4) 0 var(--space-2); }
.picker-search input[type="search"] { flex: 1 1 18rem; margin: 0; }
.picker-search select { flex: 0 1 12rem; width: auto; margin: 0; }
.picker-results[aria-busy="true"], #lesson-folders[aria-busy="true"] { opacity: 0.55; transition: opacity 0.15s ease; }
.picker-hint, .picker-count { margin: var(--space-2) 0; }
.pick-list { list-style: none; margin: 0; padding: 0; }
.pick-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--space-4);
    align-items: start;
    margin: 0;
    padding: var(--space-3) 0;
    list-style: none;
    border-top: 1px solid var(--pico-muted-border-color);
}
.pick-card:first-child { border-top: none; }
.pick-card > :not(.pick-add):not(.pick-remove) { grid-column: 1; }
.pick-card > :is(.pick-add, .pick-remove) { grid-column: 2; grid-row: 1 / span 4; align-self: center; width: auto; margin: 0; }
.pick-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: 0.2rem; }
.pick-chips:empty { display: none; }
.pick-chips .chip, .pick-chips .badge { font-size: var(--text-sm); margin-left: 0; }
.pick-path { margin: 0; color: var(--pico-muted-color); font-size: var(--text-sm); }
.pick-parent { margin: 0.15rem 0 0; color: var(--pico-muted-color); font-size: var(--text-sm); }
.pick-text { margin: 0.2rem 0 0; }
/* A linked medium's per-lesson note: a compact rich-text editor under the
 * title (the card's first column; the unlink button stays beside it). */
.pick-note { margin: var(--space-2) 0 0; }
.pick-note .rich-label { font-size: var(--text-sm); color: var(--pico-muted-color); }
.pick-note .ql-editor { min-height: 2.5em; }
/* A list of linked media stays light: a note's toolbar shows only while
 * you are in that note (its buttons and pickers are focusable, so using
 * them keeps it open). */
.pick-note:not(:focus-within) .ql-toolbar.ql-snow { display: none; }
/* (Beats quill.snow.css's `toolbar + container { border-top: 0 }`, which loads later.) */
.pick-note:not(:focus-within) .ql-toolbar.ql-snow + .ql-container.ql-snow {
    border-top: 1px solid var(--pico-form-element-border-color);
    border-radius: var(--pico-border-radius);
}
/* The media section's "add and link" row, below the picker search. */
.media-new-hint { margin: var(--space-4) 0 var(--space-2); }
.row .narrow-kind { flex: 0 1 14ch; }
/* Calendar: every row of a section (the entries and the add row) sits on one
 * shared grid -- each form is a subgrid -- so the date, time and text columns
 * line up however wide a field's content renders (a filled "03:12" vs an
 * empty "--:--"), and the buttons end flush right. Each form keeps its own
 * box, so the autosave bar still shows. Narrow screens keep the wrapping
 * .row layout. */
@media (min-width: 761px) {
    .cal-rows { display: grid; column-gap: 0.6rem; }
    .cal-appointments {
        grid-template-columns: auto auto auto minmax(7ch, 1.3fr) minmax(7ch, 1fr) auto;
    }
    .cal-anniversaries { grid-template-columns: auto minmax(7ch, 1.3fr) minmax(7ch, 1fr) auto; }
    .cal-rows > form.row {
        display: grid;
        grid-column: 1 / -1;
        grid-template-columns: subgrid;
        align-items: center;
    }
    .cal-rows > form.row > input { width: 100%; min-width: 0; }
    .cal-rows > form.row > button { justify-self: end; }
}
.pick-linked .pick-card { padding: var(--space-2) 0; }
.pick-chips .badge.ok {
    background: color-mix(in srgb, var(--pico-ins-color) 15%, transparent);
    color: var(--pico-ins-color);
}
/* Narrow screens: the add button goes under the text instead of a column. */
@media (max-width: 600px) {
    .pick-card { grid-template-columns: minmax(0, 1fr); }
    .pick-card > .pick-add { grid-column: 1; grid-row: auto; justify-self: start; margin-top: var(--space-2); }
    .picker-search select { flex: 1 1 100%; }
}
/* Search hits: an accent tint that works on light and dark cards. */
.pick-card mark, .lesson-row mark {
    padding: 0;
    border-radius: 0.15em;
    background: color-mix(in srgb, var(--accent) 35%, transparent);
    color: inherit;
}
/* ---------- Curriculum browser ---------- */
.lp-layout { display: grid; grid-template-columns: minmax(14rem, 17rem) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.lp-overview { grid-template-columns: minmax(0, 1fr); }
.lp-overview .lp-areas { display: none; }
/* Narrow screens: one column; once a subject area is open, its tree replaces
 * the area list (the "← Fachbereiche" link leads back). */
.lp-back { display: none; }
@media (max-width: 900px) {
    .lp-layout { grid-template-columns: minmax(0, 1fr); }
    .lp-layout:not(.lp-overview) nav.lp-areas { display: none; }
    .lp-back { display: block; }
}
/* Pico lays every <nav> and its lists out as a flex row; this one is a list. */
nav.lp-areas { display: block; position: sticky; top: var(--space-5); max-height: calc(100dvh - 2.5rem); overflow-y: auto; }
nav.lp-areas ul { display: block; }
nav.lp-areas li { padding: 0; }
.lp-areas h2 { font-size: var(--text-lg); }
.lp-areas ul { list-style: none; margin: 0; padding: 0; }
.lp-areas li { margin: 0; list-style: none; }
.lp-areas a { display: block; padding: 0.4rem 0.6rem; border-radius: 0.45rem; text-decoration: none; color: var(--pico-color); }
.lp-areas a small { display: block; color: var(--pico-muted-color); font-size: 0.75rem; }
.lp-areas a:hover { background: color-mix(in srgb, var(--pico-primary) 8%, transparent); }
.lp-areas a[aria-current="page"] { background: color-mix(in srgb, var(--pico-primary) 14%, transparent); color: var(--pico-primary); font-weight: 600; }
.lp-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: var(--space-3); }
.lp-card {
    display: flex; flex-direction: column; gap: 0.3rem; align-items: flex-start;
    padding: var(--space-4); border: 1px solid var(--pico-muted-border-color);
    border-radius: var(--pico-border-radius); text-decoration: none; color: var(--pico-color);
}
.lp-card:hover { border-color: var(--pico-primary-border); background: color-mix(in srgb, var(--pico-primary) 5%, transparent); }
.lp-card .chip { font-size: var(--text-sm); }
.zyklus-switch { display: inline-flex; --cal-text: var(--pico-color); }
/* `button.` + the heading colour: Pico paints button text white otherwise. */
.zyklus-switch button.cal-btn {
    width: auto; height: auto; margin: 0; padding: 0.3rem 0.7rem; font-size: var(--text-sm);
    background: var(--pico-card-background-color); color: var(--pico-h1-color);
    border: 1px solid var(--pico-muted-border-color); border-radius: 0;
}
.zyklus-switch .cal-btn + .cal-btn { margin-left: -1px; }
.zyklus-switch .cal-btn:first-child { border-radius: var(--pico-border-radius) 0 0 var(--pico-border-radius); }
.zyklus-switch .cal-btn:last-child { border-radius: 0 var(--pico-border-radius) var(--pico-border-radius) 0; }
.zyklus-switch button.cal-btn[aria-pressed="true"] { background: var(--pico-primary-background); color: var(--pico-primary-inverse); border-color: var(--pico-primary-background); }
.lp-tools { display: flex; gap: var(--space-4); margin: 0 0 var(--space-3); font-size: var(--text-sm); }
button.lp-toggle { color: var(--pico-primary); font-weight: 500; padding: 0; }
.lp-kb { margin: 0 0 var(--space-3); border-top: 1px solid var(--pico-muted-border-color); padding-top: var(--space-3); }
.lp-kb > summary { font-family: var(--font-head); font-size: var(--text-lg); font-weight: 600; }
.lp-kb > summary .chip { font-family: var(--pico-font-family); font-size: var(--text-sm); vertical-align: 0.15em; }
.lp-kb > summary small { font-family: var(--pico-font-family); font-size: var(--text-sm); font-weight: 400; }
.lp-ha { margin: var(--space-4) 0 var(--space-2); font-size: var(--text-base); font-weight: 600; }
.lp-code { font-family: var(--pico-font-family-monospace); font-size: var(--text-sm); color: var(--pico-muted-color); margin-right: 0.4rem; }
.lp-k { margin: 0 0 0.25rem; padding: 0.35rem 0.5rem; border-radius: var(--pico-border-radius); }
.lp-k[open] { background: color-mix(in srgb, var(--pico-muted-color) 6%, transparent); }
.lp-k > summary { display: flex; gap: 0.4rem; align-items: baseline; }
.lp-k-text { flex: 1; }
.lp-stufen { list-style: none; margin: var(--space-2) 0 0; padding: 0 0 0 var(--space-4); }
.lp-stufen li { margin: 0; padding: var(--space-2) 0; list-style: none; border-top: 1px solid var(--pico-muted-border-color); }
.lp-stufen li:first-child { border-top: none; }
.chip.lp-used { background: color-mix(in srgb, var(--pico-ins-color) 15%, transparent); color: var(--pico-ins-color); }
.lp-usage { display: flex; flex-wrap: wrap; gap: 0.2rem 1rem; margin: 0.25rem 0 0; font-size: var(--text-sm); }
.lp-usage a { text-decoration: none; }
/* The Zyklus switch hides stufen and competences outside the chosen cycle. */
.lp-tree[data-zyklus-filter="1"] .lp-stufen li:not([data-zyklus="1"]),
.lp-tree[data-zyklus-filter="2"] .lp-stufen li:not([data-zyklus="2"]),
.lp-tree[data-zyklus-filter="3"] .lp-stufen li:not([data-zyklus="3"]),
.lp-tree[data-zyklus-filter="1"] .lp-k:not([data-zyklen~="1"]),
.lp-tree[data-zyklus-filter="2"] .lp-k:not([data-zyklen~="2"]),
.lp-tree[data-zyklus-filter="3"] .lp-k:not([data-zyklen~="3"]) { display: none; }
/* A competence or stufe reached through a link flashes once. */
@keyframes lp-flash { from { background: color-mix(in srgb, var(--accent) 35%, transparent); } to { background: transparent; } }
.lp-flash { animation: lp-flash 2.4s ease-out; }
/* ---------- Class page (same layout as the student page) ---------- */
.class-head { margin-bottom: var(--space-5); }
.class-head .title-edit-h1 { margin-bottom: var(--space-2); }
/* A narrow form whose fields stack (sidebar cards). */
.stack-form label { display: block; margin-bottom: var(--space-3); font-size: var(--text-sm); color: var(--pico-muted-color); }
.stack-form label > :is(input, select) { margin-top: 0.2rem; color: var(--pico-color); }
.stack-form .autosave-hint { margin: 0; }
form.stack-form[data-autosave-row] { border-left: 0; padding-left: 0; margin-left: 0; }
.chips a { color: inherit; text-decoration: none; }
details.promote > summary { list-style: none; }
details.promote > summary h2 { display: inline; font-size: var(--text-lg); }
/* Card title with a control on the right (e.g. the semester picker). */
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.card-head h2 { margin: 0; font-size: var(--text-lg); }
.card-head-form { margin: 0; }
.card-head-form select { margin: 0; width: auto; }
.card-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-4); }
.card-actions > * { width: auto; margin: 0; }
.roster { list-style: none; margin: 0; padding: 0; }
.roster li {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: 0;
    padding: 0.45rem 0;
    list-style: none;
    border-top: 1px solid var(--pico-muted-border-color);
}
.roster li:first-child { border-top: none; }
.roster-name { display: flex; align-items: center; gap: var(--space-3); flex: 1; min-width: 0; text-decoration: none; }
.roster .chip { font-size: var(--text-sm); }
/* The "add students" checklist: scrolls inside the dialog. */
.enroll-dialog article { width: min(32rem, 100%); }
.enroll-list { list-style: none; margin: var(--space-2) 0; padding: 0; max-height: 45vh; overflow-y: auto; border: 1px solid var(--pico-muted-border-color); border-radius: var(--pico-border-radius); }
.enroll-list li { margin: 0; padding: 0.35rem 0.7rem; list-style: none; border-top: 1px solid var(--pico-muted-border-color); }
.enroll-list li:first-child { border-top: none; }
.enroll-list label { margin: 0; display: flex; align-items: center; gap: 0.5rem; }
.enroll-list label small { margin-left: auto; }
.enroll-list.only-free li.has-class { display: none; }
.enroll-scope { font-size: var(--text-sm); }
.profile-new { max-width: 60rem; }
/* Lesson editor header: title + context, series arrows on the right. */
.lesson-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-5); }
.lesson-head h1 { margin-bottom: var(--space-2); }
.series-nav { display: flex; gap: var(--space-2); flex: none; }
.series-nav svg { width: 1.1rem; height: 1.1rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.more-fields { margin: var(--space-2) 0 var(--space-4); }
.more-fields > summary { color: var(--pico-muted-color); font-size: var(--text-sm); font-weight: 600; }
.danger-zone h2 { font-size: var(--text-lg); }
.profile-new .form-actions button, .profile-new .form-actions a { width: auto; margin: 0; }
/* Name column with a leading round avatar in the student list. */
.name-cell { display: flex; align-items: center; gap: var(--space-3); }
.avatar {
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    object-fit: cover;
}
/* Placeholder keeps names aligned when a student has no photo. */
.avatar-empty { background: color-mix(in srgb, var(--pico-primary) 12%, transparent); }

/* ---------- Seating plan drag-and-drop ---------- */
/* Chips are role="button" (tap to swap), which Pico and the compact-control
 * rule above would paint and size as buttons: keep them plain names. The
 * tray's pill style below still applies. */
.seat-chip[role="button"],
.seat-chip[role="button"]:is(:hover, :active, :focus) {
    width: auto;
    height: auto;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
    color: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    text-align: inherit;
}
.seat-chip { cursor: grab; }
.seat-chip:active { cursor: grabbing; }
/* A seated chip: the short name with the student's photo (if any) below it.
 * The cell grows to fit; the photo is cropped square. */
table.seatgrid .seat-chip { display: inline-flex; flex-direction: column; align-items: center; gap: 0.25rem; }
.seat-chip img {
    display: block;
    width: 3.5rem;
    height: 3.5rem;
    object-fit: cover;
    border-radius: var(--pico-border-radius);
    pointer-events: none;
}
/* The unseated students tray: a dashed drop zone of draggable name pills. */
.seat-tray {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    align-items: center;
    min-height: 2.4rem;
    padding: 0.45rem;
    margin-bottom: 0.7rem;
    border: 1px dashed var(--pico-muted-border-color);
    border-radius: var(--pico-border-radius);
}
.seat-tray .seat-chip,
.seat-tray .seat-chip[role="button"]:is(:hover, :active, :focus) {
    padding: 0.15rem 0.6rem;
    background: color-mix(in srgb, var(--pico-primary) 12%, transparent);
    border-radius: 999px;
    font-size: 0.85rem;
}
/* Tap to swap: the picked student is ringed; every free seat and classmate
 * becomes a target. */
.seat-chip:focus-visible { outline: 2px solid var(--pico-primary); outline-offset: 2px; }
.seat-chip.is-picked {
    outline: 3px solid var(--pico-primary);
    outline-offset: 3px;
    border-radius: var(--pico-border-radius);
}
table.seatgrid.is-picking td:not(.blocked) { cursor: pointer; }
table.seatgrid.is-picking td:not(.blocked):hover {
    background: color-mix(in srgb, var(--pico-primary) 14%, transparent);
}
.seat-pick-status {
    margin: 0 0 var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--pico-border-radius);
    background: color-mix(in srgb, var(--pico-primary) 10%, transparent);
    color: var(--pico-primary);
    font-weight: 600;
    font-size: var(--text-sm);
}
/* Highlight whatever a chip is hovering over during a drag. */
.drop-target { outline: 2px dashed var(--pico-primary); outline-offset: -2px; }
table.seatgrid td.drop-target {
    background: color-mix(in srgb, var(--pico-primary) 20%, transparent);
}
/* Blocked seats: hatched, not a drop target. */
table.seatgrid td.blocked {
    background: repeating-linear-gradient(
        45deg,
        var(--pico-muted-border-color) 0 4px,
        transparent 4px 8px
    );
    cursor: not-allowed;
}

/* Blocked-seat editor on the classroom form: a grid of toggle buttons. */
.blocked-editor {
    display: grid;
    grid-template-columns: repeat(var(--cols, 6), 1.6rem);
    gap: 3px;
    margin: 0.35rem 0 0.2rem;
}
.blk-cell {
    width: 1.6rem;
    height: 1.6rem;
    padding: 0;
    margin: 0;
    border: 1px solid var(--pico-muted-border-color);
    border-radius: 3px;
    background: var(--pico-card-background-color);
    cursor: pointer;
}
.blk-cell.blocked {
    background: var(--pico-muted-color);
    border-color: var(--pico-muted-color);
}

/* Rich-text editor (Quill): theming lives in quill-theme.css, loaded after
 * quill.snow.css so it wins the cascade. Only the wrapper spacing stays here. */
.rich-editor { margin-bottom: 0.25rem; }
