:root {
    --bg: #0b1020;
    --panel: #11182a;
    --panel-2: #151f35;
    --panel-3: #1a2843;
    --line: #2a3958;
    --line-soft: rgba(146, 166, 211, .14);
    --text: #e8edf8;
    --muted: #91a0bd;
    --faint: #637395;
    --cyan: #72d9e7;
    --green: #8be0ae;
    --yellow: #f2d38a;
    --red: #ff929e;
    --purple: #c4b1ff;
    --orange: #f4b47b;
    --shadow: 0 24px 70px rgba(0, 0, 0, .3);
    --radius: 16px;
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
* { box-sizing: border-box; }
html, body { min-height: 100%; }
body { margin: 0; color: var(--text); background: radial-gradient(circle at 8% 0%, rgba(87, 104, 190, .2), transparent 34rem), radial-gradient(circle at 95% 15%, rgba(38, 153, 165, .12), transparent 30rem), var(--bg); }
button, input, textarea, select { font: inherit; }
button { cursor: pointer; }
code, pre, textarea, .file-list, .db-summary, .diagnostics-output, .field-panel { font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; }
.app-shell { width: min(1800px, calc(100% - 28px)); margin: 0 auto; padding: 20px 0 16px; }
.app-header { display: flex; align-items: center; justify-content: space-between; gap: 18px; margin-bottom: 14px; }
.brand-lockup { display: flex; align-items: center; gap: 13px; }
/* Logo jest odnośnikiem na pulpit — wygląd zostaje ten sam, co div.
   Bez tego <a> dziedziczyłby niebieski kolor linku przeglądarki. */
a.brand-lockup { color: inherit; text-decoration: none; }
a.brand-lockup:hover .brand-mark { filter: brightness(1.1); }
/* Nagłówek w odnośniku nie może wyglądać jak link: h1 nie ma własnej
   reguły koloru, więc jawnie przejmuje kolor tekstu. Eyebrow ma własny
   kolor (cyjan) i go nie ruszamy. */
a.brand-lockup h1 { color: inherit; }
.brand-mark { display: grid; width: 45px; height: 45px; place-items: center; color: #08101c; border-radius: 13px; background: linear-gradient(135deg, var(--cyan), var(--purple)); font: 900 15px Consolas, monospace; box-shadow: 0 8px 25px rgba(114, 217, 231, .2); }
.eyebrow { margin: 0 0 3px; color: var(--cyan); font-size: 10px; font-weight: 850; letter-spacing: .14em; }
h1 { margin: 0; font: 500 clamp(22px, 3vw, 31px)/1.1 Georgia, "Times New Roman", serif; letter-spacing: -.025em; }
.header-actions { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.simulation-badge, .ghost-button, .tiny-button { display: inline-flex; align-items: center; justify-content: center; min-height: 32px; padding: 6px 10px; color: var(--muted); border: 1px solid var(--line); border-radius: 8px; background: rgba(20, 29, 50, .8); font-size: 11px; text-decoration: none; }
.simulation-badge { gap: 7px; color: var(--green); border-color: rgba(139, 224, 174, .25); background: rgba(139, 224, 174, .08); }
.simulation-badge i, .status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 4px rgba(139, 224, 174, .1); }
.ghost-button:hover, .tiny-button:hover { color: var(--text); border-color: #536a98; background: var(--panel-3); }
.file-button { cursor: pointer; }
.app-notice { margin-bottom: 14px; padding: 10px 13px; color: #c2cde4; border: 1px solid rgba(114, 217, 231, .18); border-radius: 10px; background: rgba(61, 116, 145, .1); font-size: 11px; line-height: 1.5; }
.app-notice strong { color: var(--cyan); }
/* Układ zbudowany na nazwanych obszarach siatki, a nie na recznym
   grid-column/grid-row dla kazdego elementu. Wczesniejsza wersja ustawiała
   kolumny i wiersze osobno, przez co kombinacja "podgląd pod panelem" +
   "zwinięty panel boczny" zostawiała dziurê w siatce: edytor i panel żądania
   znikały albo dostawały szerokość kolumny panelu bocznego. Obszary siatki
   opisują caly uklad naraz, wiec kombinacje nie koliduja ze soba. */
.workspace {
    display: grid;
    grid-template-columns: 225px minmax(390px, .95fr) minmax(420px, 1.05fr);
    grid-template-areas: "side main preview";
    gap: 14px;
    align-items: start;
}
.sidebar { grid-area: side; }
.main-column { grid-area: main; }
.preview-column { grid-area: preview; }
.sidebar, .main-column, .preview-column { display: flex; min-width: 0; flex-direction: column; gap: 12px; }

/* Podgląd pod panelem żądania HTTP: dwie kolumny, podgląd schodzi pod
   kolumnê edytora, a panel boczny zajmuje oba wiersze. */
body.preview-below .workspace {
    grid-template-columns: 225px minmax(390px, 1fr);
    grid-template-areas:
        "side main"
        "side preview";
}

/* Zwiniêty panel boczny zostawia wąski pasek na przycisk rozwijania —
   tak jak w aplikacjach z panelami bocznymi. Bez niego kombinacja z trybem
   "pod panelem" gubiła kolumnê i edytor wpadał w miejsce panelu.

   Pasek musi mieć realną wysokość. Przy align-items: start kurczył się do
   zera, a przycisk przywracania — ustawiony bezwzględnie przy górnej krawędzi —
   zostawał samotnie w pustce nad kartą edytora. W układzie pionowym było to
   wyraźnie widoczne: guzik » leżał w lewym marginesie, nad edytorem, i wyglądał
   jak przypadkowy element. Dlatego zwinięty panel rozciąga się na cały wiersz
   siatki (a w pionowym na oba wiersze), a pasek dostaje widoczną krawędź. */
body.sidebar-collapsed .workspace {
    grid-template-columns: 36px minmax(390px, .95fr) minmax(420px, 1.05fr);
}
body.sidebar-collapsed.preview-below .workspace {
    grid-template-columns: 36px minmax(390px, 1fr);
}
body.sidebar-collapsed .sidebar {
    align-self: stretch;
    min-height: 44px;
    border-right: 1px solid var(--line-soft);
}

/* Przełącznik układu podglądu siedzi w jego pasku narzêdzi. Dwa kwadraty
   obok siebie = podglád w osobnej kolumnie, ułożone w pionie = podgląd
   pod panelem. Sam symbol byłby nieczytelny, wiec dochodzi krótkie słowo. */
.layout-switch { display: flex; gap: 3px; margin-left: 8px; padding: 3px; border: 1px solid var(--line-soft); border-radius: 9px; background: rgba(0,0,0,.22); }
.layout-option {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 9px; border: 0; border-radius: 6px;
    background: transparent; color: var(--muted);
    font: 700 10.5px "Inter", system-ui, sans-serif; cursor: pointer;
}
.layout-option:hover { color: var(--text); background: rgba(255,255,255,.05); }
.layout-option.is-active { color: #0b1020; background: var(--cyan); }
/* Opcja „obok” w wąskim oknie nie ma czego zmienić. Nie chowamy jej —
   zostaje widoczna, przygaszona i z powodem w podpowiedzi, bo uczeń
   musi widzieć, że taki układ w ogóle istnieje. */
.layout-option:disabled { opacity: .4; cursor: not-allowed; }
.layout-option:disabled:hover { color: var(--muted); background: transparent; }
.layout-option:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
.layout-icon { position: relative; display: inline-block; width: 15px; height: 14px; flex: 0 0 auto; }
.layout-icon::before, .layout-icon::after {
    content: ''; position: absolute; border: 1.5px solid currentColor; border-radius: 2px;
}
/* obok siebie — układ poziomy */
.layout-icon--side::before { left: 0; top: 0; width: 6px; height: 14px; }
.layout-icon--side::after { right: 0; top: 0; width: 6px; height: 14px; }
/* jeden nad drugim — układ pionowy */
.layout-icon--below::before { left: 0; top: 0; width: 15px; height: 6px; }
.layout-icon--below::after { left: 0; bottom: 0; width: 15px; height: 6px; }

/* Zwijanie panelu bocznego: przycisk w jego prawym górnym rogu, a po
   zwiniêciu zostaje pasek szerokości jednego przycisku. */
.sidebar { position: relative; }
.sidebar-toggle {
    position: absolute; top: 8px; right: 8px; z-index: 3;
    display: flex; align-items: center; justify-content: center;
    width: 30px; height: 24px; padding: 0;
    color: var(--faint); border: 1px solid var(--line-soft); border-radius: 7px;
    background: rgba(11, 16, 32, .92); cursor: pointer;
    font: 700 12px/1 Consolas, monospace;
}
.sidebar-toggle:hover { color: var(--cyan); border-color: rgba(122, 215, 238, .45); background: rgba(122, 215, 238, .1); }
.sidebar-toggle:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
/* Miejsce pod przyciskiem, żeby nie zasłaniał liczby plików ani tytułu. */
body:not(.sidebar-collapsed) .file-card .card-heading { padding-right: 34px; }
body.sidebar-collapsed .sidebar > *:not(.sidebar-toggle) { display: none; }
body.sidebar-collapsed .sidebar-toggle { top: 10px; right: 3px; }

.side-card, .editor-card, .request-card, .preview-card, .diagnostics-card { min-width: 0; border: 1px solid var(--line); border-radius: var(--radius); background: rgba(17, 24, 42, .9); box-shadow: var(--shadow); }
.side-card, .editor-card, .request-card, .preview-card, .diagnostics-card { min-width: 0; border: 1px solid var(--line); border-radius: var(--radius); background: rgba(17, 24, 42, .9); box-shadow: var(--shadow); }
/* Bez overflow: hidden — karta nie może przyciąć własnej treści, gdy lista
   tabel z opisami urosłaby ponad jej ramkę (przestałoby być widać i nie
   dałoby się do tego przewinąć). Menu pliku jest position: fixed, więc
   i tak nie zależy od tego kadrowania. */
.side-card { padding: 13px; }
.card-heading { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 11px; color: var(--muted); font-size: 11px; font-weight: 850; letter-spacing: .08em; text-transform: uppercase; }
.file-count, .request-hint { color: var(--faint); font-size: 10px; font-weight: 500; letter-spacing: 0; text-transform: none; }
/* minmax(0, 1fr) jest tu konieczne: domyślna kolumna „auto” rozpychała listę
   do szerokości najdłuższej nazwy pliku, przez co przyciski akcji wychodziły
   spod panelu i chowały się pod edytorem. */
.file-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 5px; }
.file-button { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 8px; overflow: hidden; color: var(--muted); border: 1px solid transparent; border-radius: 8px; background: rgba(255,255,255,.03); text-align: left; font-size: 11px; }
.file-button:hover { color: var(--text); border-color: rgba(114, 217, 231, .25); background: rgba(114, 217, 231, .06); }
.file-button.is-active { color: var(--cyan); border-color: rgba(114, 217, 231, .32); background: rgba(114, 217, 231, .09); }
.file-icon { color: var(--purple); }
.file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Wiersz pliku: nazwa i jeden zwijany przycisk akcji. Trzy osobne ikony
   (otwórz, zmień nazwę, usuń) nie mieściły się w wąskim panelu i zjadały
   miejsce na nazwę, więc kryją się w rozwijanej liście „⋯”. */
.file-row { display: flex; align-items: stretch; gap: 4px; }
.file-row .file-button { flex: 1 1 auto; min-width: 0; }
.file-menu-button {
    flex: 0 0 auto; align-self: stretch; width: 26px; padding: 0;
    color: var(--faint); border: 1px solid var(--line-soft); border-radius: 8px;
    background: rgba(255,255,255,.045); cursor: pointer;
    font: 15px/1 "Cascadia Code", Consolas, monospace;
}
.file-menu-button:hover { color: var(--text); border-color: rgba(114,217,231,.35); background: rgba(114,217,231,.09); }
.file-menu-button[aria-expanded="true"] { color: var(--cyan); border-color: rgba(114,217,231,.5); background: rgba(114,217,231,.13); }

/* Rozwinięte menu. position: fixed i przyklejone do body, bo przycisk siedzi
   w wąskim panelu, a lista musi swobodnie wychodzić poza jego krawędzie. */
.file-menu { position: fixed; z-index: 15; min-width: 208px; padding: 5px; border: 1px solid var(--line); border-radius: 11px; background: #16203a; box-shadow: 0 16px 38px rgba(0,0,0,.55); }
.file-menu-title { overflow: hidden; margin: 0 4px 5px; padding: 3px 5px 6px; color: var(--cyan); border-bottom: 1px solid var(--line-soft); text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 700; }
.file-menu-item { display: flex; align-items: center; gap: 9px; width: 100%; padding: 8px 9px; color: var(--muted); border: 0; border-radius: 7px; background: transparent; text-align: left; cursor: pointer; font: 11.5px "Inter", system-ui, sans-serif; }
.file-menu-item:hover, .file-menu-item:focus-visible { color: var(--text); background: rgba(114,217,231,.11); outline: 0; }
.file-menu-glyph { width: 13px; color: var(--faint); text-align: center; font-size: 12px; }
.file-menu-item:hover .file-menu-glyph { color: var(--cyan); }
.file-menu-item--danger { color: #ff9aa6; }
.file-menu-item--danger:hover { color: #ffb3bc; background: rgba(255,90,110,.13); }
.file-menu-item--danger .file-menu-glyph { color: #ff9aa6; }
.file-menu-sep { height: 1px; margin: 5px 4px; background: var(--line-soft); }
.new-file-button { width: 100%; margin-top: 7px; padding: 7px; color: var(--muted); border: 1px dashed rgba(114, 217, 231, .28); border-radius: 8px; background: transparent; font-size: 11px; }
.new-file-button:hover { color: var(--cyan); border-color: rgba(114, 217, 231, .55); background: rgba(114, 217, 231, .06); }
.undo-button { width: 100%; margin-top: 5px; padding: 6px; color: #ffd479; border: 1px solid rgba(255, 212, 121, .3); border-radius: 8px; background: rgba(255, 212, 121, .06); font-size: 11px; }
.undo-button:hover { color: #1a1206; background: #ffd479; }

/* Okno nowego pliku */
.field-label { display: block; margin: 0 0 5px; color: var(--muted); font-size: 11px; font-weight: 700; }
.text-input { width: 100%; padding: 9px 10px; color: var(--text); border: 1px solid var(--line); border-radius: 8px; background: rgba(0, 0, 0, .25); font: inherit; font-size: 13px; }
.text-input:focus { outline: 2px solid rgba(114, 217, 231, .5); outline-offset: 1px; }
.file-type-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 12px 0 0; }
.file-type { display: flex; align-items: center; gap: 7px; padding: 8px 9px; color: var(--muted); border: 1px solid var(--line); border-radius: 8px; cursor: pointer; font-size: 11px; }
.file-type:hover { color: var(--text); border-color: rgba(114, 217, 231, .3); }
.file-type:has(input:checked) { color: var(--cyan); border-color: rgba(114, 217, 231, .5); background: rgba(114, 217, 231, .08); }
.file-type input { accent-color: var(--cyan); }
.file-type span { display: grid; line-height: 1.35; }
.file-type small { color: var(--faint); font-size: 9px; }
.file-dialog-hint { min-height: 16px; margin: 11px 0 0; color: var(--faint); font-size: 10px; }
.file-dialog-error { margin: 6px 0 0; color: #ff9aa6; font-size: 11px; font-weight: 700; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }

/* Pytanie o usunięcie: zostają wyjaśnienie i przyciski. Sama nazwa i rodzaj
   pliku są nieistotne, więc je chowamy. Używamy klasy, a nie atrybutu [hidden],
   bo .field-label i .file-type-grid mają własne display i przebilyby go. */
#fileForm.is-delete-mode .field-label,
#fileForm.is-delete-mode #fileNameInput,
#fileForm.is-delete-mode .file-type-grid { display: none; }
#fileForm.is-delete-mode .file-dialog-hint { margin-top: 4px; color: var(--muted); font-size: 12px; line-height: 1.6; }
.scenario-list { display: grid; gap: 6px; }
.scenario-list button { padding: 8px 9px; color: var(--muted); border: 1px solid transparent; border-radius: 8px; background: rgba(255,255,255,.035); text-align: left; font-size: 11px; }
.scenario-list button:hover { color: var(--yellow); border-color: rgba(242, 211, 138, .25); background: rgba(242, 211, 138, .06); }
.db-summary { margin-bottom: 9px; color: var(--faint); font-size: 10px; line-height: 1.5; }
/* Lista tabel nie ma sztucznego limitu wysokości. Bez niego panel bazy
   przewijał się własnym paskiem wewnątrz strony, która przewija się już
   razem z podglądem — dwa niezależne przewijania, z których łatwo się
   zgubić, a dolna część listy z opisami tabel nie mieściła się na ekranie.
   Teraz jedynym przewijaniem jest strona (a w trybie osadzonym .sidebar),
   więc wszystkie tabele i ich opisy są zwykłym kółkiem myszy dostępne. */
.db-tables {
    display: grid; gap: 6px; align-content: start;
    overflow-x: hidden;
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
}

/* Paski przewijania w kolorach motywu, dla KAŻDEGO elementu, który może
   przewijać: strona, lista plików, edytor, panel parametrów, diagnostyka,
   okna dialogowe. Wcześniej motyw dotyczył tylko bazy i podglądu, więc
   pozostałe panele pokazywały szare, szerokie paski przeglądarki.
   Standardowe właściwości obsługuje Firefox i nowszy Chromium, pseudoelementy
   zostają jako zapas dla przeglądarek z własną szyną. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
}
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
    background: var(--line); border-radius: 5px;
}
*::-webkit-scrollbar-thumb:hover { background: var(--faint); }
*::-webkit-scrollbar-thumb:active { background: var(--cyan); }
*::-webkit-scrollbar-corner { background: transparent; }

/* Podgląd to dokument ucznia na białym tle — jego pasków nie ruszamy,
   bo to obca strona, a nie nasz interfejs. */
#previewFrame { scrollbar-width: auto; scrollbar-color: auto; }
.db-table { position: relative; padding: 0; border: 1px solid var(--line-soft); border-radius: 8px; background: rgba(255,255,255,.025); overflow: hidden; }
.db-table.is-open { border-color: rgba(122, 215, 238, .28); background: rgba(122, 215, 238, .05); }

/* Nagłówek tabeli to przycisk — rozwijany klawiaturą, a nie tylko myszą. */
.db-table-head {
    display: flex; align-items: center; gap: 6px; width: 100%;
    padding: 7px 8px; border: 0; background: none; cursor: pointer;
    color: inherit; font: inherit; text-align: left;
}
.db-table-head:hover { background: rgba(255,255,255,.04); }
.db-table-head:focus-visible { outline: 2px solid var(--cyan); outline-offset: -2px; }
.db-caret { flex: 0 0 auto; color: var(--cyan); font-size: 10px; }
.db-table-name { flex: 1 1 auto; min-width: 0; color: var(--purple); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.db-table-count { flex: 0 0 auto; color: var(--faint); font-size: 10px; font-variant-numeric: tabular-nums; }

/* Przycisk siatki stoi za liczbą rekordów, w tym samym wierszu co nagłówek,
   ale poza nim — inaczej kliknięcie rozwijałoby tabelę zamiast pokazać dane. */
.db-grid-button {
    position: absolute; top: 4px; right: 4px; z-index: 1;
    width: 24px; height: 22px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--line-soft); border-radius: 6px;
    background: rgba(0,0,0,.25); color: var(--faint);
    font-size: 12px; line-height: 1; cursor: pointer;
}
.db-grid-button:hover { color: var(--cyan); border-color: rgba(122,215,238,.4); }
.db-grid-button:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
.db-grid-button.is-active { color: var(--yellow); border-color: rgba(242,211,138,.45); background: rgba(242,211,138,.12); }
/* Miejsce na przycisk, żeby liczba rekordów nie chowała się pod nim. */
.db-table-head { padding-right: 32px; }

/* Opis kolumn: nazwa w swoim wierszu (do lewej), typ ze znacznikami
   w wierszu poniżej (do prawej). Dzięki temu nazwa ma całą szerokość
   i nie łamie się, gdy pojawia się pasek przewijania. */
.db-fields { display: grid; gap: 2px; padding: 6px 8px 8px; border-top: 1px solid var(--line-soft); }
.db-fields-count { margin: 0 0 3px; color: var(--faint); font-size: 9px; text-transform: uppercase; letter-spacing: .04em; }
.db-field { display: grid; gap: 0; padding: 3px 0; }
.db-field + .db-field { border-top: 1px dotted rgba(255,255,255,.06); }
.db-field-name { color: var(--text); font-size: 10.5px; text-align: left; overflow-wrap: break-word; }
.db-field-desc { display: flex; align-items: baseline; justify-content: flex-end; gap: 5px; }
.db-field-type { color: var(--cyan); font-size: 9.5px; text-align: right; overflow-wrap: break-word; }
.db-field-flags { display: flex; flex: 0 0 auto; gap: 2px; }
.db-field-flags i { font-style: normal; font-size: 10px; cursor: help; }
.db-note { margin: 6px 0 0; color: var(--faint); font-size: 9.5px; line-height: 1.55; overflow-wrap: break-word; }
.db-note code { font-size: 9.5px; }

/* Podgląd zawartości tabeli w osobnym oknie. Szeroki, bo siatka ma pokazać
   kolumny obok siebie; wysoka z przewijaniem, bo 25 wierszy się nie mieści
   w ekranie przy małej wysokości. */
.modal-card--table { display: flex; flex-direction: column; max-height: calc(100vh - 40px); }
.db-preview-body { flex: 1 1 auto; min-height: 0; overflow: auto; border: 1px solid var(--line-soft); border-radius: 9px; }
.db-preview-body .db-preview-scroll { border: 0; border-radius: 0; }
.db-preview-body .db-preview-scroll .db-grid { font-size: 11.5px; }
.db-preview-body .db-grid th, .db-preview-body .db-grid td { padding: 4px 9px; }
.modal-card--table .db-preview-nav { margin-top: 0; }
.modal-card--table .db-preview-info { font-size: 11.5px; }
.modal-card--table .modal-actions { flex: 0 0 auto; }
.modal-card--table .modal-actions .db-preview-info { order: 2; margin: 0 auto; }
.modal-card--table .modal-actions #dbPreviewPrev { order: 1; }
.modal-card--table .modal-actions #dbPreviewNext { order: 3; }
.db-grid { border-collapse: collapse; width: auto; font-size: 11.5px; white-space: nowrap; }
.db-grid th, .db-grid td { padding: 2px 6px; text-align: left; border-bottom: 1px solid rgba(255,255,255,.05); }
.db-grid th { position: sticky; top: 0; z-index: 1; background: #1b2130; color: var(--cyan); font-weight: 600; }
.db-grid tbody tr:nth-child(even) { background: rgba(255,255,255,.02); }
.db-grid-nr { position: sticky; left: 0; z-index: 2; background: #1b2130; color: var(--faint); text-align: right !important; font-variant-numeric: tabular-nums; }
.db-grid th.db-grid-nr { z-index: 3; }
.db-null { color: var(--faint); font-style: italic; }
.db-preview-nav { display: flex; align-items: center; justify-content: space-between; gap: 6px; margin-top: 10px; min-width: 240px; }
.db-preview-btn {
    width: 26px; height: 22px; padding: 0; border: 1px solid var(--line-soft);
    border-radius: 6px; background: rgba(0,0,0,.2); color: var(--text);
    font-size: 13px; line-height: 1; cursor: pointer;
}
.db-preview-btn:hover:not(:disabled) { color: var(--cyan); border-color: rgba(122,215,238,.4); }
.db-preview-btn:disabled { opacity: .35; cursor: default; }
.db-preview-info { color: var(--faint); font-size: 9.5px; font-variant-numeric: tabular-nums; }

/* Legenda oznaczeń — jedna linia zwija się, gdy panel jest wąski. */
.db-legend { display: flex; flex-wrap: wrap; gap: 3px 8px; margin: -2px 0 8px; color: var(--faint); font-size: 9px; line-height: 1.4; }
.db-legend-item { display: inline-flex; align-items: center; gap: 2px; }
.db-legend-item i { font-style: normal; font-size: 10px; }

/* Import pliku .sql ze schematem zadania */
.db-import { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.db-import .ghost-button { flex: 1 1 auto; justify-content: center; min-height: 30px; padding: 5px 8px; font-size: 10.5px; }
.sql-import-result { margin-top: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); }
.sql-import-result[hidden] { display: none; }
.sql-import-result p { margin: 0 0 5px; color: var(--muted); font-size: 11.5px; line-height: 1.55; }
.sql-import-result .sql-ok strong { color: var(--green); }
/* `--amber` nie istnieje w tym pliku — CSS po cichu odrzucal kolor,
   a ostrzezenie nie odroznialo sie od reszty tekstu. Najblizsza
   istniejaca zmienna to --yellow (#f2d38a). */
.sql-import-result .sql-warn strong { color: var(--yellow); }
.sql-import-result .sql-tables { color: var(--faint); font-size: 11px; }
.sql-import-result .sql-tables code { color: var(--cyan); }
.sql-import-result .sql-more { color: var(--faint); font-size: 11px; }
.sql-import-result .sql-skip { color: var(--faint); font-size: 11px; line-height: 1.5; }
.sql-import-result .sql-skip code { color: var(--faint); }
.sql-errors { display: grid; gap: 6px; margin: 8px 0 0; padding: 0; list-style: none; }
.sql-errors li { display: grid; gap: 3px; padding: 7px 9px; border-radius: 7px; background: rgba(255, 146, 158, .08); }
.sql-errors code { overflow: hidden; color: var(--red); font: 10.5px/1.5 Consolas, monospace; text-overflow: ellipsis; white-space: nowrap; }
.sql-errors span { color: var(--muted); font-size: 11px; }
.modal-card--wide { width: min(680px, 100%); }
/* Szerokość kart musi mieć wyższą specyficzność niż .modal-card (linia niżej),
   inaczej zawsze wygrywa domyślne 480 px. */
.modal .modal-card--wide { width: min(680px, 100%); }
/* Szerokość okna dopasowana do zawartości, a nie rozstrzelona na cały ekran:
   zbyt szerokie kolumny utrudniają powiązanie wartości z rekordem, a wąskie
   trzymają rekord w jednym miejscu. Przy naprawdę szerokiej tabeli okno
   zatrzymuje się na 96% ekresu, a reszta przewija się w poziomie. */
.modal .modal-card--table { width: auto; max-width: 96vw; }
/* `--terminal-ink` i `--terminal` pochodza z terminal.css innego
   laboratorium i w tym pliku nie istnieja. Pole importu SQL nie
   dostawalo wiec ani koloru tekstu, ani tla. Bierzemy zmienne
   z tego pliku: --text na kolor tekstu, --bg na tlo. */
.sql-paste { width: 100%; min-height: 200px; padding: 11px 12px; color: var(--text); border: 1px solid var(--line); border-radius: 10px; background: var(--bg); font: 12px/1.6 Consolas, monospace; resize: vertical; }
.sql-paste:focus { border-color: var(--cyan); outline: none; }
.sql-paste-actions { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.editor-card { overflow: hidden; }
.editor-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--line); background: #121a2d; }
.file-tabs { display: flex; min-width: 0; gap: 3px; overflow: auto; }
.file-tab { padding: 6px 8px; color: var(--faint); border: 1px solid transparent; border-radius: 6px; background: transparent; font-size: 10px; white-space: nowrap; }
.file-tab:hover { color: var(--text); }
.file-tab.is-active { color: var(--text); border-color: var(--line); background: rgba(255,255,255,.05); }
.editor-actions { display: flex; align-items: center; gap: 6px; }
.language-pill { padding: 4px 6px; color: var(--purple); border-radius: 5px; background: rgba(196, 177, 255, .1); font: 10px Consolas, monospace; }
/* Regulatory rozmiaru czcionki edytora. Mały A zmniejsza, duży A zwiększa.
   Symbole mają różnić się nie tylko wielkością, ale i grubością, żeby było
   widać który jest który także na słabym projectorze. */
.font-stepper { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px; border: 1px solid var(--line); border-radius: 7px; background: rgba(20, 29, 50, .8); }
.font-button { display: inline-flex; align-items: center; justify-content: center; min-width: 26px; min-height: 26px; padding: 0 5px; color: var(--muted); border: 1px solid transparent; border-radius: 5px; background: transparent; font-family: Georgia, "Times New Roman", serif; line-height: 1; cursor: pointer; }
.font-button--small { font-size: 12px; font-weight: 700; }
.font-button--large { font-size: 21px; font-weight: 700; }
.font-button:hover:not(:disabled) { color: var(--text); border-color: var(--line); background: var(--panel-3); }
.font-button:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
.font-button:disabled { opacity: .35; cursor: not-allowed; }
.font-readout { min-width: 18px; color: var(--faint); font: 10px/1 Consolas, monospace; text-align: center; }
/* --- Panel egzaminow INF.03 ---
 * Listy zadań nie ma tu już: siedzi w oknie modalnym i na osobnej stronie,
 * a jej styl żyje w egzaminy-lista.css. Zostaje tylko karta szczegółów
 * wybranego zadania. */
/* Pliki do pobrania w karcie zadania. Nazwy klas jak w pozostalych
   elementach karty (exam-*), a nie jak na stronie spisu — tam obowiazuje
   konwencja egz-*. */
.exam-downloads {
    margin: 10px 0;
    padding: 10px 11px;
    border: 1px solid var(--line-soft);
    border-radius: 9px;
    background: rgba(255,255,255,.03);
}
.exam-downloads[hidden] { display: none; }
.exam-downloads-tytul {
    margin: 0 0 8px; color: var(--faint);
    font: 700 9.5px/1 Inter, system-ui, sans-serif;
    text-transform: uppercase; letter-spacing: .1em;
}
.exam-downloads-lista { display: flex; flex-wrap: wrap; gap: 7px; }
/* Ikona i rozmiar, bez napisu — szerokosc musi byc naturalna. Przy
   flex: 1 1 150px kazdy odnosnik rozciegal sie do polowy panelu
   (346 px) i zostawial pusto w srodku. */
.exam-download {
    display: inline-flex; align-items: center; gap: 7px;
    flex: 0 1 auto; min-width: 0; padding: 7px 11px;
    color: var(--text); text-decoration: none;
    border: 1px solid var(--line-soft); border-radius: 8px;
    background: rgba(255,255,255,.04);
}
.exam-download[hidden] { display: none; }
.exam-download:hover { border-color: var(--cyan); background: rgba(114,217,231,.10); }
.exam-download .egz-ikona { width: 15px; height: 15px; }
.exam-download-rodzaj { font-size: 11.5px; font-weight: 700; }
.exam-download-rozmiar { font-size: 10px; color: var(--faint); }
.exam-downloads-opis { margin: 8px 0 0; font-size: 10.5px; color: var(--muted); }

.exam-types { display: flex; flex-wrap: wrap; gap: 4px; margin: 9px 0; }
.exam-type {
    padding: 3px 7px; color: var(--muted); border: 1px solid var(--line-soft);
    border-radius: 999px; background: rgba(255,255,255,.03); font-size: 10px; white-space: nowrap;
}
.exam-queries {
    margin: 6px 0 0; padding: 9px 11px; max-height: 220px; overflow: auto;
    color: #cfe6ea; border: 1px solid var(--line-soft); border-radius: 8px;
    background: var(--bg); font: 11.5px/1.6 Consolas, monospace;
    white-space: pre-wrap; overflow-wrap: break-word;
}
.exam-files { margin: 6px 0 0; padding-left: 18px; color: var(--muted); font-size: 11px; line-height: 1.6; }
.exam-files code { color: var(--cyan); font: 11px Consolas, monospace; }
.check-result.is-ok { border-color: rgba(139,224,174,.4); }
.check-result.is-error { border-color: rgba(255,124,140,.45); }

.build-stamp { margin-left: auto; color: var(--faint); font: 9.5px Consolas, monospace; letter-spacing: .04em; }
.run-button, .secondary-button { min-height: 31px; padding: 6px 11px; color: #08101c; border: 0; border-radius: 7px; background: var(--cyan); font-size: 11px; font-weight: 850; }
.run-button:hover, .secondary-button:hover { background: #a1eff4; }
/* Edytor ma mieć STAŁĄ wysokość okna i przewijać zawartość wewnętrznie.
   Wcześniej .editor-wrap dostawał height od kolumny numerów (ta rosła
   z liczbą linii), przez co textarea zostawała na swoich 540 px, a pod spodem
   ciągnęło się puste pole z samymi numerami. Kolumna numerów i textarea muszą
   mieć identyczną wysokość i przewijać się razem — scrollTop guttera jest
   ustawiany z scrollTop textarea. */
/* Rozmiar czcionki edytora sterowany jest jedną zmienną, bo podświetlanie
   <pre>, przezroczysta textarea i numeracja linii muszą mieć identyczne
   metryki tekstu. Ustawienie jej osobno w każdym z tych trzech miejsc
   rozjechałoby podświetlenie względem tekstu. Przyciski A−/A+ w pasku
   edytora zmieniają tę zmienną; skoro na zajęciach trzeba powiększyć kod
   na tyle, by było widać z ostatnich rzędów. */
:root { --edytor-czcionka: 12px; }

.editor-wrap { display: grid; grid-template-columns: calc(var(--edytor-czcionka) * 2.4 + 14px) minmax(0, 1fr); height: min(72vh, 720px); min-height: 420px; background: #0a0f1d; }
.line-numbers { height: 100%; padding: 14px 9px 14px 0; overflow: hidden; color: #455674; border-right: 1px solid var(--line-soft); font: var(--edytor-czcionka)/1.6 "Cascadia Code", Consolas, monospace; text-align: right; user-select: none; }
/* Każdy numer dostaje wysokość swojej linii po zawinięciu, żeby kolumna
   numerów rosła tak samo jak kod. */
.line-numbers > div { overflow: hidden; }

/* Edytor składa się z dwóch warstw: podświetlanego <pre> i przezroczystej
   textarea na wierzchu. Muszą mieć identyczne metryki tekstu, inaczej
   podświetlenie rozjedzie się z tekstem przy zawijaniu wierszy. */
.code-area { position: relative; min-width: 0; height: 100%; overflow: hidden; }
/* Niewidoczne lustro tekstu o metrykach identycznych z textarea i
   podświetleniem. Służy wyłącznie do pomiaru, w ile wierszy ekranu
   zmienia się każda linia kodu po zawinięciu — bez niego numeracja gubi
   się przy powiększonej czcionce. */
.line-metrics {
    position: absolute; top: 0; left: 0;
    visibility: hidden; pointer-events: none;
    padding: 14px 13px;
    font: var(--edytor-czcionka)/1.6 "Cascadia Code", Consolas, monospace;
    white-space: pre-wrap; overflow-wrap: break-word; word-break: normal;
    tab-size: 4;
}
/* Pusta linia kodu nie ma treści, a w bloku bez treści nie ma wiersza
   tekstowego — dawałaby wysokość 0 i numer zjeżdżałby na poprzedni. */
.line-metrics > div { min-height: calc(var(--edytor-czcionka) * 1.6); }
.code-highlight {
    position: absolute; top: 0; left: 0; width: 100%; height: 100%; margin: 0; padding: 14px 13px;
    border: 0; overflow: hidden; pointer-events: none; color: #dce6f7;
    background: transparent;
    box-sizing: border-box;
    font: var(--edytor-czcionka)/1.6 "Cascadia Code", Consolas, monospace;
    white-space: pre-wrap; overflow-wrap: break-word; word-break: normal;
    tab-size: 4;
}
#codeEditor {
    position: relative; display: block; width: 100%; height: 100%;
    padding: 14px 13px; resize: none; color: transparent; border: 0;
    outline: 0; background: transparent; caret-color: var(--cyan);
    overflow: auto;
    box-sizing: border-box;
    /* Pasek przewijania textarea zabierał 10 px i zawijał linie inaczej niż
       warstwa <pre> — zaznaczenie nie pokrywało się z kodem. Ukrywamy pasek
       (przewijanie kółkiem/klawiszami działa), żeby obie warstwy miały
       dokładnie tę samą szerokość. */
    scrollbar-width: none;
    font: var(--edytor-czcionka)/1.6 "Cascadia Code", Consolas, monospace; tab-size: 4;
    white-space: pre-wrap; overflow-wrap: break-word; word-break: normal;
}
#codeEditor::-webkit-scrollbar { width: 0; height: 0; }
#codeEditor::selection { background: rgba(122, 226, 238, 0.28); color: transparent; }

/* Barwy tokenów — kontrast na tle #0a0f1d, sprawdzony pod kątem czytelności.
   UWAGA: żaden token nie może mieć innej grubości ani pochylenia. Podświetlanie
   <pre> i przezroczysta textarea muszą zawijać tekst w identycznych
   miejscach, a każda różnica szerokości znaków (font-weight, font-style,
   letter-spacing) to rozjazd — przy czcionce 12 px przypadkiem się zgadzał,
   a przy 30 px podświetlenie było o 3 wiersze wyższe niż textarea, więc
   kursor stawał nie tam, gdzie widać tekst. Wyróżnienie robimy więc tłem
   (tło nie zmienia szerokości znaków), a nie grubością kształtu. */
.tok-tag { color: #6b7ba8; }
.tok-comment { color: #6d8093; background: rgba(93, 112, 128, .14); }
.tok-string { color: #9fe0a4; }
.tok-variable { color: #ffd479; }
.tok-number { color: #ffa9c8; }
.tok-keyword { color: #c4b0ff; background: rgba(183, 156, 255, .13); }
.tok-builtin { color: #7ad7ee; }
.tok-class { color: #9fe0f5; background: rgba(122, 215, 238, .13); }
.tok-function { color: #8fd0ff; }
.tok-operator { color: #93a3c4; }
.tok-punctuation { color: #7d8db0; }
.tok-html { color: #c9d4e8; }

.editor-footer { display: flex; justify-content: space-between; gap: 10px; padding: 7px 11px; color: var(--faint); border-top: 1px solid var(--line-soft); font-size: 10px; }
.request-card { padding: 13px; }
.request-controls { display: grid; grid-template-columns: 95px minmax(0, 1fr) auto; gap: 7px; align-items: end; }
.request-controls label, .field-row label { display: grid; gap: 4px; color: var(--faint); font-size: 10px; }
.request-controls input, .request-controls select, .field-row input { min-width: 0; padding: 7px 8px; color: var(--text); border: 1px solid var(--line); border-radius: 7px; outline: 0; background: #0d1527; font-size: 11px; }
.request-controls input:focus, .request-controls select:focus, .field-row input:focus { border-color: var(--cyan); }
.uri-field { min-width: 0; }
.request-body { margin-top: 11px; border: 1px solid var(--line-soft); border-radius: 9px; overflow: hidden; }
.request-tabs, .diagnostic-tabs { display: flex; gap: 2px; padding: 5px; border-bottom: 1px solid var(--line-soft); background: rgba(255,255,255,.02); }
.request-tab, .diagnostic-tab { padding: 6px 8px; color: var(--faint); border: 0; border-radius: 5px; background: transparent; font-size: 10px; }
.request-tab:hover, .diagnostic-tab:hover { color: var(--text); }
.request-tab.is-active, .diagnostic-tab.is-active { color: var(--cyan); background: rgba(114, 217, 231, .1); }
.field-panel { display: grid; gap: 6px; min-height: 62px; padding: 9px; }
.field-panel.is-hidden { display: none; }
.field-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr) 25px; gap: 6px; align-items: center; }
.field-row button { width: 25px; height: 25px; color: var(--red); border: 1px solid transparent; border-radius: 5px; background: transparent; }
.field-row button:hover { border-color: rgba(255, 146, 158, .25); background: rgba(255, 146, 158, .08); }
.request-actions { display: flex; justify-content: space-between; gap: 8px; margin-top: 8px; }
.text-button { padding: 4px 0; color: var(--cyan); border: 0; background: transparent; font-size: 10px; }
.text-button:hover { color: var(--text); }
.preview-card { overflow: hidden; }
.preview-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; border-bottom: 1px solid var(--line); background: #121a2d; }
.preview-title, .preview-actions { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 11px; font-weight: 800; }
.status-dot { width: 6px; height: 6px; box-shadow: none; }
.preview-actions { gap: 9px; }
#responseStatus { color: var(--green); font: 700 11px Consolas, monospace; }
.response-meta { display: flex; justify-content: space-between; gap: 8px; padding: 6px 12px; color: var(--faint); border-bottom: 1px solid var(--line-soft); font: 9px Consolas, monospace; }
#previewFrame { display: block; width: 100%; height: 625px; border: 0; background: #fff; }
.diagnostics-card { overflow: hidden; }
.diagnostic-tabs { overflow: auto; }
.diagnostic-tab span { display: inline-block; min-width: 15px; margin-left: 3px; padding: 1px 3px; color: var(--faint); border-radius: 4px; background: rgba(255,255,255,.05); font-size: 9px; text-align: center; }
.diagnostics-output { min-height: 90px; max-height: 180px; margin: 0; overflow: auto; padding: 11px 12px; color: var(--muted); background: #0a0f1d; font-size: 10px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.app-footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 2px 0; color: var(--faint); font-size: 10px; }
.modal { position: fixed; inset: 0; z-index: 20; display: grid; place-items: center; padding: 20px; background: rgba(3, 6, 14, .72); }
.modal[hidden] { display: none; }
.modal-card { width: min(480px, 100%); padding: 20px; color: var(--text); border: 1px solid var(--line); border-radius: 15px; background: var(--panel); box-shadow: var(--shadow); }
.modal-heading { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.modal-card p { color: var(--muted); font-size: 12px; line-height: 1.6; }
.modal-card code { color: var(--cyan); }
.close-button { width: 26px; height: 26px; color: var(--muted); border: 1px solid var(--line); border-radius: 6px; background: transparent; }
.close-button:hover { color: var(--text); background: var(--panel-3); }

/* Panel zadania kursu INF.03 */
.exercise-card { display: flex; flex-direction: column; gap: 10px; flex: 0 0 auto; border-color: rgba(114, 217, 231, .38); position: relative; }
.exercise-card.is-hidden { display: none; }
/* Panel zadania egzaminacyjnego musi dać się ukryć — klasa is-hidden była
   tu zgłaszana przez skrypt, ale nie miała reguły, więc otwarcie ćwiczenia
   zostawiało na ekranie pusty panel INF.03. */
.exam-detail.is-hidden { display: none; }
.exercise-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.exercise-title { display: flex; align-items: center; gap: 9px; min-width: 0; font-size: 13px; }
.exercise-title strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Powrót do części kursu, z której uczeń przyszedł. Bez tego zadanie
   jest jednoklikowym skokiem w pustkę — jedyny odnośnik prowadził
   do spisu arkuszy egzaminacyjnych. */
/* Odnosnik powrotu. Dwa bledy w pierwszej wersji, zmierzone w
   przegladarce na przycisku "Wróć do sprawdzianu w części 12":
     • tlo bylo `var(--soft)`, a tej zmiennej php-web.css NIE definiuje
       (jest w materialy/styl/*.css i materialy-web/motyw-ciemny.css, ale nie
       tutaj) — `background` bylo wiec nieprawidlowe, a element
       przezroczysty;
     • `color` nie bylo ustawione wcale, wiec <a> dziedziczyl domyslny
       niebieski linku przegladarki: rgb(0, 0, 238).
   Razem dawalo to kontrast 2,03:1 na tle #0b1020 — ponizej minimum
   WCAG (4,5:1 dla tekstu 11,5 px). Uczen widzial przycisk jako ledwo
   widoczny zarys.
   Teraz tlo bierze sie z istniejacej zmiennej, a kolor tekstu jest
   podany jawnie. Kontrast: 14,1:1. */
.exercise-back { flex: 0 0 auto; margin-left: 4px; padding: 3px 9px; border: 1px solid var(--line); border-radius: 999px; background: var(--panel-2); color: var(--text); font-size: 11.5px; font-weight: 700; text-decoration: none; }
.exercise-back:hover { border-color: var(--purple); color: var(--purple); }
@media (max-width: 720px) { .exercise-title { flex-wrap: wrap; } .exercise-back { margin-left: 0; } }
.exercise-badge { padding: 3px 7px; color: #06202a; border-radius: 5px; background: var(--cyan); font: 850 10px/1.3 Inter, sans-serif; letter-spacing: .04em; }
.exercise-body { display: grid; gap: 8px; }
.exercise-task { margin: 0; color: var(--text); font-size: 13px; line-height: 1.65; }
.exercise-task code, .exercise-hint code { padding: 1px 5px; color: var(--cyan); border-radius: 4px; background: rgba(114, 217, 231, .12); font: .92em Consolas, monospace; }
.exercise-task em { color: var(--yellow); font-style: normal; }
/* `--amber` nie istnieje — pasek i wyroznienie opisu egzaminacyjnego
   nie mialy koloru. --yellow jest najblizsza istniejaca zmienna
   (#f2d38a) i pasuje do tla rgba(165, 114, 29, .1). */
.exercise-exam { margin: 0; padding: 8px 10px; color: var(--muted); border-left: 3px solid var(--yellow); border-radius: 0 7px 7px 0; background: rgba(165, 114, 29, .1); font-size: 11px; line-height: 1.55; }
.exercise-exam strong { color: var(--yellow); }
.exercise-hint { border: 1px solid var(--line); border-radius: 8px; background: var(--panel-2); }
.exercise-hint summary { padding: 7px 11px; color: var(--muted); cursor: pointer; font-size: 11px; font-weight: 700; }
.exercise-hint > div { padding: 0 11px 9px; color: var(--muted); font-size: 12px; line-height: 1.6; }
.exercise-actions { display: flex; flex-wrap: wrap; gap: 8px; }

.check-result { padding: 11px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); }
.check-result.is-hidden { display: none; }
/* Przycisk zamknięcia komunikatu. Jest w rogu karty zadania, nie przy
   samym tekście — komunikat bywa długi i przycisk w jego wnętrzu uciekałby
   przy zwijaniu. Pozycjonujemy względem .exercise-card (position: relative),
   więc zawsze zostaje przy tym, do czego się odnosi. */
.check-result-close {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    width: 22px;
    height: 22px;
    padding: 0;
    color: var(--muted);
    font-size: 16px;
    line-height: 1;
    background: var(--panel-3);
    border: 1px solid var(--line);
    border-radius: 6px;
    cursor: pointer;
}
.check-result-close:hover { color: var(--text); border-color: var(--cyan); }
.check-result-close[hidden] { display: none; }
/* Gdy komunikat jest widoczny, przycisk nie może leżeć na nim — przesuwamy
   tekst w prawo, żeby oba się nie nakładały. */
.check-result-close:not([hidden]) ~ .check-result { padding-right: 34px; }
.check-summary { margin: 0 0 9px; font-size: 12px; font-weight: 700; }
.check-summary strong { font-size: 15px; }
.check-summary.is-ok { color: var(--green); }
.check-summary.is-partial { color: var(--yellow); }
.check-note { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.6; }
.check-note--error { color: var(--red); }
.check-note code { display: inline-block; margin-top: 5px; padding: 4px 7px; border-radius: 5px; background: rgba(255, 146, 158, .12); font: 11px/1.5 Consolas, monospace; }
.check-list { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.check-list li { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 8px; align-items: start; padding: 7px 9px; border-radius: 8px; font-size: 12px; line-height: 1.55; }
.check-list li.is-ok { color: var(--green); background: rgba(139, 224, 174, .08); }
.check-list li.is-fail { color: var(--red); background: rgba(255, 146, 158, .08); }
.check-list b { color: var(--text); font-weight: 700; }
.check-list small { display: block; margin-top: 3px; color: var(--muted); font-size: 11px; }
.check-mark { font-weight: 900; }
/* Waskie okno: trzy kolumny nie mieszcza sie, wiec podglad schodzi pod
   kolumne edytora. Obszary siatki opisuja caly uklad, dzieki czemu wybor
   ukladu i zwinięcie panelu nie zostawiają pustej kolumny. */
@media (max-width: 1100px) {
    /* Trzy kolumny wymagaja 225 + 390 + 420 + 28 px przerwy = 1063 px,
       a .app-shell zjada jeszcze 28 px marginesow, wiec przelacznik na
       1090 px. Wczesniejszy prog 1250 px blokowal uklad trzech kolumn w
       oknach 1100-1249 px, gdzie miejsce bylo — i pozostawal tylko
       pionowy wariant, ktory po kliknieciu wygladal na bezczynny.
       Prog musi zgadzac sie z ukladObokMozliwy() w php-web.js: JS liczy
       clientWidth (bez 10-px paska przewijania), CSS patrzy na innerWidth
       (z nim), stad 1100, a nie 1090. */
    .workspace { grid-template-columns: 205px minmax(360px, 1fr); grid-template-areas: "side main" "side preview"; }
    body.sidebar-collapsed .workspace { grid-template-columns: 36px minmax(360px, 1fr); }
    body.sidebar-collapsed.preview-below .workspace { grid-template-columns: 36px minmax(360px, 1fr); }
    /* Przelacznika nie ukrywamy — w waskim oknie opcja „obok" i tak nie ma
       czego zmieniac, wiec JavaScript ja wylacza i podaje powód w tytule.
       Lepiej widoczny przycisk z wyjasnieniem niz cisza. */
    #previewFrame { height: 560px; }
}
@media (max-width: 760px) {
    .app-shell { width: min(100% - 14px, 1800px); padding-top: 10px; }
    .app-header { align-items: flex-start; flex-direction: column; }
    .header-actions { justify-content: flex-start; }
    /* Jedna kolumna — obszary siatki nie mają tu zastosowania.
       stretch jest konieczny: bazowy align-items: start kurczyłby
       dzieci do szerokości treści, przez co panel boczny rozpychał układ,
       a edytor i podgląd nie dochodziły do krawędzi ramki. */
    .workspace { display: flex; flex-direction: column; align-items: stretch; }
    .sidebar, .main-column, .preview-column { width: 100%; }
    /* Zwinięty panel boczny to wiersz z samym przyciskiem rozwijaiającym. */
    body.sidebar-collapsed .sidebar > .sidebar-toggle { position: static; margin: 0 auto; }
    body.sidebar-collapsed.preview-below .workspace { display: flex; }
    .editor-wrap { height: min(62vh, 560px); min-height: 320px; }
    #previewFrame { height: 500px; }
    .request-controls { grid-template-columns: 82px minmax(0, 1fr); }
    .request-controls .secondary-button { grid-column: 1 / -1; }
    .app-footer { align-items: flex-start; flex-direction: column; }
    /* Przełącznik układu podgladu ma w waskim pasku za malo miejsca na
       symbol wraz z opisem, wiec zostaje sam symbol. */
    .layout-option-text { display: none; }
    .layout-option { padding: 4px 7px; }
}
@media (max-width: 450px) { .request-controls { grid-template-columns: 1fr; } .request-controls .secondary-button { grid-column: auto; } }

/* Układ pełnoekranowy używany, gdy playground jest osadzony w iframe. */
body.is-embedded,
body.is-embedded #codeEditor {
    height: 100%;
}

body.is-embedded {
    overflow: hidden;
}

body.is-embedded .app-shell {
    display: flex;
    width: 100%;
    height: 100vh;
    flex-direction: column;
    padding: 8px;
}

body.is-embedded .app-header {
    min-height: 42px;
    margin-bottom: 8px;
}

body.is-embedded .brand-mark {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    font-size: 12px;
}

body.is-embedded .brand-lockup {
    gap: 9px;
}

body.is-embedded h1 {
    font-size: 24px;
}

body.is-embedded .app-notice,
body.is-embedded .app-footer {
    display: none;
}

body.is-embedded .workspace {
    display: grid;
    flex: 1 1 auto;
    grid-template-columns: 190px minmax(0, 1fr) minmax(0, 1.05fr);
    /* Ramka na stronie kursu ma 860 px, wiec media query dla waskich okien
       nadaje tu uklad dwuwierszowy. Tryb osadzony musi go nadpisac wlasnymi
       obszarami — inaczej podglad laduje pod edytorem, edytor rośnie do
       wysokości strony, a panel boczny wychodzi poza swoja kolumne. */
    grid-template-areas: "side main preview";
    grid-template-rows: minmax(0, 1fr);
    gap: 8px;
    height: auto;
    min-height: 0;
}

body.is-embedded .preview-column {
    grid-column: auto;
    grid-row: auto;
}

/* Zwinięcie panelu bocznego działa także w ramce kursu — zostaje pasek
   36 px, a edytor i podgląd dostają resztę szerokości. */
body.is-embedded.sidebar-collapsed .workspace {
    grid-template-columns: 36px minmax(0, 1fr) minmax(0, 1.05fr);
}

/* Podgląd pod panelem żądania także w trybie osadzonym. Bez tych reguł
   przełącznik układu był martwy: blok osadzony ustawia własne
   grid-template-areas na "side main preview" i wygrywał z regułą
   pionową, a body.is-embedded ma overflow: hidden przy height: 100vh,
   więc podgląd schodził poza ramkę i był po prostu ucięty — bez
   przewijania nic się nie działo. */
body.is-embedded.preview-below {
    overflow: auto;
}

body.is-embedded.preview-below .app-shell {
    height: auto;
    min-height: 100vh;
}

body.is-embedded.preview-below .workspace {
    grid-template-columns: 190px minmax(0, 1fr);
    grid-template-areas:
        "side main"
        "side preview";
    grid-template-rows: auto auto;
    height: auto;
}

body.is-embedded.sidebar-collapsed.preview-below .workspace {
    grid-template-columns: 36px minmax(0, 1fr);
}

/* W pionie kolumny nie są już rozciągnięte na wysokość ramki, a edytor
   dostaje mniej miejsca niż obok — inaczej podgląd wypadałby poza
   ekranem jeszcze zanim dało się do niego dojechać. */
body.is-embedded.preview-below .sidebar,
body.is-embedded.preview-below .main-column,
body.is-embedded.preview-below .preview-column {
    height: auto;
}

body.is-embedded.preview-below .editor-wrap {
    height: min(56vh, 520px);
    min-height: 320px;
}

body.is-embedded .sidebar,
body.is-embedded .main-column,
body.is-embedded .preview-column {
    height: 100%;
    min-height: 0;
    gap: 8px;
}

body.is-embedded .sidebar {
    overflow: auto;
}

body.is-embedded .side-card,
body.is-embedded .request-card,
body.is-embedded .editor-card,
body.is-embedded .preview-card,
body.is-embedded .diagnostics-card {
    border-radius: 10px;
}

body.is-embedded .side-card,
body.is-embedded .request-card {
    padding: 9px;
}

body.is-embedded .main-column,
body.is-embedded .preview-column {
    display: flex;
    flex-direction: column;
}

body.is-embedded .editor-card {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
}

body.is-embedded .editor-wrap {
    flex: 1 1 auto;
    height: auto;
    min-height: 0;
}

body.is-embedded .code-area {
    min-height: 0;
}

body.is-embedded #codeEditor {
    min-height: 0;
    height: 100%;
}

body.is-embedded .request-card {
    flex: 0 0 auto;
    max-height: 250px;
    overflow: auto;
}

body.is-embedded .preview-card {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
}

body.is-embedded #previewFrame {
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
    min-height: 0;
}

body.is-embedded .diagnostics-card {
    flex: 0 0 105px;
    min-height: 0;
}

body.is-embedded .diagnostics-output {
    min-height: 0;
    max-height: 62px;
}

@media (max-width: 900px) {
    body.is-embedded {
        overflow: auto;
    }

    body.is-embedded .app-shell {
        height: auto;
        min-height: 100vh;
    }

    /* Ramka na stronie kursu ma 860 px, wiec ten układ jest w praktyce
       jedynym, w jakim Playground bywa osadzony. Kolumny flex dostaja
       stretch: bez tego bazowy align-items: start kurczy je do szerokości
       tresci — panel boczny wychodził poza 190 px, a edytor przybierał
       jego szerokość zamiast zajmowac cała szerokość. */
    body.is-embedded .workspace {
        display: flex;
        height: auto;
        flex-direction: column;
        align-items: stretch;
    }

    body.is-embedded .sidebar,
    body.is-embedded .main-column,
    body.is-embedded .preview-column {
        height: auto;
        width: 100%;
    }

    /* Zwinięty panel boczny zostaje cienkim paskiem z samym przyciskiem
       rozwijaiającym. Przy układzie kolumnowym nie ma obok czego
       rezerwować kolumny, wiec pasek idzie na całą szerokość. */
    body.is-embedded.sidebar-collapsed .sidebar > *:not(.sidebar-toggle) { display: none; }
    body.is-embedded.sidebar-collapsed .sidebar-toggle { position: static; margin: 0 auto; }

    body.is-embedded .editor-wrap {
        height: auto;
        min-height: 430px;
    }
}

