Q-Handbuch – Standard-Transformation (v1.3 Grid-Layout)
/* --- merged from original style block --- */
/* Base */
:root {
--gap-main: 10px;
--gap-sub: 8px;
--card-border: #ddd;
--accent: #003366;
--blue: #0000ff;
--green: #00cc33;
--pink: #ff0066;
--link: #0066cc;
--pdf-bg: #cc0000;
--highlight-bg: #fffd7a;
--highlight-border: #e6d600;
}
* { box-sizing: border-box; }
body { color:#000; font-size:10pt; font-family:"SansSerif", Arial, Helvetica, sans-serif; margin:0; }
p { margin:0; }
li { list-style:none; margin:0; }
a { text-decoration:none; }
/* Headings */
h1 {
background: var(--accent);
color:#ffffff;
padding:8px 12px;
margin:0 0 10px 0;
}
h2 { color: var(--blue); font-size:12pt; margin:0 0 6px 0; }
h3 { color: var(--green); font-size:11pt; margin:6px 0 4px 0; }
.dept-title { color: var(--pink); font-size:12pt; margin-bottom:4px; }
/* Controls row */
.controls {
margin:6px 12px 10px 12px;
font-size:10pt;
display:flex;
flex-wrap:wrap;
gap:6px;
align-items:center;
}
.controls .btn {
display:inline-block;
padding:2px 6px;
border:1px solid #bbb;
background:#f4f4f4;
cursor:pointer;
user-select:none;
}
.controls input[type="text"]{
padding:3px 6px;
border:1px solid #bbb;
min-width:240px;
font-size:10pt;
}
/* Link labels */
.pdf-link, .web-link { color: var(--link); }
.pdf-link:hover, .web-link:hover { text-decoration:underline; }
.pdf-label, .web-label {
color:#fff;
font-size:8pt;
font-weight:bold;
padding:1px 4px;
border-radius:3px;
margin-left:4px;
white-space:nowrap;
}
.pdf-label { background: var(--pdf-bg); }
.web-label { background: var(--link); }
/* Highlight */
.highlight {
background: var(--highlight-bg);
outline: 1px solid var(--highlight-border);
}
/* Two-level Grid Layout */
.page {
padding: 0 12px 12px 12px;
}
.main-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: var(--gap-main);
align-items: start;
}
.category {
border:1px solid var(--card-border);
padding:8px;
background:#fff;
border-radius:4px;
min-width:0;
}
.category > ul { padding-left: 0; }
.category h2 { margin-top: 0; }
/* Nested grid for departments within Category 4 */
.sub-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: var(--gap-sub);
align-items: start;
}
.dept-card {
border:1px solid var(--card-border);
padding:8px;
background:#fff;
border-radius:4px;
min-width:0;
}
.dept-card ul { padding-left: 0; }
/* Folding toggle */
.fold-toggle {
font-size:10px;
font-family:monospace;
border:1px solid #ccc;
background:#e0e0e0;
padding:0 4px;
margin-right:6px;
cursor:pointer;
user-select:none;
}
.folded { display:none; }
/* Spacing helpers */
.mb-6 { margin-bottom:6px; }
/* --- merged from original style block --- */
/* ==== Tile Grid: fixed 4×3 on wide screens, responsive below ==== */
.main-grid { display: grid; gap: var(--gap-main, 12px); grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1280px){ .main-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 960px){ .main-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px){ .main-grid { grid-template-columns: 1fr; } }
/* Tiles */
.category { display:flex; flex-direction:column; overflow:hidden; }
.category > h2 { cursor:pointer; position:relative; padding-right:2rem; }
.category > h2::after { content:"▾"; position:absolute; right:.5rem; top:50%; transform:translateY(-50%) rotate(-90deg); transition:transform .2s ease; opacity:.7; }
.category.open > h2::after { transform:translateY(-50%) rotate(0deg); }
.category:not(.open) > :not(h2) { display:none !important; }
.category.open { box-shadow: 0 2px 8px rgba(0,0,0,.08); border-color: rgba(0,0,0,.1); }
/* Search highlight + current */
.tfy-hi { background: #ffef99; outline: 1px solid #d9c34f; }
.tfy-current { outline: 2px solid #ff8c00; box-shadow: 0 0 0 2px #ff8c00 inset; }
.controls .tfy-nav-btn { margin-left:.35rem; }
/* --- merged from original style block --- */
/* Abteilungen als Kachel-Subgrid (4/3/2/1 Spalten) */
.category.dept-tiles .sub-grid {
display: grid;
gap: var(--gap-sub, 10px);
grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 1280px){ .category.dept-tiles .sub-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 960px){ .category.dept-tiles .sub-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px){ .category.dept-tiles .sub-grid { grid-template-columns: 1fr; } }
/* Dept cards: collapsible tiles */
.category.dept-tiles .dept-card {
background: #fff;
border: 1px solid rgba(0,0,0,.12);
border-radius: 6px;
padding: 8px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.category.dept-tiles .dept-header {
cursor: pointer;
position: relative;
padding-right: 2rem;
margin: 0 0 .25rem 0;
font-weight: 600;
}
.category.dept-tiles .dept-header::after {
content: "▾";
position: absolute;
right: .5rem;
top: 50%;
transform: translateY(-50%) rotate(-90deg);
transition: transform .2s ease;
opacity: .7;
}
.category.dept-tiles .dept-card.open .dept-header::after { transform: translateY(-50%) rotate(0deg); }
.category.dept-tiles .dept-card:not(.open) > .dept-body { display: none !important; }
.category.dept-tiles .dept-card.open { box-shadow: 0 2px 8px rgba(0,0,0,.06); border-color: rgba(0,0,0,.16); }
/* --- merged from original style block --- */
/* Typografie global etwas größer */
html { font-size: 17px; }
body { line-height: 1.6; }
/* Haupt-Kacheln: gleiche Höhe im geschlossenen Zustand */
.category > h2, .tfy-cat > .tfy-header {
min-height: 72px;
display: flex;
align-items: center;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Geöffnete Hauptkategorie → Grid auf 1 Spalte (volle Breite) */
.main-grid.one-col { grid-template-columns: 1fr !important; }
.tfy-grid.one-col { grid-template-columns: 1fr !important; }
/* Abteilungen-Subgrid: 3/2/1 Spalten (statt 4) */
.category.dept-tiles .sub-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 960px){
.category.dept-tiles .sub-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px){
.category.dept-tiles .sub-grid { grid-template-columns: 1fr; }
}
/* Detailmodus A: geöffnete Abteilung über alle Spalten spannen */
.category.dept-tiles .sub-grid .dept-card.open { grid-column: 1 / -1; }
/* --- merged from original style block --- */
/* Abteilungen: strikt 2 Spalten (Desktop), 1 Spalte mobil */
.category.dept-tiles .sub-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
@media (max-width: 640px){
.category.dept-tiles .sub-grid { grid-template-columns: 1fr !important; }
}
/* Optional: Header nur anzeigen, Body standardmäßig zu */
.category.dept-tiles .dept-card:not(.open) > .dept-body { display: none !important; }
/* --- merged from original style block --- */
/* Abteilungen: 2×2 Matrix bleibt bestehen (falls schon gesetzt) */
/* Sichtbarkeit steuern über .dept-body */
.category.dept-tiles .dept-card:not(.open) > .dept-body { display: none !important; }
/* Titel klickbar + Pfeil */
.category.dept-tiles .dept-card > .dept-title,
.category.dept-tiles .dept-card > .dept-header {
cursor: pointer;
position: relative;
padding-right: 2rem;
font-weight: 600;
}
.category.dept-tiles .dept-card > .dept-title::after,
.category.dept-tiles .dept-card > .dept-header::after {
content:"▾";
position:absolute;
right:.5rem;
top:50%;
transform:translateY(-50%) rotate(-90deg);
opacity:.7;
transition: transform .2s ease;
}
.category.dept-tiles .dept-card.open > .dept-title::after,
.category.dept-tiles .dept-card.open > .dept-header::after {
transform:translateY(-50%) rotate(0deg);
}
/* --- merged from original style block --- */
/* Hauptkacheln dunkelblau mit weißer Schrift */
.main-grid .category,
.tfy-grid .tfy-cat {
background-color: #003366; /* gleiche Farbe wie Q-Handbuch-Header */
color: #fff;
border: none;
border-radius: 10px;
box-shadow: none;
transition: box-shadow 0.2s ease, transform 0.2s ease;
}
/* Schrift im Titel */
.main-grid .category h2,
.tfy-grid .tfy-cat .tfy-header {
color: #fff !important;
}
/* Pfeil-Icons weiß */
.main-grid .category h2::after,
.tfy-grid .tfy-cat .tfy-header::after {
color: #fff !important;
opacity: 0.9;
}
/* Hover-Effekt mit Schatten */
.main-grid .category:hover,
.tfy-grid .tfy-cat:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
transform: translateY(-2px);
}
/* Schriftfarbe in untergeordneten Elementen beibehalten */
.main-grid .category *,
.tfy-grid .tfy-cat * {
color: inherit;
}
/* --- merged from original style block --- */
/* Lesbarkeit in Unterkategorien/Abteilungen verbessern */
.category.dept-tiles,
.category.dept-tiles *,
.sub-grid .dept-card,
.sub-grid .dept-card * {
color: #222 !important; /* leicht abgetöntes Schwarz */
}
/* Überschriften innerhalb der Abteilungen (z. B. 01_Rundschreiben) */
.category.dept-tiles .dept-card h1,
.category.dept-tiles .dept-card h2,
.category.dept-tiles .dept-card h3,
.category.dept-tiles .dept-card h4,
.category.dept-tiles .dept-card h5,
.category.dept-tiles .dept-card h6,
.category.dept-tiles .dept-card strong,
.category.dept-tiles .dept-card .dept-title,
.category.dept-tiles .dept-card .dept-header {
color: #003366 !important; /* dunkles Q-Handbuch-Blau */
font-weight: 600;
}
/* --- merged from original style block --- */
/* Einheitliche +/- Toggle-Gestaltung & Ausrichtung */
/* 1) Grundstil der kleinen Kästchen */
li > .toggle,
li > .fold-toggle,
li > .tree-toggle,
li > .li-toggle,
li > button[aria-controls],
li > button[data-toggle],
li > .btn-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
line-height: 20px;
font-size: 12px;
font-weight: 700;
border-radius: 3px;
background: #eee; /* heller Hintergrund */
border: 1px solid #d0d5dd;
color: #000; /* schwarz für + und - */
margin-right: .5rem; /* Abstand vor dem Text */
vertical-align: middle; /* baseline angleichen */
text-align: center;
cursor: pointer;
}
/* 2) Einheitliche Darstellung im geöffneten Zustand (auch schwarz) */
li:not(.folded) > .toggle,
li:not(.folded) > .fold-toggle,
li:not(.folded) > .tree-toggle,
li:not(.folded) > .li-toggle,
li:not(.folded) > button[aria-controls],
li:not(.folded) > button[data-toggle],
li[aria-expanded="true"] > .toggle,
li[aria-expanded="true"] > .fold-toggle,
li[aria-expanded="true"] > .tree-toggle,
li[aria-expanded="true"] > .li-toggle,
li > button[aria-expanded="true"] {
color: #000; /* bleibt schwarz */
}
/* 3) Falls Symbol in
steckt */
li > .toggle > span,
li > .fold-toggle > span,
li > .tree-toggle > span,
li > .li-toggle > span {
line-height: 1;
}
/* 4) Zeilenlayout stabil halten */
li {
line-height: 1.5;
}
/* --- merged from original style block --- */
/* Plus/Minus neben dem Text – generisch und robust */
/* 1) LI mit direktem Toggle: zweispaltiges Grid */
li:has(> .toggle),
li:has(> .fold-toggle),
li:has(> .tree-toggle),
li:has(> .li-toggle),
li:has(> button[aria-controls]),
li:has(> button[data-toggle]),
li:has(> .btn-toggle) {
display: grid;
grid-template-columns: 22px 1fr;
align-items: center;
column-gap: .5rem;
}
/* 2) Toggle sitzt immer in Spalte 1 */
li > .toggle,
li > .fold-toggle,
li > .tree-toggle,
li > .li-toggle,
li > button[aria-controls],
li > button[data-toggle],
li > .btn-toggle {
grid-column: 1 !important;
}
/* 3) ALLE anderen direkten Kinder (außer UL und Toggle) kommen in Spalte 2 */
li:has(> .toggle) > :not(ul):not(.toggle),
li:has(> .fold-toggle) > :not(ul):not(.fold-toggle),
li:has(> .tree-toggle) > :not(ul):not(.tree-toggle),
li:has(> .li-toggle) > :not(ul):not(.li-toggle),
li:has(> button[aria-controls]) > :not(ul):not(button[aria-controls]),
li:has(> button[data-toggle]) > :not(ul):not(button[data-toggle]),
li:has(> .btn-toggle) > :not(ul):not(.btn-toggle) {
grid-column: 2;
}
/* 4) Unterlisten spannen unter dem Titel über beide Spalten */
li > ul {
grid-column: 1 / -1;
margin-top: .25rem;
}
/* --- merged from original style block --- */
:root{
--toggle-w: 22px;
--toggle-gap: 0.5rem;
--indent-step: calc(var(--toggle-w) + var(--toggle-gap));
--guide-light: rgba(0,0,0,0.08); /* dezente Linie auf weiß */
}
/* Basis: Listen in Karten */
.category.dept-tiles .dept-card ul { list-style: none; margin: .25rem 0 0 0; padding-left: 0; }
/* EINZUG: jede tiefere UL rückt um --indent-step ein (kumulativ) */
.category.dept-tiles .dept-card ul ul {
margin-left: var(--indent-step);
padding-left: .5rem; /* kleiner Innenabstand zum Guide */
border-left: 1px solid var(--guide-light); /* vertikale Führungslinie */
}
/* Inline-Layout bleibt: Unterlisten spannen unter dem Titel über beide Spalten */
li > ul { grid-column: 1 / -1; margin-top: .25rem; }
/* --- merged from original style block --- */
:root{
--toggle-w: 22px;
--toggle-gap: 0.5rem;
--indent-step: calc(var(--toggle-w) + var(--toggle-gap));
--guide-on-white: rgba(0,0,0,0.08);
}
/* Nur innerhalb der Abteilungen-Karten hart überschreiben */
.category.dept-tiles .dept-card ul { list-style:none; margin:.25rem 0 0 0; padding-left:0; }
.category.dept-tiles .dept-card li { margin:.15rem 0; }
/* Inline-Layout für li (Toggle | Text) bleibt wie zuvor,
aber wir erzwingen es hier nochmals innerhalb der dept-tiles,
falls andere Regeln überlagern. */
.category.dept-tiles .dept-card li:has(> .toggle),
.category.dept-tiles .dept-card li:has(> .fold-toggle),
.category.dept-tiles .dept-card li:has(> .tree-toggle),
.category.dept-tiles .dept-card li:has(> .li-toggle),
.category.dept-tiles .dept-card li:has(> button[aria-controls]),
.category.dept-tiles .dept-card li:has(> button[data-toggle]),
.category.dept-tiles .dept-card li:has(> .btn-toggle) {
display: grid;
grid-template-columns: 22px 1fr;
align-items: center;
column-gap: .5rem;
}
/* UL-Nachfolger (Unterebene) rückt ein und hat eine dezente Führungslinie */
.category.dept-tiles .dept-card li > ul {
grid-column: 1 / -1;
margin-top: .25rem;
padding-left: var(--indent-step);
border-left: 1px solid var(--guide-on-white);
}
/* Sicherstellen, dass das Toggle ganz links bleibt */
.category.dept-tiles .dept-card li > .toggle,
.category.dept-tiles .dept-card li > .fold-toggle,
.category.dept-tiles .dept-card li > .tree-toggle,
.category.dept-tiles .dept-card li > .li-toggle,
.category.dept-tiles .dept-card li > button[aria-controls],
.category.dept-tiles .dept-card li > button[data-toggle],
.category.dept-tiles .dept-card li > .btn-toggle {
grid-column: 1 !important;
}
/* Titel/Text unmittelbar neben das Toggle (Spalte 2) – generisch */
.category.dept-tiles .dept-card li:has(> .toggle) > :not(ul):not(.toggle),
.category.dept-tiles .dept-card li:has(> .fold-toggle) > :not(ul):not(.fold-toggle),
.category.dept-tiles .dept-card li:has(> .tree-toggle) > :not(ul):not(.tree-toggle),
.category.dept-tiles .dept-card li:has(> .li-toggle) > :not(ul):not(.li-toggle),
.category.dept-tiles .dept-card li:has(> button[aria-controls]) > :not(ul):not(button[aria-controls]),
.category.dept-tiles .dept-card li:has(> button[data-toggle]) > :not(ul):not(button[data-toggle]),
.category.dept-tiles .dept-card li:has(> .btn-toggle) > :not(ul):not(.btn-toggle) {
grid-column: 2;
}
/* --- merged from original style block --- */
:root{
--toggle-w: 22px;
--toggle-gap: 0.5rem;
--indent-step: calc(var(--toggle-w) + var(--toggle-gap));
--guide-on-white: rgba(0,0,0,0.08);
}
/* Grundlayout innerhalb der Abteilungen */
.category.dept-tiles .dept-card ul { list-style: none; padding-left: 0; margin: .25rem 0 0 0; }
.category.dept-tiles .dept-card li { margin: .15rem 0; }
/* Li mit Toggle → zweispaltiges Grid (Toggle | Titel) */
.category.dept-tiles .dept-card li:has(> .toggle),
.category.dept-tiles .dept-card li:has(> .fold-toggle),
.category.dept-tiles .dept-card li:has(> .tree-toggle),
.category.dept-tiles .dept-card li:has(> .li-toggle),
.category.dept-tiles .dept-card li:has(> button[aria-controls]),
.category.dept-tiles .dept-card li:has(> button[data-toggle]),
.category.dept-tiles .dept-card li:has(> .btn-toggle) {
display: grid;
grid-template-columns: 22px 1fr;
align-items: center;
column-gap: .5rem;
}
/* Toggle links fixieren */
.category.dept-tiles .dept-card li > .toggle,
.category.dept-tiles .dept-card li > .fold-toggle,
.category.dept-tiles .dept-card li > .tree-toggle,
.category.dept-tiles .dept-card li > .li-toggle,
.category.dept-tiles .dept-card li > button[aria-controls],
.category.dept-tiles .dept-card li > button[data-toggle],
.category.dept-tiles .dept-card li > .btn-toggle { grid-column: 1 !important; }
/* Titel/Text neben das Toggle (alles außer UL/Toggle in Spalte 2) */
.category.dept-tiles .dept-card li:has(> .toggle) > :not(ul):not(.toggle),
.category.dept-tiles .dept-card li:has(> .fold-toggle) > :not(ul):not(.fold-toggle),
.category.dept-tiles .dept-card li:has(> .tree-toggle) > :not(ul):not(.tree-toggle),
.category.dept-tiles .dept-card li:has(> .li-toggle) > :not(ul):not(.li-toggle),
.category.dept-tiles .dept-card li:has(> button[aria-controls]) > :not(ul):not(button[aria-controls]),
.category.dept-tiles .dept-card li:has(> button[data-toggle]) > :not(ul):not(button[data-toggle]),
.category.dept-tiles .dept-card li:has(> .btn-toggle) > :not(ul):not(.btn-toggle) { grid-column: 2; }
/* EINZUG für Unterlisten – auch mit Wrappern (div/p/span …) */
.category.dept-tiles .dept-card li:has(> ul) > ul,
.category.dept-tiles .dept-card li:has(> * > ul) > * > ul,
.category.dept-tiles .dept-card li:has(> * > * > ul) > * > * > ul {
grid-column: 1 / -1;
margin-top: .25rem;
padding-left: var(--indent-step);
border-left: 1px solid var(--guide-on-white);
}
/* --- merged from original style block --- */
:root{
--toggle-w: 22px;
--toggle-gap: 0.5rem;
--indent-step: calc(var(--toggle-w) + var(--toggle-gap));
--guide-on-white: rgba(0,0,0,0.10);
}
/* Kumulative Einzüge je Ebene und vertikale Führungslinien je Ebene */
.category.dept-tiles .dept-card ul { list-style:none; padding-left:0; margin:.25rem 0 0 0; }
.category.dept-tiles .dept-card ul ul {
margin-left: var(--indent-step);
padding-left: .5rem;
position: relative;
}
.category.dept-tiles .dept-card ul ul::before {
content:"";
position:absolute;
left: 0;
top: .25rem;
bottom: .25rem;
border-left: 1px solid var(--guide-on-white);
}
/* tiefere Ebenen additiv */
.category.dept-tiles .dept-card ul ul ul {
margin-left: calc(var(--indent-step) * 2);
}
.category.dept-tiles .dept-card ul ul ul ul {
margin-left: calc(var(--indent-step) * 3);
}
.category.dept-tiles .dept-card ul ul ul ul ul {
margin-left: calc(var(--indent-step) * 4);
}
/* Falls Unterlisten in Wrappern stecken (div/p/span...), trotzdem Linien + Einzug */
.category.dept-tiles .dept-card li:has(> * > ul) > * > ul,
.category.dept-tiles .dept-card li:has(> * > * > ul) > * > * > ul {
padding-left: .5rem;
position: relative;
}
.category.dept-tiles .dept-card li:has(> * > ul) > * > ul::before,
.category.dept-tiles .dept-card li:has(> * > * > ul) > * > * > ul::before {
content:"";
position:absolute;
left: 0;
top: .25rem;
bottom: .25rem;
border-left: 1px solid var(--guide-on-white);
}
/* Fallbacks für Browser ohne :has() (z. B. ältere Firefox-Versionen) */
@supports not selector(:has(*)) {
/* Annahme: LI-Elemente mit Toggle erhalten Klasse .li-has-toggle per JS */
.li-has-toggle { padding-left: 0.5rem; position: relative; }
.li-has-toggle > .toggle { margin-right: .25rem; }
/* Einrückungen für mehrstufige Listen */
ul ul { margin-left: 1rem; }
/* Grid-/Zeilenlayout minimal nachbilden */
.li-has-toggle { display: block; }
}
/* Konsolidierte Design-Variablen (dezente Anpassung) */
:root {
--tile-shadow: 0 2px 6px rgba(0,0,0,0.08);
--tile-border: rgba(0,0,0,0.12);
--muted-text: #222;
--heading: #003366;
}
@media (prefers-color-scheme: dark) {
:root {
--muted-text: #e6e6e6;
--heading: #a7c8ff;
}
}
/* Beispielhafte Anwendung – ohne vorhandene Regeln zu überschreiben */
.dept .subtext, .subtext { color: var(--muted-text); }
.dept h2, h2.dept-title { color: var(--heading); }
.card, .tile, .dept { box-shadow: var(--tile-shadow); border-color: var(--tile-border); }
#toc { margin: 1rem 0; border: 1px solid var(--tile-border); padding: .5rem .75rem; border-radius: .5rem; }
#toc summary { cursor: pointer; }
#toc a { text-decoration: none; }
#toc a:focus, #toc a:hover { text-decoration: underline; }
/* === FILE ICON SYSTEM - INLINE SVG =================================== */
li.file-item {
list-style: none;
margin-left: 0;
padding-left: 0;
}
li.file-item > .file-link {
display: inline-flex;
align-items: center;
gap: 0.4rem;
}
.file-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.2em;
height: 1.5em;
}
.file-icon svg {
width: 100%;
height: 100%;
display: block;
}
/* Disable all old emoji/link icons */
a[href]::before,
a[href]::after {
content: none !important;
margin-right: 0 !important;
}
/* === CATEGORY CARD LAYOUT (Variant C) ================================ */
.main-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: var(--gap-main);
align-items: start;
}
.category {
border-radius: 12px;
border: 1px solid rgba(0, 0, 0, 0.08);
background: #ffffff !important;
padding: 0;
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
min-width: 0;
color: #000000;
}
.category > h2 {
margin: 0;
padding: 12px 18px;
background: #003b73;
color: #ffffff !important;
font-size: 1.05rem;
font-weight: 600;
border-radius: 12px 12px 0 0;
}
.category > ul,
.category > .sub-grid {
padding: 10px 18px 14px 26px;
background: #ffffff;
color: #000000;
border-radius: 0 0 12px 12px;
}
.category > ul:last-child,
.category > .sub-grid:last-child {
margin-bottom: 6px;
}
/* department cards remain white but inherit shadow border style softly */
.dept-card {
border-radius: 10px;
border: 1px solid rgba(0, 0, 0, 0.08);
background: #ffffff;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.06);
}
.dept-card .dept-title {
font-weight: 600;
}
/* V19: neutral text colors and card backgrounds (Variant C) */
/* neutralize old dark-blue category background */
.main-grid .category,
.tfy-grid .tfy-cat {
background-color: #ffffff !important;
color: #000000 !important;
}
/* default text in categories: black */
.category * {
color: #000000 !important;
}
/* keep category headers white on blue */
.category > h2 {
color: #ffffff !important;
}
/* subheadings (converted from MindMap green) in dark grey */
.category h3 {
color: #333333 !important;
}
/* links inherit surrounding color, subtle hover underline */
.category a {
color: inherit !important;
text-decoration: none;
}
.category a:hover {
text-decoration: underline;
}
/* ensure only our SVG icons are used, disable old emoji link icons */
a[href]::before,
a[href]::after {
content: none !important;
margin: 0 !important;
}
/* === Layout: main content + search sidebar ============================ */
.layout-grid {
display: grid;
grid-template-columns: minmax(0, 3.5fr) minmax(260px, 1.6fr);
gap: var(--gap-main);
align-items: flex-start;
}
.search-sidebar {
background: #f7f7f9;
border-radius: 4px;
padding: 0.75rem 0.9rem;
font-size: 0.9rem;
border: 1px solid var(--card-border);
position: sticky;
top: var(--sidebar-offset, 0.75rem);
align-self: flex-start;
max-height: calc(100vh - 1.5rem);
overflow: auto;
}
.search-sidebar-title {
margin: 0 0 0.5rem;
font-size: 0.9rem;
font-weight: 600;
}
.search-summary {
font-size: 0.83rem;
color: #555555;
margin-bottom: 0.5rem;
}
.search-results {
list-style: none;
padding: 0;
margin: 0;
}
.search-result-item {
padding: 0.35rem 0.3rem;
border-radius: 4px;
cursor: pointer;
}
.search-result-item + .search-result-item {
margin-top: 0.2rem;
}
.search-result-item:hover {
background: #e4f0ff;
}
.search-result-item.is-current {
background: #d0e2ff;
}
.search-result-path {
font-weight: 500;
font-size: 0.84rem;
margin-bottom: 0.1rem;
}
.search-result-snippet {
font-size: 0.78rem;
color: #555555;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 900px) {
.layout-grid {
grid-template-columns: 1fr;
}
.search-sidebar {
position: static;
max-height: none;
}
}
/* ===================================================================== */
/* Typography: use Corbel as primary font */
body {
font-family: "Corbel", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.page-header .header-main {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 1rem;
}
.page-header .qhb-logo {
max-height: 70px;
height: auto;
width: auto;
}
@media (max-width: 600px) {
.page-header .header-main {
flex-direction: column;
align-items: flex-start;
}
.page-header .qhb-logo {
max-height: 60px;
}
}
/* Header layout with QHB logo */
.header-main {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 1rem;
margin-bottom: 0.75rem;
}
.qhb-logo {
max-height: 70px;
height: auto;
width: auto;
}
@media (max-width: 600px) {
.header-main {
flex-direction: column;
align-items: flex-start;
}
.qhb-logo {
max-height: 60px;
}
}
/* Dark blue background for header incl. logo */
.qhb-header-dark {
background: #003366;
padding: 1rem 1.5rem;
border-radius: 6px;
margin-bottom: 1.5rem;
}
.qhb-header-dark .header-main h1 {
color: white;
}
.qhb-header-dark .qhb-logo {
filter: drop-shadow(0 0 2px rgba(0,0,0,0.2));
}
/* === Kategorie-Titel lesbarer (Nummer, Titel, Untertitel) === */
.category > h2 {
align-items: flex-start;
flex-direction: column;
white-space: normal;
}
.category > h2 .cat-title-line1 {
display: flex;
align-items: baseline;
gap: 0.35rem;
}
.category > h2 .cat-num {
font-weight: 600;
}
.category > h2 .cat-title-main {
font-weight: 600;
}
.category > h2 .cat-title-sub {
font-size: 0.8rem;
opacity: 0.9;
margin-top: 0.05rem;
}
/* === Globale Navigation / Schnellzugriff === */
.global-nav {
margin: 0 12px 0.75rem 12px;
padding: 0.35rem 0.75rem;
background: #f5f7fa;
border-radius: 6px;
border: 1px solid #dde1eb;
font-size: 0.88rem;
}
.global-nav-list {
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 0.35rem 0.6rem;
padding: 0;
margin: 0;
}
.global-nav a {
display: inline-block;
padding: 0.15rem 0.55rem;
border-radius: 999px;
border: 1px solid transparent;
text-decoration: none;
color: #003366;
background: transparent;
}
.global-nav a:hover {
background: #e4f0ff;
border-color: #c0d4f5;
}
@media (max-width: 640px) {
.global-nav {
margin: 0 8px 0.75rem 8px;
}
}
/* === Abstände & Typografie im Inhalt === */
.category ul {
margin-top: 0.25rem;
}
.category li {
margin-bottom: 0.08rem;
}
.category h3 {
font-size: 0.95rem;
margin-top: 0.5rem;
margin-bottom: 0.1rem;
}
.category.dept-tiles .dept-card h3 {
margin-top: 0.4rem;
}
/* Ensure category headers stay white on blue */
.category > h2,
.category > h2 * {
color: #ffffff !important;
}
/* Extra safety: ensure Abteilungen tile header is also white */
#cat-4 > h2,
#cat-4 > h2 * {
color: #ffffff !important;
}
/* Override: controls row scrollt normal mit (kein sticky) */
/* Anpassung: Suchleiste und Schnellnavigation sticky unter dem Header */
.controls {
position: sticky;
top: var(--nav-offset, 3rem);
z-index: 35;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
padding-top: 0.4rem;
padding-bottom: 0.4rem;
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
background: #f5f7fa;
}
/* Schnellnavigation klebt direkt unter der Suchleiste */
.global-nav {
position: sticky;
top: 0;
z-index: 40;
}
/* Visuelle Hervorhebung für Vorlagen-Dokumente */
li.file-template {
background: #fff8e1;
border-left: 3px solid #f9a825;
padding-left: 0.35rem;
border-radius: 4px;
}
li.file-template + li.file-template {
margin-top: 0.05rem;
}
/* Strukturüberschriften in Kategorien (Lesbarkeit der Listen) */
.category:not(.dept-tiles) li.li-heading {
font-weight: 600;
margin-top: 0.45rem;
}
.category:not(.dept-tiles) li.li-heading-depth-1 {
font-weight: 700;
}
.category:not(.dept-tiles) li.li-heading-depth-2 {
font-weight: 600;
}
.category:not(.dept-tiles) li.li-heading > ul {
margin-top: 0.12rem;
}
/* Patch v4: align list items without JS-inserted .fold-toggle */
.category.dept-tiles .dept-card ul > li:not(:has(> .fold-toggle)) {
padding-left: 1.5rem;
}
.category{scroll-margin-top:80px;}
mark.tfy-hi { background: yellow; color: black; padding: 0 2px; }
mark.tfy-hi-current { outline: 2px solid orange; }
1.Überblick und Nutzung
- Nutzung des Q-Handbuchs
- Anleitung zur VIBE-Nutzung
2.Organisationsstruktur
- PDFOrganigramm
- Schulleitung
- stellvertrende Schulleitung
- Rollen & Verantwortlichkeiten
- Gremien und Teams
3.ProzesslandkarteZiel: schnelle Orientierung
- 01_Prozessübersicht
- Kernprozesse: Unterrichtsorganisation, Prüfungen, Schüleraufnahme
- Führungsprozesse: Qualitätsentwicklung (QMPG), Zielvereinbarungen
- Unterstützungsprozesse: Stundenplanung, IT-Support, Formularbereitstellung
- 02_Prozessklassifikation
- Kernprozess
- Schüleraufnahme BFS
- Verantwortlich: Abt. 1 Leitung
- Ablageort: Abteilung 1 → 02 Prozesse
- Zeugniserstellung
- Verantwortlich: Klassenleitung
- Ablageort: In allen Abteilungen
- Lernstandserhebung
- Verantwortlich: Fachlehrkräfte
- Ablageort: Nach BG/Fach sortiert
- Führungsprozess
- Evaluation SE-Projekt
- Verantwortlich: QMPG
- Ablageort: QM → Projekte → Evaluation
- Feedbackverfahren
- Verantwortlich: QMPG/SL
- Ablageort: QM → Feedbackformate
- Unterstützungsprozess
- Stundenplanerstellung
- Verantwortlich: SL/Koordinator
- Ablageort: Verwaltung
- Gerätebereitstellung (IT)
- Verantwortlich: IT-Beauftragter
- Ablageort: Verwaltung / Support
4.Abteilungen
Abteilung 1 – BFS, AVdual, VAB
01_Rundschreiben
- Abteilungsinterne Infos
- Konferenzprotokolle
- Hinweise zu laufenden Vorgängen
02_Prozesse_wiederkehrend
- Schuljahresstart
- Schüleraufnahme, Bücherausgabe, Arbeitsvertrageverträge einsammeln
- Zeugnisprozesse
- Notenerfassung, Notenweitergabe, Zeugnisdruck, Zeugnisausgabe –> siehe Klassenlehrkraft
- Lernstandserhebung
- Notenschlüssel
- Notenlisten (für verschiedene BGs)
- Prüfungen
- reguläre Ausbildungsdauer/ Frühauslerner
- Vorberitung der Prüfung (Teilnehmer melden, Anmeldenoten, …), Einschlagbögen, Prüfungsbögen, Notenlisten, Notenerfassung, Notenweitergabe, Zeugniserstellung
- Eltern-/Ausbilderabende
- Einladungen
- Präsentationen
- Protokolle
03_Ereignisse_einmalig
- Projektwochen, Fahrten, Messen
- Besondere Veranstaltungen
- Kooperationen mit externen Partnern
04_Aufgaben_und_Rollen
- Klassenleitung
- Berufsgruppenbetreuer
05_Infos_und_Fortbildungen
- Ablage & Dokumentation von Fortbildungen nach BGs oder Fächern sortiert
- Fachinformationen
- Links & Materialien
06_Vorlagen_und_Formulare
- Elternbriefe, Checklisten
- Bewertungsschemata (z.B. Projektkompetenz)
- Gesprächsprotokolle (Firmen, Eltern), Formulare zur Entschuldigung, Formulare zur Befreiung von D, GK etc.
Abteilung 2 – Berufsschule
- Abteilungsinterne Infos
- Konferenzprotokolle
- Hinweise zu laufenden Vorgängen
02_Prozesse_wiederkehrend
- Schuljahresstart
- aufnehmende LK (Dokument: Leitfaden – Schüleraufnahme, Gruppenteilung, Rundgang, Bücherausgabe, Arbeitsvertrageverträge einsammeln)
- Zeugnisprozesse
- Notenerfassung, Notenweitergabe, Zeugnisdruck, Zeugnisausgabe –> siehe Klassenlehrkraft
- Lernstandserhebung
- Notenschlüssel
- Notenlisten (für verschiedene BGs)
- Projektkompetenz (Leitfaden)
- Prüfungen
- reguläre Ausbildungsdauer/ Frühauslerner
- Vorberitung der Prüfung (Teilnehmer melden, Anmeldenoten, …), Einschlagbögen, Prüfungsbögen, Notenlisten, Notenerfassung, Notenweitergabe, Zeugniserstellung
- Prüfungsbögen (Musterdokumente je Fach)
- Eltern-/Ausbilderabende
- nur Abt.-Leitung Einladungen (Musterdokument)
- Präsentationen (Musterdokument)
- Protokolle (Musterdokument)
03_Ereignisse_einmalig
- Projektwochen, Fahrten, Messen
- Besondere Veranstaltungen
- Kooperationen mit externen Partnern
- Ablage & Dokumentation von Fortbildungen nach BGs oder Fächern sortiert
- Bildungspläne BS
- Links & Materialien (Links zur BG spezifischewn FoBi, Anmeldungen, FoBi Anmeldeformular GSGP)
- Antrag auf Ausflüge
- FoBi Angebot
06_Vorlagen und Formulare
Abteilung 3 – Fachschulen Bildungszentren
01_Rundschreiben
- Abteilungsinterne Infos
- Rückblicke auf Konferenzen
- Hinweise zu laufenden Vorgängen
- Schuljahresstart & Stundenplanung
- Zeugnisprozesse
- Lernstandserhebung & Prüfungen
- Eltern-/Ausbilderabende
- FMMK
03_Ereignisse_einmalig
- Projektwochen, Fahrten, Messen
- Besondere Veranstaltungen
- Kooperationen mit externen Partnern
04_Aufgaben_und_Rollen
- Aufgabenbeschreibungen (z. B. Klassenleitung, BORS)
- Vertretungsregelungen
- Verantwortungsmatrix
05_Infos_und_Fortbildungen
- Rückblick & Dokumentation von Fortbildungen
- Fachinformationen
- Links & Materialien
06_Vorlagen_und_Formulare
- Elternbriefe, Checklisten
- Praktikumsunterlagen, Bewertungsschemata
- Gesprächsprotokolle, Formulare zur Entschuldigung etc.
Abteilung 4 – Technisches Gymnasium
01_Rundschreiben
- Abteilungsinterne Infos
- Konferenzprotokolle
- Hinweise zu laufenden Vorgängen
02_Prozesse (wiederkehrend)
- Info Realschule
- Infoabend
- Elternabend (Links auf Vorträge, Musterdokumente, Musterpräsentationen jahrgangsspezifisch)
- POL (Beschreibungen – Ablauf, Orga. …, Bewertungsbögen)
- Abiturprüfung
- Erlasse
- Link auf Altprüfungen
- Ausfahrten
- Studienfahrten
- Coachingtage
- Lernevent
- Klassenregeln (Dokumentation)
- Notengebung
- Profil UT (Dokumentation pro Jahrgangsstufe)
- Profil TM (Dokumentation pro Jahrgangsstufe)
- Profil IT (Dokumentation pro Jahrgangsstufe)
- D (Dokumentation pro Jahrgangsstufe)
- Mathe (Dokumentation pro Jahrgangsstufe)
- Physik usw. (Dokumentation pro Jahrgangsstufe)
03_Ereignisse (einmalig)
04_Aufgaben und Rollen
- Klassenleitung
- Aufnahmetag
- erster Schultag
- Taschenrechner
- Tabletausgabe
06_Vorlagen und Formulare
- Vorlage Elternbriefe, Checklisten
- Praktikumsunterlagen, Bewertungsschemata
- Vorlage Gesprächsprotokolle
5.Qualitätsmanagement
- QMPG
- Pädagogische Tage (als Ablage?)
- Individualfeedback
- S-L
- Edkimo (Anleitungen, Vorlagen, Auswertugnen)
- Projekte
- Link auf aktuelle Projekte
- (F) Projektantrag (Vorlagedokument)
- (F) Protokoll (Vorlagedokument)
- (F) Projektabschluss (Vorlagedokument)
- (F) Selbstevaluation (Vorlagedokument)
- Archiv (Link)
- Sitzungen
- Protokoll (Vorlagedokument)
- Einladungen (Vorlagedokument)
- Aufgaben- und Rollenbeschreibung (Dokument)
- Evaluation (Anleitung mit Links und Vorlagedokumenten)
- Ziel- und Leistungsvereinbarungen
- Kontinuierliche Verbesserung der Prozesse (KVP) (Dokumentation)
6.Internationale Beziehungen
8.Arbeits- und Gesundheitsschutz
9.Öffentlichkeitarbeit PR
10.Digitale Kommunikation
11.Zentrale Verwaltung und Support
- Schulsekretariat
- Informationstechnik
- Schulverwaltung
12.weitere Funktionen & Beauftragte
- ÖPR
- BFC (Beauftragte für Chancengleichheit)
- Personen mit besonderen Aufgabenbereichen
- Schwerbehindertenbeauftragte
- Schulsozialarbeit und Beratungslehrkräfte
// Ensure labels/attributes for links (v1.3)
function ensureLinkLabels(root=document) {
const anchors = root.querySelectorAll('a[href]');
anchors.forEach(a => {
const href = (a.getAttribute('href') || '').trim();
const isHashLink = href.charAt(0) === '#';
const isPdf = /\.pdf(\?|#|$)/i.test(href);
const inGlobalNav = !!a.closest('.global-nav');
const inFileLink = !!a.closest('.file-link');
// Internal Sprungmarken (z.B. Schnellzugriff) sollen im gleichen Tab bleiben
if (isHashLink) {
a.removeAttribute('target');
a.removeAttribute('rel');
} else {
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener noreferrer');
}
const hasPdfLabel = !!a.querySelector('.pdf-label');
const hasWebLabel = !!a.querySelector('.web-label');
// Für Schnellzugriff (globale Navigation) und Datei-Links
// keine zusätzlichen "Link"/"PDF"-Badges anzeigen
if (isHashLink || inGlobalNav || inFileLink) {
a.classList.remove('pdf-link', 'web-link');
a.querySelectorAll('.pdf-label, .web-label').forEach(n => n.remove());
return;
}
if (isPdf) {
a.classList.add('pdf-link');
a.classList.remove('web-link');
if (!hasPdfLabel) {
const span = document.createElement('span');
span.className = 'pdf-label';
span.textContent = 'PDF';
a.appendChild(span);
}
a.querySelectorAll('.web-label').forEach(n => n.remove());
} else {
a.classList.add('web-link');
a.classList.remove('pdf-link');
if (!hasWebLabel) {
const span = document.createElement('span');
span.className = 'web-label';
span.textContent = 'Link';
a.appendChild(span);
}
a.querySelectorAll('.pdf-label').forEach(n => n.remove());
}
});
}
old-toggle')) {
const btn = document.createElement('span');
btn.className = 'fold-toggle';
btn.textContent = '−'; // initial geöffnet
li.insertBefore(btn, li.firstChild);
let opened = true;
btn.addEventListener('click', () => {
opened = !opened;
if (opened) {
sub.classList.remove('folded');
btn.textContent = '−';
} else {
sub.classList.add('folded');
btn.textContent = '+';
}
});
}
});
}
// Global expand/collapse
function expandOrCollapseAll(expand=true) {
document.querySelectorAll('li').forEach(li => {
var sub = li.querySelector(':scope > ul');
if (!sub) return;
// Neues System: Button mit class="toggle"
var btnToggle = li.querySelector(':scope > button.toggle');
if (btnToggle){
btnToggle.setAttribute('aria-expanded', expand ? 'true' : 'false');
sub.style.display = expand ? '' : 'none';
btnToggle.textContent = expand ? '–' : '+';
}
// Altes System: .fold-toggle und .folded (falls noch vorhanden)
var btnFold = li.querySelector(':scope > .fold-toggle');
if (btnFold){
if (expand){
sub.classList.remove('folded');
btnFold.textContent = '−';
} else {
sub.classList.add('folded');
btnFold.textContent = '+';
}
}
});
}
// Initialisierung nur für Link-Labels und Expand/Collapse
document.addEventListener('DOMContentLoaded', () => {
ensureLinkLabels();
var expandBtn = document.getElementById('expandAll');
if (expandBtn) {
expandBtn.addEventListener('click', function(){ expandOrCollapseAll(true); });
}
var collapseBtn = document.getElementById('collapseAll');
if (collapseBtn) {
collapseBtn.addEventListener('click', function(){ expandOrCollapseAll(false); });
}
});
(function(){
const categories = Array.from(document.querySelectorAll('.category'));
// Default: all closed
categories.forEach(cat => cat.classList.remove('open'));
function setExpanded(c, yes){
c.classList.toggle('open', !!yes);
const h = c.querySelector(':scope > h2'); if (h) h.setAttribute('aria-expanded', yes ? 'true' : 'false');
}
// Header toggle + accordion
categories.forEach(cat => {
const header = cat.querySelector(':scope > h2');
if (!header) return;
header.setAttribute('role', 'button'); header.setAttribute('tabindex', '0'); header.setAttribute('aria-expanded', 'false');
function toggle(){
const willOpen = !cat.classList.contains('open');
if (willOpen) categories.forEach(c => { if (c !== cat) setExpanded(c, false); });
setExpanded(cat, willOpen);
if (willOpen) try { cat.scrollIntoView({block:'nearest', behavior:'smooth'}); } catch(e){}
}
header.addEventListener('click', toggle);
header.addEventListener('keydown', (e)=>{ if (e.key==='Enter' || e.key===' ') { e.preventDefault(); toggle(); } });
});
// Bind global controls
const setAll = (open) => categories.forEach(c => setExpanded(c, open));
const exp = document.querySelector('#expandAll, [data-action="expand-all"], .btn-expand-all');
const col = document.querySelector('#collapseAll, [data-action="collapse-all"], .btn-collapse-all');
if (exp) exp.addEventListener('click', ()=> setAll(true));
if (col) col.addEventListener('click', ()=> setAll(false));
})();
(function(){
function updateGrid(){
var grid = document.querySelector('.main-grid, .tfy-grid');
if (!grid) return;
// any open top-level category?
var anyOpen = !!document.querySelector('.category.open, .tfy-cat.tfy-open');
grid.classList.toggle('one-col', anyOpen);
}
// initial + on interactions
document.addEventListener('DOMContentLoaded', updateGrid);
document.addEventListener('click', function(){ setTimeout(updateGrid, 0); }, true);
document.addEventListener('keydown', function(e){
if (e.key === 'Enter' || e.key === ' ' || e.key === 'Escape' || e.key === 'ArrowRight' || e.key === 'ArrowLeft'){
setTimeout(updateGrid, 0);
}
});
// also hook expand/collapse all if present
['#expandAll','[data-action="expand-all"]','.btn-expand-all','#collapseAll','[data-action="collapse-all"]','.btn-collapse-all']
.forEach(function(sel){
var b = document.querySelector(sel);
if (b) b.addEventListener('click', function(){ setTimeout(updateGrid,0); });
});
// expose for other scripts
window.__updateMainGridOneCol = updateGrid;
})();
(function(){
function $(sel, root=document){ return root.querySelector(sel); }
function $all(sel, root=document){ return Array.from(root.querySelectorAll(sel)); }
function findDeptCat(){
const cats = $all('.category, .tfy-cat');
return cats.find(sec => {
const h = sec.querySelector(':scope > h2, :scope > .tfy-header');
return h && /(^|)abteilungen/i.test((h.textContent||''));
}) || cats[3];
}
function closeAllDeptCards(cat){
if (!cat) return;
const cards = $all('.dept-card', cat);
cards.forEach(c => {
// Karten mit aktiven Suchtreffern geöffnet lassen
if (c.querySelector('mark.tfy-hi')) return;
c.classList.remove('open');
const h = c.querySelector(':scope > .dept-header, :scope > .dept-title');
if (h) h.setAttribute('aria-expanded','false');
});
}
function ensureClosed(){
const cat = findDeptCat();
if (!cat) return;
// only when main category is open do we enforce "all dept cards closed initially"
if (cat.classList.contains('open') || cat.classList.contains('tfy-open')){
closeAllDeptCards(cat);
}
}
// Run once after DOM loaded, with a couple of delayed retries to cover late DOM mutations
document.addEventListener('DOMContentLoaded', function(){
ensureClosed();
setTimeout(ensureClosed, 50);
setTimeout(ensureClosed, 200);
setTimeout(ensureClosed, 500);
});
// Observe class changes on the Abteilungen category (e.g., header click, script toggles, search opens ancestors)
const obsTarget = findDeptCat();
if (obsTarget){
const mo = new MutationObserver(function(muts){
for (const m of muts){
if (m.type === 'attributes' && m.attributeName === 'class'){
ensureClosed();
}
}
});
mo.observe(obsTarget, { attributes: true });
}
// Hook header interactions
const deptCat = findDeptCat();
if (deptCat){
const header = deptCat.querySelector(':scope > h2, :scope > .tfy-header');
if (header){
header.addEventListener('click', function(){ setTimeout(ensureClosed, 0); });
header.addEventListener('keydown', function(e){ if (e.key==='Enter'||e.key===' '){ setTimeout(ensureClosed, 0); } });
}
}
// Hook expand/collapse all controls
const btnAllOpen = $('#expandAll, [data-action="expand-all"], .btn-expand-all');
const btnAllClose = $('#collapseAll, [data-action="collapse-all"], .btn-collapse-all');
if (btnAllOpen) btnAllOpen .addEventListener('click', function(){ setTimeout(ensureClosed, 0); });
if (btnAllClose) btnAllClose.addEventListener('click', function(){ setTimeout(ensureClosed, 0); });
// Expose for manual triggers (optional)
window.__deptEnsureClosed = ensureClosed;
})();
(function(){
function $(sel, root){ return (root||document).querySelector(sel); }
function $all(sel, root){ return Array.from((root||document).querySelectorAll(sel)); }
function findDeptSection(){
// Find section whose header text contains "Abteilungen"
const sections = $all('section.category, section.tfy-cat, section');
for (const sec of sections){
const h = sec.querySelector(':scope > h2, :scope > .tfy-header, :scope > h3');
if (h && /abteilungen/i.test((h.textContent||'').trim())) return sec;
}
// fallback: 4th category
const cats = $all('section.category, section.tfy-cat');
return cats[3] || null;
}
function normalizeDeptCards(deptSec){
if (!deptSec) return;
// mark section for CSS
deptSec.classList.add('dept-tiles');
// locate cards; prefer .sub-grid > .dept-card, else any .dept-card inside
let cards = $all(':scope .sub-grid .dept-card', deptSec);
if (!cards.length) cards = $all(':scope .dept-card', deptSec);
// if still none, try to chunk by "Abteilung " anchors (older layout)
// (but your file already has .dept-card, so this is usually not needed)
cards.forEach(card => {
// HEADER: prefer .dept-header, then .dept-title, else build one from first text
let header = card.querySelector(':scope > .dept-header, :scope > .dept-title');
if (!header){
// find a likely title element inside the card
header = card.querySelector(':scope > p.dept-title, :scope > strong, :scope > header, :scope > h3, :scope > h4');
if (header){
header.classList.add('dept-title');
// move to top if not already direct child
if (header.parentElement !== card){
card.insertBefore(header, card.firstChild);
}
} else {
// create title from first non-empty text
const txt = (card.textContent||'Abteilung').trim().split(/
?
/).find(Boolean) || 'Abteilung';
header = document.createElement('div');
header.className = 'dept-title';
header.textContent = txt.trim();
card.insertBefore(header, card.firstChild);
}
}
// BODY: ensure .dept-body exists and contains all siblings except header
let body = card.querySelector(':scope > .dept-body');
if (!body){
body = document.createElement('div');
body.className = 'dept-body';
// move all direct children except header into body
const kids = Array.from(card.children).filter(c => c !== header);
kids.forEach(k => body.appendChild(k));
card.appendChild(body);
}
// START closed; allow multiple open
card.classList.remove('open');
header.setAttribute('role','button');
header.setAttribute('tabindex','0');
header.setAttribute('aria-expanded','false');
const toggle = ()=>{
const willOpen = !card.classList.contains('open');
card.classList.toggle('open', willOpen);
header.setAttribute('aria-expanded', willOpen ? 'true' : 'false');
if (willOpen){
try { card.scrollIntoView({block:'nearest', behavior:'smooth'}); } catch(e){}
}
};
header.addEventListener('click', toggle);
header.addEventListener('keydown', (e)=>{ if (e.key==='Enter' || e.key===' '){ e.preventDefault(); toggle(); } });
});
}
function init(){
const sec = findDeptSection();
if (!sec) return;
normalizeDeptCards(sec);
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
// Patch v7: robust scroll for Chrome — scroll the nearest *scrollable* container.
(function(){
function getStickyOffset(){
var el = document.querySelector('.controls') || document.querySelector('header');
if (!el) return 0;
return (el.getBoundingClientRect().height || 0) + 8;
}
function isScrollable(el){
if (!el) return false;
var st = getComputedStyle(el);
var oy = st.overflowY;
if (/(auto|scroll|overlay)/.test(oy)) {
return el.scrollHeight > el.clientHeight + 1;
}
return false;
}
function nearestScrollParent(el){
var p = el.parentElement;
while(p){
if (isScrollable(p)) return p;
p = p.parentElement;
}
// fallback to the document scroller
return document.scrollingElement || document.documentElement || document.body;
}
function scrollContainerTo(container, targetEl){
var off = getStickyOffset();
var rect = targetEl.getBoundingClientRect();
var currentTop = (container === (document.scrollingElement||document.documentElement||document.body))
? window.pageYOffset
: container.scrollTop;
var newTop = currentTop + rect.top - off;
try {
if (container === (document.scrollingElement||document.documentElement||document.body)) {
window.scrollTo({ top: newTop, left: 0, behavior: 'smooth' });
} else {
container.scrollTo({ top: newTop, left: 0, behavior: 'smooth' });
}
} catch(e) {
// Fallback without smooth
if (container === (document.scrollingElement||document.documentElement||document.body)) {
window.scrollTo(0, newTop);
} else {
container.scrollTop = newTop;
}
}
}
function scrollToCategory(cat){
if (!cat) return;
var container = nearestScrollParent(cat);
scrollContainerTo(container, cat);
}
function afterToggle(header){
setTimeout(function(){
var cat = header.closest('.category');
if (cat && cat.classList.contains('open')) scrollToCategory(cat);
}, 0);
}
// Bind to headers
var headers = Array.prototype.slice.call(document.querySelectorAll('.category > h2'));
headers.forEach(function(h){
h.addEventListener('click', function(){ afterToggle(h); });
h.addEventListener('keydown', function(e){ if (e.key==='Enter'||e.key===' ') afterToggle(h); });
});
// Observe programmatic open
var obs = new MutationObserver(function(muts){
muts.forEach(function(m){
if (m.type==='attributes' && m.attributeName==='class'){
var target = m.target;
if (target.classList && target.classList.contains('category') && target.classList.contains('open')){
scrollToCategory(target);
}
}
});
});
Array.prototype.forEach.call(document.querySelectorAll('.category'), function(cat){
obs.observe(cat, {attributes:true});
});
})();
// Patch v10: Suche ohne Dropdown; Pfeile vor/zurück, Zähler im Buttontext ("Suchen (n)").
(function(){
function $(sel, root){ return (root||document).querySelector(sel); }
function $all(sel, root){ return Array.prototype.slice.call((root||document).querySelectorAll(sel)); }
function escapeRe(s){ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
var matches = [];
var idx = -1;
var term = "";
function unwrapMarks(){
$all('mark.tfy-hi').forEach(function(el){
var p = el.parentNode;
while(el.firstChild) p.insertBefore(el.firstChild, el);
p.removeChild(el);
if (p.normalize) p.normalize();
});
}
function clearHighlights(){
unwrapMarks();
matches = [];
idx = -1;
term = "";
updateUI();
}
function highlightTextNode(node, termRe){
var text = node.nodeValue;
var m, last = 0, out = [];
while ((m = termRe.exec(text))){
out.appendChild
}
}
// Sauber neu schreiben (statt line-by-line edit), um Fehler zu vermeiden:
function highlightTextNode(node, termRe){
var text = node.nodeValue;
var m, last = 0, out = [];
while ((m = termRe.exec(text))){
out.push(document.createTextNode(text.slice(last, m.index)));
var mark = document.createElement('mark');
mark.className = 'tfy-hi';
mark.textContent = m[0];
out.push(mark);
last = m.index + m[0].length;
}
if (out.length){
out.push(document.createTextNode(text.slice(last)));
var frag = document.createDocumentFragment();
out.forEach(function(n){ frag.appendChild(n); });
node.parentNode.replaceChild(frag, node);
}
}
function collectScope(){
return document.querySelectorAll('.category');
}
function ensureVisible(node){
var el = node.closest('li');
while (el){
var sub = el.querySelector(':scope > ul');
if (sub){
// Neues System: Unterliste sichtbar schalten
sub.style.display = '';
// Altes System: Falt-Klasse entfernen
sub.classList.remove('folded');
}
// Neues System: Toggle-Button öffnen
var btnToggle = el.querySelector(':scope > button.toggle');
if (btnToggle){
btnToggle.setAttribute('aria-expanded','true');
btnToggle.textContent = '–';
}
// Altes System: Fold-Button synchronisieren
var btnFold = el.querySelector(':scope > .fold-toggle');
if (btnFold){
btnFold.textContent = '−';
}
el = el.parentElement ? el.parentElement.closest('li') : null;
}
var cat = node.closest('.category'); if (cat) cat.classList.add('open');
var dept = node.closest('.dept-card'); if (dept) dept.classList.add('open');
}
function nearestScrollParent(el){
var p = el.parentElement;
while(p){
var st = getComputedStyle(p);
if (/(auto|scroll|overlay)/.test(st.overflowY) && (p.scrollHeight > p.clientHeight + 1)) return p;
p = p.parentElement;
}
return document.scrollingElement || document.documentElement || document.body;
}
function getStickyOffset(){
var el = document.querySelector('.controls') || document.querySelector('header');
if (!el) return 0;
return (el.getBoundingClientRect().height || 0) + 8;
}
function scrollToEl(el){
try {
var container = nearestScrollParent(el);
var rect = el.getBoundingClientRect();
var baseTop = (container === (document.scrollingElement||document.documentElement||document.body)) ? window.pageYOffset : container.scrollTop;
var newTop = baseTop + rect.top - getStickyOffset();
if (container === (document.scrollingElement||document.documentElement||document.body)){
window.scrollTo({ top: newTop, left: 0, behavior: 'smooth' });
} else {
container.scrollTo({ top: newTop, left: 0, behavior: 'smooth' });
}
} catch(e){}
}
function updateUI(){
var btn = $('#searchBtn');
if (btn){
btn.textContent = term ? 'Suchen (' + (matches.length||0) + ')' : 'Suchen';
}
}
function focusMatch(i, doScroll){
if (!matches.length){ idx = -1; updateUI(); return; }
matches.forEach(function(m){ m.classList.remove('tfy-hi-current'); });
idx = ((i % matches.length) + matches.length) % matches.length;
var m = matches[idx];
if (m){
m.classList.add('tfy-hi-current');
ensureVisible(m);
if (doScroll !== false) scrollToEl(m);
}
updateUI();
}
function searchRun(q){
clearHighlights();
term = (q||'').trim();
if (!term){ updateUI(); return 0; }
var termRe = new RegExp(escapeRe(term), 'gi'); // case-insensitive
collectScope().forEach(function(block){
var walker = document.createTreeWalker(block, NodeFilter.SHOW_TEXT, null);
var nodes = [];
while (walker.nextNode()) nodes.push(walker.currentNode);
nodes.forEach(function(n){ highlightTextNode(n, termRe); });
});
matches = Array.prototype.slice.call(document.querySelectorAll('mark.tfy-hi'));
if (matches.length){
ensureVisible(matches[0]);
focusMatch(0, true);
} else {
idx = -1;
updateUI();
}
return matches.length;
}
// Globale API
window.__tfySearch = {
run: searchRun,
next: function(){ if (matches.length) focusMatch(idx+1, true); },
prev: function(){ if (matches.length) focusMatch(idx-1, true); },
clear: function(){ clearHighlights(); }
};
// Verdrahten
document.addEventListener('DOMContentLoaded', function(){
var input = document.getElementById('searchInput');
var searchBtn = document.getElementById('searchBtn');
var clearBtn = document.getElementById('clearBtn');
if (searchBtn) searchBtn.addEventListener('click', function(){ window.__tfySearch.run((input.value||'').trim()); });
if (clearBtn) clearBtn.addEventListener('click', function(){ window.__tfySearch.clear(); });
if (input) input.addEventListener('keydown', function(e){ if (e.key==='Enter') window.__tfySearch.run((input.value||'').trim()); });
var prevBtn = document.getElementById('tfyPrevBtn');
var nextBtn = document.getElementById('tfyNextBtn');
if (prevBtn && !prevBtn.__wired){
prevBtn.addEventListener('click', function(e){ e.preventDefault(); window.__tfySearch.prev(); });
prevBtn.__wired = true;
}
if (nextBtn && !nextBtn.__wired){
nextBtn.addEventListener('click', function(e){ e.preventDefault(); window.__tfySearch.next(); });
nextBtn.__wired = true;
}
});
})();
/* === Search sidebar integration (with direct jump to match) ========= */
(function(){
function $(sel, root){ return (root||document).querySelector(sel); }
function $all(sel, root){ return Array.prototype.slice.call((root||document).querySelectorAll(sel)); }
function openContext(node){
if (!node || !node.closest) return;
// UL-Kette sichtbar machen und Toggles synchronisieren
var el = node.closest('li');
while (el){
var sub = el.querySelector(':scope > ul');
if (sub){
sub.style.display = '';
sub.classList.remove('folded');
}
var btnToggle = el.querySelector(':scope > button.toggle');
if (btnToggle){
btnToggle.setAttribute('aria-expanded','true');
btnToggle.textContent = '–';
}
var btnFold = el.querySelector(':scope > .fold-toggle');
if (btnFold){
btnFold.textContent = '−';
}
el = el.parentElement ? el.parentElement.closest('li') : null;
}
// Kategorie öffnen
var cat = node.closest('.category');
if (cat){
cat.classList.add('open');
var ch = cat.querySelector(':scope > h2');
if (ch) ch.setAttribute('aria-expanded','true');
}
// Abteilungskarte öffnen
var dept = node.closest('.dept-card, .dept');
if (dept){
dept.classList.add('open');
var dh = dept.querySelector(':scope > .dept-header, :scope > .dept-title');
if (dh) dh.setAttribute('aria-expanded','true');
}
}
function ensureVisible(node){
openContext(node);
}
function ensureVisibleForSidebar(node){
openContext(node);
}
function buildPath(el){
if (!el || !el.closest) return '';
var parts = [];
var cat = el.closest('.category');
if (cat){
var h2 = cat.querySelector(':scope > h2');
if (h2 && h2.textContent) parts.push(h2.textContent.trim());
}
var dept = el.closest('.dept-card');
if (dept){
var dt = dept.querySelector('.dept-title');
if (dt && dt.textContent) parts.push(dt.textContent.trim());
}
var h3Text = '';
var cur = el.parentElement;
while(cur && cur !== document.body){
if (cur.tagName && cur.tagName.toLowerCase() === 'h3'){
h3Text = cur.textContent.trim();
break;
}
cur = cur.parentElement;
}
if (!h3Text){
var li = el.closest('li');
if (li){
var h3 = li.querySelector('h3');
if (h3 && h3.textContent) h3Text = h3.textContent.trim();
}
}
if (h3Text) parts.push(h3Text);
return parts.join(' → ');
}
function updateSidebar(){
var sidebar = $('#searchSidebar');
var list = $('#searchResults');
var summary = $('#searchSummary');
if (!sidebar || !list || !summary) return;
var input = $('#searchInput');
var term = input && input.value ? input.value.trim() : '';
list.innerHTML = '';
var marks = $all('mark.tfy-hi');
if (!term){
summary.textContent = 'Keine Suche aktiv.';
return;
}
if (!marks.length){
summary.textContent = 'Keine Treffer für „' + term + '“.';
return;
}
var current = document.querySelector('mark.tfy-hi-current');
var currentIndex = current ? marks.indexOf(current) : -1;
if (currentIndex < 0) currentIndex = 0;
summary.textContent = 'Treffer: ' + (currentIndex+1) + ' / ' + marks.length;
if (current) {
try {
current.scrollIntoView({behavior: 'smooth', block: 'center'});
} catch(e) {
current.scrollIntoView();
}
}
marks.forEach(function(m, idx){
var li = document.createElement('li');
li.className = 'search-result-item' + (idx === currentIndex ? ' is-current' : '');
var path = document.createElement('div');
path.className = 'search-result-path';
path.textContent = buildPath(m) || '(Allgemein)';
var snippet = document.createElement('div');
snippet.className = 'search-result-snippet';
snippet.textContent = m.textContent || term;
li.appendChild(path);
li.appendChild(snippet);
li.addEventListener('click', function(){
focusByIndex(idx);
});
list.appendChild(li);
});
}
function focusByIndex(idx){
var input = $('#searchInput');
var term = input && input.value ? input.value.trim() : '';
if (!term || !window.__tfySearch) return;
// frische Suche ausführen, Markierungen aktualisieren
window.__tfySearch.run(term);
var marks = $all('mark.tfy-hi');
if (!marks.length) { updateSidebar(); return; }
if (idx = marks.length) idx = marks.length - 1;
// aktuelle Markierung zurücksetzen
$all('mark.tfy-hi-current').forEach(function(m){
m.classList.remove('tfy-hi-current');
});
var m = marks[idx];
// Kontext öffnen (Kategorie, Abteilung, verschachtelte Listen)
ensureVisibleForSidebar(m);
m.classList.add('tfy-hi-current');
try {
m.scrollIntoView({behavior: 'smooth', block: 'center'});
} catch(e) {
m.scrollIntoView();
}
setTimeout(updateSidebar, 0);
}
function hook(){
if (!window.__tfySearch){
setTimeout(hook, 150);
return;
}
var s = window.__tfySearch;
if (s.__sidebarHooked) return;
s.__sidebarHooked = true;
var origRun = s.run;
var origNext = s.next;
var origPrev = s.prev;
var origClear = s.clear || function(){};
s.run = function(q){
var out = origRun.call(s, q);
setTimeout(updateSidebar, 0);
return out;
};
s.next = function(){
origNext.call(s);
setTimeout(updateSidebar, 0);
};
s.prev = function(){
origPrev.call(s);
setTimeout(updateSidebar, 0);
};
s.clear = function(){
origClear.call(s);
var input = $('#searchInput');
if (input) { input.value = ''; }
setTimeout(updateSidebar, 0);
};
var clearBtn = $('#clearBtn');
if (clearBtn && !clearBtn.__sidebarWired){
clearBtn.addEventListener('click', function(){ setTimeout(updateSidebar,0); });
clearBtn.__sidebarWired = true;
}
updateSidebar();
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', hook, {once:true});
} else {
hook();
}
})();
/* ===================================================================== */
// QHB Schnellzugriff: Kategorien öffnen + sanftes Scrollen
(function(){
function getNavOffset(){
var nav = document.querySelector('.global-nav');
if (!nav) return 8;
try {
var rect = nav.getBoundingClientRect();
return (rect.height || 0) + 8;
} catch(e){
return 8;
}
}
function closeAllCategories(){
var cats = Array.prototype.slice.call(document.querySelectorAll('.category'));
cats.forEach(function(c){
c.classList.remove('open');
var h = c.querySelector(':scope > h2');
if (h) h.setAttribute('aria-expanded', 'false');
});
if (window.__updateMainGridOneCol) {
try { window.__updateMainGridOneCol(); } catch(e){}
}
}
function openCategoryById(id){
var target = document.getElementById(id.replace(/^#/, ''));
if (!target) return null;
if (!target.classList.contains('category')) return target;
var cats = Array.prototype.slice.call(document.querySelectorAll('.category'));
cats.forEach(function(c){
var isTarget = (c === target);
c.classList.toggle('open', isTarget);
var h = c.querySelector(':scope > h2');
if (h) h.setAttribute('aria-expanded', isTarget ? 'true' : 'false');
});
if (window.__updateMainGridOneCol) {
try { window.__updateMainGridOneCol(); } catch(e){}
}
return target;
}
function scrollToElement(el){
if (!el) return;
var rect = el.getBoundingClientRect();
var offset = getNavOffset();
var y = window.pageYOffset + rect.top - offset;
try {
window.scrollTo({ top: y, left: 0, behavior: 'smooth' });
} catch(e){
window.scrollTo(0, y);
}
}
function handleClick(ev){
var a = ev.currentTarget;
var href = (a.getAttribute('href') || '').trim();
if (!href || href.charAt(0) !== '#') return;
ev.preventDefault();
var el = null;
if (href === '#main') {
closeAllCategories();
el = document.querySelector(href);
} else {
el = openCategoryById(href);
if (!el) {
el = document.querySelector(href);
}
}
scrollToElement(el);
}
function initNav(){
var nav = document.querySelector('.global-nav');
if (!nav) return;
var links = nav.querySelectorAll('a[href^="#"]');
links.forEach(function(a){
if (a.__qhbNavBound) return;
a.addEventListener('click', handleClick);
a.__qhbNavBound = true;
});
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', initNav, {once:true});
} else {
initNav();
}
})();// QHB: Faltbare Unterpunkte in Abteilungsbäumen
document.addEventListener('DOMContentLoaded', function(){
// Alle LI mit direktem UL-Kindelement bekommen einen Toggle
var cards = document.querySelectorAll('section.category');
cards.forEach(function(card){
var listItems = card.querySelectorAll('li');
listItems.forEach(function(li){
var sub = li.querySelector(':scope > ul');
if (!sub) return;
// Toggle nur einmal anlegen
if (li.querySelector(':scope > .toggle')) return;
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'toggle';
btn.setAttribute('aria-expanded', 'false');
btn.setAttribute('aria-label', 'Unterpunkte ein- und ausklappen');
btn.textContent = '+';
li.insertBefore(btn, li.firstChild);
li.classList.add('li-has-toggle');
sub.style.display = 'none';
function update(){
var expanded = btn.getAttribute('aria-expanded') === 'true';
sub.style.display = expanded ? '' : 'none';
btn.textContent = expanded ? '–' : '+';
}
btn.addEventListener('click', function(){
var current = btn.getAttribute('aria-expanded');
btn.setAttribute('aria-expanded', current === 'true' ? 'false' : 'true');
update();
});
btn.addEventListener('keydown', function(e){
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
btn.click();
}
});
// initial state
update();
});
});
});
// Dynamische Höhe von Schnellnavigation und Suchleiste für Sticky-Offsets
(function(){
function updateStickyOffsets(){
try {
var nav = document.querySelector('.global-nav');
var controls = document.querySelector('.controls');
var navH = nav ? (nav.getBoundingClientRect().height || nav.offsetHeight || 0) : 0;
var controlsH = controls ? (controls.getBoundingClientRect().height || controls.offsetHeight || 0) : 0;
// Offset, um die Suchleiste direkt unter der Navigation zu platzieren
document.documentElement.style.setProperty('--nav-offset', navH + 'px');
// Gesamt-Offset für rechte Trefferliste (Navigation + Suchleiste + kleiner Abstand)
var stack = navH + controlsH + 8;
document.documentElement.style.setProperty('--sidebar-offset', stack + 'px');
} catch(e){}
}
if (document.readyState === 'loading'){
document.addEventListener('DOMContentLoaded', updateStickyOffsets);
} else {
updateStickyOffsets();
}
window.addEventListener('resize', updateStickyOffsets);
})();