/* Stufe 0 — bewusst nüchtern. Das Aussehen wird in Stufe 1 an inf-schule
   angepasst; hier zählt Lesbarkeit und Messbarkeit. */

/* Farben nach der inf-schule-Palette
   (https://inf-schule.de/infschule/dokumentation/farben):
     Highlight blau  #0077b6   Dunkelblau (Header) #024f7f
     Highlight rot   #b82929   Hintergrund grau    #f5f5f5
     Rahmen          #c8c8c8
   Die beiden Blautöne tragen die Akzente der Anwendung. */
:root {
  --oopy-rahmen: #c8c8c8;
  --oopy-grund: #ffffff;
  --oopy-flaeche: #f5f5f5;
  --oopy-kopf: #e4eef5;
  --oopy-akzent: #0077b6;
  --oopy-akzent-dunkel: #024f7f;
  --oopy-gedaempft: #5d6b7a;
  --oopy-fehler: #b82929;
  --oopy-fehlergrund: #fbeaea;

  /* Zehn Farben für die Objektnummern (US-16).
     Abgeleitet aus den drei nicht-blauen inf-schule-Farbtönen — rot 0°,
     gelb 48°, türkis 163° — und dazwischen gleichmäßig ergänzt. Der
     Blaubereich bleibt frei, damit keine Nummer wie ein Bedienelement
     aussieht. Jede Farbe trägt weiße Schrift mit mindestens 5:1 Kontrast;
     der kleinste Abstand zweier Farben beträgt ΔE 28, der Abstand zu den
     beiden Akzentblautönen ΔE 44. */
  --oopy-objekt-0: #d32d2d;   /* rubin   — inf-schule rot */
  --oopy-objekt-1: #aa5a24;   /* orange  */
  --oopy-objekt-2: #866c06;   /* gold    — inf-schule gelb */
  --oopy-objekt-3: #5a7828;   /* oliv    */
  --oopy-objekt-4: #06810a;   /* grün    */
  --oopy-objekt-5: #1b7d61;   /* türkis  — inf-schule türkis */
  --oopy-objekt-6: #5b61dc;   /* indigo  */
  --oopy-objekt-7: #9b41dc;   /* violett */
  --oopy-objekt-8: #c128ad;   /* magenta */
  --oopy-objekt-9: #cd2b73;   /* himbeer */
}

/* Das `hidden`-Attribut muss stärker sein als jede eigene `display`-Regel.
   Ohne diese Zeile bliebe eine per Zuschnitt abgeschaltete Werkzeugleiste
   sichtbar, weil `.oopy-werkzeugleiste { display: flex }` die Browserregel
   `[hidden] { display: none }` überstimmt (US-37 AK3). */
.oopy [hidden],
.oopy[hidden] { display: none !important; }

.oopy {
  border: 1px solid var(--oopy-rahmen);
  border-radius: 6px;
  background: var(--oopy-grund);
  margin: 1.5rem 0;
  font: 15px/1.45 system-ui, sans-serif;
  overflow: hidden;
  /* Die Breite kommt von außen und wird nach außen nicht weitergemeldet.
     Ohne diese Zeile schiebt der breiteste Klassenkasten die ganze Buchseite
     auf: Bei inf-schule ist der Textbereich ein Flex-Element, das auf seine
     max-content-Breite wächst — und `overflow-x: auto` weiter innen ändert
     daran nichts, weil es nur die min-content-Breite senkt. Auf einem 375 px
     breiten Bildschirm wurde die Seite dadurch 452 px breit und wanderte
     seitlich weg (QA-3). */
  contain: inline-size;
}

/* Rückstellung gegen die Regeln der Buchseite.

   inf-schule gestaltet den Kapiteltext über den Vorfahren `article`:

     article h1, article h2, article h3  { border-bottom: 0.2em solid …; text-align: right }
     article h4                          { width: fit-content; border-bottom: 0.08em dotted … }
     article pre                         { font-family: PTMono; margin: 1.5rem 0 !important }

   Diese Regeln greifen nicht über unsere Klassen, sondern über den Vorfahren —
   ein anderer Elementname hilft deshalb nicht, nur ausdrückliches Zurücksetzen.
   Unsere Überschriften trugen sonst die rote Kapitellinie und standen
   rechtsbündig, die Bereichsüberschriften schrumpften auf `fit-content`.

   Der Block steht bewusst **vor** allen Einzelregeln: Er hat dieselbe
   Spezifität wie sie, und bei Gleichstand gewinnt die spätere Regel. */
.oopy :where(h1, h2, h3, h4, h5, h6) {
  border: none; text-align: left; clear: none; width: auto;
  padding: 0; background: none; text-transform: none; letter-spacing: normal;
}

/* `revert` statt eigener Werte: Zurück auf den Standard des Browsers, nicht auf
   ein zweites eigenes Aussehen. Betroffen sind die Elementarten, die inf-schule
   im Kapiteltext gestaltet — bei neuen Elementarten ist das erneut zu prüfen.

   `:where()` ist hier kein Zierrat, sondern die ganze Rechnung: Der Elementname
   darin zählt für die Spezifität nicht mit, also wiegt `.oopy :where(button)`
   genau eine Klasse (0,1,0).

     article button          (0,0,2)  fremd     — wird geschlagen
     .oopy :where(button)    (0,1,0)  Rückstellung
     .oopy-ausfuehren        (0,1,0)  eigen     — gleich stark, steht später, gewinnt

   Mit `.oopy button` (0,1,1) war die Rückstellung stärker als die eigenen
   Knopfregeln und hat den blauen „Ausführen"-Knopf grau gemacht. */
.oopy :where(button) {
  border: revert; background: revert; border-radius: revert; padding: revert;
  color: revert; box-shadow: revert; text-transform: revert;
  display: revert; transition: revert;
  /* `margin: 0` und nicht `revert`: Der Kapiteltext gibt Knöpfen 1.5rem
     Außenabstand, was den Werkzeugkopf auf das Vierfache aufgeblasen hat. */
  margin: 0;
}
.oopy :where(summary) {
  background: revert; border-radius: revert; padding: revert;
  display: revert; box-shadow: revert; transition: revert;
}
/* Der Aufklapp-Pfeil der Buchseite ist ein absolut gesetztes CSS-Dreieck:

     article summary:before { content: ""; border-color: … transparent … #434343;
                              position: absolute; top: 2rem; left: 2.5rem }

   „Absolut" heißt: gemessen am nächsten Vorfahren mit `position`. Die Kästen
   von inf-schule stellen den her (`article .def`, `.achtung`, `.information`,
   … tragen alle `position: relative`) — unsere nicht. Der Pfeil wanderte
   deshalb bis zum Artikelrahmen hoch und stand als herrenloses Dreieck oben
   links auf der Buchseite, sobald ein Werkzeug den Quelltext-Aufklapper zeigte
   (`quelltextAnzeigen`, B7).

   Abgeschaltet statt umgehängt: Unser Aufklapper trägt bereits den Marker des
   Browsers, weil `display: revert` eine Zeile höher `list-item` wiederherstellt.
   Zwei Pfeile nebeneinander wären die schlechtere Antwort. */
.oopy :where(summary)::before { content: revert; }
.oopy :where(details) { transition: revert; }
.oopy :where(pre) { font-family: ui-monospace, monospace; font-size: revert; }

/* `!important` nur an diesen beiden Stellen, und nur weil die fremden Regeln
   `article pre { margin: … !important }` und `article details { padding: …
   !important }` es selbst benutzen. */
.oopy :where(pre) { margin: 0 !important; }
.oopy :where(details) { padding: revert !important; }

/* Die einzige Regel dieses Blatts außerhalb der Werkzeugwurzel — und der
   Gegenpol zur Regel darüber: Der Kasten `details.oopy-zuschnitt` auf den
   Erprobungsseiten *will* wie ein Kasten der Buchseite aussehen, samt ihrem
   Pfeil. Er braucht dafür nur, was die Kästen von inf-schule selbst mitbringen
   (B7). Ohne diese Zeile landet sein Pfeil oben links im Artikel — auf der
   Erarbeitungsseite lagen drei davon übereinander. */
.oopy-zuschnitt { position: relative; }

.oopy-kopf {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.6rem 0.9rem;
  background: var(--oopy-kopf);
  border-bottom: 1px solid var(--oopy-rahmen);
}
.oopy-kopf h3 { margin: 0; font-size: 1rem; }
.oopy-schalter { display: flex; flex-wrap: wrap; gap: 0.9rem; font-size: 0.85rem; }
.oopy-schalter label { display: inline-flex; align-items: center; gap: 0.35rem; }

.oopy-zustand { padding: 0.9rem; color: var(--oopy-gedaempft); }
.oopy-zustand p { margin: 0.4rem 0; }
.oopy-zustand button {
  margin-top: 0.5rem; padding: 0.35rem 0.8rem; cursor: pointer;
  border: 1px solid var(--oopy-akzent); border-radius: 4px;
  background: var(--oopy-akzent); color: #fff; font: inherit;
}
.oopy-fehler { background: var(--oopy-fehlergrund); color: var(--oopy-fehler); }

.oopy-balken {
  height: 4px; border-radius: 2px; overflow: hidden;
  background: linear-gradient(90deg, var(--oopy-akzent) 0 30%, transparent 30% 100%)
              0 0 / 250% 100% no-repeat;
  animation: oopy-lauf 1.1s linear infinite;
}
@keyframes oopy-lauf { to { background-position: 150% 0; } }
@media (prefers-reduced-motion: reduce) { .oopy-balken { animation: none; } }

/* --- Klassendiagramm --- */

.oopy-inhalt { padding: 1rem; overflow-x: auto; }
/* Oberklassen oben, Unterklassen darunter — UML-Konvention. Die Ebenen
   werden nach Vererbungstiefe aufsteigend eingefügt. */
.oopy-diagramm { position: relative; display: flex; flex-direction: column;
                gap: 2.5rem; align-items: center; min-width: max-content; }
.oopy-ebene { display: flex; gap: 1.5rem; justify-content: center; flex-wrap: wrap; }

.oopy-pfeile { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.oopy-vererbung { fill: none; stroke: var(--oopy-gedaempft); stroke-width: 1.5; }
.oopy-pfeile marker path { fill: var(--oopy-grund); stroke: var(--oopy-gedaempft); stroke-width: 1; }

.oopy-klasse {
  border: 1px solid var(--oopy-gedaempft);
  background: var(--oopy-grund);
  /* Breit genug für die meisten UML-Signaturen in einer Zeile. */
  min-width: 12rem; max-width: 26rem;
  font-family: ui-monospace, monospace; font-size: 0.8rem;
}
.oopy-klasse-kopf {
  padding: 0.4rem 0.6rem; text-align: center; font-weight: 700;
  background: var(--oopy-kopf); border-bottom: 1px solid var(--oopy-gedaempft);
}
.oopy-fach { margin: 0; padding: 0.35rem 0.6rem; list-style: none;
            border-bottom: 1px solid var(--oopy-rahmen); }
.oopy-fach:last-child { border-bottom: none; }
/* Hängender Einzug: Eine umgebrochene Signatur bleibt als Fortsetzung
   derselben Methode erkennbar. */
.oopy-fach li { padding: 0.1rem 0 0.1rem 1.2em; text-indent: -1.2em;
               overflow-wrap: anywhere; }
.oopy-klassenattribut { text-decoration: underline; }  /* UML: unterstrichen */
.oopy-intern { color: var(--oopy-gedaempft); font-style: italic; }
.oopy-leer { color: var(--oopy-rahmen); }
.oopy-hinweis { color: var(--oopy-gedaempft); font-size: 0.9rem; }

.oopy-quelltext { border-top: 1px solid var(--oopy-rahmen); padding: 0.5rem 0.9rem; }
.oopy-quelltext pre { overflow-x: auto; font-size: 0.8rem; }

/* ============================================================
   Stufe 1 — Objektbank, Menüs, Dialoge, Code-Spiegel
   ============================================================ */

.oopy-werkzeugleiste {
  display: flex; flex-wrap: wrap; gap: 0.9rem; align-items: center;
  font-size: 0.85rem;
}
.oopy-werkzeugleiste label { display: inline-flex; align-items: center; gap: 0.35rem; }
.oopy-zuruecksetzen {
  padding: 0.25rem 0.7rem; cursor: pointer; font: inherit; font-size: 0.85rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 4px; background: #fff;
}
.oopy-zuruecksetzen:hover { border-color: var(--oopy-akzent); color: var(--oopy-akzent); }

.oopy-bereich { border-top: 1px solid var(--oopy-rahmen); }
.oopy-bereich:first-child { border-top: none; }
.oopy-bereich > h4 {
  margin: 0; padding: 0.45rem 0.9rem; font-size: 0.75rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--oopy-gedaempft);
  background: var(--oopy-flaeche);
}

/* --- Klassenkasten: Menüzugang --- */

.oopy-klasse-kopf { display: flex; align-items: center; justify-content: center; gap: 0.4rem; }
.oopy-klasse-name { flex: 1; }
.oopy-klasse-menue {
  border: none; background: none; cursor: pointer; font: inherit; line-height: 1;
  padding: 0.1rem 0.25rem; border-radius: 3px; color: var(--oopy-gedaempft);
}
.oopy-klasse-menue:hover, .oopy-klasse-menue:focus-visible {
  background: var(--oopy-akzent); color: #fff;
}

/* --- Objektbank --- */

.oopy-bank {
  display: flex; flex-wrap: wrap; gap: 0.6rem; padding: 0.9rem;
  min-height: 3.5rem; align-items: flex-start;
  background: repeating-linear-gradient(45deg, #fafbfc 0 8px, #f4f6f8 8px 16px);
}
.oopy-objekt {
  display: grid; gap: 0.1rem; text-align: left; cursor: pointer; font: inherit;
  padding: 0.45rem 0.7rem; border-radius: 4px;
  border: 1px solid var(--oopy-gedaempft); background: #fffdf3;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.12);
  font-family: ui-monospace, monospace; font-size: 0.8rem; max-width: 18rem;
}
.oopy-objekt:hover, .oopy-objekt:focus-visible { border-color: var(--oopy-akzent); }
.oopy-objekt-name { font-weight: 700; }
.oopy-objekt-klasse { color: var(--oopy-akzent); font-size: 0.72rem; }
.oopy-objekt-repr { color: var(--oopy-gedaempft); font-size: 0.72rem;
                   overflow-wrap: anywhere; }
.oopy-objekt.oopy-geteilt { border-style: double; border-width: 3px; }

/* --- Ergebnis eines Aufrufs --- */

.oopy-ergebnis { padding: 0.7rem 0.9rem; background: #f2f7fc; font-size: 0.9rem; }
.oopy-ergebnis p { margin: 0.25rem 0; }
.oopy-ergebnis-code { font-family: ui-monospace, monospace; font-size: 0.8rem;
                     color: var(--oopy-gedaempft); }
.oopy-ergebnis-wert { font-family: ui-monospace, monospace; font-size: 0.95rem; }
.oopy-ergebnis-typ {
  display: inline-block; padding: 0.05rem 0.4rem; border-radius: 3px;
  background: var(--oopy-akzent); color: #fff; font-size: 0.72rem;
}
.oopy-ergebnis button {
  margin-top: 0.4rem; padding: 0.25rem 0.7rem; cursor: pointer; font: inherit;
  font-size: 0.85rem; border: 1px solid var(--oopy-akzent); border-radius: 4px;
  background: #fff; color: var(--oopy-akzent);
}
.oopy-ergebnis-fehler { background: var(--oopy-fehlergrund); color: var(--oopy-fehler); }
.oopy-ergebnis-titel { font-weight: 700; }
.oopy-ergebnis-ort { font-size: 0.8rem; }

/* --- Code-Spiegel-Protokoll --- */

.oopy-protokoll-kopf {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: 0.45rem 0.9rem; background: var(--oopy-flaeche); font-size: 0.75rem;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--oopy-gedaempft);
}
.oopy-protokoll-kopieren {
  padding: 0.15rem 0.5rem; cursor: pointer; font: inherit; font-size: 0.7rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 3px; background: #fff;
  text-transform: none; letter-spacing: 0;
}
.oopy-protokoll-liste {
  margin: 0; padding: 0.6rem 0.9rem 0.6rem 2.6rem; max-height: 11rem; overflow-y: auto;
  font-family: ui-monospace, monospace; font-size: 0.8rem;
}
.oopy-protokoll-liste li { padding: 0.1rem 0; overflow-wrap: anywhere; }
.oopy-protokoll-liste .oopy-fehlgeschlagen {
  color: var(--oopy-fehler); text-decoration: line-through;
}
.oopy-protokoll-liste .oopy-hinweis { list-style: none; margin-left: -1.4rem; }

/* --- Aufklappmenü --- */

.oopy-menue {
  position: absolute; z-index: 60; min-width: 15rem; max-width: 26rem;
  padding: 0.25rem; border: 1px solid var(--oopy-gedaempft); border-radius: 5px;
  background: #fff; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
  font: 14px/1.4 system-ui, sans-serif;
}
.oopy-menue-titel {
  margin: 0.3rem 0.5rem 0.15rem; font-size: 0.7rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--oopy-gedaempft);
}
.oopy-menue-eintrag {
  display: block; width: 100%; text-align: left; cursor: pointer; font: inherit;
  padding: 0.3rem 0.5rem; border: none; border-radius: 3px; background: none;
}
.oopy-menue-eintrag:hover:not(:disabled),
.oopy-menue-eintrag:focus-visible { background: var(--oopy-akzent); color: #fff; }
.oopy-menue-eintrag:disabled { color: var(--oopy-rahmen); cursor: default; }
.oopy-menue-text { font-family: ui-monospace, monospace; font-size: 0.82rem; }
.oopy-menue-hinweis {
  display: block; font-size: 0.72rem; opacity: 0.75;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- Dialog --- */

.oopy-dialog {
  border: 1px solid var(--oopy-gedaempft); border-radius: 6px; padding: 0;
  max-width: min(32rem, 92vw); font: 15px/1.45 system-ui, sans-serif;
  color: #24303d;
}
.oopy-dialog::backdrop { background: rgba(20, 30, 40, 0.35); }
.oopy-dialog form { padding: 1rem 1.2rem 1.1rem; }
.oopy-dialog h4 { margin: 0 0 0.3rem; font-size: 1rem; font-family: ui-monospace, monospace; }
.oopy-dok { margin: 0 0 0.9rem; color: var(--oopy-gedaempft); font-size: 0.88rem; }

.oopy-feld { margin-bottom: 0.75rem; }
.oopy-feld > label { display: block; font-size: 0.85rem; font-weight: 600;
                    font-family: ui-monospace, monospace; margin-bottom: 0.2rem; }
.oopy-typ { font-weight: 400; color: var(--oopy-akzent); }
.oopy-feld-reihe { display: flex; gap: 0.4rem; }
.oopy-feld input {
  flex: 1; min-width: 0; padding: 0.35rem 0.5rem; font: inherit; font-size: 0.9rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 4px;
}
.oopy-feld input:focus { outline: 2px solid var(--oopy-akzent); outline-offset: 1px; }
.oopy-einsetzen {
  padding: 0.3rem 0.55rem; cursor: pointer; font: inherit; font-size: 0.8rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 4px; background: var(--oopy-flaeche);
}
.oopy-einsetzen:disabled { opacity: 0.45; cursor: default; }
.oopy-feld-hinweis { margin: 0.15rem 0 0; font-size: 0.75rem; color: var(--oopy-gedaempft);
                    min-height: 1em; }
.oopy-art-text-ergaenzt { color: #8a5a00; }
.oopy-art-objekt { color: var(--oopy-akzent); font-weight: 600; }
.oopy-namensfeld > label { color: var(--oopy-gedaempft); }

.oopy-spiegel-titel { margin: 1rem 0 0.25rem; font-size: 0.72rem; text-transform: uppercase;
                     letter-spacing: 0.04em; color: var(--oopy-gedaempft); }
.oopy-spiegel {
  margin: 0; padding: 0.55rem 0.7rem; border-radius: 4px; overflow-x: auto;
  background: var(--oopy-akzent-dunkel); color: #f2f7fa;
  font-family: ui-monospace, monospace; font-size: 0.85rem;
}
.oopy-dialog-fehler {
  margin: 0.8rem 0 0; padding: 0.5rem 0.7rem; border-radius: 4px;
  background: var(--oopy-fehlergrund); color: var(--oopy-fehler); font-size: 0.88rem;
}
.oopy-dialog menu {
  display: flex; justify-content: flex-end; gap: 0.5rem;
  margin: 1.1rem 0 0; padding: 0;
}
.oopy-dialog menu button {
  padding: 0.4rem 0.9rem; cursor: pointer; font: inherit; border-radius: 4px;
  border: 1px solid var(--oopy-rahmen); background: #fff;
}
.oopy-dialog .oopy-ok { border-color: var(--oopy-akzent); background: var(--oopy-akzent);
                      color: #fff; }

/* --- Quelltextansicht mit Sprungziel (US-08) --- */

.oopy-quelltext-zeilen {
  margin: 0.4rem 0 0; padding: 0.5rem 0.5rem 0.5rem 3rem; max-height: 20rem;
  overflow: auto; background: #fbfcfd; border: 1px solid var(--oopy-rahmen);
  font-family: ui-monospace, monospace; font-size: 0.78rem;
}
.oopy-quelltext-zeilen li { white-space: pre; color: #24303d; }
.oopy-quelltext-zeilen li::marker { color: var(--oopy-rahmen); font-size: 0.72rem; }
.oopy-zeile-treffer { background: #fff3bf; font-weight: 700; }

@media (max-width: 768px) {
  .oopy-kopf { flex-direction: column; align-items: stretch; }
  .oopy-bank { padding: 0.6rem; }
  .oopy-objekt { max-width: 100%; }
  .oopy-menue { max-width: calc(100vw - 1rem); }
}

/* ============================================================
   Stufe 2 — Objektinspektor, Objektidentität, Konsole
   ============================================================ */

/* --- Objektnummern und Verweise (US-16) --- */

.oopy-nummer {
  display: inline-block; padding: 0.05rem 0.35rem; border-radius: 999px;
  background: var(--oopy-gedaempft); color: #fff;
  font-size: 0.68rem; font-weight: 700; line-height: 1.4;
  font-family: ui-monospace, monospace; vertical-align: middle;
  white-space: nowrap;
}
.oopy-nummer[data-farbe="0"] { background: var(--oopy-objekt-0); }
.oopy-nummer[data-farbe="1"] { background: var(--oopy-objekt-1); }
.oopy-nummer[data-farbe="2"] { background: var(--oopy-objekt-2); }
.oopy-nummer[data-farbe="3"] { background: var(--oopy-objekt-3); }
.oopy-nummer[data-farbe="4"] { background: var(--oopy-objekt-4); }
.oopy-nummer[data-farbe="5"] { background: var(--oopy-objekt-5); }
.oopy-nummer[data-farbe="6"] { background: var(--oopy-objekt-6); }
.oopy-nummer[data-farbe="7"] { background: var(--oopy-objekt-7); }
.oopy-nummer[data-farbe="8"] { background: var(--oopy-objekt-8); }
.oopy-nummer[data-farbe="9"] { background: var(--oopy-objekt-9); }
.oopy-bankverweis {
  display: inline-block; padding: 0 0.3rem; border-radius: 3px;
  background: #e6f0e2; color: #3c6b28; font-size: 0.68rem;
  font-family: ui-monospace, monospace;
}
.oopy-kreis {
  display: inline-block; padding: 0 0.3rem; border-radius: 3px;
  background: #f4e6d2; color: #8a5a00; font-size: 0.68rem;
}

.oopy-objekt-kopf { display: flex; align-items: center; gap: 0.35rem; }
.oopy-objekt.oopy-geteilt { border-style: dashed; border-width: 2px; }

/* --- Inspektor --- */

.oopy-inspektoren {
  display: flex; flex-wrap: wrap; gap: 0.8rem; padding: 0.9rem;
  align-items: flex-start;
}
.oopy-inspektoren:has(.oopy-hinweis) { display: block; }

.oopy-inspektor {
  flex: 1 1 20rem; max-width: 30rem; min-width: 0;
  border: 1px solid var(--oopy-gedaempft); border-radius: 4px; background: #fff;
  overflow: hidden;
}
.oopy-inspektor-kopf {
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0.35rem 0.5rem; background: var(--oopy-kopf);
  border-bottom: 1px solid var(--oopy-gedaempft);
  font-family: ui-monospace, monospace; font-size: 0.8rem; font-weight: 700;
}
.oopy-inspektor-titel { flex: 1; overflow-wrap: anywhere; }
.oopy-inspektor-schliessen {
  border: none; background: none; cursor: pointer; font: inherit; font-size: 1rem;
  line-height: 1; padding: 0 0.25rem; border-radius: 3px; color: var(--oopy-gedaempft);
}
.oopy-inspektor-schliessen:hover, .oopy-inspektor-schliessen:focus-visible {
  background: var(--oopy-fehler); color: #fff;
}

.oopy-brotkrumen { padding: 0.3rem 0.5rem; border-bottom: 1px solid var(--oopy-rahmen); }
.oopy-brotkrumen button {
  border: none; background: none; cursor: pointer; font: inherit; font-size: 0.75rem;
  color: var(--oopy-akzent); padding: 0.1rem 0.25rem; border-radius: 3px;
}
.oopy-brotkrumen button:hover { text-decoration: underline; }

.oopy-attribute { width: 100%; border-collapse: collapse; font-size: 0.78rem; }
.oopy-attribute th, .oopy-attribute td {
  text-align: left; padding: 0.25rem 0.5rem; vertical-align: top;
  border-bottom: 1px solid #eef2f6;
}
.oopy-attribute tr:last-child th, .oopy-attribute tr:last-child td { border-bottom: none; }
.oopy-abschnitt th {
  background: var(--oopy-flaeche); color: var(--oopy-gedaempft); font-weight: 600;
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em;
}
.oopy-attribute tbody th {
  font-family: ui-monospace, monospace; font-weight: 600; white-space: nowrap;
}
.oopy-attribut-typ { color: var(--oopy-akzent); font-family: ui-monospace, monospace;
                    font-size: 0.72rem; white-space: nowrap; }
.oopy-attribut-wert { font-family: ui-monospace, monospace; overflow-wrap: anywhere; }
.oopy-attribut-wert > * + * { margin-left: 0.35rem; }
.oopy-attribute .oopy-intern th, .oopy-attribute .oopy-intern .oopy-wertanzeige {
  color: var(--oopy-gedaempft); font-style: italic;
}
.oopy-aufklappen {
  padding: 0 0.35rem; cursor: pointer; font: inherit; font-size: 0.68rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 3px; background: var(--oopy-flaeche);
  color: var(--oopy-akzent);
}
.oopy-aufklappen:hover { border-color: var(--oopy-akzent); }

/* US-19: geänderte Werte fallen kurz ins Auge. */
.oopy-attribute tr.oopy-geaendert { background: #fff3bf; }
.oopy-attribute tr.oopy-geaendert .oopy-wertanzeige { font-weight: 700; }
@media (prefers-reduced-motion: no-preference) {
  .oopy-attribute tr { transition: background-color 0.6s ease-out; }
}

/* --- Konsole --- */

.oopy-konsole-kopf {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: 0.45rem 0.9rem; background: var(--oopy-flaeche); font-size: 0.75rem;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--oopy-gedaempft);
}
.oopy-konsole-leeren {
  padding: 0.15rem 0.5rem; cursor: pointer; font: inherit; font-size: 0.7rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 3px; background: #fff;
  text-transform: none; letter-spacing: 0;
}
.oopy-konsole-text {
  margin: 0; padding: 0.6rem 0.9rem; max-height: 10rem; overflow: auto;
  background: var(--oopy-akzent-dunkel); color: #f2f7fa;
  font-family: ui-monospace, monospace; font-size: 0.78rem;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.oopy-konsole-text.oopy-leer { background: #fbfcfd; color: var(--oopy-gedaempft);
                             font-style: italic; }

@media (max-width: 768px) {
  .oopy-inspektor { flex-basis: 100%; max-width: 100%; }
}

/* ============================================================
   Stufe 3 — Editor und Code-Pad
   ============================================================ */

.oopy-bereich > h4 { display: flex; align-items: center; gap: 0.75rem; }
.oopy-bereich > h4 > span:first-child { flex: none; }
.oopy-editor-stand, .oopy-hp-stand {
  flex: 1; font-weight: 400; text-transform: none; letter-spacing: 0;
  font-size: 0.72rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.oopy-stand-fehler { color: var(--oopy-fehler); font-weight: 600; }
.oopy-stand-geaendert { color: #8a5a00; }
.oopy-stand-erfolg { color: var(--oopy-akzent); }
.oopy-ausfuehren {
  flex: none; padding: 0.2rem 0.8rem; cursor: pointer; font: inherit;
  font-size: 0.78rem; text-transform: none; letter-spacing: 0;
  border: 1px solid var(--oopy-akzent); border-radius: 4px;
  background: var(--oopy-akzent); color: #fff;
}
.oopy-ausfuehren:hover { background: var(--oopy-akzent-dunkel); }

.oopy-bereich-diagramm.oopy-veraltet .oopy-inhalt { opacity: 0.55; }
.oopy-bereich-diagramm.oopy-veraltet .oopy-inhalt::after {
  content: "Diagramm veraltet — der Quelltext ist gerade nicht lesbar.";
  display: block; margin-top: 0.6rem; text-align: center;
  font-size: 0.75rem; color: var(--oopy-fehler);
}

/* --- Editor: Textfeld über Hervorhebungsschicht --- */

/* Die Höhe steht am Editor selbst, nicht am Textbereich.
   Sonst wächst die Zeilennummernspalte mit der Zeilenzahl, zieht den Editor
   auf — und der Text bricht nach der Höhe des Textbereichs einfach ab, während
   die Nummern weiterlaufen. */
.oopy-editor {
  display: flex; align-items: stretch; background: var(--oopy-grund);
  height: 22rem;
  --oopy-zeilenhoehe: 1.5;
  font-family: ui-monospace, monospace; font-size: 0.82rem;
}
.oopy-zeilennummern {
  flex: none; padding: 0.6rem 0.5rem 0.6rem 0.9rem; overflow: hidden;
  text-align: right; color: var(--oopy-rahmen); background: var(--oopy-flaeche);
  border-right: 1px solid var(--oopy-rahmen);
  line-height: var(--oopy-zeilenhoehe); user-select: none;
}
.oopy-zeilennummern .oopy-nummer-fehler { color: var(--oopy-fehler); font-weight: 700; }
.oopy-zeilennummern .oopy-nummer-marke { color: var(--oopy-akzent); font-weight: 700; }

.oopy-schacht { position: relative; flex: 1; min-width: 0; }
.oopy-bloecke, .oopy-hervorhebung, .oopy-eingabe {
  position: absolute; inset: 0; margin: 0;
  padding: 0.6rem 0.9rem;
  font: inherit; line-height: var(--oopy-zeilenhoehe);
  white-space: pre; overflow-wrap: normal; tab-size: 4;
}
.oopy-bloecke { padding: 0; overflow: hidden; pointer-events: none; }
/* Bezugspunkt ist die Hervorhebungsschicht: Die Flächen übernehmen deren
   `offsetTop`-Werte, also darf hier kein eigener Versatz dazukommen. */
.oopy-blockinhalt { position: absolute; inset: 0; will-change: transform; }
.oopy-hervorhebung { overflow: hidden; pointer-events: none; color: #24303d; }
.oopy-eingabe {
  overflow: auto; resize: none; border: none; outline: none;
  background: transparent; color: transparent; caret-color: var(--oopy-akzent);
}
.oopy-eingabe::selection { background: rgba(0, 119, 182, 0.22); }
.oopy-quellzeile { min-height: 1em; }

/* Blockflächen (US-28).
   Alle Tiefen tragen dieselbe schwache Deckkraft — verschachtelte Blöcke
   liegen übereinander, ihre Flächen addieren sich also von selbst. Je tiefer
   die Verschachtelung, desto kräftiger die Fläche, ohne dass es je Ebene eine
   eigene Farbe braucht. */
/* `left` setzt der Editor je Block auf die Einrückung seines Kopfes. */
.oopy-block { position: absolute; right: 0;
             background: rgba(0, 119, 182, 0.05); }
.oopy-zeile-fehler, .oopy-zeile-marke { position: absolute; left: 0; right: 0; }
.oopy-zeile-fehler { background: rgba(184, 41, 41, 0.14);
                    border-left: 3px solid var(--oopy-fehler); }
.oopy-zeile-marke { background: rgba(0, 119, 182, 0.12);
                   border-left: 3px solid var(--oopy-akzent); }

/* Syntaxfarben, abgestimmt auf die inf-schule-Palette */
.oopy-m-schluesselwort { color: #9b41dc; font-weight: 600; }
.oopy-m-definition { color: var(--oopy-akzent-dunkel); font-weight: 700; }
.oopy-m-selbst { color: #aa5a24; font-style: italic; }
.oopy-m-eingebaut { color: var(--oopy-akzent); }
.oopy-m-text { color: #1b7d61; }
.oopy-m-zahl { color: #c128ad; }
.oopy-m-kommentar { color: var(--oopy-gedaempft); font-style: italic; }
.oopy-m-operator { color: #5d6b7a; }
.oopy-m-name { color: #24303d; }

/* --- Code-Pad --- */

.oopy-pad-kopf {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding: 0.45rem 0.9rem; background: var(--oopy-flaeche);
  font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--oopy-gedaempft);
}
.oopy-pad-hilfe { text-transform: none; letter-spacing: 0; font-size: 0.7rem; }
.oopy-pad-verlauf {
  margin: 0; padding: 0.5rem 0.9rem; max-height: 12rem; overflow-y: auto;
  list-style: none; font-family: ui-monospace, monospace; font-size: 0.78rem;
}
.oopy-pad-verlauf li { padding: 0.05rem 0; overflow-wrap: anywhere; white-space: pre-wrap; }
.oopy-pad-eingegeben::before { content: ">>> "; color: var(--oopy-akzent); }
.oopy-pad-eingegeben { color: #24303d; }
.oopy-pad-wert { color: var(--oopy-akzent-dunkel); font-weight: 600; }
.oopy-pad-ausgabe { color: var(--oopy-gedaempft); }
.oopy-pad-fehler { color: var(--oopy-fehler); }
.oopy-pad-hinweis { color: #8a5a00; font-style: italic; }
.oopy-pad-eingabezeile {
  display: flex; align-items: flex-start; gap: 0.5rem;
  padding: 0.4rem 0.9rem; border-top: 1px solid var(--oopy-rahmen);
}
.oopy-pad-zeichen { color: var(--oopy-akzent); font-family: ui-monospace, monospace;
                   font-size: 0.8rem; line-height: 1.5; }
.oopy-pad-eingabe {
  flex: 1; min-width: 0; border: none; outline: none; resize: none;
  font-family: ui-monospace, monospace; font-size: 0.8rem; line-height: 1.5;
  background: transparent; color: #24303d;
}
.oopy-ergebnis-hinweis { color: #8a5a00; font-style: italic; }

@media (max-width: 768px) {
  .oopy-editor { height: 16rem; }
}

/* --- Dateireiter (US-32) --- */

.oopy-reiter-leiste {
  display: flex; flex-wrap: wrap; gap: 0.2rem; align-items: flex-end;
  padding: 0.35rem 0.9rem 0; background: var(--oopy-flaeche);
  border-bottom: 1px solid var(--oopy-rahmen);
}
.oopy-reiter {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.25rem 0.6rem; cursor: pointer; font: inherit; font-size: 0.78rem;
  font-family: ui-monospace, monospace;
  border: 1px solid var(--oopy-rahmen); border-bottom: none;
  border-radius: 4px 4px 0 0; background: #fff; color: var(--oopy-gedaempft);
  margin-bottom: -1px;
}
.oopy-reiter:hover { color: var(--oopy-akzent); }
.oopy-reiter-aktiv {
  background: var(--oopy-grund); color: #24303d; font-weight: 600;
  border-color: var(--oopy-rahmen); border-bottom: 1px solid var(--oopy-grund);
}
.oopy-reiter-weg { color: var(--oopy-rahmen); font-size: 0.9rem; line-height: 1; }
.oopy-reiter-weg:hover { color: var(--oopy-fehler); }
.oopy-reiter-neu {
  padding: 0.25rem 0.5rem; cursor: pointer; font: inherit; font-size: 0.9rem;
  line-height: 1; border: 1px dashed var(--oopy-rahmen); border-radius: 4px;
  background: none; color: var(--oopy-gedaempft); margin-bottom: 0.2rem;
}
.oopy-reiter-neu:hover { border-color: var(--oopy-akzent); color: var(--oopy-akzent); }

/* Entzogenes Bearbeitungsrecht: der Quelltext bleibt lesbar und kopierbar,
   nur eben unveränderlich (US-64). */
.oopy-editor.oopy-nur-lesen .oopy-eingabe { caret-color: transparent; cursor: default; }
.oopy-editor.oopy-nur-lesen .oopy-zeilennummern { background: #eef0f2; }

/* ============================================================
   Stufe 4a — Werkzeugseite mit Umschaltleiste
   ============================================================ */

.oopy-seite-leiste {
  display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem; align-items: flex-start;
  padding: 0.75rem 0.9rem; margin-bottom: 0.5rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 6px;
  background: var(--oopy-flaeche); font-size: 0.85rem;
}
.oopy-seite-feld { display: flex; align-items: center; gap: 0.5rem; }
.oopy-seite-feld > label { display: flex; align-items: center; gap: 0.4rem; font-weight: 600; }
.oopy-seite-abweichung {
  padding: 0.05rem 0.4rem; border-radius: 999px; font-size: 0.7rem;
  background: #f4e6d2; color: #8a5a00;
}
.oopy-seite-gruppe {
  display: flex; flex-wrap: wrap; gap: 0.15rem 0.9rem; align-items: center;
  margin: 0; padding: 0.3rem 0.7rem 0.5rem;
  border: 1px solid var(--oopy-rahmen); border-radius: 5px; background: var(--oopy-grund);
}
.oopy-seite-gruppe > legend {
  padding: 0 0.35rem; font-size: 0.7rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--oopy-gedaempft);
}
.oopy-seite-schalter { display: inline-flex; align-items: center; gap: 0.3rem;
                 white-space: nowrap; }
.oopy-seite-aufgabe { flex: 1; min-width: 20rem; }
.oopy-seite-code { width: 12rem; padding: 0.2rem 0.4rem; font: inherit; font-size: 0.8rem;
             border: 1px solid var(--oopy-rahmen); border-radius: 4px; }
.oopy-seite-aufgabe button {
  padding: 0.2rem 0.7rem; cursor: pointer; font: inherit; font-size: 0.8rem;
  border: 1px solid var(--oopy-akzent); border-radius: 4px;
  background: var(--oopy-akzent); color: #fff;
}
.oopy-seite-aufgabe button:disabled { opacity: 0.5; cursor: default; }
.oopy-seite-aufgabenname { font-weight: 700; color: var(--oopy-akzent-dunkel); }
.oopy-seite-dateiwahl { font-size: 0.78rem; max-width: 14rem; }
.oopy-seite-meldung {
  margin: 0 0 0.5rem; padding: 0.5rem 0.8rem; border-radius: 5px; font-size: 0.88rem;
}
.oopy-seite-hinweis { background: #e3eef5; color: var(--oopy-akzent-dunkel); }
.oopy-seite-fehler { background: var(--oopy-fehlergrund); color: var(--oopy-fehler); }

@media (max-width: 768px) {
  .oopy-seite-gruppe { flex-direction: column; align-items: flex-start; }
  .oopy-seite-aufgabe { min-width: 0; }
}

/* ============================================================
   Hauptprogramm (US-65)
   ============================================================ */

.oopy-hp-behalten {
  flex: none; display: inline-flex; align-items: center; gap: 0.3rem;
  font-weight: 400; text-transform: none; letter-spacing: 0; font-size: 0.78rem;
  color: var(--oopy-text); cursor: pointer;
}
.oopy-hp-behalten input { margin: 0; }
.oopy-hp-hinweis {
  margin: 0; padding: 0.45rem 0.9rem; font-size: 0.82rem; color: #8a5a00;
  background: #fffdf3; border-bottom: 1px solid var(--oopy-rahmen);
}
.oopy-protokoll-liste .oopy-protokoll-block {
  white-space: pre-wrap; font-family: ui-monospace, monospace;
  border-left: 3px solid var(--oopy-akzent); padding-left: 0.5rem; margin: 0.2rem 0;
}

/* ============================================================
   Bereichsmarken (Sinnbild + Wort, src/marken.js)
   ============================================================

   Die einzigen Regeln dieses Blatts, die keine Werkzeugwurzel über sich haben
   — und das müssen sie sein: Eine Marke im Aufgabentext der Buchseite steht
   außerhalb jedes `.oopy`.

   Deshalb steht hier auch nichts über `revert` wie im Rückstellungsblock oben,
   sondern jede Eigenschaft ausdrücklich. Was inf-schule einem `span` oder
   einem `svg` im Kapiteltext mitgibt, wissen wir nicht; eine Klasse (0,1,0)
   schlägt aber jede Regel über Elementnamen wie `article svg` (0,0,2). Wer
   hier etwas ergänzt, setzt es also selbst, statt sich auf einen Erbwert zu
   verlassen. */

.oopy-marke {
  white-space: nowrap;
  color: inherit; font: inherit;
  margin: 0; padding: 0; border: none; background: none;
}
/* Nur das Paar aus Sinnbild und Wort soll zusammenbleiben — innerhalb eines
   mehrwortigen Markentextes darf weiter umbrochen werden. */
.oopy-marke-wort { white-space: normal; }

.oopy-marke-sinnbild {
  width: var(--oopy-marke-groesse, 1em);
  height: var(--oopy-marke-groesse, 1em);
  /* `inline-block` und `vertical-align` statt Flexbox: Im Fließtext behält der
     Satz so seine Grundlinie, und das Sinnbild wird an ihr ausgerichtet. Eine
     inline-flex-Marke hätte keine eigene Grundlinie und würde die Zeile der
     Buchseite verschieben. */
  display: inline-block; vertical-align: -0.14em;
  margin: 0 0.3em 0 0; padding: 0; border: none; box-shadow: none;
  max-width: none; min-width: 0;
  /* Farbe und Größe kommen von der Umgebung — dieselbe Marke trägt sich
     dadurch im hellen Bereichskopf, im Fließtext und auf dunklem Grund. */
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.oopy-marke-voll { fill: currentColor; stroke: none; }

/* In den Bereichsköpfen ist die Marke ein Flex-Element: Dort richtet der Kopf
   selbst aus (`align-items: center`), die Grundlinienrechnung entfällt. Das
   Sinnbild wird etwas größer als die Schrift, weil die Köpfe mit 0.75rem
   gesetzt sind — bei 12 px verliert eine gezeichnete Form ihre Lesbarkeit. */
.oopy-bereich > h4 > .oopy-marke,
.oopy-konsole-kopf > .oopy-marke,
.oopy-pad-kopf > .oopy-marke,
.oopy-protokoll-kopf > .oopy-marke {
  --oopy-marke-groesse: 1.35em;
  display: flex; align-items: center; flex: none;
}
.oopy-bereich > h4 > .oopy-marke > .oopy-marke-sinnbild,
.oopy-konsole-kopf > .oopy-marke > .oopy-marke-sinnbild,
.oopy-pad-kopf > .oopy-marke > .oopy-marke-sinnbild,
.oopy-protokoll-kopf > .oopy-marke > .oopy-marke-sinnbild {
  vertical-align: 0;
}

/* Die Erklärung neben der Marke „Code-Spiegel". Sie darf umbrechen statt zu
   drängeln: In Buchseitenbreite steht sonst der Kopierknopf am Rand. */
.oopy-protokoll-kopf { flex-wrap: wrap; }
.oopy-protokoll-erklaerung {
  flex: 1 1 10rem; text-transform: none; letter-spacing: 0; font-size: 0.7rem;
}
