Commit ·
5cf774c
1
Parent(s): ac53235
feat: add Josephine personalized study dashboard
Browse filesDeliver the German-first interactive StudyFlow frontend with daily briefing, materials, study canvas, calendar, learning plan, knowledge gaps, flashcards, quiz, reminders, and local-first privacy cues.
Co-authored-by: Codex <codex@openai.com>
- app.js +456 -0
- assets/hero/josephine-mainz-morning.png +3 -0
- assets/materials/mq3zhq9n-clipboard.png +3 -0
- assets/materials/mq3zhqat-clipboard.png +3 -0
- assets/materials/mq3zhqbu-clipboard.png +3 -0
- assets/materials/mq3zhqdk-clipboard.png +0 -0
- assets/materials/mq3zhqe0-clipboard.png +0 -0
- assets/materials/mq3zhqe3-clipboard.png +0 -0
- assets/materials/mq3zhqea-clipboard.png +0 -0
- assets/materials/mq3zhqeg-clipboard.png +0 -0
- index.html +83 -0
- styles.css +656 -0
app.js
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const assets = {
|
| 2 |
+
calendar: "assets/materials/mq3zhq9n-clipboard.png",
|
| 3 |
+
slide: "assets/materials/mq3zhqat-clipboard.png",
|
| 4 |
+
notes: "assets/materials/mq3zhqbu-clipboard.png",
|
| 5 |
+
evidence: "assets/materials/mq3zhqdk-clipboard.png",
|
| 6 |
+
recent: [
|
| 7 |
+
"assets/materials/mq3zhqe0-clipboard.png",
|
| 8 |
+
"assets/materials/mq3zhqe3-clipboard.png",
|
| 9 |
+
"assets/materials/mq3zhqea-clipboard.png",
|
| 10 |
+
"assets/materials/mq3zhqeg-clipboard.png"
|
| 11 |
+
]
|
| 12 |
+
};
|
| 13 |
+
|
| 14 |
+
const routes = ["overview", "uploads", "canvas", "calendar", "learning-plan", "gaps", "flashcards", "quiz", "reminders"];
|
| 15 |
+
const app = document.querySelector("#app");
|
| 16 |
+
const navList = document.querySelector("#navList");
|
| 17 |
+
const toast = document.querySelector("#toast");
|
| 18 |
+
|
| 19 |
+
const pageHead = (title, subtitle, actions = "") => `
|
| 20 |
+
<header class="page-head">
|
| 21 |
+
<div><h1>${title}</h1><p>${subtitle}</p></div>
|
| 22 |
+
<div class="head-actions">${actions}</div>
|
| 23 |
+
</header>`;
|
| 24 |
+
|
| 25 |
+
const panel = (title, body, extra = "", className = "") => `
|
| 26 |
+
<section class="panel ${className}">
|
| 27 |
+
<div class="panel-head"><h2>${title}</h2>${extra || '<span class="more">...</span>'}</div>
|
| 28 |
+
${body}
|
| 29 |
+
</section>`;
|
| 30 |
+
|
| 31 |
+
function overviewPage() {
|
| 32 |
+
const agenda = [
|
| 33 |
+
["09:00", "Mehrsprachigkeitsdidaktik", "Seminar im Hörsaal 3 · Sprachbewusstsein & Transferstrategien", "book-open", "green"],
|
| 34 |
+
["11:30", "Englischdidaktik", "Übung · Classroom Interaction & Feedback", "globe", "blue"],
|
| 35 |
+
["13:00", "Mittagspause", "Zeit für gutes Essen und einen kurzen Spaziergang am Rhein", "fork-knife", "rose"],
|
| 36 |
+
["15:00", "Lernblock Bildungspsychologie", "Kapitel 4: Motivation & Selbstregulation · Karteikarten erstellen", "brain", "aubergine"],
|
| 37 |
+
["17:30", "Familie & Freunde", "Abendessen bei Mama & Papa", "users-three", "gold"]
|
| 38 |
+
].map(([time, title, sub, icon, tone]) => `
|
| 39 |
+
<button class="day-entry ${tone}" data-route="${time === "15:00" ? "canvas" : "calendar"}">
|
| 40 |
+
<time>${time}</time>
|
| 41 |
+
<span class="day-icon"><i class="ph ph-${icon}"></i></span>
|
| 42 |
+
<span><strong>${title}</strong><small>${sub}</small></span>
|
| 43 |
+
<i class="ph ph-caret-right entry-arrow"></i>
|
| 44 |
+
</button>`).join("");
|
| 45 |
+
|
| 46 |
+
return `
|
| 47 |
+
<div class="josephine-home">
|
| 48 |
+
<section class="josephine-hero">
|
| 49 |
+
<img src="assets/hero/josephine-mainz-morning.png" alt="Josephine lernt an einem sonnigen Morgen in Mainz, umgeben von Erinnerungen an Familie, Freunde und ihr Lieblingspferd.">
|
| 50 |
+
<div class="weather-line">Dienstag, 7. Juni <span>·</span> Mainz <span>·</span> 18° <i class="ph ph-sun"></i></div>
|
| 51 |
+
<div class="hero-copy">
|
| 52 |
+
<h1>Josephine<br>Wendland</h1>
|
| 53 |
+
<p class="hero-motto">Lehren. Verstehen. Verbinden.</p>
|
| 54 |
+
<h2>Guten Morgen, Josephine</h2>
|
| 55 |
+
<p>Heute ist ein guter Tag, etwas zu lernen,<br>zu wachsen und Menschen zu inspirieren.</p>
|
| 56 |
+
</div>
|
| 57 |
+
</section>
|
| 58 |
+
|
| 59 |
+
<section class="daily-journal">
|
| 60 |
+
<div class="journal-agenda">
|
| 61 |
+
<header><i class="ph ph-calendar-blank"></i><h2>Mein Tag</h2><span>7. Juni</span></header>
|
| 62 |
+
<div class="day-list">${agenda}</div>
|
| 63 |
+
</div>
|
| 64 |
+
<aside class="today-important">
|
| 65 |
+
<header><i class="ph ph-star"></i><h2>Heute wichtig</h2></header>
|
| 66 |
+
<button class="important-row deadline" data-route="calendar">
|
| 67 |
+
<span class="important-icon"><i class="ph ph-calendar-dots"></i></span>
|
| 68 |
+
<span><small>Deadline</small><strong>Reflexionsbericht Mehrsprachigkeit</strong><em>Abgabe: Freitag, 10. Juni</em></span>
|
| 69 |
+
<i class="ph ph-caret-right"></i>
|
| 70 |
+
</button>
|
| 71 |
+
<button class="important-row gap" data-route="gaps">
|
| 72 |
+
<span class="important-icon"><i class="ph ph-target"></i></span>
|
| 73 |
+
<span><small>Wissenslücke</small><strong>Selbstwirksamkeit verstehen</strong><em>Wiederholen · Karte 24–27</em></span>
|
| 74 |
+
<i class="ph ph-caret-right"></i>
|
| 75 |
+
</button>
|
| 76 |
+
<button class="important-row next" data-route="canvas">
|
| 77 |
+
<span class="important-icon"><i class="ph ph-book-open"></i></span>
|
| 78 |
+
<span><small>Nächster Schritt</small><strong>Lernen fortsetzen</strong><em>Bildungspsychologie · Kapitel 4</em></span>
|
| 79 |
+
<i class="ph ph-caret-right"></i>
|
| 80 |
+
</button>
|
| 81 |
+
<p class="journal-note">Kleine Schritte jeden Tag<br>führen zu großen Veränderungen.</p>
|
| 82 |
+
</aside>
|
| 83 |
+
</section>
|
| 84 |
+
</div>`;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
function uploadsPage() {
|
| 88 |
+
const extracted = `Sprachbewusstheit fördern (VL 07)
|
| 89 |
+
|
| 90 |
+
Begriff: Fähigkeit, Sprache(n) als System(e) wahrzunehmen und über Sprache(n) nachzudenken.
|
| 91 |
+
|
| 92 |
+
Ziele:
|
| 93 |
+
- Sensibilisierung für sprachliche Strukturen und Variation
|
| 94 |
+
- Vergleich von Sprachen als Ressourcen nutzen
|
| 95 |
+
- Transferstrategien entwickeln
|
| 96 |
+
|
| 97 |
+
Vergleich DE - FR
|
| 98 |
+
DE: Ich gehe in die Schule.
|
| 99 |
+
FR: Je vais à l'école.
|
| 100 |
+
|
| 101 |
+
Gemeinsamkeiten: Subjekt - Verb - Objekt
|
| 102 |
+
Unterschiede: Artikel, Präpositionen, Akkordanz
|
| 103 |
+
|
| 104 |
+
Didaktische Prinzipien:
|
| 105 |
+
1) Sprachenvergleich
|
| 106 |
+
2) Bewusstmachung
|
| 107 |
+
3) Funktionaler Einsatz im Fachunterricht`;
|
| 108 |
+
|
| 109 |
+
return pageHead("Materialien", "Notizen, Folien und Kalender an einem ruhigen Ort.", `
|
| 110 |
+
<button class="button secondary" id="addFiles">Dateien hinzufügen</button>
|
| 111 |
+
<button class="button primary" data-route="canvas">In Arbeitsfläche öffnen</button>
|
| 112 |
+
`) + `
|
| 113 |
+
<div class="uploads-grid">
|
| 114 |
+
${panel("Upload-Queue (3)", `<div class="queue-list">
|
| 115 |
+
<div class="queue-item selected"><div class="queue-title"><strong>Mehrsprachigkeitsdidaktik_VL07.pdf</strong><span class="badge green">100%</span></div><div class="progress"><span style="width:100%"></span></div><small>OCR abgeschlossen · 32 Seiten</small></div>
|
| 116 |
+
<div class="queue-item"><div class="queue-title"><strong>Englischdidaktik_Orthografie.pdf</strong><span class="badge blue">76%</span></div><div class="progress"><span style="width:76%;background:var(--blue)"></span></div><small>OCR läuft · Seite 3 von 11</small></div>
|
| 117 |
+
<div class="queue-item"><div class="queue-title"><strong>Bildungspsychologie_Notizen.jpg</strong><span class="badge">0%</span></div><div class="progress"><span style="width:0%"></span></div><small>Wartet in der Queue</small></div>
|
| 118 |
+
<div class="dropzone" id="dropzone"><strong>Dateien hier ablegen</strong><br><small>PDF, JPG oder PNG · Verarbeitung bleibt lokal</small></div>
|
| 119 |
+
</div>`, '<span class="badge green">Lokal</span>', "upload-queue")}
|
| 120 |
+
${panel("Mehrsprachigkeitsdidaktik_VL07.pdf", `<div class="doc-review">
|
| 121 |
+
<div class="doc-pane"><div class="doc-toolbar"><button class="icon-button">‹</button><span>4 / 32</span><button class="icon-button">›</button><span>100%</span><button class="icon-button">↗</button></div><div class="document-page"><img src="${assets.slide}" alt="Vorlesungsfolie zu Scaffolding im mehrsprachigen Unterricht"></div></div>
|
| 122 |
+
<div class="note-pane"><img src="${assets.notes}" alt="Handschriftliche Notizen zu Scaffolding im mehrsprachigen Unterricht"></div>
|
| 123 |
+
</div>`, '<span class="badge blue">Seite 4 verknüpft</span>')}
|
| 124 |
+
${panel("OCR-Extraktion", `<div class="panel-body ocr-panel">
|
| 125 |
+
<div class="language-tabs"><button class="badge green">Deutsch 99%</button><button class="badge blue">Französisch 82%</button><button class="badge">Englisch 12%</button></div>
|
| 126 |
+
<div class="confidence">Konfidenz der Seite: <strong>93%</strong> · 7 Markierungen prüfen</div>
|
| 127 |
+
<label class="field"><span class="label">Extrahierter Text</span><textarea id="ocrText">${extracted}</textarea></label>
|
| 128 |
+
<div class="row" style="justify-content:space-between"><span class="badge amber">Niedrige Konfidenz: Akkordanz</span><button class="button secondary" id="reviewAll">Alle prüfen</button></div>
|
| 129 |
+
<div class="ocr-actions"><button class="button secondary">Verwerfen</button><button class="button primary" id="saveOcr">Übernehmen & speichern</button></div>
|
| 130 |
+
<div class="trust-inline">Speichern in: Mehrsprachigkeitsdidaktik · nur lokal</div>
|
| 131 |
+
</div>`, '<span class="badge green">Abgeschlossen</span>')}
|
| 132 |
+
</div>`;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
function canvasPage() {
|
| 136 |
+
const thumbs = [assets.recent[0], assets.recent[1], assets.slide, assets.recent[2], assets.recent[3]]
|
| 137 |
+
.map((src, i) => `<button class="slide-thumb ${i === 2 ? "active" : ""}" data-slide="${i}"><img src="${src}" alt="Materialvorschau ${i + 1}"></button>`).join("");
|
| 138 |
+
return `<div class="canvas-page">
|
| 139 |
+
<header class="canvas-head">
|
| 140 |
+
<h1>Smart Study Canvas <span>Mehrsprachigkeitsdidaktik / Woche 7</span></h1>
|
| 141 |
+
<div class="head-actions"><button class="button secondary">Verknüpfungen</button><button class="button secondary">Notiz hinzufügen</button><button class="button secondary">Exportieren</button></div>
|
| 142 |
+
</header>
|
| 143 |
+
<div class="canvas-grid">
|
| 144 |
+
${panel("Vorlesungsfolien", `<div class="slide-workspace"><div class="slide-thumbs">${thumbs}</div><div class="slide-main"><img id="mainSlide" src="${assets.slide}" alt="Vorlesungsfolie Scaffolding"></div></div>`)}
|
| 145 |
+
${panel("Handschriftliche Notizen", `<div class="notes-main"><img src="${assets.notes}" alt="Maya Hoffmanns handschriftliche Scaffolding-Notizen"></div>`, '<span class="badge blue">4 semantische Links</span>')}
|
| 146 |
+
${panel("AI-Copilot", `<div class="chat"><div class="messages" id="messages">
|
| 147 |
+
<div class="message user">Wie hängen Translanguaging und Scaffolding zusammen?</div>
|
| 148 |
+
<div class="message ai"><strong>Maya</strong><br>Scaffolding schafft temporäre sprachliche und kognitive Stützen. Translanguaging erlaubt Lernenden, ihr gesamtes sprachliches Repertoire für Bedeutungsbildung zu nutzen. Zusammen fördern sie fachliche Teilhabe, ohne die Zielsprache auszublenden.<div class="language-tabs"><span class="badge green">Folie 14</span><span class="badge blue">Notiz S. 1</span></div></div>
|
| 149 |
+
<div class="alert-card"><strong>Fehlendes Konzept erkannt: Interlanguage</strong>Die Unterscheidung zur Interlanguage fehlt in deinen verknüpften Notizen.<div class="language-tabs"><button class="badge">Konzept erklären</button><button class="badge">Quelle suchen</button><button class="badge">Karte erstellen</button></div></div>
|
| 150 |
+
</div><form class="chat-compose" id="chatForm"><input id="chatInput" placeholder="Stelle eine Frage zu deinen Materialien..." required><button class="button primary" aria-label="Senden">➤</button></form></div>`, '<span class="badge green">Lokal · Quellengebunden</span>')}
|
| 151 |
+
</div>
|
| 152 |
+
</div>`;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
function calendarPage() {
|
| 156 |
+
const cells = Array.from({length: 35}, () => "<div></div>").join("");
|
| 157 |
+
const roadmapRows = [
|
| 158 |
+
["Mehrsprachigkeitsdidaktik","on,on,on,,blue,blue,,"],
|
| 159 |
+
["Englischdidaktik","blue,blue,,on,on,,,"],
|
| 160 |
+
["Französischdidaktik",",amber,amber,,on,on,,"],
|
| 161 |
+
["Bildungspsychologie","on,,blue,blue,,on,on,on"]
|
| 162 |
+
].map(([name, states]) => `<b>${name}</b>${states.split(",").map(s => `<span class="${s}"></span>`).join("")}`).join("");
|
| 163 |
+
return pageHead("Kalender & Lernplan", "Geprüfte Termine, realistische Lernblöcke und dein 8-Tage-Fokus.", `
|
| 164 |
+
<button class="button secondary" id="reviewExtractions">Extraktionen prüfen · 3</button>
|
| 165 |
+
<button class="button primary" id="planBlock">Lernblock planen</button>
|
| 166 |
+
`) + `
|
| 167 |
+
<div class="calendar-grid">
|
| 168 |
+
${panel("Wochenplan · 7.-11. Juni", `<div class="week-grid">
|
| 169 |
+
<div></div>${["Di 7.","Mi 8.","Do 9.","Fr 10.","Sa 11."].map(d=>`<div class="day">${d}</div>`).join("")}
|
| 170 |
+
${["09:00","10:00","11:00","12:00","13:00","14:00","15:00"].map(t=>`<div class="time">${t}</div>`).join("")}${cells}
|
| 171 |
+
<div class="event" style="grid-column:2;grid-row:2/4"><strong>09:00</strong><br>Mehrsprachigkeitsdidaktik<br>Seminar</div>
|
| 172 |
+
<div class="event amber" style="grid-column:3;grid-row:3/5"><strong>10:00</strong><br>Hausarbeit<br>Quellenarbeit</div>
|
| 173 |
+
<div class="event blue" style="grid-column:4;grid-row:4/6"><strong>11:00</strong><br>Französischdidaktik<br>Séance 5</div>
|
| 174 |
+
<div class="event" style="grid-column:5;grid-row:2/5"><strong>09:00</strong><br>Fachdidaktik Deutsch<br>Portfolio</div>
|
| 175 |
+
<div class="event blue" style="grid-column:6;grid-row:3/5"><strong>10:00</strong><br>Lerngruppe<br>Bibliothek</div>
|
| 176 |
+
</div><div class="roadmap"><h3>8-Tage-Prüfungsroadmap</h3><div class="roadmap-grid"><b></b>${["Di 7","Mi 8","Do 9","Fr 10","Sa 11","So 12","Mo 13","Di 14"].map(d=>`<b>${d}</b>`).join("")}${roadmapRows}</div><p class="muted" style="font-size:10px">Fokus: Hausarbeit abschließen → Französischdidaktik wiederholen → Prüfungssimulation</p></div>`, '<span class="badge green">72% geplant</span>', "week-calendar")}
|
| 177 |
+
<div class="stack">
|
| 178 |
+
${panel("Heute · 5 Std. 30 Min.", `<div class="panel-body"><div class="today-block"><strong>09:00-10:30 · Seminarfolien</strong><small>Translanguaging und Scaffolding verknüpfen</small></div><div class="today-block"><strong>11:30-13:00 · Reading response</strong><small>Englischdidaktik · Kapitel 4</small></div><div class="today-block"><strong>15:00-16:30 · Retrieval Practice</strong><small>Bildungspsychologie · Lernkarten 31-54</small></div></div>`, '<span class="badge green">Im Plan</span>')}
|
| 179 |
+
${panel("Geprüfte Extraktionen", `<div class="panel-body"><div class="extraction-row"><span>10. Juni</span><strong>Hausarbeit abgeben</strong><span class="badge amber">Bestätigt</span></div><div class="extraction-row"><span>14. Juni</span><strong>Französischdidaktik Prüfung</strong><span class="badge blue">Kalender</span></div><div class="extraction-row"><span>19. Juni</span><strong>Portfolio Deutsch</strong><span class="badge green">Bestätigt</span></div><img class="calendar-asset" src="${assets.calendar}" alt="Handschriftlicher Kalender Juni 2025"></div>`, '<span class="badge">3 aus PDF</span>')}
|
| 180 |
+
</div>
|
| 181 |
+
</div>`;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
function flashcardsPage() {
|
| 185 |
+
const decks = [
|
| 186 |
+
["Mehrsprachigkeitsdidaktik",48,"18 fällig · zuletzt heute",72],
|
| 187 |
+
["Englischdidaktik",36,"Nächste Wiederholung morgen",58],
|
| 188 |
+
["Französischdidaktik",42,"Nächste Wiederholung morgen",44],
|
| 189 |
+
["Bildungspsychologie",61,"Nächste Wiederholung morgen",81],
|
| 190 |
+
["Fachdidaktik Deutsch",27,"Nächste Wiederholung morgen",36]
|
| 191 |
+
].map(([name,count,sub,pct],i)=>`<div class="deck-row ${i===0?"selected":""}" data-deck="${name}"><strong>${name} · ${count} Karten</strong><small>${sub}</small><div class="progress"><span style="width:${pct}%"></span></div></div>`).join("");
|
| 192 |
+
return pageHead("Karteikarten", "Quellengebundene Karten bearbeiten, lernen und exportieren.", `
|
| 193 |
+
<button class="button secondary" id="generateCards">Aus Quellen generieren</button>
|
| 194 |
+
<button class="button primary" id="learnCards">12 Karten lernen</button>
|
| 195 |
+
`) + `
|
| 196 |
+
<div class="cards-grid">
|
| 197 |
+
${panel("Meine Decks", `<div>${decks}</div>`)}
|
| 198 |
+
${panel("Karte bearbeiten · 12 von 48", `<div class="panel-body">
|
| 199 |
+
<div class="field question"><label for="cardQuestion">Frage</label><textarea id="cardQuestion">Wie unterscheidet sich Translanguaging vom klassischen Code-Switching?</textarea></div>
|
| 200 |
+
<div class="field answer"><label for="cardAnswer">Antwort</label><textarea id="cardAnswer">Translanguaging beschreibt die flexible Nutzung des gesamten sprachlichen Repertoires zur Bedeutungsbildung. Code-Switching bezeichnet dagegen meist den situativen Wechsel zwischen getrennt gedachten Sprachen.</textarea></div>
|
| 201 |
+
<div class="field"><label>Quellen</label><div class="source-box">▣ Mehrsprachigkeitsdidaktik_Woche_7.pdf · Folie 14<br>▤ Notizen_Scaffolding_03-06.jpg · Seite 1</div><div class="evidence-strip"><img src="${assets.evidence}" alt="Quellenausschnitt aus einer Notiz"><img src="${assets.notes}" alt="Handschriftliche Evidenz zu Scaffolding"></div></div>
|
| 202 |
+
<div class="language-tabs"><span class="badge green">Translanguaging</span><span class="badge blue">Code-Switching</span><span class="badge">Woche 7</span></div>
|
| 203 |
+
<div class="row" style="justify-content:space-between"><button class="button danger" id="deleteCard">Karte löschen</button><button class="button primary" id="saveCard">Änderungen speichern</button></div>
|
| 204 |
+
</div>`)}
|
| 205 |
+
${panel("Vorschau & Export", `<div class="panel-body stack"><div class="card-preview" id="cardPreview"><div class="front"><small>Vorderseite</small><strong>Wie unterscheidet sich Translanguaging vom klassischen Code-Switching?</strong><span class="muted">Klicken zum Umdrehen</span></div><div class="back"><small>Rückseite</small><p>Translanguaging nutzt das gesamte sprachliche Repertoire flexibel. Code-Switching beschreibt den situativen Wechsel zwischen getrennt gedachten Sprachen.</p></div></div><div class="divider"></div><h3 style="font-family:var(--serif);margin:2px 0">Deck exportieren</h3><span class="muted" style="font-size:11px">48 Karten · Quellen enthalten · DE</span><div class="export-list"><button class="button" data-export="Anki">Anki (.apkg)</button><button class="button" data-export="CSV">CSV</button><button class="button" data-export="PDF">PDF zum Drucken</button></div><small class="muted">Letzte Generierung: heute, 10:42 · vollständig lokal</small></div>`)}
|
| 206 |
+
</div>`;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
function quizPage() {
|
| 210 |
+
return pageHead("Quizmodus", "Prüfungssimulation · Mehrsprachigkeitsdidaktik", `<button class="button secondary" id="endQuiz">Simulation beenden</button>`) + `
|
| 211 |
+
<div class="quiz-grid">
|
| 212 |
+
${panel("Frage 7 von 12", `<div class="quiz-content">
|
| 213 |
+
<div class="quiz-meta"><span class="muted">Fortschritt · <span id="quizProgressText">58%</span></span><span class="badge amber">Schwierigkeit: Anspruchsvoll</span></div>
|
| 214 |
+
<div class="progress"><span id="quizProgress" style="width:58%"></span></div>
|
| 215 |
+
<h2 class="quiz-question">Welche Aussage beschreibt den didaktischen Nutzen von Translanguaging am präzisesten?</h2>
|
| 216 |
+
<div class="answers" id="answers">
|
| 217 |
+
<button class="answer-option" data-answer="A"><span class="answer-letter">A</span><span>Es verhindert den Wechsel zwischen Unterrichtssprachen vollständig.</span></button>
|
| 218 |
+
<button class="answer-option" data-answer="B"><span class="answer-letter">B</span><span><strong>Es aktiviert das gesamte sprachliche Repertoire zur Bedeutungsbildung und fachlichen Teilhabe.</strong></span></button>
|
| 219 |
+
<button class="answer-option" data-answer="C"><span class="answer-letter">C</span><span>Es ersetzt fachsprachliche Lernziele durch alltagssprachliche Kommunikation.</span></button>
|
| 220 |
+
<button class="answer-option" data-answer="D"><span class="answer-letter">D</span><span>Es ist ausschließlich für den Fremdsprachenunterricht geeignet.</span></button>
|
| 221 |
+
</div>
|
| 222 |
+
<div class="explanation" id="quizExplanation" hidden><h3 id="answerState">Richtig beantwortet</h3><p>Translanguaging nutzt vorhandene sprachliche Ressourcen gezielt als Brücke zum fachlichen Verstehen. Die Zielsprache bleibt wichtig, wird aber nicht als isoliertes System behandelt.</p><div class="source-citation">Quelle: Mehrsprachigkeitsdidaktik_Woche_7.pdf · Folie 14<br>„Dynamische Nutzung des gesamten sprachlichen Repertoires zur Bedeutungskonstruktion.“</div><div class="row" style="justify-content:space-between;margin-top:14px"><small class="muted" id="chosenAnswer"></small><button class="button primary" id="nextQuestion">Nächste Frage →</button></div></div>
|
| 223 |
+
</div>`, '<span class="more">...</span>', "quiz-card")}
|
| 224 |
+
<div class="stack">
|
| 225 |
+
${panel("Simulationsstatus", `<div class="panel-body"><div class="stats-grid"><div class="stat"><strong id="correctCount">5</strong><small>richtig</small></div><div class="stat"><strong id="wrongCount">1</strong><small>falsch</small></div><div class="stat"><strong id="hitRate">82%</strong><small>Trefferquote</small></div><div class="stat"><strong id="timer">06:42</strong><small>verbleibend</small></div></div></div>`)}
|
| 226 |
+
${panel("Schwierigkeit", `<div class="panel-body"><div class="difficulty"><button data-level="Adaptiv">Adaptiv</button><button data-level="Mittel">Mittel</button><button class="active" data-level="Anspruchsvoll">Anspruchsvoll</button></div><p class="muted" style="font-size:11px">Die nächsten Fragen gewichten deine Wissenslücken stärker.</p></div>`)}
|
| 227 |
+
${panel("Prüfungsfokus", `<div class="panel-body"><div class="focus-list"><div><span class="badge red">Lücke</span> Interlanguage</div><div><span class="badge amber">Prüfen</span> Scaffolding</div><div><span class="badge green">Sicher</span> Translanguaging</div></div><div class="divider" style="margin:14px 0"></div><small class="muted">12 Fragen · 15 Minuten<br>Nur aus 3 ausgewählten lokalen Quellen</small></div>`)}
|
| 228 |
+
</div>
|
| 229 |
+
</div>`;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
function learningPlanPage() {
|
| 233 |
+
return pageHead("Mein Lernplan", "Ein realistischer Plan, der zu Josephines Woche passt.", `
|
| 234 |
+
<button class="button secondary" data-route="calendar">Kalender ansehen</button>
|
| 235 |
+
<button class="button primary" data-route="canvas">Lernblock starten</button>
|
| 236 |
+
`) + `
|
| 237 |
+
<div class="quiet-page">
|
| 238 |
+
<section class="plan-intro">
|
| 239 |
+
<span class="eyebrow">Prüfung in 8 Tagen</span>
|
| 240 |
+
<h2>Diese Woche zählt Beständigkeit,<br>nicht Perfektion.</h2>
|
| 241 |
+
<p>StudyFlow verbindet deine Termine, Materialien und offenen Themen zu kleinen, machbaren Schritten.</p>
|
| 242 |
+
</section>
|
| 243 |
+
<div class="plan-days">
|
| 244 |
+
<button data-route="canvas"><time>Heute</time><strong>Grundlagen wiederholen</strong><span>Mehrsprachigkeitsdidaktik · 75 Min.</span></button>
|
| 245 |
+
<button data-route="flashcards"><time>Morgen</time><strong>Scaffolding vertiefen</strong><span>Folien, Notizen und 12 Karten · 60 Min.</span></button>
|
| 246 |
+
<button data-route="quiz"><time>Donnerstag</time><strong>Formative Bewertung üben</strong><span>Quiz und Reflexion · 45 Min.</span></button>
|
| 247 |
+
<button data-route="gaps"><time>Freitag</time><strong>Wissenslücken schließen</strong><span>Selbstwirksamkeit und Interlanguage · 60 Min.</span></button>
|
| 248 |
+
</div>
|
| 249 |
+
</div>`;
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
function gapsPage() {
|
| 253 |
+
return pageHead("Wissenslücken", "Was noch unsicher ist, wird hier verständlich und machbar.", `
|
| 254 |
+
<button class="button primary" data-route="quiz">Kurzes Quiz starten</button>
|
| 255 |
+
`) + `
|
| 256 |
+
<div class="quiet-page two-column">
|
| 257 |
+
<section class="focus-story">
|
| 258 |
+
<span class="eyebrow">Heute empfohlen</span>
|
| 259 |
+
<h2>Selbstwirksamkeit verstehen</h2>
|
| 260 |
+
<p>In deinen Notizen fehlt noch die Verbindung zwischen Selbstwirksamkeit, Motivation und Lernerfolg.</p>
|
| 261 |
+
<button class="button primary" data-route="canvas">Mit Quellen erklären</button>
|
| 262 |
+
</section>
|
| 263 |
+
<section class="calm-list">
|
| 264 |
+
<button data-route="canvas"><span class="signal red"></span><span><strong>Interlanguage</strong><small>Nur indirekt in drei Quellen erklärt</small></span><em>Hoch</em></button>
|
| 265 |
+
<button data-route="flashcards"><span class="signal amber"></span><span><strong>Scaffolding</strong><small>Zwei unsichere Karten</small></span><em>Mittel</em></button>
|
| 266 |
+
<button data-route="canvas"><span class="signal green"></span><span><strong>Translanguaging</strong><small>Quellenlage vollständig</small></span><em>Sicher</em></button>
|
| 267 |
+
</section>
|
| 268 |
+
</div>`;
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
function remindersPage() {
|
| 272 |
+
return pageHead("Erinnerungen", "Freundliche Hinweise, damit Wichtiges nicht im Alltag untergeht.", `
|
| 273 |
+
<button class="button primary" id="newReminder">Erinnerung hinzufügen</button>
|
| 274 |
+
`) + `
|
| 275 |
+
<div class="quiet-page reminders-page">
|
| 276 |
+
<section class="reminder-date"><span>Heute</span><strong>7. Juni</strong><p>Du hast einen ruhigen Abend ohne Studienfrist.</p></section>
|
| 277 |
+
<section class="calm-list">
|
| 278 |
+
<button data-route="calendar"><span class="important-icon"><i class="ph ph-file-text"></i></span><span><strong>Reflexionsbericht Mehrsprachigkeit</strong><small>Freitag, 10. Juni · 23:59</small></span><em>In 3 Tagen</em></button>
|
| 279 |
+
<button data-route="calendar"><span class="important-icon"><i class="ph ph-presentation-chart"></i></span><span><strong>Französische Präsentation</strong><small>Montag, 13. Juni · 10:00</small></span><em>In 6 Tagen</em></button>
|
| 280 |
+
<button data-route="learning-plan"><span class="important-icon"><i class="ph ph-book-open"></i></span><span><strong>Bildungspsychologie wiederholen</strong><small>Morgen · 15:00</small></span><em>Geplant</em></button>
|
| 281 |
+
</section>
|
| 282 |
+
</div>`;
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
const renderers = {
|
| 286 |
+
overview: overviewPage,
|
| 287 |
+
uploads: uploadsPage,
|
| 288 |
+
canvas: canvasPage,
|
| 289 |
+
calendar: calendarPage,
|
| 290 |
+
"learning-plan": learningPlanPage,
|
| 291 |
+
gaps: gapsPage,
|
| 292 |
+
flashcards: flashcardsPage,
|
| 293 |
+
quiz: quizPage,
|
| 294 |
+
reminders: remindersPage
|
| 295 |
+
};
|
| 296 |
+
|
| 297 |
+
function normalizeRoute() {
|
| 298 |
+
const route = location.hash.replace("#/", "").replace("#", "");
|
| 299 |
+
return routes.includes(route) ? route : "overview";
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
function navigate(route) {
|
| 303 |
+
if (!routes.includes(route)) return;
|
| 304 |
+
if (location.hash !== `#/${route}`) location.hash = `#/${route}`;
|
| 305 |
+
else render();
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
function render() {
|
| 309 |
+
const route = normalizeRoute();
|
| 310 |
+
app.innerHTML = renderers[route]();
|
| 311 |
+
navList.querySelectorAll("[data-route]").forEach(btn => btn.classList.toggle("active", btn.dataset.route === route));
|
| 312 |
+
document.title = `${route === "overview" ? "Heute" : app.querySelector("h1")?.textContent || "StudyFlow"} · StudyFlow AI`;
|
| 313 |
+
closeMenu();
|
| 314 |
+
app.focus({ preventScroll: true });
|
| 315 |
+
bindPage(route);
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
function bindPage(route) {
|
| 319 |
+
app.querySelectorAll("[data-route]").forEach(el => el.addEventListener("click", () => navigate(el.dataset.route)));
|
| 320 |
+
if (route === "uploads") bindUploads();
|
| 321 |
+
if (route === "canvas") bindCanvas();
|
| 322 |
+
if (route === "calendar") bindCalendar();
|
| 323 |
+
if (route === "flashcards") bindFlashcards();
|
| 324 |
+
if (route === "quiz") bindQuiz();
|
| 325 |
+
if (route === "reminders") {
|
| 326 |
+
document.querySelector("#newReminder")?.addEventListener("click", () => showToast("Neue Erinnerung wird lokal angelegt."));
|
| 327 |
+
}
|
| 328 |
+
app.querySelector("[data-action='open-plan']")?.addEventListener("click", () => navigate("calendar"));
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
function bindUploads() {
|
| 332 |
+
const dropzone = document.querySelector("#dropzone");
|
| 333 |
+
["dragenter", "dragover"].forEach(type => dropzone.addEventListener(type, event => { event.preventDefault(); dropzone.classList.add("drag"); }));
|
| 334 |
+
["dragleave", "drop"].forEach(type => dropzone.addEventListener(type, event => { event.preventDefault(); dropzone.classList.remove("drag"); }));
|
| 335 |
+
dropzone.addEventListener("drop", () => showToast("Datei zur lokalen Queue hinzugefügt."));
|
| 336 |
+
document.querySelector("#addFiles").addEventListener("click", () => showToast("Dateiauswahl geöffnet. Demo bleibt lokal."));
|
| 337 |
+
document.querySelector("#reviewAll").addEventListener("click", () => {
|
| 338 |
+
document.querySelector("#ocrText").focus();
|
| 339 |
+
showToast("7 unsichere Stellen sind zur Prüfung markiert.");
|
| 340 |
+
});
|
| 341 |
+
document.querySelector("#saveOcr").addEventListener("click", () => showToast("OCR-Text lokal gespeichert und verknüpft."));
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
function bindCanvas() {
|
| 345 |
+
const mainSlide = document.querySelector("#mainSlide");
|
| 346 |
+
const slideAssets = [assets.recent[0], assets.recent[1], assets.slide, assets.recent[2], assets.recent[3]];
|
| 347 |
+
document.querySelectorAll(".slide-thumb").forEach(button => button.addEventListener("click", () => {
|
| 348 |
+
document.querySelectorAll(".slide-thumb").forEach(item => item.classList.remove("active"));
|
| 349 |
+
button.classList.add("active");
|
| 350 |
+
mainSlide.src = slideAssets[Number(button.dataset.slide)];
|
| 351 |
+
}));
|
| 352 |
+
document.querySelector("#chatForm").addEventListener("submit", event => {
|
| 353 |
+
event.preventDefault();
|
| 354 |
+
const input = document.querySelector("#chatInput");
|
| 355 |
+
const text = input.value.trim();
|
| 356 |
+
if (!text) return;
|
| 357 |
+
const messages = document.querySelector("#messages");
|
| 358 |
+
messages.insertAdjacentHTML("beforeend", `<div class="message user">${escapeHtml(text)}</div><div class="message ai"><strong>Maya</strong><br>Ich prüfe diese Frage gegen die lokal verknüpften Folien und Notizen. Die relevanten Stellen liegen auf Folie 14 und in deiner Scaffolding-Notiz.</div>`);
|
| 359 |
+
input.value = "";
|
| 360 |
+
messages.scrollTop = messages.scrollHeight;
|
| 361 |
+
});
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
function bindCalendar() {
|
| 365 |
+
document.querySelector("#planBlock").addEventListener("click", () => showToast("Neuer Lernblock für 17:15 vorgeschlagen."));
|
| 366 |
+
document.querySelector("#reviewExtractions").addEventListener("click", () => showToast("Drei bestätigte Termine aus lokalen Quellen."));
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
function bindFlashcards() {
|
| 370 |
+
const preview = document.querySelector("#cardPreview");
|
| 371 |
+
preview.addEventListener("click", () => preview.classList.toggle("flipped"));
|
| 372 |
+
document.querySelector("#saveCard").addEventListener("click", () => showToast("Karte lokal gespeichert."));
|
| 373 |
+
document.querySelector("#deleteCard").addEventListener("click", () => showToast("Karte zur Löschung vorgemerkt."));
|
| 374 |
+
document.querySelector("#generateCards").addEventListener("click", () => showToast("6 Kartenvorschläge aus zwei Quellen erzeugt."));
|
| 375 |
+
document.querySelector("#learnCards").addEventListener("click", () => showToast("Lernsession mit 12 fälligen Karten gestartet."));
|
| 376 |
+
document.querySelectorAll("[data-export]").forEach(button => button.addEventListener("click", () => showToast(`${button.dataset.export}-Export lokal vorbereitet.`)));
|
| 377 |
+
document.querySelectorAll(".deck-row").forEach(row => row.addEventListener("click", () => {
|
| 378 |
+
document.querySelectorAll(".deck-row").forEach(item => item.classList.remove("selected"));
|
| 379 |
+
row.classList.add("selected");
|
| 380 |
+
showToast(`${row.dataset.deck} ausgewählt.`);
|
| 381 |
+
}));
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
function bindQuiz() {
|
| 385 |
+
const options = [...document.querySelectorAll(".answer-option")];
|
| 386 |
+
const explanation = document.querySelector("#quizExplanation");
|
| 387 |
+
options.forEach(option => option.addEventListener("click", () => {
|
| 388 |
+
options.forEach(item => item.classList.remove("selected", "wrong"));
|
| 389 |
+
const correct = option.dataset.answer === "B";
|
| 390 |
+
option.classList.add(correct ? "selected" : "wrong");
|
| 391 |
+
explanation.hidden = false;
|
| 392 |
+
document.querySelector("#answerState").textContent = correct ? "Richtig beantwortet" : "Noch nicht richtig";
|
| 393 |
+
document.querySelector("#answerState").style.color = correct ? "var(--emerald-dark)" : "var(--red)";
|
| 394 |
+
document.querySelector("#chosenAnswer").textContent = `Antwort gewählt · ${option.dataset.answer}`;
|
| 395 |
+
}));
|
| 396 |
+
document.querySelectorAll("[data-level]").forEach(button => button.addEventListener("click", () => {
|
| 397 |
+
document.querySelectorAll("[data-level]").forEach(item => item.classList.remove("active"));
|
| 398 |
+
button.classList.add("active");
|
| 399 |
+
showToast(`Schwierigkeit auf ${button.dataset.level} gesetzt.`);
|
| 400 |
+
}));
|
| 401 |
+
document.querySelector("#nextQuestion")?.addEventListener("click", () => {
|
| 402 |
+
document.querySelector(".panel-head h2").textContent = "Frage 8 von 12";
|
| 403 |
+
document.querySelector("#quizProgress").style.width = "67%";
|
| 404 |
+
document.querySelector("#quizProgressText").textContent = "67%";
|
| 405 |
+
showToast("Nächste Frage geladen.");
|
| 406 |
+
});
|
| 407 |
+
document.querySelector("#endQuiz").addEventListener("click", () => showToast("Simulation pausiert. Dein Stand bleibt lokal gespeichert."));
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
function showToast(message) {
|
| 411 |
+
toast.textContent = message;
|
| 412 |
+
toast.classList.add("show");
|
| 413 |
+
clearTimeout(showToast.timer);
|
| 414 |
+
showToast.timer = setTimeout(() => toast.classList.remove("show"), 2600);
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
function escapeHtml(value) {
|
| 418 |
+
return value.replace(/[&<>"']/g, char => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[char]));
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
const sidebar = document.querySelector("#sidebar");
|
| 422 |
+
const scrim = document.querySelector("#scrim");
|
| 423 |
+
const menuButton = document.querySelector("#menuButton");
|
| 424 |
+
function closeMenu() {
|
| 425 |
+
sidebar.classList.remove("open");
|
| 426 |
+
scrim.classList.remove("show");
|
| 427 |
+
menuButton.setAttribute("aria-expanded", "false");
|
| 428 |
+
}
|
| 429 |
+
menuButton.addEventListener("click", () => {
|
| 430 |
+
const open = sidebar.classList.toggle("open");
|
| 431 |
+
scrim.classList.toggle("show", open);
|
| 432 |
+
menuButton.setAttribute("aria-expanded", String(open));
|
| 433 |
+
});
|
| 434 |
+
scrim.addEventListener("click", closeMenu);
|
| 435 |
+
navList.addEventListener("click", event => {
|
| 436 |
+
const button = event.target.closest("[data-route]");
|
| 437 |
+
if (button) navigate(button.dataset.route);
|
| 438 |
+
});
|
| 439 |
+
|
| 440 |
+
document.querySelector("#askButton").addEventListener("click", () => document.querySelector("#aiDialog").showModal());
|
| 441 |
+
document.querySelector("#aiSubmit").addEventListener("click", () => {
|
| 442 |
+
const prompt = document.querySelector("#aiPrompt").value.trim();
|
| 443 |
+
showToast(prompt ? "Lokale Antwort wird aus 12 Materialien erzeugt." : "Bitte gib zuerst eine Frage ein.");
|
| 444 |
+
});
|
| 445 |
+
document.querySelector("#globalSearch").addEventListener("keydown", event => {
|
| 446 |
+
if (event.key === "Enter" && event.currentTarget.value.trim()) showToast(`Lokale Suche nach „${event.currentTarget.value.trim()}“`);
|
| 447 |
+
});
|
| 448 |
+
document.addEventListener("keydown", event => {
|
| 449 |
+
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
|
| 450 |
+
event.preventDefault();
|
| 451 |
+
document.querySelector("#globalSearch").focus();
|
| 452 |
+
}
|
| 453 |
+
if (event.key === "Escape") closeMenu();
|
| 454 |
+
});
|
| 455 |
+
window.addEventListener("hashchange", render);
|
| 456 |
+
render();
|
assets/hero/josephine-mainz-morning.png
ADDED
|
Git LFS Details
|
assets/materials/mq3zhq9n-clipboard.png
ADDED
|
Git LFS Details
|
assets/materials/mq3zhqat-clipboard.png
ADDED
|
Git LFS Details
|
assets/materials/mq3zhqbu-clipboard.png
ADDED
|
Git LFS Details
|
assets/materials/mq3zhqdk-clipboard.png
ADDED
|
assets/materials/mq3zhqe0-clipboard.png
ADDED
|
assets/materials/mq3zhqe3-clipboard.png
ADDED
|
assets/materials/mq3zhqea-clipboard.png
ADDED
|
assets/materials/mq3zhqeg-clipboard.png
ADDED
|
index.html
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="de">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
+
<meta name="color-scheme" content="light">
|
| 7 |
+
<title>StudyFlow AI</title>
|
| 8 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 9 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 10 |
+
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600&family=DM+Sans:wght@400;500;600&display=swap" rel="stylesheet">
|
| 11 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.1/src/regular/style.css">
|
| 12 |
+
<link rel="stylesheet" href="styles.css">
|
| 13 |
+
</head>
|
| 14 |
+
<body>
|
| 15 |
+
<div class="app-shell">
|
| 16 |
+
<aside class="sidebar" id="sidebar" aria-label="Hauptnavigation">
|
| 17 |
+
<div class="brand">
|
| 18 |
+
<span class="brand-mark" aria-hidden="true"><i class="ph ph-feather"></i></span>
|
| 19 |
+
<span class="brand-name">StudyFlow AI</span>
|
| 20 |
+
</div>
|
| 21 |
+
|
| 22 |
+
<div class="profile">
|
| 23 |
+
<span class="avatar">JW</span>
|
| 24 |
+
<span><strong>Josephine Wendland</strong><small>Lehramt · Mainz</small></span>
|
| 25 |
+
<button class="icon-button" aria-label="Profil öffnen"><i class="ph ph-caret-down"></i></button>
|
| 26 |
+
</div>
|
| 27 |
+
|
| 28 |
+
<nav class="nav-list" id="navList">
|
| 29 |
+
<button data-route="overview"><i class="ph ph-house"></i>Heute</button>
|
| 30 |
+
<button data-route="uploads"><i class="ph ph-folder"></i>Materialien</button>
|
| 31 |
+
<button data-route="canvas"><i class="ph ph-chalkboard-teacher"></i>Arbeitsfläche</button>
|
| 32 |
+
<button data-route="calendar"><i class="ph ph-calendar-blank"></i>Kalender</button>
|
| 33 |
+
<button data-route="learning-plan"><i class="ph ph-book-open"></i>Lernplan</button>
|
| 34 |
+
<button data-route="gaps"><i class="ph ph-target"></i>Wissenslücken</button>
|
| 35 |
+
<button data-route="flashcards"><i class="ph ph-cards"></i>Karten</button>
|
| 36 |
+
<button data-route="quiz"><i class="ph ph-question"></i>Quiz</button>
|
| 37 |
+
<button data-route="reminders"><i class="ph ph-heart"></i>Erinnerungen</button>
|
| 38 |
+
</nav>
|
| 39 |
+
|
| 40 |
+
<div class="local-status">
|
| 41 |
+
<strong><span class="status-dot"></span>Lokale Verarbeitung aktiv</strong>
|
| 42 |
+
<span>Deine Daten bleiben auf diesem Gerät.</span>
|
| 43 |
+
</div>
|
| 44 |
+
</aside>
|
| 45 |
+
|
| 46 |
+
<div class="app-main">
|
| 47 |
+
<header class="topbar">
|
| 48 |
+
<button class="menu-button" id="menuButton" aria-label="Navigation öffnen" aria-expanded="false">☰</button>
|
| 49 |
+
<span class="today">Dienstag, 7. Juni · Mainz</span>
|
| 50 |
+
<label class="global-search">
|
| 51 |
+
<span aria-hidden="true">⌕</span>
|
| 52 |
+
<input id="globalSearch" type="search" placeholder="Material, Kurs oder Begriff suchen">
|
| 53 |
+
<kbd>⌘ K</kbd>
|
| 54 |
+
</label>
|
| 55 |
+
<button class="ask-button" id="askButton"><i class="ph ph-sparkle"></i> KI fragen</button>
|
| 56 |
+
<button class="icon-button notification" aria-label="Benachrichtigungen"><i class="ph ph-bell"></i><span>3</span></button>
|
| 57 |
+
<span class="user-label">Josephine Wendland · Lehramt</span>
|
| 58 |
+
</header>
|
| 59 |
+
<main id="app" tabindex="-1"></main>
|
| 60 |
+
</div>
|
| 61 |
+
</div>
|
| 62 |
+
|
| 63 |
+
<div class="scrim" id="scrim"></div>
|
| 64 |
+
<div class="toast" id="toast" role="status" aria-live="polite"></div>
|
| 65 |
+
|
| 66 |
+
<dialog id="aiDialog">
|
| 67 |
+
<form method="dialog" class="dialog-card">
|
| 68 |
+
<div class="dialog-head">
|
| 69 |
+
<div><small>Lokaler KI-Copilot</small><h2>Frage an deine Materialien</h2></div>
|
| 70 |
+
<button class="icon-button" value="cancel" aria-label="Schließen">×</button>
|
| 71 |
+
</div>
|
| 72 |
+
<label>Deine Frage<textarea id="aiPrompt" rows="4" placeholder="Zum Beispiel: Erkläre den Unterschied zwischen Translanguaging und Code-Switching."></textarea></label>
|
| 73 |
+
<p class="trust-note">Die Antwort wird ausschließlich aus deinen lokalen Quellen erzeugt.</p>
|
| 74 |
+
<div class="dialog-actions">
|
| 75 |
+
<button class="button secondary" value="cancel">Abbrechen</button>
|
| 76 |
+
<button class="button primary" id="aiSubmit" value="cancel">Antwort erzeugen</button>
|
| 77 |
+
</div>
|
| 78 |
+
</form>
|
| 79 |
+
</dialog>
|
| 80 |
+
|
| 81 |
+
<script src="app.js"></script>
|
| 82 |
+
</body>
|
| 83 |
+
</html>
|
styles.css
ADDED
|
@@ -0,0 +1,656 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:root {
|
| 2 |
+
--sidebar: #071f29;
|
| 3 |
+
--sidebar-2: #0a2b34;
|
| 4 |
+
--paper: #fbfcfa;
|
| 5 |
+
--surface: #ffffff;
|
| 6 |
+
--ink: #102126;
|
| 7 |
+
--muted: #647278;
|
| 8 |
+
--line: #d9e0dd;
|
| 9 |
+
--line-soft: #e9eeeb;
|
| 10 |
+
--emerald: #0c9656;
|
| 11 |
+
--emerald-dark: #086a42;
|
| 12 |
+
--emerald-soft: #eaf6ef;
|
| 13 |
+
--blue: #2369b3;
|
| 14 |
+
--blue-soft: #edf5ff;
|
| 15 |
+
--amber: #b56700;
|
| 16 |
+
--amber-soft: #fff6e5;
|
| 17 |
+
--red: #bb3e36;
|
| 18 |
+
--red-soft: #fff0ee;
|
| 19 |
+
--radius: 7px;
|
| 20 |
+
--serif: Georgia, "Times New Roman", serif;
|
| 21 |
+
--sans: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
|
| 22 |
+
--mono: "Cascadia Mono", Consolas, monospace;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
* { box-sizing: border-box; }
|
| 26 |
+
html, body { margin: 0; min-height: 100%; background: var(--paper); color: var(--ink); font-family: var(--sans); }
|
| 27 |
+
body { font-size: 14px; }
|
| 28 |
+
button, input, textarea, select { font: inherit; }
|
| 29 |
+
button { color: inherit; }
|
| 30 |
+
button:focus-visible, input:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
|
| 31 |
+
outline: 2px solid color-mix(in srgb, var(--emerald) 75%, white);
|
| 32 |
+
outline-offset: 2px;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.app-shell { min-height: 100dvh; display: grid; grid-template-columns: 218px minmax(0, 1fr); }
|
| 36 |
+
.sidebar {
|
| 37 |
+
position: sticky; top: 0; height: 100dvh; padding: 20px 14px 17px; background: var(--sidebar);
|
| 38 |
+
color: #eef6f3; display: flex; flex-direction: column; overflow-y: auto; z-index: 20;
|
| 39 |
+
}
|
| 40 |
+
.brand { display: flex; align-items: center; gap: 10px; padding: 4px 7px 18px; }
|
| 41 |
+
.brand-mark {
|
| 42 |
+
display: grid; place-items: center; width: 31px; height: 35px; color: white; font-size: 22px; font-weight: 800;
|
| 43 |
+
background: linear-gradient(145deg, #18aa70, #087044); clip-path: polygon(50% 0,100% 25%,78% 42%,100% 60%,50% 100%,0 75%,22% 57%,0 40%);
|
| 44 |
+
}
|
| 45 |
+
.brand-name { font-size: 20px; letter-spacing: -.02em; white-space: nowrap; }
|
| 46 |
+
.brand-name b { color: #38c782; }
|
| 47 |
+
.profile {
|
| 48 |
+
display: grid; grid-template-columns: 34px minmax(0,1fr) 24px; gap: 9px; align-items: center;
|
| 49 |
+
padding: 10px; margin-bottom: 15px; border: 1px solid #28434a; border-radius: var(--radius); background: #0b2a34;
|
| 50 |
+
}
|
| 51 |
+
.avatar { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--emerald); font-weight: 700; }
|
| 52 |
+
.profile strong, .profile small { display: block; }
|
| 53 |
+
.profile strong { font-size: 12px; }
|
| 54 |
+
.profile small { color: #a7bbb9; font-size: 10px; margin-top: 3px; }
|
| 55 |
+
.icon-button { border: 0; background: transparent; min-width: 32px; min-height: 32px; cursor: pointer; border-radius: 6px; }
|
| 56 |
+
.icon-button:hover { background: rgba(255,255,255,.08); }
|
| 57 |
+
.nav-list { display: grid; gap: 5px; }
|
| 58 |
+
.nav-list button, .course-list button {
|
| 59 |
+
width: 100%; border: 0; background: transparent; color: #eef6f3; text-align: left; cursor: pointer;
|
| 60 |
+
}
|
| 61 |
+
.nav-list button {
|
| 62 |
+
min-height: 44px; display: flex; align-items: center; gap: 12px; padding: 9px 12px; border-radius: var(--radius);
|
| 63 |
+
transition: background .16s ease, transform .16s ease;
|
| 64 |
+
}
|
| 65 |
+
.nav-list button:hover { background: rgba(255,255,255,.07); }
|
| 66 |
+
.nav-list button:active { transform: translateY(1px); }
|
| 67 |
+
.nav-list button.active { background: #176b4d; }
|
| 68 |
+
.nav-icon { width: 20px; text-align: center; font-family: var(--mono); font-size: 17px; }
|
| 69 |
+
.course-list { padding: 21px 8px 12px; border-top: 1px solid #28434a; margin-top: 18px; }
|
| 70 |
+
.course-list p { margin: 0 0 8px; color: #93aaa9; font: 10px/1 var(--mono); text-transform: uppercase; letter-spacing: .08em; }
|
| 71 |
+
.course-list button { padding: 5px 0; font-size: 11px; color: #bdd0ce; }
|
| 72 |
+
.course-list button:hover { color: white; }
|
| 73 |
+
.local-status {
|
| 74 |
+
margin-top: auto; padding: 12px; border: 1px solid #16805a; border-radius: var(--radius); background: #092c2b;
|
| 75 |
+
display: grid; gap: 6px; font-size: 10px; line-height: 1.35;
|
| 76 |
+
}
|
| 77 |
+
.local-status strong { font-size: 12px; }
|
| 78 |
+
.status-dot { display: inline-block; width: 8px; height: 8px; margin-right: 7px; border-radius: 50%; background: #55d68d; }
|
| 79 |
+
|
| 80 |
+
.app-main { min-width: 0; }
|
| 81 |
+
.topbar {
|
| 82 |
+
height: 64px; position: sticky; top: 0; z-index: 15; padding: 0 26px; display: grid;
|
| 83 |
+
grid-template-columns: max-content minmax(260px, 480px) max-content max-content max-content;
|
| 84 |
+
justify-content: end; align-items: center; gap: 12px; border-bottom: 1px solid var(--line); background: rgba(251,252,250,.97);
|
| 85 |
+
}
|
| 86 |
+
.today { margin-right: auto; font-size: 12px; color: var(--muted); }
|
| 87 |
+
.global-search {
|
| 88 |
+
height: 40px; display: flex; align-items: center; gap: 8px; padding: 0 10px; border: 1px solid var(--line);
|
| 89 |
+
border-radius: var(--radius); background: white; color: var(--muted);
|
| 90 |
+
}
|
| 91 |
+
.global-search input { min-width: 0; width: 100%; border: 0; outline: 0; background: transparent; color: var(--ink); }
|
| 92 |
+
kbd { padding: 2px 6px; border-radius: 4px; background: #f0f3f1; font: 10px var(--mono); color: var(--muted); }
|
| 93 |
+
.ask-button, .button {
|
| 94 |
+
min-height: 40px; padding: 8px 15px; border: 1px solid var(--line); border-radius: var(--radius); background: white; cursor: pointer;
|
| 95 |
+
}
|
| 96 |
+
.ask-button { color: var(--emerald-dark); border-color: #a8d6bf; font-weight: 600; }
|
| 97 |
+
.button:hover, .ask-button:hover { border-color: #9dafaa; background: #f7faf8; }
|
| 98 |
+
.button:active, .ask-button:active { transform: translateY(1px); }
|
| 99 |
+
.button.primary { border-color: var(--emerald-dark); background: var(--emerald-dark); color: white; }
|
| 100 |
+
.button.primary:hover { background: #075838; }
|
| 101 |
+
.button.danger { border-color: #e6aca8; color: var(--red); background: var(--red-soft); }
|
| 102 |
+
.notification { position: relative; }
|
| 103 |
+
.notification span { position: absolute; right: -1px; top: 0; display: grid; place-items: center; width: 16px; height: 16px; background: var(--emerald-dark); color: white; font-size: 9px; border-radius: 50%; }
|
| 104 |
+
.user-label { font-size: 12px; color: var(--muted); white-space: nowrap; }
|
| 105 |
+
.menu-button { display: none; border: 0; background: transparent; font-size: 20px; }
|
| 106 |
+
|
| 107 |
+
main { padding: 17px 26px 28px; min-height: calc(100dvh - 64px); }
|
| 108 |
+
.page-head { display: flex; align-items: end; justify-content: space-between; gap: 20px; margin-bottom: 13px; }
|
| 109 |
+
.page-head h1 { margin: 0; font: 400 clamp(31px, 2.65vw, 43px)/1 var(--serif); letter-spacing: -.025em; }
|
| 110 |
+
.page-head p { margin: 7px 0 0; color: var(--muted); font-size: 13px; }
|
| 111 |
+
.head-actions { display: flex; gap: 8px; }
|
| 112 |
+
.panel {
|
| 113 |
+
border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; min-width: 0;
|
| 114 |
+
}
|
| 115 |
+
.panel-head {
|
| 116 |
+
min-height: 47px; padding: 10px 14px; display: flex; align-items: center; justify-content: space-between; gap: 12px;
|
| 117 |
+
border-bottom: 1px solid var(--line);
|
| 118 |
+
}
|
| 119 |
+
.panel-head h2, .panel-head h3 { margin: 0; font: 400 20px/1.1 var(--serif); }
|
| 120 |
+
.panel-head h3 { font-size: 17px; }
|
| 121 |
+
.panel-body { padding: 14px; }
|
| 122 |
+
.muted { color: var(--muted); }
|
| 123 |
+
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
|
| 124 |
+
.label { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
|
| 125 |
+
.badge {
|
| 126 |
+
display: inline-flex; align-items: center; min-height: 24px; padding: 3px 8px; border: 1px solid var(--line);
|
| 127 |
+
border-radius: 5px; background: #f7faf8; font-size: 10px; white-space: nowrap;
|
| 128 |
+
}
|
| 129 |
+
.badge.green { border-color: #bad8c8; color: #09603d; background: var(--emerald-soft); }
|
| 130 |
+
.badge.blue { border-color: #b8d3ee; color: #145992; background: var(--blue-soft); }
|
| 131 |
+
.badge.amber { border-color: #efc67d; color: var(--amber); background: var(--amber-soft); }
|
| 132 |
+
.badge.red { border-color: #efb3ae; color: var(--red); background: var(--red-soft); }
|
| 133 |
+
.progress { height: 6px; border-radius: 5px; background: #e6ece9; overflow: hidden; }
|
| 134 |
+
.progress > span { display: block; height: 100%; background: var(--emerald-dark); border-radius: inherit; }
|
| 135 |
+
.row { display: flex; align-items: center; gap: 10px; }
|
| 136 |
+
.stack { display: grid; gap: 10px; }
|
| 137 |
+
.divider { height: 1px; background: var(--line); }
|
| 138 |
+
.more { font-weight: 700; letter-spacing: .15em; }
|
| 139 |
+
.empty-note { padding: 28px; text-align: center; color: var(--muted); }
|
| 140 |
+
|
| 141 |
+
/* Overview */
|
| 142 |
+
.overview-grid { display: grid; grid-template-columns: minmax(0,1.55fr) minmax(270px,.82fr) minmax(250px,.72fr); gap: 14px; }
|
| 143 |
+
.briefing { grid-row: span 2; }
|
| 144 |
+
.briefing-intro { padding: 17px; border-bottom: 1px solid var(--line); background: #fcfdfb; }
|
| 145 |
+
.briefing-intro strong { display: block; font: 400 24px var(--serif); margin-bottom: 5px; }
|
| 146 |
+
.agenda-list { display: grid; }
|
| 147 |
+
.agenda-item { display: grid; grid-template-columns: 48px 8px minmax(0,1fr) max-content; gap: 10px; padding: 13px 16px; border-bottom: 1px solid var(--line-soft); align-items: start; }
|
| 148 |
+
.agenda-item:last-child { border-bottom: 0; }
|
| 149 |
+
.agenda-item time { font: 11px var(--mono); color: var(--muted); }
|
| 150 |
+
.agenda-item i { width: 7px; height: 7px; margin-top: 3px; border-radius: 50%; background: var(--emerald); }
|
| 151 |
+
.agenda-item.blue i { background: var(--blue); }
|
| 152 |
+
.agenda-item.amber i { background: #d48a18; }
|
| 153 |
+
.agenda-item strong { display: block; margin-bottom: 4px; font-size: 13px; }
|
| 154 |
+
.agenda-item small { color: var(--muted); }
|
| 155 |
+
.metric-list { display: grid; gap: 13px; }
|
| 156 |
+
.metric-line { display: grid; grid-template-columns: minmax(0,1fr) 38px; gap: 7px; }
|
| 157 |
+
.metric-line .progress { grid-column: 1 / -1; }
|
| 158 |
+
.source-list, .gap-list, .activity-list { display: grid; }
|
| 159 |
+
.source-row, .gap-row, .activity-row { padding: 11px 14px; border-bottom: 1px solid var(--line-soft); }
|
| 160 |
+
.source-row:last-child, .gap-row:last-child, .activity-row:last-child { border-bottom: 0; }
|
| 161 |
+
.source-row { display: grid; grid-template-columns: 38px minmax(0,1fr) max-content; gap: 10px; align-items: center; }
|
| 162 |
+
.thumb {
|
| 163 |
+
width: 38px; height: 38px; object-fit: cover; border: 1px solid var(--line); border-radius: 5px; background: #f1f3f2;
|
| 164 |
+
}
|
| 165 |
+
.source-row strong, .source-row small { display: block; }
|
| 166 |
+
.source-row strong { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
| 167 |
+
.source-row small { font-size: 10px; color: var(--muted); margin-top: 3px; }
|
| 168 |
+
.gap-row { display: grid; grid-template-columns: minmax(0,1fr) max-content; gap: 8px; }
|
| 169 |
+
.gap-row strong { font-size: 12px; }
|
| 170 |
+
.gap-row small { display: block; margin-top: 4px; color: var(--muted); font-size: 10px; }
|
| 171 |
+
.roadmap-mini { display: grid; grid-template-columns: 76px repeat(8,1fr); gap: 4px; font-size: 9px; align-items: center; }
|
| 172 |
+
.roadmap-mini span { height: 20px; border-radius: 3px; background: #eef2f0; }
|
| 173 |
+
.roadmap-mini span.on { background: #cfe8d9; border: 1px solid #9dc9af; }
|
| 174 |
+
.roadmap-mini span.info { background: #d9e8f7; border: 1px solid #b3cee8; }
|
| 175 |
+
.roadmap-mini span.warn { background: #ffedc8; border: 1px solid #ecc77d; }
|
| 176 |
+
.roadmap-mini b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
| 177 |
+
.trust-inline { margin-top: 12px; padding: 10px; border: 1px solid #b7daca; border-radius: var(--radius); background: var(--emerald-soft); color: #0b6441; font-size: 11px; }
|
| 178 |
+
|
| 179 |
+
/* Uploads */
|
| 180 |
+
.uploads-grid { display: grid; grid-template-columns: 280px minmax(430px, 1.4fr) 320px; gap: 10px; }
|
| 181 |
+
.upload-queue { min-height: 720px; }
|
| 182 |
+
.queue-item { padding: 13px; border-bottom: 1px solid var(--line-soft); }
|
| 183 |
+
.queue-title { display: flex; justify-content: space-between; gap: 8px; font-size: 11px; }
|
| 184 |
+
.queue-title strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
| 185 |
+
.queue-item .progress { margin: 9px 0 7px; }
|
| 186 |
+
.queue-item small { color: var(--muted); }
|
| 187 |
+
.queue-item.selected { background: #f2f8f5; box-shadow: inset 3px 0 var(--emerald); }
|
| 188 |
+
.dropzone { margin: 13px; padding: 18px; border: 1px dashed #a9b9b2; border-radius: var(--radius); text-align: center; background: #fafcfb; }
|
| 189 |
+
.dropzone.drag { border-color: var(--emerald); background: var(--emerald-soft); }
|
| 190 |
+
.doc-review { display: grid; grid-template-columns: 1fr .86fr; min-height: 720px; }
|
| 191 |
+
.doc-pane { padding: 12px; background: #f2f3f1; border-right: 1px solid var(--line); }
|
| 192 |
+
.doc-toolbar { display: flex; gap: 7px; align-items: center; padding-bottom: 10px; font-size: 11px; }
|
| 193 |
+
.document-page { height: 635px; padding: 25px 22px; background: white; border: 1px solid #bac3bf; box-shadow: 0 3px 8px rgba(12,31,37,.08); overflow: hidden; }
|
| 194 |
+
.document-page img { width: 100%; height: 100%; object-fit: contain; }
|
| 195 |
+
.note-pane { background: #f5f3ee; overflow: hidden; }
|
| 196 |
+
.note-pane img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
|
| 197 |
+
.ocr-panel textarea {
|
| 198 |
+
width: 100%; min-height: 425px; padding: 11px; border: 1px solid var(--line); border-radius: var(--radius);
|
| 199 |
+
resize: vertical; font: 11px/1.65 var(--mono); color: #27363a; background: white;
|
| 200 |
+
}
|
| 201 |
+
.language-tabs { display: flex; gap: 7px; flex-wrap: wrap; margin: 9px 0 15px; }
|
| 202 |
+
.ocr-actions { display: grid; grid-template-columns: .7fr 1.3fr; gap: 8px; margin-top: 12px; }
|
| 203 |
+
.confidence { margin: 9px 0 14px; color: var(--muted); font-size: 11px; }
|
| 204 |
+
|
| 205 |
+
/* Canvas */
|
| 206 |
+
.canvas-page { margin: -17px -26px -28px; min-height: calc(100dvh - 64px); background: #f7f8f6; }
|
| 207 |
+
.canvas-head { min-height: 70px; padding: 14px 18px; display: flex; align-items: center; justify-content: space-between; gap: 18px; border-bottom: 1px solid var(--line); background: white; }
|
| 208 |
+
.canvas-head h1 { margin: 0; font: 400 32px var(--serif); }
|
| 209 |
+
.canvas-head h1 span { margin-left: 18px; font: 14px var(--serif); color: var(--muted); }
|
| 210 |
+
.canvas-grid { display: grid; grid-template-columns: minmax(360px,1.04fr) minmax(360px,.95fr) minmax(320px,.86fr); height: calc(100dvh - 134px); gap: 10px; padding: 10px; }
|
| 211 |
+
.canvas-grid .panel { display: flex; flex-direction: column; min-height: 0; }
|
| 212 |
+
.slide-workspace { display: grid; grid-template-columns: 83px minmax(0,1fr); min-height: 0; flex: 1; }
|
| 213 |
+
.slide-thumbs { padding: 8px; overflow-y: auto; background: #fafbf9; border-right: 1px solid var(--line); }
|
| 214 |
+
.slide-thumb { height: 99px; margin-bottom: 9px; border: 1px solid var(--line); border-radius: 5px; background: white; padding: 6px; overflow: hidden; }
|
| 215 |
+
.slide-thumb.active { border: 2px solid var(--emerald-dark); }
|
| 216 |
+
.slide-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
|
| 217 |
+
.slide-main { padding: 10px; background: #eef1ef; min-height: 0; }
|
| 218 |
+
.slide-main img { width: 100%; height: 100%; object-fit: contain; background: white; border: 1px solid #bcc6c1; }
|
| 219 |
+
.notes-main { min-height: 0; flex: 1; background: #f4f0e8; overflow: auto; }
|
| 220 |
+
.notes-main img { width: 100%; min-height: 100%; object-fit: cover; object-position: top; }
|
| 221 |
+
.chat { min-height: 0; display: flex; flex-direction: column; }
|
| 222 |
+
.messages { flex: 1; overflow-y: auto; padding: 14px; display: grid; align-content: start; gap: 12px; }
|
| 223 |
+
.message { max-width: 90%; padding: 11px; border: 1px solid var(--line); border-radius: var(--radius); line-height: 1.55; }
|
| 224 |
+
.message.user { justify-self: end; background: var(--emerald-soft); border-color: #bad8c8; }
|
| 225 |
+
.message.ai { background: white; }
|
| 226 |
+
.alert-card { padding: 12px; border: 1px solid #edc47f; border-radius: var(--radius); background: var(--amber-soft); line-height: 1.45; }
|
| 227 |
+
.alert-card strong { color: var(--amber); display: block; margin-bottom: 7px; }
|
| 228 |
+
.chat-compose { padding: 10px; border-top: 1px solid var(--line); display: grid; grid-template-columns: minmax(0,1fr) 40px; gap: 7px; }
|
| 229 |
+
.chat-compose input { width: 100%; border: 1px solid var(--line); border-radius: var(--radius); padding: 10px; }
|
| 230 |
+
|
| 231 |
+
/* Calendar */
|
| 232 |
+
.calendar-grid { display: grid; grid-template-columns: minmax(620px,1.75fr) minmax(290px,.8fr); gap: 14px; }
|
| 233 |
+
.week-calendar { min-height: 740px; }
|
| 234 |
+
.week-grid { padding: 12px 14px; display: grid; grid-template-columns: 50px repeat(5,1fr); grid-template-rows: 28px repeat(7,55px); position: relative; }
|
| 235 |
+
.week-grid > div { border-bottom: 1px solid var(--line-soft); border-right: 1px solid var(--line-soft); }
|
| 236 |
+
.week-grid .day { text-align: center; padding: 5px; color: var(--muted); font-size: 10px; }
|
| 237 |
+
.week-grid .time { padding-top: 7px; font: 9px var(--mono); color: var(--muted); border-right: 1px solid var(--line); }
|
| 238 |
+
.event {
|
| 239 |
+
z-index: 2; margin: 3px 6px; padding: 6px; border: 1px solid #9fcab2; border-radius: 6px; background: var(--emerald-soft);
|
| 240 |
+
font-size: 9px; line-height: 1.35; overflow: hidden;
|
| 241 |
+
}
|
| 242 |
+
.event.blue { background: var(--blue-soft); border-color: #aecce9; }
|
| 243 |
+
.event.amber { background: var(--amber-soft); border-color: #ecc57c; }
|
| 244 |
+
.roadmap { padding: 13px; border-top: 1px solid var(--line); }
|
| 245 |
+
.roadmap h3 { font: 600 17px var(--serif); margin: 0 0 12px; }
|
| 246 |
+
.roadmap-grid { display: grid; grid-template-columns: 145px repeat(8,1fr); gap: 5px; font-size: 9px; align-items: center; }
|
| 247 |
+
.roadmap-grid span { height: 25px; border-radius: 4px; background: #edf1ef; border: 1px solid #dce4df; }
|
| 248 |
+
.roadmap-grid span.on { background: #d8ebdf; border-color: #a5ceb5; }
|
| 249 |
+
.roadmap-grid span.blue { background: #dceaf7; border-color: #b7d0e7; }
|
| 250 |
+
.roadmap-grid span.amber { background: #ffedc9; border-color: #edc77e; }
|
| 251 |
+
.today-block { padding: 12px; border-left: 3px solid var(--emerald-dark); background: #f4f8f5; margin-bottom: 8px; }
|
| 252 |
+
.today-block strong, .today-block small { display: block; }
|
| 253 |
+
.today-block strong { font-size: 11px; margin-bottom: 4px; }
|
| 254 |
+
.calendar-asset { width: 100%; max-height: 260px; object-fit: cover; object-position: top; border: 1px solid var(--line); border-radius: 5px; }
|
| 255 |
+
.extraction-row { display: grid; grid-template-columns: 65px minmax(0,1fr) max-content; gap: 8px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--line-soft); font-size: 11px; }
|
| 256 |
+
|
| 257 |
+
/* Flashcards */
|
| 258 |
+
.cards-grid { display: grid; grid-template-columns: 310px minmax(450px,1fr) 300px; gap: 14px; }
|
| 259 |
+
.deck-row { padding: 14px 12px; border-bottom: 1px solid var(--line-soft); cursor: pointer; }
|
| 260 |
+
.deck-row:hover { background: #f8faf9; }
|
| 261 |
+
.deck-row.selected { background: var(--emerald-soft); }
|
| 262 |
+
.deck-row strong, .deck-row small { display: block; }
|
| 263 |
+
.deck-row small { color: var(--muted); margin: 5px 0 8px; }
|
| 264 |
+
.field { display: grid; gap: 6px; margin-bottom: 12px; }
|
| 265 |
+
.field label { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
|
| 266 |
+
.field textarea { width: 100%; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius); resize: vertical; }
|
| 267 |
+
.field.question textarea { min-height: 100px; font: 400 22px/1.25 var(--serif); }
|
| 268 |
+
.field.answer textarea { min-height: 155px; line-height: 1.55; }
|
| 269 |
+
.source-box { padding: 10px; border: 1px solid #bad2ea; border-radius: 5px; background: var(--blue-soft); color: #165b98; font-size: 11px; }
|
| 270 |
+
.evidence-strip { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 9px; }
|
| 271 |
+
.evidence-strip img { width: 100%; height: 82px; object-fit: cover; border: 1px solid var(--line); border-radius: 5px; }
|
| 272 |
+
.card-preview { min-height: 245px; padding: 26px; display: flex; flex-direction: column; justify-content: center; border: 1px solid var(--line); border-radius: 10px; background: #fdfefc; cursor: pointer; }
|
| 273 |
+
.card-preview small { color: var(--muted); text-transform: uppercase; }
|
| 274 |
+
.card-preview strong { margin: 20px 0; font: 600 23px/1.12 var(--serif); }
|
| 275 |
+
.card-preview .back { display: none; line-height: 1.55; }
|
| 276 |
+
.card-preview.flipped .front { display: none; }
|
| 277 |
+
.card-preview.flipped .back { display: block; }
|
| 278 |
+
.export-list { display: grid; gap: 8px; }
|
| 279 |
+
.export-list .button { width: 100%; }
|
| 280 |
+
|
| 281 |
+
/* Quiz */
|
| 282 |
+
.quiz-grid { display: grid; grid-template-columns: minmax(600px,1fr) 320px; gap: 14px; }
|
| 283 |
+
.quiz-card { min-height: 720px; }
|
| 284 |
+
.quiz-content { padding: 25px 34px; }
|
| 285 |
+
.quiz-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
|
| 286 |
+
.quiz-question { margin: 28px 0 21px; font: 400 clamp(25px,2.25vw,36px)/1.15 var(--serif); max-width: 900px; }
|
| 287 |
+
.answers { display: grid; gap: 9px; }
|
| 288 |
+
.answer-option {
|
| 289 |
+
width: 100%; min-height: 58px; padding: 12px 15px; display: grid; grid-template-columns: 28px minmax(0,1fr);
|
| 290 |
+
align-items: center; gap: 10px; text-align: left; border: 1px solid var(--line); border-radius: var(--radius); background: white; cursor: pointer;
|
| 291 |
+
}
|
| 292 |
+
.answer-option:hover { border-color: #91aa9e; background: #fafcfb; }
|
| 293 |
+
.answer-option.selected { border-color: var(--emerald); background: var(--emerald-soft); }
|
| 294 |
+
.answer-option.wrong { border-color: #ea9e98; background: var(--red-soft); }
|
| 295 |
+
.answer-letter { display: grid; place-items: center; width: 25px; height: 25px; border: 1px solid #bdc9c3; border-radius: 50%; font-family: var(--serif); }
|
| 296 |
+
.explanation { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
|
| 297 |
+
.explanation h3 { margin: 0 0 7px; color: var(--emerald-dark); font: 400 20px var(--serif); }
|
| 298 |
+
.source-citation { margin-top: 12px; padding: 10px; border: 1px solid #b8d0e8; border-radius: 5px; background: var(--blue-soft); color: #14558e; font-size: 11px; }
|
| 299 |
+
.stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
| 300 |
+
.stat { padding: 12px; background: #f2f5f3; border-radius: 6px; }
|
| 301 |
+
.stat strong, .stat small { display: block; }
|
| 302 |
+
.stat strong { font: 400 23px var(--serif); }
|
| 303 |
+
.stat small { margin-top: 3px; color: var(--muted); }
|
| 304 |
+
.difficulty { display: grid; grid-template-columns: repeat(3,1fr); gap: 6px; }
|
| 305 |
+
.difficulty button { min-height: 34px; border: 1px solid var(--line); border-radius: 5px; background: white; font-size: 10px; cursor: pointer; }
|
| 306 |
+
.difficulty button.active { background: var(--emerald-dark); color: white; border-color: var(--emerald-dark); }
|
| 307 |
+
.focus-list { display: grid; gap: 11px; }
|
| 308 |
+
|
| 309 |
+
.scrim { display: none; position: fixed; inset: 0; z-index: 18; background: rgba(4,19,24,.45); }
|
| 310 |
+
.toast { position: fixed; right: 24px; bottom: 24px; z-index: 50; padding: 11px 15px; border-radius: var(--radius); background: var(--sidebar); color: white; box-shadow: 0 8px 30px rgba(0,0,0,.18); opacity: 0; transform: translateY(12px); pointer-events: none; transition: .18s ease; }
|
| 311 |
+
.toast.show { opacity: 1; transform: translateY(0); }
|
| 312 |
+
dialog { border: 0; padding: 0; border-radius: 10px; width: min(560px, calc(100vw - 28px)); color: var(--ink); }
|
| 313 |
+
dialog::backdrop { background: rgba(4,19,24,.48); }
|
| 314 |
+
.dialog-card { padding: 20px; }
|
| 315 |
+
.dialog-head { display: flex; justify-content: space-between; gap: 20px; }
|
| 316 |
+
.dialog-head small { color: var(--emerald-dark); }
|
| 317 |
+
.dialog-head h2 { margin: 4px 0 18px; font: 400 27px var(--serif); }
|
| 318 |
+
.dialog-card label { display: grid; gap: 7px; font-weight: 600; }
|
| 319 |
+
.dialog-card textarea { width: 100%; padding: 11px; border: 1px solid var(--line); border-radius: var(--radius); resize: vertical; }
|
| 320 |
+
.trust-note { color: var(--muted); font-size: 11px; }
|
| 321 |
+
.dialog-actions { display: flex; justify-content: end; gap: 8px; margin-top: 18px; }
|
| 322 |
+
|
| 323 |
+
@media (max-width: 1180px) {
|
| 324 |
+
.app-shell { grid-template-columns: 196px minmax(0,1fr); }
|
| 325 |
+
.user-label, .today { display: none; }
|
| 326 |
+
.topbar { grid-template-columns: minmax(220px,1fr) max-content max-content; }
|
| 327 |
+
.overview-grid { grid-template-columns: minmax(0,1.45fr) minmax(260px,.8fr); }
|
| 328 |
+
.overview-grid > :last-child { grid-column: 1 / -1; }
|
| 329 |
+
.uploads-grid { grid-template-columns: 240px minmax(420px,1fr); }
|
| 330 |
+
.ocr-panel { grid-column: 1 / -1; }
|
| 331 |
+
.canvas-grid { grid-template-columns: 1fr 1fr; height: auto; }
|
| 332 |
+
.canvas-grid > :last-child { grid-column: 1 / -1; min-height: 580px; }
|
| 333 |
+
.calendar-grid { grid-template-columns: 1fr; }
|
| 334 |
+
.cards-grid { grid-template-columns: 250px minmax(420px,1fr); }
|
| 335 |
+
.cards-grid > :last-child { grid-column: 1 / -1; }
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
@media (max-width: 820px) {
|
| 339 |
+
.app-shell { display: block; }
|
| 340 |
+
.sidebar { position: fixed; left: 0; transform: translateX(-105%); width: 260px; transition: transform .2s ease; }
|
| 341 |
+
.sidebar.open { transform: translateX(0); }
|
| 342 |
+
.scrim.show { display: block; }
|
| 343 |
+
.menu-button { display: block; }
|
| 344 |
+
.topbar { grid-template-columns: 38px minmax(0,1fr) max-content; padding: 0 12px; }
|
| 345 |
+
.topbar .notification { display: none; }
|
| 346 |
+
main { padding: 16px; }
|
| 347 |
+
.page-head { align-items: start; }
|
| 348 |
+
.page-head h1 { font-size: 34px; }
|
| 349 |
+
.head-actions { flex-wrap: wrap; justify-content: end; }
|
| 350 |
+
.overview-grid, .uploads-grid, .calendar-grid, .cards-grid, .quiz-grid { grid-template-columns: 1fr; }
|
| 351 |
+
.overview-grid > *, .uploads-grid > *, .cards-grid > * { grid-column: auto !important; }
|
| 352 |
+
.upload-queue { min-height: auto; }
|
| 353 |
+
.doc-review { min-height: 620px; }
|
| 354 |
+
.canvas-page { margin: -16px; }
|
| 355 |
+
.canvas-head { align-items: start; }
|
| 356 |
+
.canvas-head h1 span { display: block; margin: 5px 0 0; }
|
| 357 |
+
.canvas-grid { grid-template-columns: 1fr; height: auto; }
|
| 358 |
+
.canvas-grid > :last-child { grid-column: auto; }
|
| 359 |
+
.canvas-grid .panel { min-height: 650px; }
|
| 360 |
+
.roadmap-grid { grid-template-columns: 110px repeat(8, minmax(45px,1fr)); overflow-x: auto; }
|
| 361 |
+
.quiz-card { min-height: auto; }
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
@media (max-width: 560px) {
|
| 365 |
+
.topbar { height: 58px; }
|
| 366 |
+
.ask-button { padding: 8px 10px; font-size: 0; }
|
| 367 |
+
.ask-button::after { content: "✦"; font-size: 16px; }
|
| 368 |
+
main { min-height: calc(100dvh - 58px); padding: 12px; }
|
| 369 |
+
.page-head { display: grid; }
|
| 370 |
+
.head-actions { justify-content: start; }
|
| 371 |
+
.page-head h1 { font-size: 31px; }
|
| 372 |
+
.panel-head h2 { font-size: 18px; }
|
| 373 |
+
.agenda-item { grid-template-columns: 44px 7px minmax(0,1fr); }
|
| 374 |
+
.agenda-item .badge { grid-column: 3; justify-self: start; }
|
| 375 |
+
.doc-review { grid-template-columns: 1fr; min-height: auto; }
|
| 376 |
+
.doc-pane { border-right: 0; border-bottom: 1px solid var(--line); }
|
| 377 |
+
.document-page { height: 520px; }
|
| 378 |
+
.note-pane { height: 520px; }
|
| 379 |
+
.canvas-page { margin: -12px; }
|
| 380 |
+
.canvas-head { min-height: 110px; display: grid; }
|
| 381 |
+
.canvas-head .head-actions { display: none; }
|
| 382 |
+
.canvas-grid { padding: 7px; gap: 7px; }
|
| 383 |
+
.canvas-grid .panel { min-height: 560px; }
|
| 384 |
+
.slide-workspace { grid-template-columns: 64px minmax(0,1fr); }
|
| 385 |
+
.slide-thumb { height: 75px; }
|
| 386 |
+
.week-grid { overflow-x: auto; grid-template-columns: 45px repeat(5, 130px); }
|
| 387 |
+
.cards-grid .panel, .quiz-grid .panel { min-width: 0; }
|
| 388 |
+
.quiz-content { padding: 18px 15px; }
|
| 389 |
+
.quiz-question { font-size: 27px; }
|
| 390 |
+
.answer-option { grid-template-columns: 26px minmax(0,1fr); }
|
| 391 |
+
.field.question textarea { font-size: 19px; }
|
| 392 |
+
.toast { left: 12px; right: 12px; bottom: 12px; }
|
| 393 |
+
}
|
| 394 |
+
|
| 395 |
+
@media (prefers-reduced-motion: reduce) {
|
| 396 |
+
*, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; }
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
/* Josephine editorial redesign */
|
| 400 |
+
:root {
|
| 401 |
+
--sidebar: #fbfaf6;
|
| 402 |
+
--sidebar-2: #f7f4ed;
|
| 403 |
+
--paper: #fbfaf6;
|
| 404 |
+
--surface: #fffefa;
|
| 405 |
+
--ink: #25211f;
|
| 406 |
+
--muted: #756f69;
|
| 407 |
+
--line: #ded9d0;
|
| 408 |
+
--line-soft: #eeeae3;
|
| 409 |
+
--emerald: #146a57;
|
| 410 |
+
--emerald-dark: #0f5848;
|
| 411 |
+
--emerald-soft: #edf5f0;
|
| 412 |
+
--aubergine: #54203f;
|
| 413 |
+
--aubergine-soft: #f3eaf0;
|
| 414 |
+
--rose: #ca6478;
|
| 415 |
+
--rose-soft: #faedf0;
|
| 416 |
+
--gold: #a9751e;
|
| 417 |
+
--gold-soft: #fbf3e5;
|
| 418 |
+
--serif: "Cormorant Garamond", Georgia, serif;
|
| 419 |
+
--sans: "DM Sans", "Segoe UI", sans-serif;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
body { font-family: var(--sans); background: var(--paper); }
|
| 423 |
+
.app-shell { grid-template-columns: 178px minmax(0, 1fr); }
|
| 424 |
+
.sidebar {
|
| 425 |
+
padding: 26px 13px 22px;
|
| 426 |
+
background: var(--sidebar);
|
| 427 |
+
color: var(--ink);
|
| 428 |
+
border-right: 1px solid var(--line);
|
| 429 |
+
box-shadow: none;
|
| 430 |
+
}
|
| 431 |
+
.brand { gap: 8px; padding: 2px 10px 26px; }
|
| 432 |
+
.brand-mark {
|
| 433 |
+
display: grid; place-items: center; width: 29px; height: 35px;
|
| 434 |
+
color: var(--emerald); background: none; clip-path: none; font-size: 27px;
|
| 435 |
+
}
|
| 436 |
+
.brand-name { font: 500 18px/1 var(--serif); color: #292522; letter-spacing: 0; }
|
| 437 |
+
.profile {
|
| 438 |
+
display: none;
|
| 439 |
+
}
|
| 440 |
+
.nav-list { gap: 5px; }
|
| 441 |
+
.nav-list button {
|
| 442 |
+
min-height: 48px; padding: 10px 13px; gap: 12px;
|
| 443 |
+
border: 1px solid transparent; border-radius: 7px;
|
| 444 |
+
color: #393431; background: transparent;
|
| 445 |
+
font: 500 13px/1 var(--serif);
|
| 446 |
+
}
|
| 447 |
+
.nav-list button > i { width: 21px; font-size: 21px; }
|
| 448 |
+
.nav-list button:hover { background: #f2eee7; }
|
| 449 |
+
.nav-list button.active {
|
| 450 |
+
color: white; background: var(--emerald-dark); border-color: var(--emerald-dark);
|
| 451 |
+
}
|
| 452 |
+
.local-status {
|
| 453 |
+
margin-top: auto; padding: 13px 10px 0;
|
| 454 |
+
border: 0; border-top: 1px solid var(--line); border-radius: 0; background: transparent;
|
| 455 |
+
color: var(--muted); font-size: 10px; line-height: 1.55;
|
| 456 |
+
}
|
| 457 |
+
.local-status strong { color: #554f4a; font-size: 10px; font-weight: 500; }
|
| 458 |
+
.status-dot { width: 7px; height: 7px; background: var(--emerald); }
|
| 459 |
+
|
| 460 |
+
.topbar {
|
| 461 |
+
height: 58px; padding: 0 24px;
|
| 462 |
+
grid-template-columns: max-content minmax(250px, 430px) max-content max-content max-content;
|
| 463 |
+
background: rgba(251,250,246,.96);
|
| 464 |
+
}
|
| 465 |
+
.app-main:has(.josephine-home) .topbar { display: none; }
|
| 466 |
+
.app-main:has(.josephine-home) main { padding: 0; min-height: 100dvh; }
|
| 467 |
+
.global-search, .ask-button, .button { border-radius: 6px; }
|
| 468 |
+
.page-head h1 { font-family: var(--serif); color: var(--aubergine); letter-spacing: 0; }
|
| 469 |
+
|
| 470 |
+
.josephine-home { min-height: 100dvh; background: var(--surface); }
|
| 471 |
+
.josephine-hero {
|
| 472 |
+
position: relative; min-height: 500px; overflow: hidden; background: #eee4d5;
|
| 473 |
+
}
|
| 474 |
+
.josephine-hero > img {
|
| 475 |
+
position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center;
|
| 476 |
+
}
|
| 477 |
+
.josephine-hero::after {
|
| 478 |
+
content: ""; position: absolute; inset: 0 auto 0 0; width: 53%;
|
| 479 |
+
background: linear-gradient(90deg, rgba(252,249,242,.97) 0%, rgba(252,249,242,.72) 62%, rgba(252,249,242,0) 100%);
|
| 480 |
+
pointer-events: none;
|
| 481 |
+
}
|
| 482 |
+
.weather-line {
|
| 483 |
+
position: absolute; z-index: 2; top: 31px; left: 47px;
|
| 484 |
+
display: flex; align-items: center; gap: 10px; padding: 8px 12px;
|
| 485 |
+
border-radius: 18px; background: rgba(255,255,255,.55); color: #514a45;
|
| 486 |
+
backdrop-filter: blur(8px); font: 13px var(--serif);
|
| 487 |
+
}
|
| 488 |
+
.weather-line i { font-size: 17px; }
|
| 489 |
+
.hero-copy {
|
| 490 |
+
position: absolute; z-index: 2; left: 47px; top: 83px; width: min(440px, 43%);
|
| 491 |
+
}
|
| 492 |
+
.hero-copy h1 {
|
| 493 |
+
margin: 0; color: var(--aubergine);
|
| 494 |
+
font: 500 clamp(65px, 7vw, 106px)/.77 var(--serif);
|
| 495 |
+
letter-spacing: -2px;
|
| 496 |
+
}
|
| 497 |
+
.hero-motto {
|
| 498 |
+
margin: 16px 0 26px !important; color: #8a684c !important;
|
| 499 |
+
font: italic 22px/1.2 var(--serif); letter-spacing: .02em;
|
| 500 |
+
}
|
| 501 |
+
.hero-copy h2 { margin: 0 0 8px; font: 500 29px/1.1 var(--serif); }
|
| 502 |
+
.hero-copy > p:last-child { margin: 0; color: #4f4a45; font-size: 13px; line-height: 1.55; }
|
| 503 |
+
|
| 504 |
+
.daily-journal {
|
| 505 |
+
display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(315px, .9fr);
|
| 506 |
+
min-height: 448px; background: #fffefa;
|
| 507 |
+
}
|
| 508 |
+
.journal-agenda { padding: 23px 34px 29px 47px; border-right: 1px solid var(--line); }
|
| 509 |
+
.journal-agenda > header, .today-important > header {
|
| 510 |
+
display: flex; align-items: center; gap: 10px; min-height: 38px;
|
| 511 |
+
padding-bottom: 10px; border-bottom: 1px solid var(--line);
|
| 512 |
+
}
|
| 513 |
+
.journal-agenda header > i, .today-important header > i { font-size: 20px; }
|
| 514 |
+
.journal-agenda header h2, .today-important header h2 {
|
| 515 |
+
margin: 0; font: 500 20px/1 var(--serif);
|
| 516 |
+
}
|
| 517 |
+
.journal-agenda header span { margin-left: 8px; color: #79685b; font: italic 19px var(--serif); }
|
| 518 |
+
.day-list { position: relative; padding-left: 25px; }
|
| 519 |
+
.day-list::before {
|
| 520 |
+
content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px; background: #ddd7ce;
|
| 521 |
+
}
|
| 522 |
+
.day-entry {
|
| 523 |
+
position: relative; width: 100%; min-height: 69px; padding: 10px 5px 10px 9px;
|
| 524 |
+
display: grid; grid-template-columns: 72px 45px minmax(0,1fr) 20px; gap: 10px; align-items: center;
|
| 525 |
+
border: 0; border-bottom: 1px solid var(--line-soft); background: transparent; text-align: left; cursor: pointer;
|
| 526 |
+
}
|
| 527 |
+
.day-entry::before {
|
| 528 |
+
content: ""; position: absolute; left: -25px; top: 31px; width: 8px; height: 8px;
|
| 529 |
+
border-radius: 50%; background: var(--emerald); box-shadow: 0 0 0 4px #fffefa;
|
| 530 |
+
}
|
| 531 |
+
.day-entry.blue::before { background: #3d7298; }
|
| 532 |
+
.day-entry.rose::before { background: var(--rose); }
|
| 533 |
+
.day-entry.aubergine::before { background: var(--aubergine); }
|
| 534 |
+
.day-entry.gold::before { background: var(--gold); }
|
| 535 |
+
.day-entry:hover { background: #fbf8f2; }
|
| 536 |
+
.day-entry time { color: var(--emerald); font: 500 23px var(--serif); }
|
| 537 |
+
.day-entry.blue time { color: #3d7298; }
|
| 538 |
+
.day-entry.rose time { color: var(--rose); }
|
| 539 |
+
.day-entry.aubergine time { color: var(--aubergine); }
|
| 540 |
+
.day-entry.gold time { color: var(--gold); }
|
| 541 |
+
.day-icon {
|
| 542 |
+
display: grid; place-items: center; width: 39px; height: 39px; border-radius: 50%;
|
| 543 |
+
color: var(--emerald); background: var(--emerald-soft); font-size: 21px;
|
| 544 |
+
}
|
| 545 |
+
.blue .day-icon { color: #3d7298; background: #edf3f7; }
|
| 546 |
+
.rose .day-icon { color: var(--rose); background: var(--rose-soft); }
|
| 547 |
+
.aubergine .day-icon { color: var(--aubergine); background: var(--aubergine-soft); }
|
| 548 |
+
.gold .day-icon { color: var(--gold); background: var(--gold-soft); }
|
| 549 |
+
.day-entry strong, .day-entry small { display: block; }
|
| 550 |
+
.day-entry strong { margin-bottom: 4px; font: 500 16px var(--serif); }
|
| 551 |
+
.day-entry small { color: var(--muted); font-size: 10px; line-height: 1.4; }
|
| 552 |
+
.entry-arrow { opacity: 0; color: var(--muted); }
|
| 553 |
+
.day-entry:hover .entry-arrow { opacity: 1; }
|
| 554 |
+
|
| 555 |
+
.today-important { padding: 23px 31px 29px; }
|
| 556 |
+
.important-row {
|
| 557 |
+
width: 100%; min-height: 92px; padding: 13px 4px;
|
| 558 |
+
display: grid; grid-template-columns: 45px minmax(0,1fr) 18px; gap: 12px; align-items: center;
|
| 559 |
+
border: 0; border-bottom: 1px solid var(--line-soft); background: transparent; text-align: left; cursor: pointer;
|
| 560 |
+
}
|
| 561 |
+
.important-row:hover { background: #fbf8f2; }
|
| 562 |
+
.important-icon {
|
| 563 |
+
display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%;
|
| 564 |
+
background: var(--rose-soft); color: var(--rose); font-size: 21px;
|
| 565 |
+
}
|
| 566 |
+
.important-row.gap .important-icon { background: var(--aubergine-soft); color: var(--aubergine); }
|
| 567 |
+
.important-row.next { margin-top: 14px; padding: 13px; border: 0; border-radius: 8px; background: var(--emerald-soft); }
|
| 568 |
+
.important-row.next .important-icon { background: #fff; color: var(--emerald); }
|
| 569 |
+
.important-row small, .important-row strong, .important-row em { display: block; }
|
| 570 |
+
.important-row small { margin-bottom: 4px; color: var(--rose); font-size: 10px; font-style: normal; }
|
| 571 |
+
.important-row.gap small { color: #8e5480; }
|
| 572 |
+
.important-row.next small { color: var(--emerald); }
|
| 573 |
+
.important-row strong { margin-bottom: 4px; font: 500 15px var(--serif); }
|
| 574 |
+
.important-row em { color: var(--muted); font-size: 10px; font-style: normal; }
|
| 575 |
+
.journal-note {
|
| 576 |
+
margin: 25px 0 0 54px; color: #5c907d; transform: rotate(-2deg);
|
| 577 |
+
font: italic 18px/1.25 var(--serif);
|
| 578 |
+
}
|
| 579 |
+
|
| 580 |
+
.quiet-page {
|
| 581 |
+
max-width: 1120px; margin: 0 auto; display: grid; gap: 18px;
|
| 582 |
+
}
|
| 583 |
+
.quiet-page.two-column { grid-template-columns: minmax(320px,.8fr) minmax(480px,1.2fr); }
|
| 584 |
+
.plan-intro, .focus-story, .reminder-date {
|
| 585 |
+
padding: 35px 0 28px; border-bottom: 1px solid var(--line);
|
| 586 |
+
}
|
| 587 |
+
.eyebrow { color: var(--emerald); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; }
|
| 588 |
+
.plan-intro h2, .focus-story h2 {
|
| 589 |
+
margin: 10px 0; color: var(--aubergine); font: 500 38px/1.05 var(--serif);
|
| 590 |
+
}
|
| 591 |
+
.plan-intro p, .focus-story p { max-width: 620px; color: var(--muted); line-height: 1.65; }
|
| 592 |
+
.plan-days, .calm-list { display: grid; border-top: 1px solid var(--line); }
|
| 593 |
+
.plan-days button, .calm-list button {
|
| 594 |
+
min-height: 78px; display: grid; grid-template-columns: 120px minmax(0,1fr) max-content;
|
| 595 |
+
gap: 18px; align-items: center; padding: 14px 8px; border: 0; border-bottom: 1px solid var(--line);
|
| 596 |
+
background: transparent; text-align: left; cursor: pointer;
|
| 597 |
+
}
|
| 598 |
+
.plan-days button:hover, .calm-list button:hover { background: #f8f5ef; }
|
| 599 |
+
.plan-days time { color: var(--emerald); font: 500 19px var(--serif); }
|
| 600 |
+
.plan-days strong, .plan-days span, .calm-list strong, .calm-list small { display: block; }
|
| 601 |
+
.plan-days strong, .calm-list strong { font: 500 17px var(--serif); }
|
| 602 |
+
.plan-days span, .calm-list small { margin-top: 4px; color: var(--muted); font-size: 11px; }
|
| 603 |
+
.calm-list button { grid-template-columns: 12px minmax(0,1fr) max-content; }
|
| 604 |
+
.calm-list em { color: var(--muted); font-size: 11px; font-style: normal; }
|
| 605 |
+
.signal { width: 8px; height: 8px; border-radius: 50%; background: var(--emerald); }
|
| 606 |
+
.signal.red { background: var(--rose); }
|
| 607 |
+
.signal.amber { background: var(--gold); }
|
| 608 |
+
.reminders-page { grid-template-columns: 260px minmax(0,1fr); align-items: start; }
|
| 609 |
+
.reminder-date { border: 0; }
|
| 610 |
+
.reminder-date span, .reminder-date strong { display: block; font-family: var(--serif); }
|
| 611 |
+
.reminder-date span { color: var(--emerald); font-size: 18px; }
|
| 612 |
+
.reminder-date strong { color: var(--aubergine); font-size: 48px; }
|
| 613 |
+
.reminder-date p { color: var(--muted); line-height: 1.55; }
|
| 614 |
+
.reminders-page .calm-list button { grid-template-columns: 45px minmax(0,1fr) max-content; }
|
| 615 |
+
|
| 616 |
+
@media (max-width: 1050px) {
|
| 617 |
+
.app-shell { grid-template-columns: 164px minmax(0,1fr); }
|
| 618 |
+
.hero-copy { width: 48%; }
|
| 619 |
+
.hero-copy h1 { font-size: 72px; }
|
| 620 |
+
.daily-journal { grid-template-columns: 1fr; }
|
| 621 |
+
.journal-agenda { border-right: 0; border-bottom: 1px solid var(--line); }
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
@media (max-width: 820px) {
|
| 625 |
+
.sidebar { width: 250px; }
|
| 626 |
+
.app-main:has(.josephine-home) .topbar { display: grid; }
|
| 627 |
+
.app-main:has(.josephine-home) main { padding: 0; }
|
| 628 |
+
.josephine-hero { min-height: 610px; }
|
| 629 |
+
.josephine-hero > img { object-position: 66% center; }
|
| 630 |
+
.josephine-hero::after { width: 72%; }
|
| 631 |
+
.hero-copy { left: 28px; top: 80px; width: 58%; }
|
| 632 |
+
.weather-line { left: 28px; }
|
| 633 |
+
.journal-agenda, .today-important { padding-left: 24px; padding-right: 24px; }
|
| 634 |
+
.quiet-page.two-column, .reminders-page { grid-template-columns: 1fr; }
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
@media (max-width: 560px) {
|
| 638 |
+
.josephine-hero { min-height: 690px; background: #fffefa; }
|
| 639 |
+
.josephine-hero > img { height: 390px; object-position: 68% center; }
|
| 640 |
+
.josephine-hero::after { display: none; }
|
| 641 |
+
.hero-copy {
|
| 642 |
+
top: 390px; left: 0; width: 100%; padding: 19px 20px 22px;
|
| 643 |
+
background: #fffefa;
|
| 644 |
+
}
|
| 645 |
+
.hero-copy h1 { font-size: 52px; line-height: .78; }
|
| 646 |
+
.hero-motto { margin: 13px 0 18px !important; font-size: 17px; }
|
| 647 |
+
.hero-copy h2 { margin: 0 0 7px; font-size: 25px; }
|
| 648 |
+
.weather-line { top: 20px; left: 20px; font-size: 11px; }
|
| 649 |
+
.journal-agenda, .today-important { padding: 20px 15px; }
|
| 650 |
+
.day-list { padding-left: 17px; }
|
| 651 |
+
.day-entry { grid-template-columns: 55px 37px minmax(0,1fr); gap: 7px; }
|
| 652 |
+
.day-entry::before { left: -17px; }
|
| 653 |
+
.day-entry time { font-size: 19px; }
|
| 654 |
+
.day-icon { width: 34px; height: 34px; }
|
| 655 |
+
.entry-arrow { display: none; }
|
| 656 |
+
}
|