Compare commits
2 Commits
7faa65d6c9
...
0d03f21a4c
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d03f21a4c | |||
| d0d5bad803 |
@@ -36,6 +36,14 @@ from .main import main_bp
|
|||||||
WEEKDAY_NAMES = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"]
|
WEEKDAY_NAMES = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"]
|
||||||
WEEKDAY_SHORT_NAMES = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
|
WEEKDAY_SHORT_NAMES = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
|
||||||
DEFAULT_RELEASE_URL = "https://git.hnz.io/hnzio/nouri-App/releases"
|
DEFAULT_RELEASE_URL = "https://git.hnz.io/hnzio/nouri-App/releases"
|
||||||
|
DAYPART_ICON_CLASSES = {
|
||||||
|
"breakfast": "icon-daypart-breakfast",
|
||||||
|
"morning-snack": "icon-daypart-morning-snack",
|
||||||
|
"lunch": "icon-daypart-lunch",
|
||||||
|
"afternoon-snack": "icon-daypart-afternoon-snack",
|
||||||
|
"dinner": "icon-daypart-dinner",
|
||||||
|
"late-snack": "icon-daypart-late-snack",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def load_secret_key(data_dir: Path) -> str:
|
def load_secret_key(data_dir: Path) -> str:
|
||||||
@@ -149,6 +157,7 @@ def create_app() -> Flask:
|
|||||||
"push_available": bool(app.config["VAPID_PUBLIC_KEY"] and app.config["VAPID_PRIVATE_KEY"]),
|
"push_available": bool(app.config["VAPID_PUBLIC_KEY"] and app.config["VAPID_PRIVATE_KEY"]),
|
||||||
"weekday_name": lambda value: WEEKDAY_NAMES[value.weekday()],
|
"weekday_name": lambda value: WEEKDAY_NAMES[value.weekday()],
|
||||||
"weekday_short_name": lambda value: WEEKDAY_SHORT_NAMES[value.weekday()],
|
"weekday_short_name": lambda value: WEEKDAY_SHORT_NAMES[value.weekday()],
|
||||||
|
"daypart_icon_class": lambda slug: DAYPART_ICON_CLASSES.get(slug, "icon-calendar"),
|
||||||
"is_admin": lambda: bool(getattr(g, "user", None)) and g.user["role"] == "admin",
|
"is_admin": lambda: bool(getattr(g, "user", None)) and g.user["role"] == "admin",
|
||||||
"asset_url": asset_url,
|
"asset_url": asset_url,
|
||||||
"image_url": lambda filename, variant="md": image_url(
|
"image_url": lambda filename, variant="md": image_url(
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ button,
|
|||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
color: white;
|
color: white;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 160ms ease, background 160ms ease, border-color 160ms ease;
|
transition: transform 160ms ease, background 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:focus-visible,
|
button:focus-visible,
|
||||||
@@ -124,19 +124,64 @@ button:hover,
|
|||||||
.button.secondary,
|
.button.secondary,
|
||||||
button.secondary,
|
button.secondary,
|
||||||
.ghost-button {
|
.ghost-button {
|
||||||
background: transparent;
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
color-mix(in srgb, var(--surface-soft) 72%, #fff 28%),
|
||||||
|
color-mix(in srgb, var(--surface-strong) 82%, #fff 18%)
|
||||||
|
);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border-color: var(--line);
|
border-color: color-mix(in srgb, var(--accent) 34%, var(--line) 66%);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.8),
|
||||||
|
0 8px 20px rgba(225, 181, 138, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button.secondary:hover,
|
.button.secondary:hover,
|
||||||
button.secondary:hover,
|
button.secondary:hover,
|
||||||
.ghost-button:hover {
|
.ghost-button:hover {
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
color-mix(in srgb, var(--accent-soft) 58%, #fff 42%),
|
||||||
|
color-mix(in srgb, var(--surface-soft) 88%, #fff 12%)
|
||||||
|
);
|
||||||
|
border-color: color-mix(in srgb, var(--accent) 46%, var(--line) 54%);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.84),
|
||||||
|
0 12px 28px rgba(212, 155, 104, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] button:not(.secondary):not(.ghost-button),
|
||||||
|
[data-theme="dark"] .button:not(.secondary):not(.ghost-button) {
|
||||||
|
background: #d7935f;
|
||||||
|
color: #201a17;
|
||||||
|
border-color: rgba(243, 177, 125, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] button:not(.secondary):not(.ghost-button):hover,
|
||||||
|
[data-theme="dark"] .button:not(.secondary):not(.ghost-button):hover {
|
||||||
|
background: #e0a270;
|
||||||
|
color: #181311;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .button.secondary,
|
||||||
|
[data-theme="dark"] button.secondary,
|
||||||
|
[data-theme="dark"] .ghost-button {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text);
|
||||||
|
border-color: var(--line);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .button.secondary:hover,
|
||||||
|
[data-theme="dark"] button.secondary:hover,
|
||||||
|
[data-theme="dark"] .ghost-button:hover {
|
||||||
background: var(--accent-soft);
|
background: var(--accent-soft);
|
||||||
|
border-color: rgba(243, 177, 125, 0.2);
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-shell {
|
.page-shell {
|
||||||
width: min(1320px, calc(100% - 2rem));
|
width: min(1680px, calc(100% - 2rem));
|
||||||
margin: 1rem auto 2rem;
|
margin: 1rem auto 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,6 +278,7 @@ h3,
|
|||||||
}
|
}
|
||||||
|
|
||||||
.site-nav a {
|
.site-nav a {
|
||||||
|
flex: 0 0 auto;
|
||||||
padding: 0.55rem 0.85rem;
|
padding: 0.55rem 0.85rem;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
@@ -265,6 +311,8 @@ h3,
|
|||||||
column-gap: 1.5rem;
|
column-gap: 1.5rem;
|
||||||
row-gap: 0.9rem;
|
row-gap: 0.9rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding-left: 1rem;
|
||||||
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desktop-header-main {
|
.desktop-header-main {
|
||||||
@@ -279,6 +327,7 @@ h3,
|
|||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 0.3rem;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -309,6 +358,10 @@ h3,
|
|||||||
.desktop-actions > * {
|
.desktop-actions > * {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.desktop-nav a {
|
||||||
|
padding: 0.5rem 0.74rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-chip,
|
.user-chip,
|
||||||
@@ -396,6 +449,14 @@ h3,
|
|||||||
linear-gradient(180deg, color-mix(in srgb, var(--surface) 86%, #fff 14%), color-mix(in srgb, var(--surface) 80%, #ffe5d2 20%));
|
linear-gradient(180deg, color-mix(in srgb, var(--surface) 86%, #fff 14%), color-mix(in srgb, var(--surface) 80%, #ffe5d2 20%));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .hero {
|
||||||
|
background:
|
||||||
|
linear-gradient(135deg, rgba(255, 255, 255, 0.06), transparent 42%),
|
||||||
|
linear-gradient(180deg, rgba(64, 55, 52, 0.98), rgba(49, 42, 39, 0.99));
|
||||||
|
border-color: rgba(243, 177, 125, 0.14);
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
.hero h1,
|
.hero h1,
|
||||||
.page-intro h1,
|
.page-intro h1,
|
||||||
.panel h2 {
|
.panel h2 {
|
||||||
@@ -614,6 +675,11 @@ h3 {
|
|||||||
background: var(--sky-soft);
|
background: var(--sky-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .status-idea {
|
||||||
|
background: rgba(126, 143, 160, 0.24);
|
||||||
|
color: #ece8e4;
|
||||||
|
}
|
||||||
|
|
||||||
.status-soft {
|
.status-soft {
|
||||||
background: var(--lilac-soft);
|
background: var(--lilac-soft);
|
||||||
}
|
}
|
||||||
@@ -702,6 +768,10 @@ h3 {
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-spaced-panel > .panel-head + * {
|
||||||
|
margin-top: 0.45rem;
|
||||||
|
}
|
||||||
|
|
||||||
.template-library-grid {
|
.template-library-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
@@ -910,23 +980,46 @@ legend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.day-tile-icon {
|
.day-tile-icon {
|
||||||
width: 2.8rem;
|
width: 2.95rem;
|
||||||
height: 2.8rem;
|
height: 2.95rem;
|
||||||
|
flex: 0 0 2.95rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 1rem;
|
border-radius: 0.9rem;
|
||||||
background: linear-gradient(145deg, rgba(255, 255, 255, 0.92), var(--peach-soft));
|
background: linear-gradient(
|
||||||
color: var(--accent-strong);
|
180deg,
|
||||||
|
color-mix(in srgb, var(--surface-soft) 72%, #fff 28%),
|
||||||
|
color-mix(in srgb, var(--surface-soft) 92%, #f7e2cf 8%)
|
||||||
|
);
|
||||||
|
border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--line) 74%);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.82),
|
||||||
|
0 10px 24px rgba(223, 177, 134, 0.12);
|
||||||
|
color: #cf8450;
|
||||||
}
|
}
|
||||||
|
|
||||||
.day-tile-icon .ui-icon {
|
.day-tile-icon .ui-icon {
|
||||||
width: 1.15rem;
|
width: 1.28rem;
|
||||||
height: 1.15rem;
|
height: 1.28rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .day-tile-icon {
|
||||||
|
background: linear-gradient(180deg, rgba(86, 74, 69, 0.98), rgba(67, 58, 55, 0.98));
|
||||||
|
border: 1px solid rgba(243, 177, 125, 0.14);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
||||||
|
color: #f3bf90;
|
||||||
}
|
}
|
||||||
|
|
||||||
.day-tile.has-entries .day-tile-icon {
|
.day-tile.has-entries .day-tile-icon {
|
||||||
background: linear-gradient(145deg, rgba(255, 255, 255, 0.98), color-mix(in srgb, var(--accent-soft) 68%, #fff 32%));
|
background: linear-gradient(
|
||||||
box-shadow: 0 10px 22px rgba(94, 68, 49, 0.14);
|
180deg,
|
||||||
|
color-mix(in srgb, var(--surface-soft) 82%, #fff 18%),
|
||||||
|
color-mix(in srgb, var(--accent-soft) 72%, #fff 28%)
|
||||||
|
);
|
||||||
|
border-color: color-mix(in srgb, var(--accent) 36%, var(--line) 64%);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.84),
|
||||||
|
0 12px 26px rgba(94, 68, 49, 0.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
.day-tile-summary-text {
|
.day-tile-summary-text {
|
||||||
@@ -953,8 +1046,9 @@ legend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .day-tile.has-entries .day-tile-icon {
|
[data-theme="dark"] .day-tile.has-entries .day-tile-icon {
|
||||||
background: linear-gradient(145deg, rgba(255, 255, 255, 0.12), rgba(243, 177, 125, 0.16));
|
background: linear-gradient(180deg, rgba(97, 82, 76, 0.98), rgba(76, 65, 61, 0.98));
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
border-color: rgba(243, 177, 125, 0.18);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .day-tile.has-entries .status-pill {
|
[data-theme="dark"] .day-tile.has-entries .status-pill {
|
||||||
@@ -1078,6 +1172,14 @@ legend {
|
|||||||
background: color-mix(in srgb, var(--surface-strong) 84%, #fff 16%);
|
background: color-mix(in srgb, var(--surface-strong) 84%, #fff 16%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .template-card,
|
||||||
|
[data-theme="dark"] .template-list-card,
|
||||||
|
[data-theme="dark"] .suggestion-card {
|
||||||
|
background: linear-gradient(180deg, rgba(66, 57, 54, 0.98), rgba(54, 47, 44, 0.99));
|
||||||
|
border-color: rgba(243, 177, 125, 0.12);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.02);
|
||||||
|
}
|
||||||
|
|
||||||
.selected-quick-action {
|
.selected-quick-action {
|
||||||
background: linear-gradient(180deg, color-mix(in srgb, var(--accent-soft) 82%, #fff 18%), color-mix(in srgb, var(--surface-strong) 82%, #fff 18%));
|
background: linear-gradient(180deg, color-mix(in srgb, var(--accent-soft) 82%, #fff 18%), color-mix(in srgb, var(--surface-strong) 82%, #fff 18%));
|
||||||
border-color: color-mix(in srgb, var(--accent) 36%, var(--line) 64%);
|
border-color: color-mix(in srgb, var(--accent) 36%, var(--line) 64%);
|
||||||
@@ -1128,6 +1230,12 @@ legend {
|
|||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .hint-chip {
|
||||||
|
background: linear-gradient(180deg, rgba(77, 68, 64, 0.96), rgba(63, 56, 53, 0.98));
|
||||||
|
border-color: rgba(243, 177, 125, 0.12);
|
||||||
|
color: #f0e8e2;
|
||||||
|
}
|
||||||
|
|
||||||
.suggestion-row {
|
.suggestion-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
@@ -1367,6 +1475,20 @@ legend {
|
|||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.week-slot-title {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.week-slot-title .ui-icon {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
color: var(--accent-strong);
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.week-slot-head-meta {
|
.week-slot-head-meta {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1607,6 +1729,11 @@ legend {
|
|||||||
min-width: 5rem;
|
min-width: 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-toggle,
|
||||||
|
.mobile-extra-button[data-theme-toggle] {
|
||||||
|
gap: 0.55rem;
|
||||||
|
}
|
||||||
|
|
||||||
.ui-icon {
|
.ui-icon {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
@@ -1651,6 +1778,36 @@ legend {
|
|||||||
mask-image: url("../icons/fa/calendar-days.svg");
|
mask-image: url("../icons/fa/calendar-days.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-daypart-breakfast {
|
||||||
|
-webkit-mask-image: url("../icons/dayparts/breakfast.svg");
|
||||||
|
mask-image: url("../icons/dayparts/breakfast.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-daypart-morning-snack {
|
||||||
|
-webkit-mask-image: url("../icons/dayparts/morning-snack.svg");
|
||||||
|
mask-image: url("../icons/dayparts/morning-snack.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-daypart-lunch {
|
||||||
|
-webkit-mask-image: url("../icons/dayparts/lunch.svg");
|
||||||
|
mask-image: url("../icons/dayparts/lunch.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-daypart-afternoon-snack {
|
||||||
|
-webkit-mask-image: url("../icons/dayparts/afternoon-snack.svg");
|
||||||
|
mask-image: url("../icons/dayparts/afternoon-snack.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-daypart-dinner {
|
||||||
|
-webkit-mask-image: url("../icons/dayparts/dinner.svg");
|
||||||
|
mask-image: url("../icons/dayparts/dinner.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-daypart-late-snack {
|
||||||
|
-webkit-mask-image: url("../icons/dayparts/late-snack.svg");
|
||||||
|
mask-image: url("../icons/dayparts/late-snack.svg");
|
||||||
|
}
|
||||||
|
|
||||||
.icon-archive {
|
.icon-archive {
|
||||||
-webkit-mask-image: url("../icons/fa/archive.svg");
|
-webkit-mask-image: url("../icons/fa/archive.svg");
|
||||||
mask-image: url("../icons/fa/archive.svg");
|
mask-image: url("../icons/fa/archive.svg");
|
||||||
@@ -1696,6 +1853,16 @@ legend {
|
|||||||
mask-image: url("../icons/fa/mobile-screen-button.svg");
|
mask-image: url("../icons/fa/mobile-screen-button.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-sun-theme {
|
||||||
|
-webkit-mask-image: url("../icons/fa/theme-sun.svg");
|
||||||
|
mask-image: url("../icons/fa/theme-sun.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-moon-theme {
|
||||||
|
-webkit-mask-image: url("../icons/fa/theme-moon.svg");
|
||||||
|
mask-image: url("../icons/fa/theme-moon.svg");
|
||||||
|
}
|
||||||
|
|
||||||
.icon-apple-whole {
|
.icon-apple-whole {
|
||||||
-webkit-mask-image: url("../icons/fa/apple-whole.svg");
|
-webkit-mask-image: url("../icons/fa/apple-whole.svg");
|
||||||
mask-image: url("../icons/fa/apple-whole.svg");
|
mask-image: url("../icons/fa/apple-whole.svg");
|
||||||
@@ -1847,6 +2014,18 @@ legend {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.day-tile-icon {
|
||||||
|
width: 2.8rem;
|
||||||
|
height: 2.8rem;
|
||||||
|
flex-basis: 2.8rem;
|
||||||
|
border-radius: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.day-tile-icon .ui-icon {
|
||||||
|
width: 1.12rem;
|
||||||
|
height: 1.12rem;
|
||||||
|
}
|
||||||
|
|
||||||
.hero,
|
.hero,
|
||||||
.page-intro,
|
.page-intro,
|
||||||
.panel,
|
.panel,
|
||||||
@@ -2005,6 +2184,10 @@ legend {
|
|||||||
.mobile-nav-button {
|
.mobile-nav-button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-bottom-nav a.active,
|
.mobile-bottom-nav a.active,
|
||||||
@@ -2012,6 +2195,62 @@ legend {
|
|||||||
.mobile-nav-button.is-open {
|
.mobile-nav-button.is-open {
|
||||||
background: var(--accent-soft);
|
background: var(--accent-soft);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .mobile-nav-button.is-open {
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--text);
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .mobile-nav-stack button.mobile-nav-button:not(.secondary):not(.ghost-button) {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .mobile-nav-stack button.mobile-nav-button:not(.secondary):not(.ghost-button):hover {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .mobile-nav-stack button.mobile-nav-button.is-open:not(.secondary):not(.ghost-button),
|
||||||
|
[data-theme="dark"] .mobile-nav-stack button.mobile-nav-button.is-open:not(.secondary):not(.ghost-button):hover {
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--text);
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .mobile-nav-extension .mobile-extra-button,
|
||||||
|
[data-theme="dark"] .mobile-nav-extension .mobile-extra-form .mobile-extra-button {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .mobile-nav-extension .mobile-extra-button[data-theme-toggle] {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .mobile-nav-extension .mobile-extra-button:hover,
|
||||||
|
[data-theme="dark"] .mobile-nav-extension .mobile-extra-button:focus-visible,
|
||||||
|
[data-theme="dark"] .mobile-nav-extension .mobile-extra-form .mobile-extra-button:hover,
|
||||||
|
[data-theme="dark"] .mobile-nav-extension .mobile-extra-form .mobile-extra-button:focus-visible {
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--text);
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-profile-link {
|
.mobile-profile-link {
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2025 Fonticons, Inc. --><path fill="currentColor" d="M362.2 37L213.9 16 81.7 86.7 16 222.1 42 370.4 149.8 475 298.1 496 430.3 425.3 496 289.9 470 141.6 362.2 37zM208 144a32 32 0 1 1 0 64 32 32 0 1 1 0-64zM144 336a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zm224-64a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>
|
||||||
|
After Width: | Height: | Size: 505 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2025 Fonticons, Inc. --><path fill="currentColor" d="M243.2 .3c4.2-.2 8.5-.3 12.8-.3 62.1 0 118.9 22.1 163.3 58.8L314.6 163.4 243.2 .3zM194 7.6L307.4 266.6 267.3 306.8 12 178.3C38.8 94.2 107.7 29 194 7.6zM1.6 226.8l166 83.6-108.9 108.9C22.1 374.9 0 318.1 0 256 0 246.1 .6 236.4 1.6 226.8zM92.7 453.2l120.1-120.1 11.2 5.6 0 171.3c-49.5-6.2-94.7-26.5-131.3-56.8zM341.2 224l-5.9-13.4 117.9-117.9c30.3 36.6 50.6 81.7 56.8 131.3l-168.8 0z"/></svg>
|
||||||
|
After Width: | Height: | Size: 648 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2025 Fonticons, Inc. --><path fill="currentColor" d="M56 16L40 16 0 152c0 41.5 31.6 75.6 72 79.6l0 264.4 48 0 0-264.4c40.4-4 72-38.1 72-79.6l-40-136-16 0 0 136-16 0-16-136-16 0-16 136-16 0 0-136zm584 0S512 32 512 160l0 160 80 0 0 176 48 0 0-480zM336 32c-43.8 0-84.7 12.6-119.2 34.3l19.1 64.9c27.4-22 62.2-35.2 100.1-35.2 52.3 0 98.8 25.1 128 64 0-29.7 5.5-55.2 14.5-76.9-38.7-31.9-88.3-51.1-142.5-51.1zm0 384c-86.1 0-156.3-68-159.9-153.2-2.7 1.5-5.4 3-8.1 4.3l0 137c41 46.5 101.1 75.8 168 75.8 82.9 0 155.3-45 194-112l-66 0 0-16c-29.2 38.9-75.7 64-128 64zM448 256a112 112 0 1 0 -224 0 112 112 0 1 0 224 0z"/></svg>
|
||||||
|
After Width: | Height: | Size: 820 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2025 Fonticons, Inc. --><path fill="currentColor" d="M359.7 21.9C272.6 43.5 208 122.2 208 216 208 326.4 297.5 416 408 416 426.5 416 444.4 413.5 461.4 408.8 414.8 471.4 340.1 512 256 512 114.6 512 0 397.4 0 256S114.6 0 256 0c36.9 0 72 7.8 103.7 21.9z"/></svg>
|
||||||
|
After Width: | Height: | Size: 464 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2025 Fonticons, Inc. --><path fill="currentColor" d="M0 64l512 0 0 112-512 0 0-112zM320 384l96-48 96 0 0 112-512 0 0-112 224 0 96 48zM144.2 209.1l111.8 29.8 111.8-29.8 8-2.1 8 2c74.8 18.7 117.2 29.3 127 31.8l-15.5 62.1c-11.2-2.8-50.9-12.7-119-29.8l-112 29.9-8.2 2.2-8.2-2.2-112-29.9c-68.1 17-107.8 27-119 29.8L1.2 240.7c9.9-2.5 52.2-13.1 127-31.8l8-2 8 2.1z"/></svg>
|
||||||
|
After Width: | Height: | Size: 572 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2025 Fonticons, Inc. --><path fill="currentColor" d="M208 96l0-16c0-44.2 35.8-80 80-80l32 0 0 32c0 44.2-35.8 80-80 80l-32 0 0-16zM0 288c0-76.3 35.7-160 112-160l112 32 112-32c76.3 0 112 83.7 112 160 0 128-80 224-160 224l-64-16-64 16C80 512 0 416 0 288z"/></svg>
|
||||||
|
After Width: | Height: | Size: 466 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 576"><path fill="currentColor" d="M99.1 99.8c36.8-31.2 88.7-50.7 158.9-51.8 70.8 1.3 118.7 27.7 149.8 67.9 32.6 42.2 48.7 102.3 48.7 172s-16.1 129.8-48.7 172c-31 40.2-79 66.6-149.8 67.9-70.2-1.1-122.1-20.6-158.9-51.8 14.2 2.5 29.3 3.8 45.4 3.8 4.1 0 8.1-.1 12-.2l0 .2c80.4 0 138.3-19.7 176.2-55.9 38-36.3 51.8-85.6 51.8-136.1s-13.8-99.8-51.8-136.1C294.8 115.7 236.9 96 156.5 96l0 .2c-3.9-.2-7.9-.2-12-.2-16.1 0-31.2 1.3-45.4 3.8zM252.5 .2C125.1 3.6 42.8 62.2 3.5 150.3l38.2 27.5c21.9-20.1 54.9-33.8 102.8-33.8 53.4 0 88.4 16.9 110.2 41.2 22.3 24.8 33.8 60.5 33.8 102.8S277 366 254.7 390.8c-21.9 24.4-56.8 41.2-110.2 41.2-47.9 0-80.9-13.6-102.8-33.8L3.5 425.7c39.3 88.2 121.6 146.7 249 150.1l0 .2c1.9 0 3.8 0 5.6 0 2.1 0 4.2 0 6.4 0 97.8 0 170.8-31.5 219.2-85.3 47.9-53.4 68.8-125.7 68.8-202.7S531.6 138.7 483.6 85.3c-48.3-53.8-121.4-85.3-219.2-85.3-2.1 0-4.3 0-6.4 0-1.9 0-3.7 0-5.6 0l0 .2zM216.5 252c0-26.5-14.4-48-48-48s-48 21.5-48 48 14.4 48 48 48 48-21.5 48-48zm-144 96c25.2 0 36-16.1 36-36s-10.8-36-36-36-36 16.1-36 36 10.8 36 36 36z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 576"><path fill="currentColor" d="M309.6 0L266.4 0 222 47.9c-13.9 15-33.5 23.3-53.9 23L89.2 63 63 89.4 70.9 164.2c.3 19.5-7.3 38.3-21.1 52.1L0 266.1 0 309.6 47.9 354c15 13.9 23.3 33.5 23 53.9l-7.9 78.8 28 26 73.3-12.8c23.9-2.2 47.3 7.7 62.4 26.4l40.2 49.6 42.3 0 40.2-49.6c15.1-18.7 38.5-28.5 62.4-26.4l73.3 12.8 28-26-7.9-78.8c-.3-20.4 8-40 23-53.9l47.9-44.4 0-43.5-49.8-49.8c-13.8-13.8-21.4-32.6-21.1-52.1l7.9-74.8-26.3-26.4-78.8 7.9c-20.4 .3-40-8-53.9-23L309.6 0zM288 64.4l4.8 9.4c26.8 52.1 87.4 77.2 143.2 59.3l10-3.2-3.2 10c-17.9 55.8 7.2 116.4 59.3 143.2l9.4 4.8-9.4 4.8c-52.1 26.8-77.2 87.4-59.3 143.2l3.2 10-10-3.2c-55.8-17.9-116.4 7.2-143.2 59.3l-4.8 9.4-4.8-9.4c-26.8-52.1-87.4-77.2-143.2-59.3l-10 3.2 3.2-10c17.9-55.8-7.2-116.4-59.3-143.2l-9.4-4.8 9.4-4.8c52.1-26.8 77.2-87.4 59.3-143.2l-3.2-10 10 3.2c55.8 17.9 116.4-7.2 143.2-59.3l4.8-9.4zM322.3 224c8.6 14.4 13.7 36.5 13.7 64s-5.1 49.6-13.7 64c-7.8 13.1-18.4 20-34.3 20s-26.5-6.9-34.3-20c-8.6-14.4-13.7-36.5-13.7-64s5.1-49.6 13.7-64c7.8-13.1 18.4-20 34.3-20s26.5 6.9 34.3 20zM288 156c-43.2 0-77.2 14-100.2 39.6-22.6 25.1-31.8 58.5-31.8 92.4s9.2 67.3 31.8 92.4c23 25.6 57 39.6 100.2 39.6s77.2-14 100.2-39.6C410.8 355.3 420 321.9 420 288s-9.2-67.3-31.8-92.4C365.2 170 331.2 156 288 156z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -12,7 +12,22 @@
|
|||||||
root.dataset.theme = finalTheme;
|
root.dataset.theme = finalTheme;
|
||||||
|
|
||||||
toggles().forEach((button) => {
|
toggles().forEach((button) => {
|
||||||
button.textContent = finalTheme === "dark" ? "Hell" : "Dunkel";
|
const nextModeLabel = finalTheme === "dark" ? "Hell" : "Dunkel";
|
||||||
|
const label = button.querySelector("[data-theme-label]");
|
||||||
|
const icon = button.querySelector("[data-theme-icon]");
|
||||||
|
|
||||||
|
if (label) {
|
||||||
|
label.textContent = nextModeLabel;
|
||||||
|
} else {
|
||||||
|
button.textContent = nextModeLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
icon.classList.toggle("icon-sun-theme", finalTheme === "dark");
|
||||||
|
icon.classList.toggle("icon-moon-theme", finalTheme !== "dark");
|
||||||
|
}
|
||||||
|
|
||||||
|
button.setAttribute("aria-label", `${nextModeLabel} aktivieren`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,10 @@
|
|||||||
{% if g.user %}
|
{% if g.user %}
|
||||||
<div class="desktop-header-sub">
|
<div class="desktop-header-sub">
|
||||||
<div class="header-actions desktop-actions">
|
<div class="header-actions desktop-actions">
|
||||||
<button class="theme-toggle ghost-button" type="button" data-theme-toggle>Hell</button>
|
<button class="theme-toggle ghost-button" type="button" data-theme-toggle aria-label="Darstellung wechseln">
|
||||||
|
<span class="ui-icon icon-sun-theme" data-theme-icon></span>
|
||||||
|
<span data-theme-label>Hell</span>
|
||||||
|
</button>
|
||||||
<a class="ghost-button" href="{{ url_for('main.settings_view') }}">Optionen</a>
|
<a class="ghost-button" href="{{ url_for('main.settings_view') }}">Optionen</a>
|
||||||
<a class="user-chip" href="{{ url_for('auth.profile') }}">
|
<a class="user-chip" href="{{ url_for('auth.profile') }}">
|
||||||
<span class="user-chip-title">{{ g.user.display_name or g.user.username }}</span>
|
<span class="user-chip-title">{{ g.user.display_name or g.user.username }}</span>
|
||||||
@@ -114,9 +117,9 @@
|
|||||||
<a class="mobile-extra-link" href="{{ url_for('admin.user_list') }}"><span class="ui-icon icon-sparkles"></span><span>Nutzer</span></a>
|
<a class="mobile-extra-link" href="{{ url_for('admin.user_list') }}"><span class="ui-icon icon-sparkles"></span><span>Nutzer</span></a>
|
||||||
<a class="mobile-extra-link" href="{{ url_for('admin.category_settings') }}"><span class="ui-icon icon-seedling"></span><span>Kategorien</span></a>
|
<a class="mobile-extra-link" href="{{ url_for('admin.category_settings') }}"><span class="ui-icon icon-seedling"></span><span>Kategorien</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="mobile-extra-link mobile-extra-button" type="button" data-theme-toggle>
|
<button class="mobile-extra-link mobile-extra-button" type="button" data-theme-toggle aria-label="Darstellung wechseln">
|
||||||
<span class="ui-icon icon-mobile-screen-button"></span>
|
<span class="ui-icon icon-sun-theme" data-theme-icon></span>
|
||||||
<span>Modus</span>
|
<span data-theme-label>Hell</span>
|
||||||
</button>
|
</button>
|
||||||
<form method="post" action="{{ url_for('auth.logout') }}" class="mobile-extra-form">
|
<form method="post" action="{{ url_for('auth.logout') }}" class="mobile-extra-form">
|
||||||
{{ csrf_input() }}
|
{{ csrf_input() }}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="panel">
|
<article class="panel dashboard-spaced-panel">
|
||||||
<div class="panel-head">
|
<div class="panel-head">
|
||||||
<h2>Kurz griffbereit</h2>
|
<h2>Kurz griffbereit</h2>
|
||||||
<a href="{{ url_for('main.home_view') }}">Alles unter Zuhause</a>
|
<a href="{{ url_for('main.home_view') }}">Alles unter Zuhause</a>
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="two-column">
|
<section class="two-column">
|
||||||
<article class="panel">
|
<article class="panel dashboard-spaced-panel">
|
||||||
<div class="panel-head">
|
<div class="panel-head">
|
||||||
<h2>Was zuhause gut zusammenpasst</h2>
|
<h2>Was zuhause gut zusammenpasst</h2>
|
||||||
<a href="{{ url_for('main.home_view') }}">Zuhause öffnen</a>
|
<a href="{{ url_for('main.home_view') }}">Zuhause öffnen</a>
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
>
|
>
|
||||||
<summary class="day-tile-summary">
|
<summary class="day-tile-summary">
|
||||||
<div class="day-tile-summary-main">
|
<div class="day-tile-summary-main">
|
||||||
<div class="day-tile-icon"><span class="ui-icon icon-calendar"></span></div>
|
<div class="day-tile-icon"><span class="ui-icon {{ daypart_icon_class(section.daypart.slug) }}"></span></div>
|
||||||
<div>
|
<div>
|
||||||
<h2>{{ section.daypart.name }}</h2>
|
<h2>{{ section.daypart.name }}</h2>
|
||||||
{% if section.summary_items %}
|
{% if section.summary_items %}
|
||||||
|
|||||||
@@ -129,7 +129,10 @@
|
|||||||
{% if slot.is_snack_daypart and not slot.visible_by_default %}hidden data-week-snack-slot{% endif %}
|
{% if slot.is_snack_daypart and not slot.visible_by_default %}hidden data-week-snack-slot{% endif %}
|
||||||
>
|
>
|
||||||
<div class="week-slot-head">
|
<div class="week-slot-head">
|
||||||
<strong>{{ slot.daypart.name }}</strong>
|
<div class="week-slot-title">
|
||||||
|
<span class="ui-icon {{ daypart_icon_class(slot.daypart.slug) }}"></span>
|
||||||
|
<strong>{{ slot.daypart.name }}</strong>
|
||||||
|
</div>
|
||||||
<div class="week-slot-head-meta">
|
<div class="week-slot-head-meta">
|
||||||
<span class="week-slot-count{% if slot.entries %} status-home{% endif %}">{{ slot.entries|length }}</span>
|
<span class="week-slot-count{% if slot.entries %} status-home{% endif %}">{{ slot.entries|length }}</span>
|
||||||
<button class="week-slot-add" type="button" data-week-slot-picker-open aria-label="{{ slot.daypart.name }} an {{ weekday_name(card.date) }} direkt ergänzen">+</button>
|
<button class="week-slot-add" type="button" data-week-slot-picker-open aria-label="{{ slot.daypart.name }} an {{ weekday_name(card.date) }} direkt ergänzen">+</button>
|
||||||
|
|||||||