:root {
    /* Light theme — main workspace */
    --bg: #f1f5f9;
    --panel: #ffffff;
    --panel-2: #f8fafc;
    /* Only the sign-in fields use this. They sit on an otherwise empty white card, where the fill
       is the one thing marking out where to type — --panel-2 is too close to white to do that job
       on its own. */
    --auth-field-bg: #e8edfa;
    --border: #e2e8f0;
    --text: #0f172a;
    --muted: #64748b;
    --accent: #4a7c62;
    --accent-hover: #3c6851;
    --danger: #ef4444;
    --ok: var(--accent);
    --warn: #d97706;

    /* The green that used to be written into a dozen rules as a different hex each time — a tint
       here, a border there, a text colour somewhere else. All four are derived from --accent, so
       the dark theme moves them by moving the accent alone. */
    --accent-text: #35664e;                                             /* readable green on a pale tint */
    --accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);  /* "selected" fills */
    --accent-line: color-mix(in srgb, var(--accent) 30%, transparent);  /* quiet borders */
    --accent-wash: color-mix(in srgb, var(--accent) 7%, var(--panel));  /* info boxes, ok status */

    /* How strongly a lesson's cell is tinted with its subject colour. The rest is transparent, so
       whatever lies under it (the day band, the tinted "today" column) shows through. Raise it for
       more colour, lower it for a paler timetable. */
    --tt-tint: 15%;
    /* Gap between the tiles of a timetable grid. */
    --tt-gap: 5px;
    /* Hours and room codes are set in a mono face, so they read as codes rather than as words. */
    --mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Consolas, monospace;

    /* Height of the top bar. The sticky columns (the rail, the waiting panel) subtract it from the
       viewport, so it is a fixed number rather than whatever the bar's content adds up to. */
    --topbar-h: 64px;

    /* Dark navy sidebar */
    --sidebar-bg: #0f172a;
    --sidebar-panel: #1e293b;
    --sidebar-text: #e2e8f0;
    --sidebar-muted: #94a3b8;
    --sidebar-active: #5f9a7c;
    --sidebar-border: #1e293b;

    /* Surfaces that used to be written straight into the rules. They are named here because the
       dark theme has to move them; a hex buried in a rule is a hole the theme cannot reach. */
    --head-bg: #eef1f6;          /* column heads of every timetable */
    --head-text: #3b4757;
    --today-bg: #e7f0ea;         /* today's column, and the band behind its row */
    --today-cell: #eaf2ec;
    --today-text: var(--accent-text);
    --rail-text: #5b6a80;        /* the day rail down the side of the school-wide grid */
    --meta-text: #52607a;        /* professor line and room chip inside a lesson */
    --hover-tint: rgba(15, 23, 42, .05);
    --shadow-sm: 0 1px 3px rgba(15, 23, 42, .12);
    --shadow-md: 0 4px 18px rgba(15, 23, 42, .05);
    --shadow-lg: 0 12px 28px rgba(15, 23, 42, .16);
}

/* ============ Dark theme ============ */
/* Opt-in: the light theme above stays the default, and js/common.js sets data-theme="dark" on the
   root when it has been chosen. Only the variables move — every rule below is written against
   them, which is why the whole app follows from this one block. */
:root[data-theme="dark"] {
    --bg: #0b1220;
    --panel: #131c2b;
    --panel-2: #1a2434;
    /* No separate value needed here: against a dark panel, --panel-2 already reads as a field. */
    --auth-field-bg: var(--panel-2);
    --border: #2a3648;
    --text: #e6edf7;
    --muted: #93a1b5;
    /* A step lighter than the light theme's, so it still separates from a dark panel — but
       the same muted sage, not the neon one it used to be. */
    --accent: #6ea88b;
    --accent-hover: #55906f;
    --danger: #f87171;
    --ok: var(--accent);
    --warn: #fbbf24;

    /* The only green the dark theme has to state outright: --accent-soft/-line/-wash are mixed
       from the accent above and follow it here without being repeated. */
    --accent-text: #93c2a8;

    /* A lesson tile needs more of its hue here: the same 15% over a dark panel reads as grey. */
    --tt-tint: 26%;

    --head-bg: #1e293b;
    --head-text: #b6c2d4;
    --today-bg: #1e3a2e;
    --today-cell: #1b352a;
    --today-text: var(--accent-text);
    --rail-text: #9fb0c6;
    --meta-text: #9aabc2;
    --hover-tint: rgba(255, 255, 255, .06);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, .5);
    --shadow-md: 0 4px 18px rgba(0, 0, 0, .35);
    --shadow-lg: 0 12px 28px rgba(0, 0, 0, .55);
}

/* What the variables above cannot reach on their own: surfaces whose light value is a tint mixed
   for white paper. Each is rebuilt from the same hue against the dark panel rather than given a
   new arbitrary colour, so the meaning a colour carries — subject identity, ok/warn/error — is the
   one thing that does not change with the theme. */

/* The landing sets its own light palette and gradient; without this the home page would stay white
   while every other page turned dark. */
:root[data-theme="dark"] .home-landing {
    --border: #24352b;
    --text: #e6edf7;
    --muted: #93a1b5;
    background:
        radial-gradient(760px 400px at 90% -10%, rgba(110, 168, 139, .10), transparent 60%),
        linear-gradient(180deg, #0d1520 0%, #0b1220 100%);
}

/* The 24 subject pastels are opaque colours picked to sit on white. Mixed into the panel at a
   quarter strength they keep their hue and stop glowing. Each class already declares its own
   --sc-accent, so this single rule covers all of them. */
:root[data-theme="dark"] [class*="subject-color-"] {
    background: color-mix(in oklab, var(--sc-accent) 26%, var(--panel));
}

/* A subject's own text colour is derived from its hue at oklch lightness 0.34 — chosen to read on
   a pale chip, and far too dark to read on this one. Same hue, lifted well above the panel; the
   accent that draws the bar and the dot moves up with it so the two stay related. Anywhere
   --sc-h is set (legend chips, lesson tiles, the unplaced-lesson cards) inherits this. */
:root[data-theme="dark"] {
    --sc-text-l: 0.86;
    --sc-accent-l: 0.72;
}
/* Each selector below mirrors the one that declares the light value, prefixed with the theme —
   matching it class for class. A shorter selector would tie on specificity and lose on order,
   since the light rules are further down the file. */
:root[data-theme="dark"] .tt-legend-chip,
:root[data-theme="dark"] .tt-wrap .tt-cell.has-lesson,
:root[data-theme="dark"] .waiting-card {
    --sc-text: oklch(var(--sc-text-l) 0.09 var(--sc-h, 265));
    --sc-accent: oklch(var(--sc-accent-l) 0.14 var(--sc-h, 265));
}

/* .info-box and #schedule-status.ok are painted from --accent-wash / --accent-line / --accent-text,
   which follow the theme's accent on their own — the dark theme no longer has to restate them. */
:root[data-theme="dark"] .tag-class { background: #1e3a5f; color: #bfdbfe; }
:root[data-theme="dark"] .tag-disc { background: #4a2c17; color: #fed7aa; }
:root[data-theme="dark"] .tag-off { background: #453016; color: #fcd34d; }

:root[data-theme="dark"] #schedule-status.warn {
    background: color-mix(in oklab, var(--warn) 14%, var(--panel));
    border-color: color-mix(in oklab, var(--warn) 34%, var(--panel));
    color: #fde68a;
}
:root[data-theme="dark"] #schedule-status.error {
    background: color-mix(in oklab, var(--danger) 14%, var(--panel));
    border-color: color-mix(in oklab, var(--danger) 34%, var(--panel));
    color: #fecaca;
}
:root[data-theme="dark"] .insight-danger {
    background: color-mix(in oklab, var(--danger) 10%, var(--panel));
}

/* The "no timetable yet" panel and the mono (print-friendly) view both lean on near-white. */
/* Two panels on the landing are painted white outright rather than through a variable, so they
   stayed white while the page around them turned dark. */
:root[data-theme="dark"] .home-landing .guide {
    background: var(--panel-2);
    box-shadow: none;
}
:root[data-theme="dark"] .home-btn.ghost {
    background: var(--panel-2);
    border-color: var(--border);
}

:root[data-theme="dark"] .tt-empty { background: color-mix(in srgb, var(--accent) 6%, transparent); }
:root[data-theme="dark"] body.tt-mono .tt-wrap .tt-cell.has-lesson { background-color: var(--panel-2); }
:root[data-theme="dark"] body.tt-mono .tt-wrap .tt-cell.has-lesson:hover { background-color: var(--head-bg); }

* { box-sizing: border-box; }

/* `hidden` must win over component display rules (e.g. .form { display: flex }). */
[hidden] { display: none !important; }

body {
    margin: 0;
    font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.5;
}

/* ============ App shell (3 zones) ============ */
.app-shell {
    display: grid;
    /* The rail is 64px collapsed whether or not the waiting panel is up — the two are independent,
       and a wider first track here left the icons stranded in an empty column on the one page that
       shows the panel. `.nav-expanded` widens it to 224px in both layouts. */
    grid-template-columns: 64px 1fr 320px;
    min-height: 100vh;
}
/* When the waiting panel is hidden it collapses out of the grid via [hidden]; its column simply
   becomes empty, so give the grid a graceful fallback. Only the Orar page has the panel at all,
   so every other page takes the same two-column layout. */
.app-shell:not(.home-mode):has(.waiting[hidden]),
.app-shell:not(.home-mode):not(:has(.waiting)) { grid-template-columns: 64px 1fr; }

/* Home page is a full-screen landing: drop the sidebar and waiting panel entirely. */
.app-shell.home-mode { grid-template-columns: 1fr; }
.app-shell.home-mode .sidebar,
.app-shell.home-mode .waiting { display: none; }
.app-shell.home-mode .main { padding: 0; }

/* Navigation that looks like a button but is a link to another page (every section is its own
   HTML file), so the underline has to go. */
.nav-item, .home-btn, .home-skip, .home-brand { text-decoration: none; }

/* ============ Top bar (the landing's header, injected above the shell on every other page) ============ */
/* It reuses the landing's .home-top parts, so only the framing differs: full width, stuck to the
   top of the window, and a fixed height the sticky columns below can subtract. */
.app-top {
    /* Second column, first row: the bar reaches only as far as the rail, which spans every row
       beside it. The area is stretched over both rows and the bar pinned to its start, so `sticky`
       has room to travel the height of the page instead of being trapped in a 64px band. */
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: start;
    position: sticky;
    top: 0;
    z-index: 30;
    height: var(--topbar-h);
    padding: 0 clamp(16px, 3vw, 28px);
    gap: 16px;
    background: color-mix(in srgb, var(--panel) 88%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--border);
}
/* Two overrides of the landing's header, written as a compound selector so they beat `.home-top`
   wherever that rule sits: the shell starts immediately under this bar (no gap off a hero), and
   with the wordmark moved to the rail the links are all that is left, so they stay at the far end
   instead of being pulled left by space-between. */
.home-top.app-top { margin-bottom: 0; justify-content: flex-end; }
/* The bar only claims the first row of the content column; the rail and the waiting panel run the
   full height of the window on either side of it. */
.app-shell:has(.app-top) { grid-template-rows: var(--topbar-h) 1fr; }
.app-shell:has(.app-top) > .sidebar { grid-column: 1; grid-row: 1 / -1; }
.app-shell:has(.app-top) > .main { grid-column: 2; grid-row: 2; }
.app-shell:has(.app-top) > .waiting { grid-column: 3; grid-row: 1 / -1; }

/* ============ Sidebar (narrow icon-only rail) ============ */
.sidebar {
    background: var(--panel);
    color: var(--text);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 14px 8px;
    gap: 6px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    border-right: 1px solid var(--border);
}

/* The head of the rail carries the wordmark and the collapse button. Expanded they share one row,
   name at the left and button at the outer edge, where it reads as "close this panel". A 64px rail
   has no room for both side by side, so collapsed they stack: mark over button, both centred. No
   rule under them — the gap alone separates the head from the nav. */
.sidebar-head {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding-bottom: 8px;
}
.nav-expanded .sidebar-head {
    flex-direction: row;
    justify-content: space-between;
    gap: 8px;
}

/* The wordmark belongs to the expanded rail only: collapsed, the head is just the button that
   opens it back up. */
.sidebar-brand { display: none; }
.nav-expanded .sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    text-decoration: none;
}
.sidebar-brand .home-brand-name { font-size: 1.1rem; }

/* Rail toggle: expands the icon-only menu to a labelled one. */
.sidebar-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: transparent;
    border: none;
    color: var(--muted);
    border-radius: 12px;
    cursor: pointer;
}
.sidebar-toggle:hover { background: var(--panel-2); color: var(--text); }

/* Colorful emoji glyphs (matching the reference) instead of stroked line icons. */
.nav-emoji { font-size: 20px; line-height: 1; }
/* Custom multicolor "students" glyph (Clase). */
.nav-students { width: 22px; height: 22px; }
.nav-students svg { display: block; width: 100%; height: 100%; }
/* Rail is icon-only: the nav section headings are hidden until it is expanded. */

.side-nav { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 100%; }

.nav-label { display: none; }

.nav-item {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    background: transparent;
    border: none;
    color: var(--text);
    padding: 0;
    border-radius: 12px;
    cursor: pointer;
    transition: background .15s, color .15s;
}
.nav-item:hover { background: var(--panel-2); }
.nav-item.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.nav-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex: none;
    color: var(--muted);
}
.nav-item:hover .nav-icon { color: var(--text); }
.nav-item.active .nav-icon { color: var(--accent); }

/* ---- Expanded sidebar (labels visible) ---- */
.app-shell.nav-expanded { grid-template-columns: 224px 1fr 320px; }
.app-shell.nav-expanded:not(.home-mode):has(.waiting[hidden]),
.app-shell.nav-expanded:not(.home-mode):not(:has(.waiting)) { grid-template-columns: 224px 1fr; }

.nav-expanded .sidebar { align-items: stretch; padding: 14px 12px; }
.nav-expanded .side-nav { align-items: stretch; }
.nav-expanded .nav-item {
    width: 100%;
    height: auto;
    justify-content: flex-start;
    gap: 12px;
    padding: 9px 12px;
    font-weight: 500;
    font-size: .93rem;
}
.nav-expanded .nav-label { display: inline; }

/* ============ Main panel ============ */
.main { padding: 24px 28px 48px; min-width: 0; }

.view.panel {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 20px;
    box-shadow: var(--shadow-md);
}

h2 { font-size: 1.15rem; margin: 0 0 14px; }
.panel h2 {
    border-bottom: 1px solid var(--border);
    padding-bottom: 8px;
}

/* ============ Forms & inputs ============ */
.form {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 12px;
}
.form.inline { flex-direction: row; align-items: center; flex-wrap: wrap; }
.form.inline label { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: .9rem; }

input, select, button {
    font: inherit;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: var(--panel);
    color: var(--text);
}
input[type="number"] { width: 80px; }
/* Tint checkboxes/radios with the theme accent (green) instead of the OS blue. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }

button {
    background: var(--accent);
    border-color: var(--accent);
    color: white;
    cursor: pointer;
    font-weight: 600;
}
/* Hover never repaints a button green: it darkens whatever colour that button already carries.
   A plain primary button is green, so it still lands on roughly --accent-hover; a chip tinted with
   a subject's hue keeps that hue; a transparent one stays transparent, so what lights up is the
   surface behind it — the timetable cell, the card, the row — over its whole area rather than a
   green patch the size of the button's text.
   `filter` is what makes this one rule enough: it works off the colour already painted, which is
   the only way a single declaration can cover buttons whose colours are set in twenty other places
   (and in `--sc-h`, computed per subject at runtime). */
button:hover { filter: brightness(.93); }
/* Nothing to darken when the button cannot be pressed. */
button:disabled:hover { filter: none; }

.daysoff, .prof-lessons { border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; }
.daysoff legend, .prof-lessons legend { color: var(--muted); font-size: .85rem; padding: 0 4px; }

.lesson-rows { display: flex; flex-direction: column; gap: 8px; }
/* Before the first subject is added the container has no height, which left a hole in the middle
   of the card. The empty state fills it with the next step instead. */
.lesson-rows:empty::before {
    /* The one piece of prose that lives in the stylesheet, because :empty is what detects the
       state. A stylesheet cannot be translated, so the sentence itself is handed in as a custom
       property by js/common.js; the fallback keeps the box sensible if that ever fails. */
    content: var(--i18n-no-lessons, " ");
    display: block;
    padding: 14px 16px;
    border: 1px dashed var(--border);
    border-radius: 12px;
    background: var(--panel);
    color: var(--muted);
    font-size: .85rem;
}
.lesson-row { display: flex; gap: 6px; align-items: center; }
.lesson-row select, .lesson-row .row-subject { flex: 1; min-width: 0; }
.lesson-row .row-periods { width: 64px; flex-shrink: 0; flex: none; }

.assign-row {
    display: flex; gap: 8px 10px; align-items: center; flex-wrap: wrap;
    border: 1px solid var(--accent-line);
    background: color-mix(in srgb, var(--accent) 6%, transparent);
    border-radius: 12px; padding: 12px;
}
/* One subject name doesn't need a third of the card: the select keeps a fixed, readable width and
   the classes get the rest of the row. */
/* No forced height: 38px was 4px shorter than the padding and line-height need, which clipped the
   descenders of names like "Educație tehnologică". */
.assign-row .row-subject { flex: 0 1 260px; min-width: 150px; align-self: center; }

/* Consistent, polished dropdowns inside the professor form (custom chevron instead of native arrow). */
#professor-form select {
    appearance: none; -webkit-appearance: none;
    background-color: var(--panel);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
    background-repeat: no-repeat;
    background-position: right 11px center;
    padding-right: 30px;
}

/* Quick-add: class pills with a periods/week stepper */
.assign-body { flex: 1 1 260px; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* The chips and the "+ clasă" button share one wrapping line: without `contents` the chip box
   claims the whole width as soon as it wraps, and the button drops to a line of its own. */
.assign-chips { display: contents; }
.assign-chip {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--panel); color: var(--text);
    border: 1px solid var(--border);
    border-radius: 999px; padding: 4px 8px 4px 12px; font-size: .82rem; font-weight: 600;
}
.assign-chip .chip-name { white-space: nowrap; }
.chip-step { display: inline-flex; align-items: center; gap: 2px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 0 2px; }
.chip-step button { background: transparent; border: none; color: var(--accent); font-weight: 700; padding: 0 5px; cursor: pointer; line-height: 1.5; }
.chip-step button:hover { background: transparent; color: var(--accent-hover); }
.chip-num { min-width: 12px; text-align: center; font-variant-numeric: tabular-nums; }
.chip-unit { font-size: .68rem; font-weight: 500; color: var(--muted); }
.chip-x { background: transparent; border: none; color: var(--muted); opacity: .7; cursor: pointer; padding: 0 2px; font-size: .8rem; }
.chip-x:hover { background: transparent; opacity: 1; color: var(--danger); }
.chip-add {
    flex: none; height: 32px; border: 1px dashed var(--accent); color: var(--accent);
    background-color: transparent;
    border-radius: 999px; padding: 0 30px 0 14px; font-size: .8rem; font-weight: 600; cursor: pointer;
}
.chip-add:disabled { opacity: .4; border-style: solid; cursor: default; }

/* "One / Many" add-mode toggle */
.add-seg { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; margin-bottom: 10px; }
.add-seg button { background: var(--panel); color: var(--muted); border: none; border-radius: 0; padding: 6px 16px; font-size: .84rem; font-weight: 600; }
.add-seg button.on { background: var(--accent); color: #fff; }
.add-seg button:hover:not(.on) { background: var(--panel-2); color: var(--text); }
.entity-add textarea { width: 100%; min-height: 96px; resize: vertical; font: inherit; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--text); }

/* Class coverage bar (filled / weekly capacity) */
.cov { display: flex; align-items: center; gap: 8px; flex: none; }
.cov-bar { width: 84px; height: 7px; border-radius: 999px; background: var(--border); overflow: hidden; }
.cov-fill { display: block; height: 100%; border-radius: 999px; }
.cov-fill.ok { background: var(--ok); }
.cov-fill.warn { background: var(--warn); }
.cov-fill.empty { background: transparent; }
.cov small { color: var(--muted); font-size: .76rem; font-variant-numeric: tabular-nums; white-space: nowrap; }

.hint { color: var(--muted); font-size: .82rem; margin: 0 0 10px; }

.rule-card {
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--panel-2);
    padding: 4px 16px;
}
.rule-fields {
    border-top: 1px solid var(--border);
    padding: 12px 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
[data-view="rules"] .rule-fields label {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; color: var(--muted); font-size: .9rem;
}
[data-view="rules"] .rule-fields label input[type=number] { width: 5rem; }
[data-view="rules"] .rule-toggle {
    display: flex; align-items: center; gap: 10px;
    padding: 14px 0; color: var(--text); font-size: .95rem; font-weight: 600;
}
[data-view="rules"] .rule-toggle input { width: auto; }
.rule-tag {
    display: inline-block;
    background: var(--warn);
    color: #fff;
    font-size: .66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 1px 7px;
    border-radius: 999px;
    margin-left: 4px;
    vertical-align: middle;
}

.row-del {
    flex: none;
    align-self: center;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid var(--danger);
    color: var(--danger);
    border-radius: 8px;
    padding: 0;
}
.row-del:hover { background: var(--danger); color: white; }

.add-row-btn {
    flex: none;
    background: transparent;
    border: 1px dashed var(--accent);
    color: var(--accent);
    font-size: .85rem;
    font-weight: 600;
    padding: 8px 14px;
    border-radius: 8px;
}
.add-row-btn:hover { background: var(--accent); color: white; }

/* Working days as chips you press, not boxes you tick: the whole day is the target, and which days
   are in the week is legible at a glance instead of by reading five small squares. The checkbox is
   still there, driving the state — it is only made invisible, so the control stays a real form
   field for the keyboard and for `checkedValues`. */
.day-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.day-chips label {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 52px;
    padding: 7px 14px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--panel);
    color: var(--muted);
    font-size: .85rem; font-weight: 600;
    cursor: pointer;
    user-select: none;
    transition: background .12s, color .12s, border-color .12s;
}
.day-chips label:hover { border-color: var(--muted); color: var(--text); }
.day-chips input { position: absolute; opacity: 0; width: 0; height: 0; }
.day-chips label:has(input:checked) {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent-text);
}
.day-chips label:has(input:focus-visible) { outline: 2px solid var(--text); outline-offset: 2px; }

/* ============ Entity lists ============ */
.entity-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.entity-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 8px 10px;
}
.entity-list .meta { color: var(--muted); font-size: .82rem; }

.actions { display: flex; gap: 6px; flex-shrink: 0; }

.del-btn {
    background: transparent;
    border: 1px solid var(--danger);
    color: var(--danger);
    padding: 4px 8px;
    font-size: .8rem;
}
.del-btn:hover { background: var(--danger); color: white; }

.edit-btn {
    background: transparent;
    border: 1px solid var(--accent);
    color: var(--accent);
    padding: 4px 8px;
    font-size: .8rem;
}
.edit-btn:hover { background: var(--accent); color: white; }

.cancel-btn {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--muted);
}
.cancel-btn:hover { color: var(--text); }

.empty { color: var(--muted); font-style: italic; padding: 4px; }

#save-form { margin-top: 16px; align-items: flex-end; }
.saved-schedules { margin-top: 24px; border-top: 1px solid var(--border); padding-top: 14px; }
.saved-schedules h3 { margin: 0 0 8px; }

.status { margin: 8px 0; font-weight: 600; }
.status.ok { color: var(--ok); }
.status.warn { color: var(--warn); }
.status.error { color: var(--danger); }
.warn-major { color: var(--danger); font-weight: 700; }

/* ============ Timetable page — empty / setup state ============ */
/* One gap between every top-level section of the page. They used to be set one by one and drifted
   apart (4, 8, 16, 24, 26px), which read as accidental rather than composed. */
.timetable-view { min-width: 0; --tt-gap-section: 16px; }
.timetable-view > .status:not(:empty) { margin: 0 0 var(--tt-gap-section); }
.timetable-view > .status:empty { margin: 0; }
.timetable-view > .insights { margin: 0 0 var(--tt-gap-section); }
.timetable-view > #schedule-output { margin-top: var(--tt-gap-section); }

/* Generation settings card */
/* Sections of this page sit inside the white panel now, like every other page's content, so they
   take the same tinted sub-card treatment as `.field-card` — no white-on-white, no second shadow. */
.tt-setup {
    background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px;
    padding: 16px 18px; margin-bottom: var(--tt-gap-section);
}
.tt-setup-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
    margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border);
}
/* A step below the panel's own h2 rather than a rival to it. */
.tt-setup-title { font-weight: 700; font-size: .92rem; color: var(--text); }
.tt-generate {
    background: var(--accent); color: #fff; border: 1px solid var(--accent);
    font-weight: 600; font-size: .88rem; padding: 9px 18px; border-radius: 9px;
    /* A seated button, not a glowing one: the coloured halo made this the loudest thing on a page
       whose subject is the timetable below it. */
    box-shadow: 0 1px 2px rgba(15, 23, 42, .08); cursor: pointer;
}
.tt-generate:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
/* Two decisions, side by side: how long a day is, and which days there are. The hours field is only
   as wide as a stepper needs; the days take the rest of the row and wrap under it when narrow. */
.tt-fields { display: flex; flex-wrap: wrap; gap: 14px 24px; }
.tt-field { display: flex; flex-direction: column; gap: 5px; }
.tt-field-label { font-weight: 600; font-size: .82rem; color: var(--text); }
.tt-field-hint { color: var(--muted); font-size: .76rem; }
.tt-field-days { flex: 1 1 260px; }

/* The hours stepper: − number + . Changing a 6 into a 7 is one click; typing still works. */
.tt-stepper {
    display: inline-flex; align-items: stretch;
    border: 1px solid var(--border); border-radius: 12px; overflow: hidden;
    background: var(--panel); width: max-content;
}
.tt-stepper input {
    width: 58px;
    border: 0; border-radius: 0;
    text-align: center;
    font-size: 1.05rem; font-weight: 700;
    -moz-appearance: textfield;
}
.tt-stepper input::-webkit-outer-spin-button,
.tt-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.tt-step {
    width: 38px;
    background: var(--panel-2); border: 0; border-radius: 0;
    color: var(--text); font-size: 1.1rem; font-weight: 700; line-height: 1;
    cursor: pointer;
}
.tt-step:hover { background: var(--hover-tint); }

/* What the settings add up to, said in words — including the rules that take part in generation
   from another page entirely. */
.tt-summary {
    display: flex; flex-wrap: wrap; gap: 4px 18px;
    margin: 14px 0 0;
    padding: 9px 12px;
    border-radius: 9px;
    /* The card around it is --panel-2 now, so this needs its own ground to stay a distinct note. */
    background: var(--panel);
    border: 1px solid var(--border);
    color: var(--muted);
    font-size: .82rem;
}
.tt-summary-grid { color: var(--text); font-weight: 600; }
.tt-summary a { color: var(--accent); font-weight: 600; }

/* The one knob most people never touch, folded away so the card shows only decisions. */
.tt-advanced { margin-top: 10px; }
.tt-advanced > summary {
    display: inline-flex; align-items: center; gap: 6px;
    color: var(--muted); font-size: .84rem; font-weight: 600;
    cursor: pointer; list-style: none; user-select: none;
}
.tt-advanced > summary::-webkit-details-marker { display: none; }
.tt-advanced > summary::before { content: "▸"; font-size: .8em; transition: transform .15s; }
.tt-advanced[open] > summary::before { transform: rotate(90deg); }
.tt-advanced > summary:hover { color: var(--text); }
.tt-advanced-body { padding: 12px 0 2px; }
.tt-advanced-body input { width: 120px; }
.tt-advanced-body .tt-field-hint { max-width: 46ch; }

/* Friendly empty state (cleared by renderSchedule once a timetable exists) */
.tt-empty {
    text-align: center; padding: 34px 20px;
    border: 1.5px dashed var(--border); border-radius: 12px; background: color-mix(in srgb, var(--accent) 5%, transparent);
}
.tt-empty-icon { font-size: 2rem; line-height: 1; margin-bottom: 8px; }
.tt-empty h3 { margin: 0 0 6px; font-size: 1.02rem; color: var(--text); }
.tt-empty p { margin: 0 auto; color: var(--muted); font-size: .92rem; max-width: 48ch; line-height: 1.5; }
/* What has to exist before a timetable can be built, in the order it is needed — each step a link
   to the page that fills it in, so the empty state is a way forward and not just a notice. */
.tt-steps {
    display: flex; flex-direction: column; gap: 6px;
    width: max-content; max-width: 100%;
    margin: 14px auto 16px; padding: 0 0 0 22px;
    text-align: left;
    color: var(--muted); font-size: .9rem;
}
.tt-steps li { line-height: 1.5; }
.tt-steps a { color: var(--accent); font-weight: 600; }

.tt-saved { margin-top: var(--tt-gap-section); }

/* Professor restrictions: compact day × period table (click a cell to block that hour,
   a day label to block the whole row, a period header to block the whole column). */
.restr-hint { font-size: .8rem; color: var(--muted); margin: 0 0 12px; }
.block-grid-wrap { overflow-x: auto; padding-bottom: 2px; }
table.block-grid { border-collapse: collapse; font-size: .72rem; }
table.block-grid th, table.block-grid td { padding: 0; }
table.block-grid .bg-corner { width: 44px; }
table.block-grid .bg-head {
    min-width: 28px; padding: 4px 0; text-align: center;
    color: var(--muted); font-weight: 600; cursor: pointer;
}
table.block-grid .bg-head:hover { color: var(--text); }
table.block-grid .bg-head.on { color: var(--danger); }
table.block-grid .bg-day {
    padding: 4px 12px 4px 2px; text-align: right; white-space: nowrap;
    color: var(--text); font-weight: 600; cursor: pointer;
}
table.block-grid .bg-day:hover,
table.block-grid .bg-day.on { color: var(--danger); }
table.block-grid .bg-cell {
    width: 28px; height: 26px;
    border: 1px solid var(--border);
    background: var(--panel); cursor: pointer;
    transition: background .1s;
}
table.block-grid .bg-cell:hover { background: rgba(216, 83, 74, .16); }
table.block-grid .bg-cell.on { background: var(--danger); border-color: var(--danger); }

.block-legend { display: flex; gap: 16px; margin-top: 12px; font-size: .8rem; color: var(--muted); }
.bl-key { display: flex; align-items: center; gap: 6px; }
.bl-swatch { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
.bl-swatch.bl-free { background: var(--panel); border: 1px solid var(--border); }
.bl-swatch.bl-blocked { background: var(--danger); }
.avail-opt { font-weight: 400; color: var(--muted); }
.avail-opt { font-weight: 400; color: var(--muted); }

/* ============ Timetable result: status banner, insights, toolbar, grid ============ */

/* The generation result line reads as a banner rather than a stray sentence. */
#schedule-status:empty { display: none; }
#schedule-status {
    margin: 14px 0;
    padding: 12px 16px;
    border: 1px solid var(--border);
    border-left: 5px solid var(--muted);
    border-radius: 12px;
    background: var(--panel);
    font-weight: 600;
    font-size: .95rem;
}
#schedule-status.ok { border-color: var(--accent-line); border-left-color: var(--ok); background: var(--accent-wash); color: var(--accent-text); }
#schedule-status.warn { border-color: #fde68a; border-left-color: var(--warn); background: #fffbeb; color: #92400e; }
#schedule-status.error { border-color: #fecaca; border-left-color: var(--danger); background: #fef2f2; color: #991b1b; }

/* Insight panels (suggestions / warnings / professor gaps) — collapsible, stacked directly under
   the status so the answers sit next to the question instead of at the bottom of the page. */
.insights { display: flex; flex-direction: column; gap: 10px; margin: 0 0 16px; }
.insight {
    border: 1px solid var(--border);
    border-left: 4px solid var(--muted);
    border-radius: 12px;
    background: var(--panel-2);
    overflow: hidden;
}
.insight-head {
    display: flex; align-items: center; gap: 10px;
    padding: 11px 16px;
    cursor: pointer;
    list-style: none;
    font-weight: 700;
    font-size: .95rem;
    user-select: none;
}
.insight-head::-webkit-details-marker { display: none; }
/* A tint of its own: the card behind it is already --panel-2, so hovering had nothing to show. */
.insight-head:hover { background: var(--hover-tint); }
.insight-ico { font-size: 1.05rem; line-height: 1; flex: none; }
.insight-title { min-width: 0; }
.insight-count {
    flex: none;
    min-width: 22px; padding: 1px 8px;
    border-radius: 999px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    color: var(--muted);
    font-size: .76rem; font-weight: 700; text-align: center;
}
.insight-count:empty { display: none; }
.insight-chev { margin-left: auto; color: var(--muted); font-size: .8rem; transition: transform .15s; }
.insight[open] .insight-chev { transform: rotate(180deg); }
.insight-body { padding: 2px 16px 14px; font-size: .9rem; }
.insight-body p { margin: 0 0 8px; color: var(--muted); }
.insight-body p:last-child { margin-bottom: 0; }
.insight-loading { font-style: italic; }
.insight-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
.insight-list li { line-height: 1.45; }
.insight-dot {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    background: var(--pc, var(--muted)); margin-right: 6px; vertical-align: middle;
}

/* Panel tones — the left bar and title colour say how urgent the panel is. */
.insight-accent { border-left-color: var(--accent); }
.insight-accent .insight-title { color: var(--accent); }
.insight-warn { border-left-color: var(--warn); }
.insight-warn .insight-title { color: var(--warn); }
.insight-danger { border-left-color: var(--danger); background: #fef7f7; }
.insight-danger .insight-title { color: var(--danger); }
.insight-ok { border-left-color: var(--ok); }
.insight-info { border-left-color: #94a3b8; }

/* Save form sits with the result controls, not at the far bottom of the page. */
.tt-save { margin: 0 0 var(--tt-gap-section); }

/* Toolbar over the rendered timetable: search, view controls and the subject legend. */
.tt-toolbar {
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 10px 14px;
    margin-bottom: 0;
}
.tt-toolbar-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Display controls on top, search under them: the first row answers "what am I looking at", the
   second "where is it". */
.tt-toolbar-views { justify-content: space-between; margin-bottom: 8px; }
.tt-toolbar-views + .tt-toolbar-row { padding-top: 8px; border-top: 1px solid var(--border); }

/* The three displays as one segmented control — the choice and its alternatives are visible at
   once, which a dropdown never shows. */
.tt-seg {
    display: inline-flex; gap: 2px;
    padding: 3px;
    border: 1px solid var(--border); border-radius: 999px;
    /* A shade under the toolbar it sits in, so the track reads as a groove and the selected
       button — which is white — stands out of it. */
    background: var(--bg);
}
.tt-seg-btn {
    background: transparent; border: 0;
    border-radius: 999px;
    padding: 7px 15px;
    color: var(--muted); font-size: .84rem; font-weight: 600;
    white-space: nowrap; cursor: pointer;
}
.tt-seg-btn:hover { background: var(--hover-tint); color: var(--text); }
.tt-seg-btn.on {
    background: var(--panel);
    color: var(--text);
    box-shadow: var(--shadow-sm);
}
/* A pressed tool button (currently only "Fără culori"), so an active option looks held down. */
.tt-tool-btn.on {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent-text);
}

.tt-search { position: relative; flex: 1 1 260px; min-width: 200px; }
.tt-search input { width: 100%; padding-left: 34px; }
.tt-search-ico {
    position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
    display: flex; color: var(--muted); pointer-events: none;
}
.tt-toolbar-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.tt-tool-btn {
    background: var(--panel); border: 1px solid var(--border); color: var(--muted);
    border-radius: 999px; padding: 6px 13px; font-size: .82rem; font-weight: 600; cursor: pointer;
    white-space: nowrap;
}
.tt-tool-btn:hover { background: var(--panel-2); color: var(--text); border-color: var(--muted); }

/* Subject legend: each swatch is also a filter — click it to isolate that subject. */
.tt-legend { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.tt-legend:empty { display: none; }
/* One pill per subject, tinted with that subject's own hue — the same three tones its cells use. */
.tt-legend-chip {
    --sc-accent: oklch(0.62 0.13 var(--sc-h, 265));
    --sc-text: oklch(0.34 0.07 var(--sc-h, 265));
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 11px 5px 8px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: color-mix(in oklab, var(--sc-accent) 12%, transparent);
    color: var(--sc-text);
    font-size: .78rem; font-weight: 600; cursor: pointer;
}
/* Hover is the global darkening, in this chip's own subject hue — no rule of its own needed. */
.tt-legend-chip.on { border-color: var(--sc-accent); box-shadow: 0 0 0 2px rgba(15, 23, 42, .06); }
.tt-legend-swatch {
    width: 8px; height: 8px; border-radius: 50%; flex: none;
    background: var(--sc-accent);
}
.tt-legend-n { color: var(--muted); font-weight: 600; font-size: .74rem; }
.tt-legend-hint { margin: 10px 0 0; color: var(--muted); font-size: .78rem; }

.tt-noresults {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    margin-top: 18px; padding: 16px 18px;
    border: 1.5px dashed var(--border); border-radius: 12px;
    color: var(--muted); font-size: .9rem;
}

/* One class / professor: a collapsible card holding its week. */
/* Kept white, unlike the other sub-cards: the lesson tiles are tinted with the subject's colour
   and need a neutral ground. Only the shadow goes, so it stops reading as a card floating over
   the panel it now lives in. */
.class-group {
    margin-top: 18px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
}
.class-group-head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    background: var(--panel);
    border: none;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    font-weight: 700;
    font-size: 1.2rem;
    padding: 14px 24px;
    cursor: pointer;
}
.class-group-head:hover { background: var(--panel-2); }
.class-group-head .chevron { transition: transform .15s; color: var(--muted); font-size: .8em; }
.class-group.collapsed .chevron { transform: rotate(-90deg); }
.class-group.collapsed .tt-wrap { display: none; }
/* Colour key, so a class/professor keeps the same colour here and on its lessons. */
.class-group-head .group-color {
    flex: none;
    width: 6px; height: 26px; border-radius: 999px;
    background: var(--pc, var(--muted));
}
.class-group-head .group-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.class-group-head .group-total { margin-left: auto; color: var(--muted); font-weight: 500; font-size: .8rem; flex: none; }

/* The timetable itself: rows = periods, columns = working days. Every slot is a rounded tile of
   the grid — a lesson fills its own tile and colours it, an empty slot stays a plain one — with the
   tiles set apart by the table's own spacing rather than by rules between them. */
.tt-wrap { padding: 12px 20px 20px; overflow-x: auto; }
.tt-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: var(--tt-gap, 5px);
    font-size: .86rem;
}
.tt-table th,
.tt-table td {
    padding: 0;
    border: 0;
    border-radius: 7px;
    text-align: left;
    vertical-align: top;
}
/* Column heads read as quiet pills, not as a ruled header band. */
.tt-table thead th {
    padding: 6px 10px;
    background: var(--head-bg);
    color: var(--head-text);
    font-weight: 700;
    font-size: .82rem;
    letter-spacing: .02em;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
}
.tt-table thead th.tt-corner {
    /* Opaque, not `none`: in the school-wide grid this corner is pinned and must mask the class
       columns sliding under it. */
    background: var(--panel);
    color: var(--muted);
    font-size: .66rem;
    letter-spacing: .1em;
    text-transform: uppercase;
}
/* Today's column is tinted so "where am I in the week" needs no counting. */
.tt-table thead th.is-today { background: var(--today-bg); color: var(--today-text); }
.tt-day-short { display: none; }
.tt-cell { min-width: 132px; }
/* A free slot draws nothing at all — no tile, no fill, no tint. Only its height is kept, so the row
   it sits in stays as tall as the lessons beside it and the week keeps its shape. */
.tt-cell.tt-free { height: 58px; }

/* Every view is drawn the same way: spaced tiles on the panel's own white, no rules and no banding.
   A day is bounded by the gap between the tiles and by its heading — nothing is tinted grey behind
   the lessons. Today is the one exception: its column keeps a green wash, the only thing on the grid
   that has to be found without reading it. */
.tt-table:not(.tt-master) tbody td.is-today { background-color: var(--today-cell); }

/* ---- School-wide grid: classes across the top, days down the side ---- */
/* This table is read as a whole — which class is free when — so it is sized to the panel rather
   than left to run past its right edge. `table-layout: fixed` is what makes that possible: column
   widths come from the header row instead of from the widest lesson in each column, so the classes
   divide whatever is left beside the day rail however many of them there are. The content inside a
   cell already clips (the subject clamps to two lines, the professor and room ellipsize), so a
   narrower column loses nothing but width. It runs full-bleed inside its card so the day rail
   reaches the panel's edge. */
.tt-wrap:has(.tt-master) { padding-left: 0; padding-right: 0; }
.tt-master { table-layout: fixed; }
/* The one column with a width of its own; the rest share what remains. Wide enough for MIERCURI,
   the longest day name, at this size. */
.tt-master .tt-corner-day,
.tt-master .tt-day-head { width: 96px; min-width: 0; }
/* The gaps a spaced table leaves around a tile would let scrolled lessons show beside the pinned
   column; this ring paints them in whatever colour that row's band is. */
.tt-master .tt-corner-day,
.tt-master .tt-day-head { box-shadow: 0 0 0 var(--tt-gap, 5px) var(--row-bg, var(--panel)); }

/* The day names run down the left as a quiet rail: uppercase and letter-spaced, no box around
   them — the band behind the block is what marks where the day starts and ends. The background is
   the band's own colour rather than `transparent`: this column is pinned, so it has to mask the
   lessons scrolling underneath it, and matching the band is how it stays invisible while doing so. */
/* The bar down the left edge is the day's boundary: the label cell spans the whole block, so it
   runs the full height of that day and stops exactly where the next one starts — which the band
   alone, being a flat tint, never marked sharply. */
.tt-master .tt-day-head {
    padding: 8px 10px 8px 12px;
    border-left: 4px solid #94a6bd;
    background: var(--row-bg, var(--panel));
    color: var(--rail-text);
    font-weight: 700;
    font-size: .8rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    text-align: left;
    vertical-align: middle;
    white-space: nowrap;
}
.tt-master .tt-day-head.is-today { color: var(--today-text); border-left-color: var(--accent); }

/* Each class header keeps its own colour as an underline, matching the dot on its lessons. */
.tt-master .tt-class-head { border-bottom: 3px solid var(--pc, var(--border)); }
/* Rows stay the panel's own white — no grey banding. `--row-bg` is still what the pinned day column
   paints itself and its surrounding gap with, so it keeps masking the lessons that scroll under it;
   today's block is the one row colour left. */
.tt-master tbody tr { --row-bg: var(--panel); background: var(--row-bg); }
.tt-master tbody tr.is-today { --row-bg: var(--today-cell); }

/* Where one day ends and the next begins. Its own row, holding a single cell across the full width,
   so the rule is drawn in one piece — and in the same colour as the bar down the side of each day
   block, so the boundary and the day rail read as one thing. It sits above the pinned day column,
   whose surrounding ring would otherwise paint over the line's left end. */
.tt-master .tt-day-sep > td {
    position: relative;
    z-index: 3;
    height: 0;
    padding: 0;
    border-radius: 0;
    border-top: 2px solid #94a6bd;
}

/* Two hundred and fifty cells are on screen at once here, so this grid is deliberately quieter
   than the per-class one: paler fill, tighter rows, two lines of text instead of three. The
   colours still carry subject and professor; they just stop shouting. */
.tt-master { --tt-tint: 10%; }
.tt-master .tt-cell { min-width: 118px; }
/* An empty slot is simply a hole in the grid — no tile of its own. */
.tt-master .tt-cell.tt-free { height: 48px; }
.tt-master .tt-lesson { padding: 6px 8px 6px 9px; }
/* A long subject name gets two lines at most; the full text is in the tooltip. */
.tt-master .tt-lesson-subject {
    font-size: .78rem;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.tt-master .tt-lesson-no { font-size: .68rem; margin-right: 3px; }
.tt-master .tt-lesson-meta { font-size: .68rem; min-width: 0; margin-top: 2px; }
/* Nine class columns have to fit, so the room chip is capped tighter here than in a class's own
   table — it is the one piece allowed to clip. */
.tt-master .tt-lesson-room { max-width: 52px; font-size: .64rem; }

/* A lesson is written straight into its cell, and it is the *cell* that carries the colour: the
   fill and the left bar are the subject's, the dot beside the name is the professor's. Colouring
   the cell rather than an element inside it means the slot is filled to its full height whatever
   the tallest lesson in that row turns out to be.
   All three tones come from the subject's single hue (--sc-h, set per cell): a pale fill, the
   accent bar, and the subject's own text colour. The fill is translucent so the day band and the
   "today" tint underneath still read through it. */
.tt-wrap .tt-cell.has-lesson {
    --sc-accent: oklch(0.62 0.13 var(--sc-h, 265));
    --sc-text: oklch(0.34 0.07 var(--sc-h, 265));
    --sc-fill: color-mix(in oklab, var(--sc-accent) var(--tt-tint, 15%), transparent);
    /* An image layer, not a background colour: the day band underneath is a background colour, and
       the two have to stack — a translucent fill over the band, exactly as it already reads over the
       banded rows of the school-wide grid. */
    background-image: linear-gradient(var(--sc-fill), var(--sc-fill));
    /* The subject bar is drawn inside the cell rather than as its left border: the per-class grid
       collapses its borders, and a 3px border here would win the collapse against the 2px day rule
       next to it — the boundary between two days would change colour depending on whether a lesson
       happened to start that day. */
    box-shadow: inset 3px 0 0 var(--sc-accent);
    transition: background-image .12s;
}
.tt-wrap .tt-cell.has-lesson:hover {
    --sc-fill: color-mix(in oklab, var(--sc-accent) 26%, transparent);
}
/* Filtered out by the search box or the legend: the whole cell fades, still in place so the week
   keeps its shape. */
.tt-cell:has(.tt-lesson.dimmed) { opacity: .25; filter: saturate(.4); }

/* The lesson itself is only the text. It stays a <button> so it can be reached and activated by
   keyboard; visually there is nothing left of it. It stretches to the full height of its cell so the
   whole slot is the target — the hover tint above then reads as one block, not as a patch behind the
   text. */
.tt-lesson {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding: 7px 9px;
    text-align: left;
    font: inherit;
    color: var(--text);
    background: transparent;
    border: 0;
    border-radius: 0;
    cursor: pointer;
}
/* Buttons are green by default on this page; a lesson must not be. Staying transparent on hover is
   what lets the cell's own subject colour underneath be the thing that lights up — and the cell is
   already doing that, so the button skips the global darkening rather than tinting its text twice. */
.tt-lesson:hover { background: transparent; filter: none; }
.tt-lesson:focus-visible { outline: 2px solid var(--text); outline-offset: -2px; }

/* The subject carries its own hue in the text as well, which is what lets the fill stay this pale
   and still read as coloured. */
.tt-lesson-subject { font-weight: 600; font-size: .8rem; line-height: 1.25; color: var(--sc-text, var(--text)); }
/* The hour, now that it is written on the lesson instead of down a column. Mono, smaller and paler
   than the subject, so it reads as a marker in front of the name rather than as part of it — a
   column of these still scans as the scale the period column used to be. */
.tt-lesson-no {
    font-family: var(--mono);
    font-weight: 500;
    font-size: .72rem;
    opacity: .6;
    margin-right: 4px;
}
.tt-lesson-meta {
    display: flex; align-items: center; gap: 6px;
    margin-top: 3px; color: var(--muted); font-size: .72rem;
}
.tt-lesson-meta.is-prof { color: var(--meta-text); }
.tt-lesson-meta-name { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tt-lesson-dot {
    width: 8px; height: 8px; border-radius: 50%; flex: none;
    background: var(--pc, var(--muted));
}
/* The room sits at the far end of that line as a small mono chip — a code, not prose. It is the
   first thing allowed to shrink: a clipped room still leaves the teacher's name readable. */
.tt-lesson-room {
    display: flex; align-items: center; gap: 4px;
    flex: 0 100 auto;
    min-width: 0;
    max-width: 74px;
    margin-left: auto;
    padding: 1px 5px;
    border-radius: 4px;
    background: rgba(255, 255, 255, .6);
    color: #5b6678;
    font-family: var(--mono);
    font-size: .68rem;
    white-space: nowrap;
}
.tt-lesson-room > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tt-lesson-room-ico { display: inline-flex; flex: none; }
.tt-lesson-room-ico svg { display: block; width: 12px; height: 12px; }

/* ---- "Fără culori": the same grid read in one colour ---- */
/* Everything coloured in a timetable derives from three custom properties — the subject's accent and
   text tones, and a person's colour — so dropping the colours is mostly a matter of redefining those
   three as greys, in one place, for every piece that reads them: cells, legend chips, the professor
   dots, the colour keys on the card headings and the waiting list. */
body.tt-mono .tt-wrap .tt-cell.has-lesson,
body.tt-mono .tt-legend-chip,
body.tt-mono .waiting-card {
    --sc-accent: #aab3c0;
    --sc-text: var(--text);
}
body.tt-mono [class*="person-color-"] { --pc: #9aa6b8; }

/* The lesson itself becomes a plain white card, held by a hairline instead of by a fill — the
   subject bar down its left edge goes with the colours it was made of. */
body.tt-mono .tt-wrap .tt-cell.has-lesson {
    background-image: none;
    background-color: var(--panel);
    box-shadow: inset 0 0 0 1px #dbe1ea;
}
body.tt-mono .tt-wrap .tt-cell.has-lesson:hover { background-color: var(--head-bg); }
body.tt-mono .tt-legend-chip,
body.tt-mono .waiting-card { background: var(--panel); }

/* Today is the one thing that still has to be found without being read, so it keeps a marker — a
   heavier underline under its heading rather than the green wash, which would be the only colour
   left on the grid. */
body.tt-mono .tt-table thead th.is-today {
    background: #e3e8ef;
    color: var(--text);
    box-shadow: inset 0 -3px 0 #7d8a9b;
}
body.tt-mono .tt-table:not(.tt-master) tbody td.is-today { background-color: transparent; }
body.tt-mono .tt-master tbody tr.is-today { --row-bg: var(--panel); }
body.tt-mono .tt-master .tt-day-head.is-today { color: #5b6a80; border-left-color: #7d8a9b; }

/* Only one of the two hints under the legend applies at a time. */
body.tt-mono .tt-hint-color,
body:not(.tt-mono) .tt-hint-mono { display: none; }

/* Narrow screens: abbreviated day names and tighter cards. */
@media (max-width: 900px) {
    .tt-day-full { display: none; }
    .tt-day-short { display: inline; }
    .tt-cell { min-width: 104px; }
}

/* Printing an orar is the point of the page: drop every control and keep the coloured grid. */
@media print {
    /* A timetable is wide whichever view is picked — five day columns, or one column per class. */
    @page { size: landscape; margin: 12mm; }
    /* The school-wide grid is the widest of the lot, so it prints a size down and lets its columns
       shrink to their content. */
    .tt-master { font-size: .72rem; }
    .tt-master .tt-cell { min-width: 0; }

    .app-top, .sidebar, .waiting, .tt-setup, .tt-toolbar, .tt-save, .tt-saved, .insights,
    .tt-noresults, .toast { display: none !important; }
    .app-shell { display: block; }
    .main { padding: 0; }
    body { background: #fff; }
    .class-group { break-inside: avoid; box-shadow: none; margin-top: 12px; }
    .class-group.collapsed .tt-wrap { display: block; }
    .class-group-head .chevron { display: none; }
    .tt-cell { break-inside: avoid; }
    /* Browsers drop backgrounds when printing, and here the backgrounds carry meaning: the subject
       colour lives on the cell and the day bands of the school-wide grid are its separators. */
    .tt-cell, .tt-table thead th, .class-group-head .group-color, .tt-master tbody tr {
        -webkit-print-color-adjust: exact; print-color-adjust: exact;
    }
}

/* A wrapping row of form fields (used by the room form: name + capacity). */
.form-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
.form-row > input[type="text"] { flex: 1; min-width: 180px; }

/* Room specialization picker: a dropdown that adds removable subject chips. */
.spec-picker { display: flex; flex-direction: column; gap: 8px; }
.spec-picker select { max-width: 320px; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 6px 3px 10px;
    border-radius: 999px;
    background: var(--sc-chip-bg, rgba(120, 120, 140, 0.14));
    font-size: .82rem;
    color: var(--text);
}
.chip-x {
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    color: var(--muted);
    padding: 0 2px;
}
.chip-x:hover { color: var(--text); }

/* ============ Subjects manager ============ */

.panel-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    border-bottom: 1px solid var(--border);
    padding-bottom: 8px;
    margin-bottom: 6px;
}
.panel-head h2 { border: none; padding: 0; margin: 0; }
.count-badge { color: var(--muted); font-size: .82rem; }

.search-field { position: relative; margin-bottom: 12px; }
.search-field input { width: 100%; padding-left: 34px; }
.search-icon {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    color: var(--muted);
    pointer-events: none;
}

.subject-add { margin-bottom: 16px; }
.subject-add input { flex: 1; min-width: 0; }
.subject-add button { display: flex; align-items: center; gap: 6px; white-space: nowrap; }

.subject-cards { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

@keyframes riseIn {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: translateY(0); }
}

.subject-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    animation: riseIn .28s ease both;
}
.subject-card.dragging { opacity: .5; }
@media (prefers-reduced-motion: reduce) { .subject-card { animation: none; } }

.subject-grip { display: flex; color: var(--muted); cursor: grab; flex-shrink: 0; }
.subject-card.dragging .subject-grip { cursor: grabbing; }

.subject-avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .75rem;
    font-weight: 700;
    flex-shrink: 0;
}

.subject-name { flex: 1; min-width: 0; font-size: .95rem; }
.subject-edit { flex: 1; min-width: 0; }

/* Card actions are always visible (clearer for non-technical users than hover-only icons). */
.subject-actions { display: flex; gap: 6px; flex-wrap: wrap; }

.icon-btn {
    display: flex;
    align-items: center;
    background: transparent;
    border: 1px solid transparent;
    color: var(--muted);
    padding: 4px;
}
.icon-btn:hover { background: transparent; color: var(--text); }
.icon-btn.danger:hover { color: var(--danger); }
.icon-btn.ok:hover { color: var(--ok); }

.confirm-text { color: var(--danger); font-size: .85rem; }
.confirm-btn { background: transparent; border: 1px solid var(--border); color: var(--muted); font-size: .8rem; padding: 4px 10px; }
.confirm-btn:hover { background: transparent; color: var(--text); }
.confirm-btn.danger { border-color: var(--danger); color: var(--danger); }
.confirm-btn.danger:hover { background: var(--danger); color: #fff; }

.list-empty {
    text-align: center;
    padding: 32px 0;
    color: var(--muted);
    font-size: .9rem;
}
.list-empty svg { color: var(--border); margin-bottom: 6px; }

/* ============ Entity cards (classes, professors, partnerships, lessons) ============ */
/* Modeled on the subjects manager so all manage pages share one card idiom. */
.entity-add input, .entity-add select { flex: 1 1 150px; min-width: 0; }
.entity-add input[type="number"] { flex: 0 0 80px; }
.entity-add button { white-space: nowrap; }

.entity-cards {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.entity-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    animation: riseIn .28s ease both;
}
@media (prefers-reduced-motion: reduce) { .entity-card { animation: none; } }

.entity-avatar {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .75rem;
    font-weight: 700;
    flex-shrink: 0;
}

.entity-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.entity-main .entity-name {
    font-size: .95rem; font-weight: 600;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.entity-main .entity-meta {
    color: var(--muted); font-size: .8rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Reuse the subjects' hover-revealed action buttons on entity cards too. */
.entity-card:hover .subject-actions,
.entity-card:focus-within .subject-actions { opacity: 1; }
.subject-actions.is-confirming { opacity: 1; }

/* ============ Subject color palette (pastel, stable per subject) ============ */
.subject-color-0 { background: #dbeafe; border-left-color: #3b82f6; --sc-accent: #3b82f6; }
.subject-color-1 { background: #dcfce7; border-left-color: #22c55e; --sc-accent: #16a34a; }
.subject-color-2 { background: #ede9fe; border-left-color: #8b5cf6; --sc-accent: #7c3aed; }
.subject-color-3 { background: #ffedd5; border-left-color: #f97316; --sc-accent: #ea580c; }
.subject-color-4 { background: #fce7f3; border-left-color: #ec4899; --sc-accent: #db2777; }
.subject-color-5 { background: #cffafe; border-left-color: #06b6d4; --sc-accent: #0891b2; }
.subject-color-6 { background: #fef9c3; border-left-color: #eab308; --sc-accent: #ca8a04; }
.subject-color-7 { background: #fee2e2; border-left-color: #ef4444; --sc-accent: #dc2626; }
.subject-color-8 { background: #e0e7ff; border-left-color: #6366f1; --sc-accent: #4f46e5; }
.subject-color-9 { background: #ccfbf1; border-left-color: #14b8a6; --sc-accent: #0d9488; }
.subject-color-10 { background: #fae8ff; border-left-color: #d946ef; --sc-accent: #c026d3; }
.subject-color-11 { background: #ecfccb; border-left-color: #84cc16; --sc-accent: #65a30d; }
.subject-color-12 { background: #ffe4e6; border-left-color: #f43f5e; --sc-accent: #e11d48; }
.subject-color-13 { background: #e0f2fe; border-left-color: #0ea5e9; --sc-accent: #0284c7; }
.subject-color-14 { background: #fef3c7; border-left-color: #f59e0b; --sc-accent: #d97706; }
.subject-color-15 { background: #f5e6d3; border-left-color: #b45309; --sc-accent: #92400e; }
/* Deeper twins of the first eight hues. The timetable hands colours out most-taught subject first,
   so these land on the rarer subjects, where a close-but-deeper tint is enough to tell them apart. */
.subject-color-16 { background: #bfdbfe; border-left-color: #2563eb; --sc-accent: #1d4ed8; }
.subject-color-17 { background: #bbf7d0; border-left-color: #16a34a; --sc-accent: #15803d; }
.subject-color-18 { background: #ddd6fe; border-left-color: #7c3aed; --sc-accent: #6d28d9; }
.subject-color-19 { background: #fed7aa; border-left-color: #ea580c; --sc-accent: #c2410c; }
.subject-color-20 { background: #fbcfe8; border-left-color: #db2777; --sc-accent: #be185d; }
.subject-color-21 { background: #a5f3fc; border-left-color: #0891b2; --sc-accent: #0e7490; }
.subject-color-22 { background: #fde68a; border-left-color: #d97706; --sc-accent: #b45309; }
.subject-color-23 { background: #fecaca; border-left-color: #dc2626; --sc-accent: #b91c1c; }

/* ============ Person color palette (professors & classes, stable per name) ============ */
/* Only sets --pc, never a background: a lesson card is already tinted by its subject, and the
   professor's colour rides along as the stripe on its right edge / the dot next to the name. */
.person-color-0 { --pc: #2563eb; }
.person-color-1 { --pc: #059669; }
.person-color-2 { --pc: #7c3aed; }
.person-color-3 { --pc: #ea580c; }
.person-color-4 { --pc: #db2777; }
.person-color-5 { --pc: #0891b2; }
.person-color-6 { --pc: #ca8a04; }
.person-color-7 { --pc: #dc2626; }
.person-color-8 { --pc: #4f46e5; }
.person-color-9 { --pc: #0d9488; }
.person-color-10 { --pc: #b45309; }
.person-color-11 { --pc: #6d28d9; }
.person-color-12 { --pc: #be123c; }
.person-color-13 { --pc: #15803d; }

/* ============ Manage pages: help toggle, form cards, room table ============ */
/* Shared by all manage pages (Materii, Clase, Profesori, Cabinete, Ore comune, Reguli). */
/* Panel head lays a title/count group beside a right-aligned help toggle. */
.panel-head-main { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.panel-optional { font-weight: 500; color: var(--muted); font-size: .82em; }

/* Header tools: the CSV pair plus the help "?" button. */
.panel-tools { display: flex; align-items: center; gap: 8px; flex: none; }
.csv-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 11px; border-radius: 999px;
    border: 1px solid var(--border); background: var(--panel); color: var(--muted);
    font-size: .8rem; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.csv-btn:hover { background: var(--panel-2); color: var(--text); border-color: var(--accent); }
.csv-btn span { display: inline-flex; }
/* The file picker is opened by the Import button, never shown. */
.csv-file { display: none; }

.help-toggle {
    flex: none;
    width: 26px; height: 26px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: 999px;
    background: var(--panel); color: var(--muted);
    font-size: .82rem; font-weight: 700; line-height: 1; cursor: pointer;
}
.help-toggle:hover { background: var(--panel-2); color: var(--text); }
.help-toggle[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }

/* Collapsible help box (green tinted, matches the accent). */
.info-box {
    margin: 4px 0 14px;
    padding: 12px 14px;
    background: var(--accent-wash);
    border: 1px solid var(--accent-line);
    border-radius: 10px;
    font-size: .84rem;
    line-height: 1.55;
    color: var(--accent-text);
}

/* Form card: a bordered, subtly-tinted panel grouping an add form's fields. Sits on the white
   manage panel, so it uses the off-white surface (like entity cards) to read as its own card. */
.field-card {
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 18px 20px;
    gap: 18px;
}
.field-grid { display: grid; grid-template-columns: var(--field-cols, 1fr); gap: 14px; }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field > input, .field > select { width: 100%; }
.field-label { font-size: .78rem; font-weight: 600; color: var(--muted); }
.field-opt { font-weight: 500; color: var(--muted); opacity: .8; }
.field-divider { height: 1px; background: var(--border); }
.field .field-help { margin: 2px 0 0; }

/* Inline add-forms (subjects, classes, partnerships) sit in the same card idiom, but keep a
   tighter gap than the block field cards and stay aligned to the button baseline. */
.form.inline.field-card { gap: 10px 12px; align-items: center; }
/* The multi-line "paste a list" forms as cards. */
.form.field-card.entity-add { gap: 12px; }

@media (max-width: 620px) {
    .field-grid { grid-template-columns: 1fr !important; }
}

/* Entity table — the shared list idiom for every manage page (Materii, Clase, Profesori,
   Cabinete, Ore comune). Each table sets its own column template via inline --etable-cols. */
.etable { margin-top: 6px; }
.etable-head {
    display: grid; grid-template-columns: var(--etable-cols); gap: 10px;
    padding: 9px 14px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-bottom: none;
    border-radius: 10px 10px 0 0;
    font-size: .68rem; font-weight: 700; color: var(--muted);
    text-transform: uppercase; letter-spacing: .04em;
}
.etable-body {
    border: 1px solid var(--border);
    border-radius: 0 0 10px 10px;
    overflow: hidden;
    background: var(--panel);
}
.etable-row {
    display: grid; grid-template-columns: var(--etable-cols); gap: 10px; align-items: center;
    padding: 11px 14px; border-top: 1px solid var(--border);
    animation: riseIn .28s ease both;
}
.etable-row:first-child { border-top: none; }
.etable-row:hover { background: var(--panel-2); }
.etable-row.dragging { opacity: .5; }
@media (prefers-reduced-motion: reduce) { .etable-row { animation: none; } }

.etable-badge { width: 28px; height: 28px; font-size: .72rem; }
.etable-grip { display: flex; color: var(--muted); cursor: grab; }
.etable-row.dragging .etable-grip { cursor: grabbing; }
.etable-name {
    font-size: .9rem; font-weight: 600;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.etable-muted { font-size: .84rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.etable-chips { display: flex; gap: 5px; flex-wrap: wrap; }
.cell-dash { color: var(--muted); opacity: .55; }
.etable-actions { display: flex; gap: 4px; justify-self: end; }
/* Inline icon action buttons sit in a bordered box so they read as buttons in a dense row. */
.etable-actions .icon-btn { border-color: var(--border); border-radius: 7px; padding: 5px; }
.etable-actions .icon-btn:hover { background: var(--panel-2); }

/* Read-only pill tags shown inside a table row. */
.tag {
    display: inline-flex; align-items: center;
    padding: 2px 9px; border-radius: 999px;
    font-size: .75rem; font-weight: 500; white-space: nowrap;
}
.tag-class { background: #dbeafe; color: #1e40af; }
.tag-disc { background: #ffedd5; color: #c2410c; }

/* Status pills on the accounts page. Built from the theme's own tokens, so the dark theme moves
   them without a second set of rules. */
.tag-ok { background: var(--accent-soft); color: var(--accent-text); }
.tag-warn { background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn); }
.tag-muted { background: var(--panel-2); color: var(--muted); border: 1px solid var(--border); }
/* Error/Critical rows on the logs page. */
.tag-danger { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }

/* A pill that is also a switch (enable / disable an account). */
.tag-button { cursor: pointer; border: 1px solid transparent; font-family: inherit; }
.tag-button:hover { filter: brightness(.96); }
.tag-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Inline delete confirmation spans the whole row. */
.etable-row.confirming { display: flex; justify-content: space-between; gap: 12px; align-items: center; }
.etable-confirm-text { font-size: .88rem; color: var(--danger); }
.etable-confirm-actions { display: flex; gap: 6px; flex: none; }

/* On narrow screens the table scrolls horizontally rather than crushing columns. */
@media (max-width: 760px) {
    .etable { overflow-x: auto; }
    .etable-head, .etable-body { min-width: 600px; }
}

/* ============ Logs page ============ */
/* The full message and stack trace, shown under a row when its toggle is expanded. Not part of
   the row's own grid — a plain block, so it can wrap instead of fighting the column widths. */
.log-details {
    padding: 12px 14px;
    border-top: 1px solid var(--border);
    background: var(--panel-2);
    font-size: .82rem;
}
.log-details pre {
    margin: 6px 0 0;
    white-space: pre-wrap;
    word-break: break-word;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    color: var(--muted);
}
.log-toggle {
    background: none; border: none; color: var(--muted); cursor: pointer;
    padding: 4px 6px; font-size: .95rem; line-height: 1;
}
.log-toggle:hover { color: var(--text); }

.log-pagination {
    display: flex; align-items: center; justify-content: center; gap: 14px;
    margin-top: 14px; font-size: .85rem; color: var(--muted);
}
.log-pagination button { padding: 6px 14px; }
.log-pagination button:disabled { opacity: .5; cursor: default; }

/* ============ Waiting list (right) ============ */
.waiting {
    background: var(--panel);
    border-left: 1px solid var(--border);
    padding: 24px 18px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}
.waiting-head { display: flex; align-items: center; gap: 8px; }
.waiting-head h2 { margin: 0; border: none; padding: 0; }
.waiting-count {
    background: var(--warn);
    color: #fff;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 700;
    padding: 1px 9px;
}
#waiting-list { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
/* Built from the subject's hue exactly like the grid's cells, so an unplaced lesson is recognisable
   at a glance as the same subject. */
.waiting-card {
    --sc-accent: oklch(0.62 0.13 var(--sc-h, 265));
    --sc-text: oklch(0.34 0.07 var(--sc-h, 265));
    border: 1px solid rgba(15, 23, 42, .07);
    border-left: 3px solid var(--sc-accent);
    border-radius: 7px;
    padding: 10px 12px;
    background: color-mix(in oklab, var(--sc-accent) var(--tt-tint, 15%), transparent);
}
.waiting-card .wc-subject { font-weight: 600; color: var(--sc-text); }
.waiting-card .wc-meta { color: var(--muted); font-size: .8rem; margin-top: 2px; }
.waiting-card .wc-reason { color: var(--muted); font-size: .78rem; margin-top: 4px; font-style: italic; }

/* ============ Suggested adjustments (inside the insights panel) ============ */
.adjust-btn { background: var(--accent); padding: 4px 10px; font-size: .8rem; flex: none; }
.adjust-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.adjust-list li { display: flex; align-items: center; gap: 8px; }
.adjust-text { color: var(--text); font-size: .9rem; }

.toast {
    position: fixed;
    top: 16px;
    right: 16px;
    padding: 12px 16px;
    border-radius: 8px;
    background: var(--danger);
    color: white;
    font-weight: 600;
    box-shadow: 0 6px 20px rgba(0,0,0,.25);
    z-index: 50;
    max-width: 360px;
}

/* ============ Accessibility helpers (labelled buttons, guide, steps, help) ============ */

/* Labelled action buttons — icon + text, always visible, clear for non-technical users. */
.label-btn {
    display: inline-flex; align-items: center; gap: 5px;
    background: var(--panel); border: 1px solid var(--border); color: var(--muted);
    border-radius: 8px; padding: 5px 10px; font-size: .82rem; font-weight: 600; cursor: pointer;
}
.label-btn svg { flex: none; }
.label-btn:hover { background: var(--panel); color: var(--text); border-color: var(--muted); }
.label-btn.ok { color: var(--ok); border-color: var(--accent-line); }
.label-btn.ok:hover { background: var(--ok); color: #fff; border-color: var(--ok); }
.label-btn.danger { color: var(--danger); border-color: #fca5a5; }
.label-btn.danger:hover { background: var(--danger); color: #fff; border-color: var(--danger); }

/* "Pasul N" chip next to a page title. */
.step-chip {
    display: inline-block; background: var(--accent); color: #fff;
    font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    padding: 2px 8px; border-radius: 999px; vertical-align: middle; margin-right: 8px;
}

/* Getting-started guide on the timetable page. */
.guide {
    border: 1px solid var(--border); background: var(--panel-2);
    border-radius: 12px; padding: 16px 18px; margin: 4px 0 14px;
}
.guide h3 { margin: 0 0 12px; font-size: 1.02rem; }
.guide-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.guide-steps li { display: flex; gap: 12px; align-items: flex-start; }
.guide-steps li div { color: var(--muted); font-size: .9rem; padding-top: 2px; }
.guide-steps li div b { color: var(--text); }
.gs-n {
    flex: none; width: 24px; height: 24px; border-radius: 50%;
    background: var(--accent); color: #fff; font-weight: 700; font-size: .82rem;
    display: grid; place-items: center;
}
.guide-note { margin: 12px 0 0; color: var(--muted); font-size: .85rem; }

/* Small helper text under a field. */
.field-help { color: var(--muted); font-size: .8rem; margin: 2px 0 0; }
.inline-lab { flex: none; }

/* Collapsible optional restrictions on the professor form. */
/* Collapsible restrictions: a divider above, title left, rotating chevron on the right. */
/* The card's own 18px gap does the spacing, so this section adds none of its own. */
.avail-details { border: none; border-top: 1px solid var(--border); border-radius: 0; padding: 0; }
.avail-details > summary {
    position: relative; cursor: pointer; list-style: none;
    padding: 14px 24px 0 0; color: var(--text);
    font-size: .95rem; font-weight: 600;
}
.avail-details > summary::-webkit-details-marker { display: none; }
.avail-details > summary::after {
    content: "▾"; position: absolute; right: 2px; top: 15px;
    color: var(--muted); transition: transform .15s;
}
.avail-details:not([open]) > summary::after { transform: rotate(-90deg); }
.avail-body { padding: 14px 0 4px; }

/* Materii predate: header row (label left, add button right) + green "subject" cards. */
.section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.section-label { font-size: .85rem; font-weight: 600; color: var(--text); }

/* ============ Home / start page (full-screen, light) ============ */
.home-view { min-width: 0; }
.home-landing {
    /* Home-only palette (green). Scoped here so the rest of the app keeps its
       original blue — descendants inherit these via var(). */
    --accent: #4a7c62;
    --accent-hover: #3c6851;
    --border: #dbe9df;
    --text: #16241b;
    --muted: #5f6f64;

    min-height: 100vh;
    background:
        radial-gradient(760px 400px at 90% -10%, rgba(74, 124, 98, .07), transparent 60%),
        linear-gradient(180deg, #ffffff 0%, #f7f9f8 100%);
    padding: 26px clamp(20px, 5vw, 60px) 60px;
}
.home-landing > * { max-width: 1280px; margin: 0 auto; }

.home-top {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: clamp(24px, 6vh, 56px);
}
.home-brand { display: flex; align-items: center; gap: 11px; }
/* The site's own favicon is the wordmark's tile everywhere it appears — the landing's header and
   footer and the rail. The file already carries its green rounded square, so it needs no tinted
   wrapper behind it; only the radius, so the shadow follows its shape. */
.brand-favicon {
    display: block;
    width: 38px;
    height: 38px;
    flex: none;
    border-radius: 10px;
    box-shadow: 0 6px 16px rgba(74, 124, 98, .3);
}
.sidebar-brand .brand-favicon {
    width: 34px;
    height: 34px;
    border-radius: 9px;
    box-shadow: 0 4px 12px rgba(74, 124, 98, .26);
}
.home-brand-name { font-size: 1.2rem; font-weight: 800; letter-spacing: -.01em; color: var(--text); }

/* Header nav (guide / login / profile / jump-to-timetable). */
.home-nav { display: flex; align-items: center; gap: 4px; }
.home-nav-item {
    background: transparent; border: 0; color: var(--muted);
    font-weight: 600; font-size: .92rem; padding: 9px 15px; border-radius: 999px; cursor: pointer;
}
.home-nav-item:hover { color: var(--accent); background: var(--accent-soft); }
/* Language switch: three codes in a groove, the one in force lifted out of it in white — the same
   segmented idiom the timetable's view switch uses, at nav size. */
/* Theme button: icon only, the same round shape and size as the language button beside it, so the
   two read as one pair of settings rather than two unrelated controls. */
.theme-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px;
    margin-right: 6px;
    padding: 0;
    border: 1px solid var(--border); border-radius: 999px;
    background: var(--panel);
    color: var(--muted);
    cursor: pointer;
}
.theme-toggle:hover { border-color: var(--muted); background: var(--panel-2); color: var(--text); }
.theme-icon { display: inline-flex; }

/* Language picker: a globe and the current language's own name, opening a list of the three.
   The button carries the answer ("Română"), so the current language is readable without opening
   anything; the list is only needed to change it. */
.lang-switch { position: relative; margin-right: 6px; }
.lang-toggle {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 6px 10px 6px 9px;
    border: 1px solid var(--border); border-radius: 999px;
    background: var(--panel);
    color: var(--text);
    font-size: .84rem; font-weight: 600;
    cursor: pointer;
}
.lang-toggle:hover { border-color: var(--muted); background: var(--panel-2); }
.lang-globe { display: inline-flex; color: var(--muted); }
.lang-caret { font-size: .7rem; color: var(--muted); line-height: 1; }
.lang-toggle[aria-expanded="true"] .lang-caret { transform: rotate(180deg); }

/* Anchored to the button and right-aligned: the switcher sits near the right edge of the bar, so a
   left-aligned menu would hang off the page. */
.lang-menu {
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 40;
    min-width: 168px;
    margin: 0; padding: 4px;
    list-style: none;
    background: var(--panel);
    border: 1px solid var(--border); border-radius: 12px;
    box-shadow: var(--shadow-lg);
}
.lang-option {
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border: 0; border-radius: 8px;
    background: transparent;
    color: var(--text);
    font-size: .88rem; font-weight: 500;
    text-align: left;
    cursor: pointer;
}
.lang-option:hover { background: var(--panel-2); }
/* The code sits in a fixed-width slot so the three names start on the same line. */
.lang-code {
    flex: none; width: 26px;
    color: var(--muted);
    font-size: .72rem; font-weight: 700; letter-spacing: .06em;
}
/* The one in force is marked by a tick after the name rather than by a highlight, which at this
   size reads as hover instead of as a state. */
.lang-option[aria-checked="true"] { font-weight: 700; }
.lang-option[aria-checked="true"]::after {
    content: "✓"; margin-left: auto; color: var(--accent); font-weight: 700;
}
.lang-option[aria-checked="true"] .lang-code { color: var(--accent); }

.home-skip {
    background: var(--accent); border: 1px solid var(--accent); color: #fff;
    padding: 11px 20px; border-radius: 999px; font-weight: 700; font-size: .94rem; cursor: pointer;
    margin-left: 6px; box-shadow: 0 6px 16px rgba(74, 124, 98, .24);
}
.home-skip:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

.home-hero {
    display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.2fr); gap: 24px;
    align-items: center; margin-bottom: clamp(24px, 5vh, 44px);
}
/* Let both columns shrink freely so the embedded scene can never blow the track out. */
.home-hero-text, .home-hero-art { min-width: 0; }
.home-eyebrow {
    display: inline-block;
    font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .12em;
    color: var(--accent); margin-bottom: 14px;
}
.home-hero h1 {
    margin: 0 0 14px; color: var(--text);
    font-size: clamp(2rem, 4.6vw, 3.1rem); line-height: 1.06; letter-spacing: -.025em;
    text-wrap: balance;
}
.home-hero p { margin: 0 0 24px; color: var(--muted); max-width: 46ch; font-size: 1.05rem; }
.home-cta-row { display: flex; flex-wrap: wrap; gap: 12px; }
.home-btn {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 12px 20px; border-radius: 12px; font-weight: 700; font-size: .96rem;
    cursor: pointer; border: 1px solid transparent;
}
.home-btn span { display: inline-flex; }
.home-btn.primary { background: var(--accent); color: #fff; box-shadow: 0 8px 20px rgba(74, 124, 98, .26); }
.home-btn.primary:hover { background: var(--accent-hover); }
.home-btn.ghost { background: #fff; color: var(--text); border-color: var(--border); }
.home-btn.ghost:hover { border-color: var(--accent); color: var(--accent); }

.home-hero-art { display: flex; justify-content: center; }
/* The scene and the sketch that stands in for it share one box, so swapping them shifts nothing. */
.hero-scene-slot { position: relative; width: 100%; max-width: 900px; aspect-ratio: 16 / 12; }
.hero-scene-slot > * { position: absolute; inset: 0; width: 100%; height: 100%; }
.home-hero-scene {
    display: block; border: 0;
    /* Transparent + no frame so the scene blends into the hero with no visible
       panel edges; the scene itself is drawn on a transparent stage. */
    background: transparent;
    opacity: 0; transition: opacity .45s ease;
}
.home-hero-scene.ready { opacity: 1; }
.hero-scene-poster { transition: opacity .45s ease; }
.hero-scene-poster.done { opacity: 0; }
/* The poster used to breathe so it wouldn't read as a broken image. It holds still now: it draws
   the scene's opening frame exactly, and the scene holds that frame too until it starts. */

/* On the landing, give the guide a plain white card look. */
.home-landing .guide { background: #fff; box-shadow: 0 4px 14px rgba(15, 23, 42, .04); }

/* Dark full-width landing footer */
.site-footer {
    background: #1f4034; color: #cfe6d8;
    padding: 56px clamp(20px, 5vw, 60px) 44px;
}
.sf-inner {
    max-width: 1280px; margin: 0 auto;
    display: grid; grid-template-columns: 1.7fr 1fr 1fr; gap: 40px; align-items: start;
}
.sf-col { display: flex; flex-direction: column; gap: 12px; }
.sf-col h4 { margin: 0 0 4px; color: #fff; font-size: 1.15rem; font-weight: 700; }
.sf-brand { justify-content: space-between; min-height: 168px; gap: 20px; }
.sf-logo { display: flex; align-items: center; gap: 12px; }
.sf-logo-name { font-size: 1.3rem; font-weight: 800; color: #fff; letter-spacing: -.01em; }
.sf-copy { margin: 0; color: #9dc4b1; font-size: .9rem; }
.sf-link, .sf-social {
    background: transparent; border: 0; padding: 0; text-align: left; width: fit-content;
    color: #cfe6d8; font: inherit; font-size: .98rem; cursor: pointer; text-decoration: none;
    display: inline-flex; align-items: center; gap: 10px;
}
/* The one place the darkening rule is the wrong way round: these sit on the dark green footer,
   where "brighter" is the hover, not "darker". They light their own text instead. */
.sf-link:hover, .sf-social:hover { color: #fff; filter: none; }
.sf-social svg { width: 20px; height: 20px; flex: none; }

@media (max-width: 760px) {
    .sf-inner { grid-template-columns: 1fr; gap: 28px; }
    .sf-brand { min-height: 0; }
}

@media (max-width: 760px) {
    .home-hero { grid-template-columns: 1fr; }
    .home-hero-art { display: none; }
}

/* Large / maximized windows: keep the widened landing balanced. */
@media (min-width: 1500px) {
    .home-hero { gap: 48px; margin-bottom: clamp(28px, 5vh, 52px); }
}

/* ============ Responsive ============ */
@media (max-width: 1000px) {
    .app-shell,
    .app-shell:has(.waiting[hidden]) { grid-template-columns: 1fr; }
    .sidebar {
        position: static;
        height: auto;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
    }
    .side-nav { flex-direction: row; flex-wrap: wrap; }
    /* The rail is a horizontal strip here, so the head sits inline with the items rather than
       spanning the row above them — and it lays its two parts out side by side, not stacked. */
    .sidebar-head { width: auto; flex-direction: row; padding-bottom: 0; }
    .waiting {
        position: static;
        height: auto;
        border-left: none;
        border-top: 1px solid var(--border);
    }
    /* One column here, so the two-column placement above would conjure an empty second track:
       everything goes back to stacking in document order. Nothing sticks to the top of the window
       either, so the bar drops its fixed height and is free to wrap its nav onto a second line. */
    .app-shell:has(.app-top) { grid-template-rows: none; }
    .app-shell:has(.app-top) > .app-top,
    .app-shell:has(.app-top) > .sidebar,
    .app-shell:has(.app-top) > .main,
    .app-shell:has(.app-top) > .waiting { grid-column: 1; grid-row: auto; }
    .app-top {
        position: static;
        height: auto;
        flex-wrap: wrap;
        padding-block: 10px;
    }
}

/* ============ Account pages (sign in, change password) ============ */
/* These two have no rail and no top bar: they are one card on an empty page, because the only
   thing to do on them is the one thing they ask for. */

.auth-body { background: var(--bg); }

.auth-shell {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 32px 20px;
}

.auth-card {
    width: min(520px, 100%);
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 16px;
    box-shadow: var(--shadow-md);
    padding: 36px 40px 40px;
}

.auth-brand {
    display: flex; align-items: center; gap: 14px;
    color: var(--text); text-decoration: none;
    font-weight: 800; font-size: 1.35rem;
    letter-spacing: -.01em;
    margin-bottom: 22px;
}

.auth-brand .brand-favicon { width: 46px; height: 46px; border-radius: 12px; }

.auth-card h1 {
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -.02em;
    margin: 0 0 26px;
}

.auth-lead { color: var(--muted); font-size: .9rem; margin: -18px 0 22px; }

/* Opt-in centring, used by the sign-in heading. A class rather than a rule on .auth-card h1 so the
   other two auth pages keep the alignment they were given. */
.center { text-align: center; }

/* Says why the visitor is here when they had no choice about it (a one-time password). */
.auth-notice {
    background: var(--accent-wash);
    border: 1px solid var(--accent-line);
    color: var(--accent-text);
    border-radius: 9px;
    padding: 10px 12px;
    font-size: .87rem;
    margin: 0 0 18px;
}

.auth-form { display: flex; flex-direction: column; gap: 20px; }

.auth-field { display: flex; flex-direction: column; gap: 8px; }
.auth-field > span, .auth-field > label { font-size: .95rem; font-weight: 700; color: var(--muted); }

/* A filled field rather than an outlined one: on a white card the fill is what marks out where to
   type, which is the whole job of these two inputs. */
.auth-field input {
    height: 52px;
    padding: 0 16px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--auth-field-bg);
    color: var(--text);
    font: inherit;
    font-size: 1rem;
}
.auth-field input:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* The password field and its show/hide button share one box; the button sits inside the field's
   right-hand padding, which is why the input reserves room for it. */
.auth-password { position: relative; display: flex; }
.auth-password input { flex: 1; padding-right: 92px; }

.auth-reveal {
    position: absolute;
    right: 6px;
    top: 6px;
    height: 40px;
    padding: 0 12px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--accent-text);
    font: inherit;
    font-size: .88rem;
    font-weight: 700;
    cursor: pointer;
}
.auth-reveal:hover { background: var(--accent-soft); }
.auth-reveal:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.auth-hint { color: var(--muted); font-size: .8rem; margin: -4px 0 0; }

/* role="alert", so it is announced when it appears rather than only being seen. */
.auth-error {
    background: color-mix(in srgb, var(--danger) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
    color: var(--danger);
    border-radius: 8px;
    padding: 10px 14px;
    font-size: .88rem;
    font-weight: 600;
    margin: 0;
}

.auth-submit {
    margin-top: 4px;
    height: 56px;
    border: none; border-radius: 10px;
    background: var(--accent); color: #fff;
    font: inherit; font-size: 1.05rem; font-weight: 800;
    cursor: pointer;
    transition: background 140ms ease;
}
.auth-submit:hover:not(:disabled) { background: var(--accent-hover); }
.auth-submit:disabled { opacity: .6; cursor: progress; }

.auth-foot { margin: 16px 0 0; font-size: .95rem; color: var(--muted); text-align: center; }
.auth-foot a { font-weight: 700; }

/* The row under the password field: "remember me" on the left, "forgotten your password?" on the
   right. It wraps rather than squeezing, because the two labels are translated and neither
   language is asked to fit the other's width. */
.auth-options {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    margin-top: -8px;
}

/* The whole label is the target, not just the 20px box — hence the min-height, which brings the
   row up to a comfortable size on a touchscreen. */
.auth-check {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    font-size: .95rem;
    color: var(--muted);
    cursor: pointer;
}
.auth-check input {
    width: 20px; height: 20px;
    accent-color: var(--accent);
    cursor: pointer;
}

/* A button that reads as a link. It is a button because it reveals text on this page rather than
   going anywhere, and the appearance follows the job the visitor thinks it does. */
.auth-linkish {
    border: none;
    background: none;
    padding: 0;
    color: var(--accent-text);
    font: inherit;
    font-size: .95rem;
    font-weight: 600;
    cursor: pointer;
}
.auth-linkish:hover { text-decoration: underline; }
.auth-linkish:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* What that button uncovers. This installation has no self-service reset — an administrator sets a
   new password — so it says what to do instead of linking somewhere that cannot help. */
.auth-aside { margin: 0; font-size: .9rem; color: var(--muted); text-align: right; }
.auth-foot a { color: var(--accent-text); }

/* The signed-in name in the top bar. Underlined only on hover, so it sits quietly beside the
   buttons instead of competing with them. */
.account-chip { text-decoration: none; font-weight: 600; }
.account-chip:hover { text-decoration: underline; }
