Initial commit: Personal Dashboard

Next.js 16 dashboard with configurable widgets (favorites, notes, calendar,
clock, calculator, search, domain-check), multi-tab support, user auth,
dark mode, and Docker deployment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-06-18 10:02:05 +02:00
commit a4051ae132
74 changed files with 18317 additions and 0 deletions
+378
View File
@@ -0,0 +1,378 @@
/* Such-Widget
Einheitliche Widget-Chrome bleibt erhalten:
- normaler Rahmen
- Bearbeitungsmenü bleibt sichtbar
- Resize-Ecke bleibt frei
- kein Widget-Titel
- Suchzeile mittig und kompakt
*/
.app .widgetCard-search {
position: relative !important;
border: 1px solid var(--border) !important;
background: color-mix(in srgb, var(--surface) 82%, transparent) !important;
border-radius: 14px !important;
overflow: visible !important;
}
/* Titel ausblenden, aber Header-Struktur fuer Menu/Griff erhalten */
.app .widgetCard-search .widgetTitle {
display: none !important;
}
/* Normalmodus: kein leerer Titelbereich */
.app .widgetCard-search:not(.widgetCardEditMode) .widgetHeader {
height: 0 !important;
min-height: 0 !important;
max-height: 0 !important;
padding: 0 !important;
margin: 0 !important;
overflow: hidden !important;
}
/* Bearbeitungsmodus: Header bleibt fuer Griff und Menue vorhanden */
.app .widgetCard-search.widgetCardEditMode .widgetHeader {
height: 26px !important;
min-height: 26px !important;
max-height: 26px !important;
padding: 0 34px 0 32px !important;
margin: 0 !important;
overflow: visible !important;
display: flex !important;
align-items: center !important;
}
/* Menue im Suchwidget darf nie verschwinden */
.app .widgetCard-search .widgetMenu {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
z-index: 1500 !important;
}
.app .widgetCard-search .widgetMenuButton {
display: inline-flex !important;
visibility: visible !important;
opacity: 1 !important;
}
.app .widgetCard-search.widgetCardMenuOpen {
z-index: 1600 !important;
overflow: visible !important;
}
.app .widgetCard-search.widgetCardMenuOpen .widgetDropdown {
z-index: 1700 !important;
max-height: min(260px, 70vh) !important;
overflow-y: auto !important;
}
/* Normalmodus: Suchzeile in kompletter Widgetflaeche zentrieren */
.app .widgetCard-search:not(.widgetCardEditMode) .widgetContent {
position: absolute !important;
inset: 0 !important;
width: auto !important;
height: auto !important;
min-width: 0 !important;
min-height: 0 !important;
display: grid !important;
place-items: center !important;
padding: 8px !important;
overflow: visible !important;
}
/* Bearbeitungsmodus: unterhalb Header zentrieren, Resize-Ecke freihalten */
.app .widgetCard-search.widgetCardEditMode .widgetContent {
position: absolute !important;
inset: 26px 0 0 0 !important;
width: auto !important;
height: auto !important;
min-width: 0 !important;
min-height: 0 !important;
display: grid !important;
place-items: center !important;
padding: 6px 10px 12px 8px !important;
overflow: visible !important;
}
/* Suchformular mittig, einzeilig, mit Luft zur Resize-Ecke */
.app .widgetCard-search .searchWidgetForm {
width: 100% !important;
min-width: 0 !important;
max-width: 100% !important;
display: grid !important;
grid-template-columns: minmax(92px, 140px) minmax(0, 1fr) 38px !important;
align-items: center !important;
justify-content: center !important;
gap: 6px !important;
margin: 0 !important;
padding: 0 !important;
}
/* Eingaben gleich hoch und kompakt */
.app .widgetCard-search .searchWidgetForm .select,
.app .widgetCard-search .searchWidgetForm .searchInput {
height: 34px !important;
min-height: 34px !important;
max-height: 34px !important;
padding: 0 10px !important;
border-radius: 9px !important;
font-size: 12px !important;
line-height: 34px !important;
box-sizing: border-box !important;
}
/* Suchbutton: einheitlich, nicht in die Ecke gedrueckt */
.app .widgetCard-search .searchWidgetForm .button,
.app .widgetCard-search .searchWidgetForm button[type="submit"] {
width: 38px !important;
min-width: 38px !important;
max-width: 38px !important;
height: 38px !important;
min-height: 38px !important;
max-height: 38px !important;
position: relative !important;
display: inline-grid !important;
place-items: center !important;
align-self: center !important;
justify-self: center !important;
padding: 0 !important;
overflow: hidden !important;
color: transparent !important;
font-size: 0 !important;
line-height: 0 !important;
text-indent: -9999px !important;
border-radius: 10px !important;
}
/* Lupenkreis */
.app .widgetCard-search .searchWidgetForm .button::before,
.app .widgetCard-search .searchWidgetForm button[type="submit"]::before {
content: "" !important;
position: absolute !important;
left: 50% !important;
top: 50% !important;
width: 14px !important;
height: 14px !important;
border: 2px solid #fff !important;
border-radius: 999px !important;
background: transparent !important;
transform: translate(-58%, -58%) !important;
box-sizing: border-box !important;
}
/* Lupengriff */
.app .widgetCard-search .searchWidgetForm .button::after,
.app .widgetCard-search .searchWidgetForm button[type="submit"]::after {
content: "" !important;
position: absolute !important;
left: 50% !important;
top: 50% !important;
width: 9px !important;
height: 2px !important;
background: #fff !important;
border: 0 !important;
border-radius: 999px !important;
transform: translate(1px, 5px) rotate(45deg) !important;
box-sizing: border-box !important;
}
/* Schmale Widgets */
@media (max-width: 640px) {
.app .widgetCard-search .searchWidgetForm {
grid-template-columns: minmax(72px, 110px) minmax(0, 1fr) 38px !important;
}
}
/* FIX: Such-Widget-Menü wieder sichtbar machen.
Nicht-destruktiv: Widget-Chrome bleibt erhalten, nur Layering/Clipping wird korrigiert. */
.app .widgetCard-search {
overflow: visible !important;
}
/* Im Bearbeitungsmodus muss der Header als Menü-/Griff-Zone sichtbar bleiben */
.app .widgetCard-search.widgetCardEditMode .widgetHeader {
position: relative !important;
z-index: 50 !important;
height: 26px !important;
min-height: 26px !important;
max-height: 26px !important;
display: flex !important;
align-items: center !important;
overflow: visible !important;
pointer-events: auto !important;
}
/* Menü explizit sichtbar und über dem Suchformular */
.app .widgetCard-search.widgetCardEditMode .widgetMenu {
display: block !important;
position: absolute !important;
top: 2px !important;
right: 6px !important;
z-index: 2000 !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: auto !important;
}
.app .widgetCard-search.widgetCardEditMode .widgetMenuButton {
display: inline-flex !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: auto !important;
}
/* Dropdown über allem und scrollbar */
.app .widgetCard-search.widgetCardMenuOpen,
.app .widgetCard-search.widgetCardEditMode.widgetCardMenuOpen {
overflow: visible !important;
z-index: 2000 !important;
}
.app .widgetCard-search.widgetCardMenuOpen .widgetDropdown {
display: grid !important;
visibility: visible !important;
opacity: 1 !important;
z-index: 2100 !important;
max-height: min(260px, 70vh) !important;
overflow-y: auto !important;
pointer-events: auto !important;
}
/* Content darf das Menü nicht überdecken */
.app .widgetCard-search.widgetCardEditMode .widgetContent {
z-index: 1 !important;
pointer-events: auto !important;
}
/* FINAL FIX: Such-Widget behält einheitliche Widget-Chrome.
Ursache: vorherige Regeln haben den Header abhängig von widgetCardEditMode versteckt.
Diese Regeln nutzen den tatsächlich vorhandenen Menü-/Drag-Button als Edit-Indikator. */
/* Sobald Menü oder Griff existieren, ist das Widget im Bearbeitungszustand:
Header sichtbar halten, damit Menü/Griff nicht verschwinden. */
.app .widgetCard-search:has(.widgetMenuButton) .widgetHeader,
.app .widgetCard-search:has(.widgetDragHandle) .widgetHeader {
display: flex !important;
position: relative !important;
z-index: 3000 !important;
height: 26px !important;
min-height: 26px !important;
max-height: 26px !important;
padding: 0 34px 0 32px !important;
margin: 0 !important;
align-items: center !important;
overflow: visible !important;
pointer-events: auto !important;
border-bottom: 0 !important;
}
/* Menü im Suchwidget sichtbar und klickbar halten */
.app .widgetCard-search:has(.widgetMenuButton) .widgetMenu {
display: block !important;
position: absolute !important;
top: 2px !important;
right: 6px !important;
z-index: 3100 !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: auto !important;
}
.app .widgetCard-search:has(.widgetMenuButton) .widgetMenuButton {
display: inline-flex !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: auto !important;
}
/* Griff links sichtbar halten */
.app .widgetCard-search:has(.widgetDragHandle) .widgetDragHandle {
display: grid !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: auto !important;
z-index: 3100 !important;
}
/* Im Bearbeitungszustand Content unter Header setzen und Resize-Ecke freihalten */
.app .widgetCard-search:has(.widgetMenuButton) .widgetContent,
.app .widgetCard-search:has(.widgetDragHandle) .widgetContent {
position: absolute !important;
inset: 26px 0 0 0 !important;
width: auto !important;
height: auto !important;
min-width: 0 !important;
min-height: 0 !important;
display: grid !important;
place-items: center !important;
padding: 5px 22px 18px 8px !important;
overflow: visible !important;
z-index: 1 !important;
pointer-events: auto !important;
}
/* Widget selbst darf Menü/Dropdown nicht clippen */
.app .widgetCard-search,
.app .widgetCard-search.widgetCardMenuOpen {
overflow: visible !important;
}
/* Dropdown über anderen Widgets und scrollbar */
.app .widgetCard-search.widgetCardMenuOpen .widgetDropdown,
.app .widgetCard-search:has(.widgetMenuButton) .widgetDropdown {
display: grid !important;
visibility: visible !important;
opacity: 1 !important;
z-index: 3200 !important;
max-height: min(260px, 70vh) !important;
overflow-y: auto !important;
pointer-events: auto !important;
}
/* Suchzeile bleibt einheitlich und ragt nicht in die Resize-Ecke */
.app .widgetCard-search:has(.widgetMenuButton) .searchWidgetForm,
.app .widgetCard-search:has(.widgetDragHandle) .searchWidgetForm {
width: 100% !important;
max-width: 100% !important;
min-width: 0 !important;
align-items: center !important;
margin: 0 !important;
}
/* FINAL FIX: Such-Widget nutzt dieselbe Transparenzlogik wie alle Widgets.
Nicht-destruktiv: Chrome, Menü, Drag, Resize und Suchfunktion bleiben erhalten. */
.app .widgetCard-search {
background: transparent !important;
border-color: var(--border) !important;
box-shadow: var(--shadow) !important;
isolation: isolate !important;
}
/* Die normale Widget-Bubble wieder aktivieren.
Wichtig: Transparenz kommt über --widget-opacity wie bei allen anderen Widgets. */
.app .widgetCard-search::before {
content: "" !important;
display: block !important;
position: absolute !important;
inset: 0 !important;
z-index: -1 !important;
pointer-events: none !important;
background:
linear-gradient(
180deg,
color-mix(in srgb, var(--surface-strong) 92%, transparent),
color-mix(in srgb, var(--surface) 92%, transparent)
) !important;
border-radius: inherit !important;
opacity: var(--widget-opacity, 1) !important;
}
/* Inhalt bleibt vollständig sichtbar und unabhängig von der Bubble-Transparenz */
.app .widgetCard-search > * {
position: relative !important;
z-index: 1 !important;
opacity: 1 !important;
}