Wichtigster Befund vorab: Es gab noch KEINEN PDF-Bereich. Weder auf der Website (28 Seiten, keine davon Anleitungen) noch auf dem Server (null PDFs). Es wurde also nichts umstrukturiert, sondern neu gebaut -- und damit war die erste Frage nicht "wie sieht es aus", sondern "wie kommen die PDFs spaeter rein". Eine feste Liste im Code waere nach drei Monaten unbrauchbar gewesen. Filipe hat entschieden: eigener Pflegebereich, und alles nur fuer das Team. Die Bibliothek liegt deshalb komplett im Workspace hinter dem Login, nicht auf der oeffentlichen Seite. GLIEDERUNG Zwanzig Kategorien woertlich nach Vorgabe, gebuendelt in sechs Welten: TikTok, Streaming einrichten, Bild & Ton, Uebertragung & Aussehen, Inhalt & Menschen, Hilfe & Schnellstart. Zwanzig gleich aussehende Kacheln untereinander findet niemand -- gebuendelt sucht man erst die Welt, und darin stehen nur noch drei bis vier. Jede Welt hat ihre eigene Farbe, jede Kategorie ihr eigenes Symbol (20 verschiedene, keins doppelt). Die Kategorietexte sind Filipes Beschreibungen -- sie beantworten beim Einsortieren die einzige Frage, die man wirklich hat. Die Gliederung steht im Code, nicht in der Datenbank: Sie ist eine bewusste Ordnung, keine Nutzdaten. JEDE PDF HAT GENAU EINE HAUPTKATEGORIE, alles Weitere laeuft ueber Tags -- so gibt es jede Anleitung nur einmal, sie ist aber ueber mehrere Begriffe auffindbar. Genau wie gefordert. SUCHE UND FILTER Suche ueber Titel, Beschreibung, Tags und Dateiname. Filter nach Stufe (Einsteiger / Fortgeschritten / Profi), Geraet und Tag. Zwei Details: - "PC" zeigt auch die Anleitungen, die fuer BEIDE Geraete gelten -- sonst filtert man sich versehentlich die Haelfte weg. - Der Tag-Filter sucht mit Kommas drumherum, sonst wuerde "pc" auch bei "pc-spiele" anschlagen. Sobald gesucht oder gefiltert wird, verschwinden die Kacheln und es erscheinen Treffer. Wer sucht, will nicht erst noch klicken. Der Zustand steht in der Adresse (?k=obs&tag=...). Damit funktionieren Zurueck-Taste, Neuladen und Weiterschicken. Eine Kategorie, die man niemandem verlinken kann, ist keine Seite. Geprueft. SICHERHEIT Hochgeladen wird nur, was WIRKLICH eine PDF ist -- geprueft an den ersten Bytes (%PDF-), nicht an der Dateiendung. Die kann jeder umbenennen. Geprueft mit einer als .pdf getarnten HTML-Datei mit Skript: abgewiesen. Nur weil diese Pruefung existiert, darf die Datei ueberhaupt im Browser angezeigt werden statt bloss heruntergeladen -- und selbst dann mit strenger CSP und nosniff. Lesen darf jeder Angemeldete, pflegen nur DogFather. Geprueft: Creator und Scout bekommen 403 beim Hochladen und sehen keine Bearbeiten-Knoepfe. Ohne Anmeldung ist auch die Datei selbst nicht erreichbar (401). Bricht das Anlegen nach dem Schreiben ab, wird die Datei wieder geloescht -- sonst laege sie fuer immer verwaist auf der Platte. Beim Bearbeiten wird die Datei bewusst NICHT ersetzt. Wer eine neue Fassung hat, stellt sie neu ein. So bleibt nachvollziehbar, was wann galt. Geprueft: 20 Kacheln, 20 verschiedene Symbole, Kategorie oeffnen, Suche, Tag-Klick, Browser-Zurueck, Handy ohne Ueberlauf, 0 Konsolenfehler.
242 lines
9.4 KiB
CSS
242 lines
9.4 KiB
CSS
/* ===================================================================
|
|
Wissens-Bibliothek.
|
|
|
|
Zwanzig Kategorien sind viel. Damit sie trotzdem in einem Blick
|
|
erfassbar bleiben, sind sie in sechs Welten gebuendelt, und jede Welt
|
|
hat ihre eigene Farbe. Man sucht dann nicht unter zwanzig gleichen
|
|
Kacheln, sondern erst die Welt -- und da stehen nur noch drei bis vier.
|
|
|
|
Die Farben sind gedeckt und tragen nur den Symbolring, nicht die
|
|
ganze Kachel. Zwanzig farbige Flaechen waeren ein Flickenteppich.
|
|
=================================================================== */
|
|
|
|
/* ---------- Suche und Filter ---------------------------------------------- */
|
|
|
|
.suchleiste {
|
|
display: grid; gap: 12px; margin-bottom: 30px;
|
|
padding: 16px 18px;
|
|
background: rgba(255, 255, 255, .028);
|
|
border: 1px solid var(--rand); border-radius: var(--radius);
|
|
}
|
|
.suchleiste__feld { position: relative; display: flex; align-items: center; }
|
|
.suchleiste__lupe {
|
|
position: absolute; left: 13px; width: 17px; height: 17px;
|
|
fill: none; stroke: var(--text-still); stroke-width: 1.8; stroke-linecap: round;
|
|
pointer-events: none;
|
|
}
|
|
.suchleiste__feld input {
|
|
width: 100%; padding: 11px 14px 11px 40px;
|
|
background: rgba(255, 255, 255, .05);
|
|
border: 1px solid var(--rand); border-radius: var(--radius-klein);
|
|
color: var(--text); font: inherit;
|
|
}
|
|
.suchleiste__feld input:focus {
|
|
outline: none; border-color: rgba(63, 189, 245, .6);
|
|
box-shadow: 0 0 0 3px rgba(63, 189, 245, .14);
|
|
}
|
|
.suchleiste__feld input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
|
|
|
|
.suchleiste__filter { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
|
|
.suchleiste__filter .feld-schild { margin: 0; }
|
|
.suchleiste__filter select {
|
|
padding: 8px 11px; min-width: 118px;
|
|
background: rgba(255, 255, 255, .05);
|
|
border: 1px solid var(--rand); border-radius: var(--radius-klein);
|
|
color: var(--text); font: inherit; font-size: .85rem;
|
|
}
|
|
.suchleiste__filter select:focus {
|
|
outline: none; border-color: rgba(63, 189, 245, .6);
|
|
box-shadow: 0 0 0 3px rgba(63, 189, 245, .14);
|
|
}
|
|
|
|
/* ---------- Bloecke -------------------------------------------------------- */
|
|
|
|
.block { margin-bottom: 34px; }
|
|
.block__kopf { display: flex; align-items: center; gap: 10px; margin-bottom: 13px; }
|
|
.block__titel {
|
|
margin: 0; font-size: .78rem; font-weight: 700;
|
|
letter-spacing: .08em; text-transform: uppercase; color: var(--akzent);
|
|
}
|
|
.block__zahl {
|
|
min-width: 22px; padding: 1px 8px; text-align: center;
|
|
font-size: .74rem; font-weight: 700; color: var(--text-still);
|
|
background: rgba(255, 255, 255, .06); border-radius: 999px;
|
|
}
|
|
|
|
/* ---------- Kacheln --------------------------------------------------------- */
|
|
|
|
.kacheln {
|
|
display: grid; gap: 11px;
|
|
grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
|
|
}
|
|
|
|
.kachel {
|
|
--w: var(--akzent);
|
|
position: relative; display: flex; align-items: flex-start; gap: 14px;
|
|
padding: 15px 16px;
|
|
text-decoration: none; color: var(--text);
|
|
border: 1px solid transparent; border-radius: 13px;
|
|
background:
|
|
linear-gradient(#111825, #0c1320) padding-box,
|
|
linear-gradient(150deg,
|
|
color-mix(in srgb, var(--w) 42%, transparent),
|
|
rgba(255, 255, 255, .06) 55%,
|
|
color-mix(in srgb, var(--w) 16%, transparent)) border-box;
|
|
transition: transform .16s ease, box-shadow .2s ease;
|
|
}
|
|
.kachel::after {
|
|
content: ""; position: absolute; left: 14px; right: 14px; top: 1px; height: 1px;
|
|
background: linear-gradient(90deg, transparent,
|
|
color-mix(in srgb, var(--w) 45%, transparent), transparent);
|
|
}
|
|
.kachel:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 24px -12px color-mix(in srgb, var(--w) 85%, transparent);
|
|
}
|
|
.kachel:focus-visible {
|
|
outline: none;
|
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--w) 32%, transparent);
|
|
}
|
|
.kachel[data-leer="ja"] { opacity: .55; }
|
|
.kachel[data-leer="ja"]:hover { opacity: 1; }
|
|
|
|
.kachel__ring {
|
|
flex: none; display: grid; place-items: center;
|
|
width: 42px; height: 42px; border-radius: 12px;
|
|
background: color-mix(in srgb, var(--w) 13%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--w) 30%, transparent);
|
|
}
|
|
.kachel__symbol {
|
|
width: 21px; height: 21px;
|
|
fill: none; stroke: var(--w); stroke-width: 1.6;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
.kachel__text { min-width: 0; flex: 1; }
|
|
.kachel__name { display: block; font-size: .93rem; font-weight: 650; line-height: 1.3; }
|
|
.kachel__beschreibung {
|
|
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
overflow: hidden; margin-top: 3px;
|
|
font-size: .78rem; color: var(--text-still); line-height: 1.45;
|
|
}
|
|
.kachel__zahl {
|
|
flex: none; min-width: 26px; padding: 2px 8px; align-self: flex-start;
|
|
text-align: center; font-size: .75rem; font-weight: 700;
|
|
color: color-mix(in srgb, var(--w) 55%, #ffffff);
|
|
background: color-mix(in srgb, var(--w) 12%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--w) 26%, transparent);
|
|
border-radius: 999px;
|
|
}
|
|
|
|
/* Eine Farbe je Welt -- die Reihenfolge folgt der Gliederung. */
|
|
.block[data-welt="tiktok"] .kachel { --w: #3fbdf5; }
|
|
.block[data-welt="aufbau"] .kachel { --w: #8a76ff; }
|
|
.block[data-welt="bildton"] .kachel { --w: #5fc99a; }
|
|
.block[data-welt="technik"] .kachel { --w: #e8b877; }
|
|
.block[data-welt="inhalt"] .kachel { --w: #e88fb4; }
|
|
.block[data-welt="hilfe"] .kachel { --w: #8e9cb0; }
|
|
|
|
/* ---------- Karte einer Anleitung -------------------------------------------- */
|
|
|
|
.karten { display: grid; gap: 10px; }
|
|
|
|
.pdf {
|
|
padding: 15px 17px;
|
|
background: rgba(255, 255, 255, .03);
|
|
border: 1px solid var(--rand); border-radius: var(--radius-klein);
|
|
transition: border-color .18s ease;
|
|
}
|
|
.pdf:hover { border-color: rgba(255, 255, 255, .18); }
|
|
.pdf[data-wichtig="ja"] {
|
|
border-color: rgba(232, 192, 125, .32);
|
|
background: rgba(232, 192, 125, .045);
|
|
}
|
|
|
|
.pdf__kopf { display: flex; gap: 14px; align-items: flex-start; }
|
|
.pdf__ring {
|
|
flex: none; display: grid; place-items: center;
|
|
width: 38px; height: 38px; border-radius: 11px;
|
|
background: rgba(63, 189, 245, .1);
|
|
border: 1px solid rgba(63, 189, 245, .24);
|
|
}
|
|
.pdf__symbol {
|
|
width: 19px; height: 19px;
|
|
fill: none; stroke: var(--akzent); stroke-width: 1.6;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
.pdf__mitte { min-width: 0; flex: 1; }
|
|
.pdf__titel { margin: 0; font-size: 1rem; font-weight: 650; line-height: 1.35; }
|
|
.pdf__text { margin: 4px 0 0; font-size: .86rem; color: var(--text-leise); max-width: 78ch; }
|
|
.pdf__fuss { margin: 9px 0 0; font-size: .75rem; color: var(--text-still); }
|
|
|
|
.pdf__marken { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 9px; }
|
|
.marke-stufe, .marke-geraet, .marke-wichtig, .marke-tag {
|
|
padding: 3px 9px; border-radius: 999px;
|
|
font: inherit; font-size: .71rem; font-weight: 600;
|
|
border: 1px solid var(--rand); color: var(--text-still);
|
|
background: transparent;
|
|
}
|
|
.marke-stufe[data-stufe="einsteiger"] {
|
|
color: #5fc99a; border-color: rgba(95, 201, 154, .38); background: rgba(95, 201, 154, .1);
|
|
}
|
|
.marke-stufe[data-stufe="fortgeschritten"] {
|
|
color: #e8b877; border-color: rgba(232, 184, 119, .38); background: rgba(232, 184, 119, .1);
|
|
}
|
|
.marke-stufe[data-stufe="profi"] {
|
|
color: #e88fb4; border-color: rgba(232, 143, 180, .4); background: rgba(232, 143, 180, .1);
|
|
}
|
|
.marke-geraet { color: var(--text-leise); }
|
|
.marke-wichtig {
|
|
color: #e8c07d; border-color: rgba(232, 192, 125, .4); background: rgba(232, 192, 125, .1);
|
|
}
|
|
.marke-tag { cursor: pointer; transition: color .16s ease, border-color .16s ease; }
|
|
.marke-tag:hover { color: var(--akzent); border-color: rgba(63, 189, 245, .42); }
|
|
|
|
.pdf__knoepfe { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 13px; }
|
|
|
|
/* ---------- Formular ---------------------------------------------------------- */
|
|
|
|
.haken { display: flex; align-items: center; gap: 9px; font-size: .87rem; cursor: pointer; }
|
|
.haken input { width: 17px; height: 17px; accent-color: var(--akzent); cursor: pointer; }
|
|
|
|
.tag-vorschlag { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
|
|
.tag-knopf {
|
|
padding: 4px 10px; cursor: pointer;
|
|
background: transparent; border: 1px dashed var(--rand); border-radius: 999px;
|
|
color: var(--text-still); font: inherit; font-size: .74rem;
|
|
transition: color .16s ease, border-color .16s ease;
|
|
}
|
|
.tag-knopf:hover { color: var(--akzent); border-color: rgba(63, 189, 245, .45); border-style: solid; }
|
|
|
|
#n-datei {
|
|
width: 100%; padding: 10px 12px;
|
|
background: rgba(255, 255, 255, .04);
|
|
border: 1px dashed var(--rand); border-radius: var(--radius-klein);
|
|
color: var(--text-leise); font: inherit; font-size: .85rem; cursor: pointer;
|
|
}
|
|
#n-datei::file-selector-button {
|
|
margin-right: 12px; padding: 6px 13px; cursor: pointer;
|
|
background: rgba(63, 189, 245, .12);
|
|
border: 1px solid rgba(63, 189, 245, .3); border-radius: 8px;
|
|
color: var(--akzent); font: inherit; font-size: .8rem; font-weight: 600;
|
|
}
|
|
|
|
.leer-hinweis {
|
|
display: grid; gap: 12px; justify-items: center;
|
|
padding: 34px 22px; margin-bottom: 26px; text-align: center;
|
|
color: var(--text-still); font-size: .92rem;
|
|
border: 1px dashed var(--rand); border-radius: var(--radius);
|
|
}
|
|
.leer-hinweis p { margin: 0; max-width: 52ch; }
|
|
|
|
@media (max-width: 620px) {
|
|
.kacheln { grid-template-columns: 1fr; }
|
|
.suchleiste__filter { display: grid; grid-template-columns: auto 1fr; gap: 8px 10px; }
|
|
.suchleiste__filter .knopf-still { grid-column: 1 / -1; justify-self: start; }
|
|
.pdf__ring { display: none; }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.kachel, .pdf, .marke-tag, .tag-knopf { transition: none; }
|
|
.kachel:hover { transform: none; }
|
|
}
|