diff --git a/components/ui/SlideOver.tsx b/components/ui/SlideOver.tsx
index 8042a09..ea33f26 100644
--- a/components/ui/SlideOver.tsx
+++ b/components/ui/SlideOver.tsx
@@ -36,8 +36,27 @@ export function SlideOver({ open, onClose, title, subtitle, children, footer }:
aria-modal="true"
aria-labelledby={titleId}
tabIndex={-1}
- className={`absolute right-0 top-0 flex h-dvh w-full max-w-md flex-col bg-white shadow-[var(--shadow-overlay)] outline-none transition-transform duration-200 ${
- open ? "translate-x-0" : "translate-x-full"
+ // ── Warum der Schatten am geschlossenen Panel wegfällt ──────────
+ //
+ // Geschlossen steht das Panel per `translate-x-full` genau hinter dem
+ // rechten Bildschirmrand: die eigene linke Kante liegt auf dem Rand.
+ // Der Schatten ist das Einzige, was von dort noch ins Bild reicht —
+ // 32 px Weichzeichnung nach aussen, und „aussen" heisst hier: nach
+ // links, in die Seite hinein.
+ //
+ // Bei einem Panel fällt das nicht auf. Die Protokollseite rendert
+ // jedoch eines **je Zeile**, also fünfzig übereinander an derselben
+ // Stelle. Bei 18 % Deckkraft bleiben nach fünfzig Lagen rechnerisch
+ // 0,01 % Durchsicht — ein fast schwarzer Streifen neben der
+ // Bildlaufleiste, mit sichtbaren Stufen dort, wo sich die
+ // Weichzeichnungen der einzelnen Lagen überlagern. Genau das hat der
+ // Kunde gemeldet.
+ //
+ // Die Tiefe gehört zum geöffneten Panel, nicht zum weggeschobenen.
+ // Sie erst beim Öffnen zu setzen kostet nichts und nimmt dem Stapel
+ // seine Wirkung.
+ className={`absolute right-0 top-0 flex h-dvh w-full max-w-md flex-col bg-white outline-none transition-transform duration-200 ${
+ open ? "translate-x-0 shadow-[var(--shadow-overlay)]" : "translate-x-full"
}`}
>
diff --git a/tests/components/SlideOver.test.tsx b/tests/components/SlideOver.test.tsx
new file mode 100644
index 0000000..58c1ea9
--- /dev/null
+++ b/tests/components/SlideOver.test.tsx
@@ -0,0 +1,68 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+import { SlideOver } from "@/components/ui/SlideOver";
+
+// Das Panel bleibt geschlossen im DOM, damit die Schiebebewegung laufen kann.
+// Es steht dann per translate-x-full hinter dem rechten Bildschirmrand — die
+// eigene linke Kante genau auf dem Rand. Ein Schatten reicht von dort noch
+// ins Bild zurück, und die Protokollseite rendert ein Panel je Zeile: fünfzig
+// Schatten an derselben Stelle ergaben einen fast schwarzen Streifen neben
+// der Bildlaufleiste.
+
+function panel(container: HTMLElement): HTMLElement {
+ const el = container.querySelector('[role="dialog"]');
+ expect(el, "Das Panel fehlt").not.toBeNull();
+ return el as HTMLElement;
+}
+
+describe("SlideOver", () => {
+ it("bleibt geschlossen im DOM", () => {
+ // Ohne das gäbe es keine Schiebebewegung beim Schliessen — und dieser
+ // Test hier hätte keinen Gegenstand.
+ const { container } = render(
+ {}} title="Titel">
+ Inhalt
+
+ );
+ expect(panel(container).className).toContain("translate-x-full");
+ });
+
+ it("trägt geschlossen keinen Schatten", () => {
+ const { container } = render(
+ {}} title="Titel">
+ Inhalt
+
+ );
+ expect(panel(container).className).not.toContain("shadow-");
+ });
+
+ it("trägt geöffnet einen Schatten", () => {
+ const { container } = render(
+ {}} title="Titel">
+ Inhalt
+
+ );
+ expect(panel(container).className).toContain("shadow-[var(--shadow-overlay)]");
+ expect(panel(container).className).toContain("translate-x-0");
+ });
+
+ it("nimmt das geschlossene Panel aus der Bedienung", () => {
+ // `inert` und nicht aria-hidden: nur das entfernt die Felder auch aus der
+ // Tabulatorreihenfolge und blockiert Klicks.
+ const { container } = render(
+ {}} title="Titel">
+ Inhalt
+
+ );
+ expect(panel(container).closest("[inert]")).not.toBeNull();
+ });
+
+ it("benennt den Dialog nach seiner Überschrift", () => {
+ render(
+ {}} title="Anton Aigner">
+ Inhalt
+
+ );
+ expect(screen.getByRole("dialog", { name: "Anton Aigner" })).toBeInTheDocument();
+ });
+});