mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
51ab30f436
* fix: hotel day-range clamping in ReservationModal + stale assignment_id on accommodation clear (issues #929, #934)
* ReservationModal hotel start/end pickers now use findIndex-based
positional clamping instead of raw ID arithmetic, matching the fix
applied to DayDetailPanel in 8e05ba7. Prevents inverted
start_day_id/end_day_id on trips with non-monotonic day IDs.
* Clearing accommodation_id on a hotel reservation now forces
assignment_id to null in the save payload, removing the stale
day-assignment link that had no UI path to clear.
* Migration: swaps inverted start_day_id/end_day_id pairs in
day_accommodations where start.day_number > end.day_number,
recovering existing corrupt rows from the pre-fix picker bug.
* Tests FE-PLANNER-RESMODAL-050/051/052 cover both fixes.
* fix: preserve line breaks and wrap long URLs in notes fields (#930)
Add remark-breaks to all reservation/place notes markdown renderers so
single newlines render as <br>, and add wordBreak/overflowWrap styles
so long unbroken URLs (e.g. booking.com tracking links) wrap correctly.
* fix: delete linked budget item when accommodation or reservation is deleted (#933)
Deleting an accommodation or reservation now removes any budget item
linked via reservation_id, preventing orphan entries in the Budget page.
Also fixes a pre-existing payload-shape bug where budget:deleted was
broadcast with {id} instead of {itemId}, breaking live updates for
collaborators when a reservation price was cleared.
Tests added: ACCOM-006, RESV-009b, BUDGET-004b.
* fix: restore scroll position in mobile Plan and Places sidebars on reopen (issue #932)
Both DayPlanSidebar and PlacesSidebar have their own internal scroll
containers (overflowY: auto). Scroll events don't bubble, so previous
attempts that tracked scrollTop on the outer portal div never fired.
Each sidebar now accepts initialScrollTop and onScrollTopChange props.
The internal scroll container saves its scrollTop via onScrollTopChange
on every scroll event, and restores it via useLayoutEffect on mount
(before the browser paints, so no visible flash).
TripPlannerPage holds the saved values in refs (mobilePlanScrollTopRef,
mobilePlacesScrollTopRef) and passes them through on each portal mount.
* fix(map): prevent auto zoom-out when opening/closing place inspector (issue #921)
Both Leaflet and Mapbox GL renderers now gate fitBounds strictly on fitKey
increments from the parent. Selecting or dismissing a place inspector changes
paddingOpts (via hasInspector) but no longer triggers a re-fit that zoomed
the map out to the full trip extent when no day was selected.
Also removes the zoom-12 visibility gate on Leaflet route info pills so they
render at all zoom levels when a route is active.
* fix: translate mobile bottom-nav tab labels (issue #931)
Replaced hardcoded English labels in BottomNav with t() lookups using the same translation keys as the desktop navbar (nav.myTrips, admin.addons.catalog.*.name).
815 lines
29 KiB
CSS
815 lines
29 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
html { height: 100%; overflow: hidden; background-color: var(--bg-primary); }
|
|
body { height: 100%; overflow: auto; overscroll-behavior: none; -webkit-overflow-scrolling: touch; }
|
|
|
|
|
|
/* Journey desktop feed: hide scrollbar (right column is a sticky map, a
|
|
visible scrollbar on the left breaks the polarsteps-style reading feel). */
|
|
.journey-feed-scroll { scrollbar-width: none; -ms-overflow-style: none; }
|
|
.journey-feed-scroll::-webkit-scrollbar { display: none; }
|
|
|
|
/* Leaflet Popups — Enter-Animation vom Anchor-Tip */
|
|
.leaflet-popup {
|
|
animation: trek-popover-enter 220ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
transform-origin: bottom center;
|
|
will-change: transform, opacity;
|
|
}
|
|
.leaflet-popup-content-wrapper {
|
|
border-radius: 14px !important;
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18) !important;
|
|
background: var(--bg-card) !important;
|
|
color: var(--text-primary) !important;
|
|
border: 1px solid var(--border-faint);
|
|
}
|
|
.leaflet-popup-tip {
|
|
background: var(--bg-card) !important;
|
|
}
|
|
.leaflet-popup-close-button {
|
|
transition: color 150ms cubic-bezier(0.23, 1, 0.32, 1), transform 150ms cubic-bezier(0.23, 1, 0.32, 1) !important;
|
|
}
|
|
.leaflet-popup-close-button:hover {
|
|
transform: scale(1.15);
|
|
color: var(--text-primary) !important;
|
|
}
|
|
|
|
.atlas-tooltip {
|
|
background: rgba(10, 10, 20, 0.6) !important;
|
|
backdrop-filter: blur(20px) saturate(180%) !important;
|
|
-webkit-backdrop-filter: blur(20px) saturate(180%) !important;
|
|
color: #f1f5f9 !important;
|
|
border: 1px solid rgba(255,255,255,0.1) !important;
|
|
border-radius: 14px !important;
|
|
padding: 10px 14px !important;
|
|
font-size: 12px !important;
|
|
font-family: inherit !important;
|
|
box-shadow: 0 8px 32px rgba(0,0,0,0.25) !important;
|
|
transition: none !important;
|
|
}
|
|
.atlas-tooltip::before { border-top-color: rgba(10, 10, 20, 0.6) !important; }
|
|
html:not(.dark) .atlas-tooltip {
|
|
background: rgba(255, 255, 255, 0.75) !important;
|
|
color: #0f172a !important;
|
|
border: 1px solid rgba(0,0,0,0.08) !important;
|
|
box-shadow: 0 8px 32px rgba(0,0,0,0.1) !important;
|
|
}
|
|
html:not(.dark) .atlas-tooltip::before { border-top-color: rgba(255, 255, 255, 0.75) !important; }
|
|
.leaflet-tooltip.atlas-tooltip { opacity: 1 !important; }
|
|
.leaflet-tooltip-pane { transition: none !important; }
|
|
.leaflet-fade-anim .leaflet-tooltip { transition: none !important; opacity: 1 !important; }
|
|
|
|
.dark .leaflet-control-zoom a {
|
|
background: rgba(10, 10, 20, 0.7) !important;
|
|
color: #e2e8f0 !important;
|
|
border-color: rgba(255, 255, 255, 0.1) !important;
|
|
backdrop-filter: blur(12px);
|
|
}
|
|
.dark .leaflet-control-zoom a:hover {
|
|
background: rgba(30, 30, 40, 0.8) !important;
|
|
}
|
|
@media (max-width: 767px) {
|
|
.leaflet-control-zoom { display: none !important; }
|
|
}
|
|
|
|
/* Dark mode overrides for pages using hardcoded slate-* Tailwind classes */
|
|
html.dark .bg-slate-50 { background-color: var(--bg-secondary) !important; }
|
|
html.dark .bg-white { background-color: var(--bg-card) !important; }
|
|
html.dark .bg-slate-100 { background-color: var(--bg-secondary) !important; }
|
|
html.dark .bg-slate-900.text-white { background-color: #e2e8f0 !important; color: #0f172a !important; }
|
|
html.dark .border-slate-200, html.dark .border-slate-300 { border-color: var(--border-primary) !important; }
|
|
html.dark .border-slate-100, html.dark .border-b-slate-100 { border-color: var(--border-secondary) !important; }
|
|
html.dark .text-slate-900 { color: var(--text-primary) !important; }
|
|
html.dark .text-slate-700 { color: var(--text-secondary) !important; }
|
|
html.dark .text-slate-600 { color: var(--text-muted) !important; }
|
|
html.dark .text-slate-500 { color: var(--text-muted) !important; }
|
|
html.dark .text-slate-400 { color: var(--text-faint) !important; }
|
|
html.dark .hover\:bg-slate-50:hover, html.dark .hover\:bg-slate-100:hover { background-color: var(--bg-hover) !important; }
|
|
html.dark .hover\:text-slate-900:hover { color: var(--text-primary) !important; }
|
|
html.dark .hover\:bg-slate-700:hover { background-color: var(--bg-hover) !important; }
|
|
html.dark .divide-slate-100 > :not([hidden]) ~ :not([hidden]) { border-color: var(--border-secondary) !important; }
|
|
html.dark .focus\:ring-slate-400:focus { --tw-ring-color: var(--text-faint) !important; }
|
|
html.dark input[class*="border-slate"], html.dark input[class*="text-slate"] { background: var(--bg-secondary) !important; color: var(--text-primary) !important; border-color: var(--border-primary) !important; }
|
|
html.dark .text-amber-900 { color: #fbbf24 !important; }
|
|
html.dark .text-amber-700 { color: #f59e0b !important; }
|
|
html.dark .bg-amber-50 { background-color: rgba(245,158,11,0.1) !important; }
|
|
html.dark .border-amber-200 { border-color: rgba(245,158,11,0.2) !important; }
|
|
html.dark .disabled\:bg-slate-400:disabled { background-color: var(--text-faint) !important; }
|
|
html.dark button.bg-slate-900 { background-color: #e2e8f0 !important; color: #0f172a !important; opacity: 1 !important; }
|
|
html.dark button.bg-slate-900:hover { background-color: #cbd5e1 !important; }
|
|
html.dark button.bg-slate-900:disabled { background-color: #ffffff !important; color: #000000 !important; opacity: 0.4 !important; }
|
|
html.dark span.bg-slate-900 { background-color: #e2e8f0 !important; color: #0f172a !important; }
|
|
html.dark span.bg-slate-100 { background-color: var(--bg-secondary) !important; color: var(--text-muted) !important; }
|
|
html.dark .border-b { border-bottom-color: var(--border-secondary) !important; }
|
|
/* Gray variants (CategoryManager, BackupPanel) */
|
|
html.dark .bg-gray-50 { background-color: var(--bg-secondary) !important; }
|
|
html.dark .bg-gray-100 { background-color: var(--bg-secondary) !important; }
|
|
html.dark .border-gray-200, html.dark .border-gray-300 { border-color: var(--border-primary) !important; }
|
|
html.dark .border-gray-100 { border-color: var(--border-secondary) !important; }
|
|
html.dark .text-gray-900 { color: var(--text-primary) !important; }
|
|
html.dark .text-gray-700 { color: var(--text-secondary) !important; }
|
|
html.dark .text-gray-600 { color: var(--text-muted) !important; }
|
|
html.dark .text-gray-500 { color: var(--text-muted) !important; }
|
|
html.dark .text-gray-400 { color: var(--text-faint) !important; }
|
|
html.dark .text-gray-300 { color: var(--text-faint) !important; }
|
|
html.dark .hover\:bg-gray-50:hover, html.dark .hover\:bg-gray-200:hover { background-color: var(--bg-hover) !important; }
|
|
html.dark .hover\:border-gray-200:hover, html.dark .hover\:border-gray-400:hover { border-color: var(--border-primary) !important; }
|
|
html.dark input.bg-white, html.dark input[class*="bg-white"] { background: var(--bg-secondary) !important; color: var(--text-primary) !important; }
|
|
html.dark .bg-gray-200 { background-color: var(--border-primary) !important; }
|
|
html.dark .border-gray-300.border-t-slate-600 { border-color: var(--border-primary) !important; border-top-color: var(--text-primary) !important; }
|
|
/* Modal buttons */
|
|
html.dark button[class*="text-slate-600"][class*="border-slate-200"] { color: var(--text-muted) !important; border-color: var(--border-primary) !important; }
|
|
html.dark button[class*="text-slate-600"][class*="border-slate-200"]:hover { background: var(--bg-hover) !important; }
|
|
/* Dashed borders */
|
|
html.dark .border-dashed.border-gray-300 { border-color: var(--border-primary) !important; }
|
|
html.dark .bg-slate-50\/60, html.dark [class*="bg-slate-50/"] { background-color: transparent !important; }
|
|
|
|
/* Reorder buttons: desktop = original style; mobile = always visible, larger touch targets */
|
|
.reorder-buttons {
|
|
flex-direction: column;
|
|
opacity: 0;
|
|
}
|
|
.reorder-buttons button {
|
|
background: none !important;
|
|
padding: 1px 2px;
|
|
}
|
|
@media (max-width: 767px) {
|
|
.reorder-buttons {
|
|
flex-direction: row !important;
|
|
opacity: 1 !important;
|
|
align-items: center;
|
|
margin-left: auto;
|
|
}
|
|
.reorder-buttons button {
|
|
background: var(--bg-tertiary) !important;
|
|
border-radius: 6px;
|
|
width: 32px;
|
|
height: 32px;
|
|
padding: 0 !important;
|
|
display: flex !important;
|
|
align-items: center !important;
|
|
justify-content: center !important;
|
|
}
|
|
.note-edit-buttons {
|
|
opacity: 1 !important;
|
|
}
|
|
}
|
|
|
|
/* Ort-Zeile Hover: Sortier-Buttons anzeigen */
|
|
.place-row:hover .reorder-btns {
|
|
opacity: 1 !important;
|
|
}
|
|
|
|
/* Ladeanimation */
|
|
@keyframes spin {
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
/* ── Press-Feedback + bessere Easings (Emil Kowalski) ─────────── */
|
|
/* Buttons sollen antworten wenn sie gedrückt werden. */
|
|
button:not(:disabled):not([data-no-press]),
|
|
[role="button"]:not([aria-disabled="true"]):not([data-no-press]) {
|
|
transition-property: transform, color, background-color, border-color, box-shadow, opacity, filter !important;
|
|
transition-duration: 180ms;
|
|
transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
|
|
}
|
|
button:not(:disabled):not([data-no-press]):active,
|
|
[role="button"]:not([aria-disabled="true"]):not([data-no-press]):active {
|
|
transform: scale(0.97);
|
|
transition-duration: 80ms;
|
|
}
|
|
|
|
/* Tailwind-Default-Easing durch ease-out-quint ersetzen.
|
|
Eingebaute CSS-Easings sind kraftlos; ease-out-quint hat Punch. */
|
|
.transition,
|
|
.transition-all,
|
|
.transition-colors,
|
|
.transition-opacity,
|
|
.transition-transform,
|
|
.transition-shadow {
|
|
transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
|
|
}
|
|
|
|
/* Input-Focus transitions — border + ring faden weich ein */
|
|
input, textarea, select {
|
|
transition: border-color 150ms cubic-bezier(0.23, 1, 0.32, 1),
|
|
box-shadow 150ms cubic-bezier(0.23, 1, 0.32, 1),
|
|
background-color 150ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
}
|
|
|
|
/* Back-Button Icon-Slide on hover */
|
|
.trek-back-btn .trek-back-icon {
|
|
transition: transform 200ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
}
|
|
.trek-back-btn:hover .trek-back-icon {
|
|
transform: translateX(-2px);
|
|
}
|
|
|
|
/* Global focus-visible ring — konsistent überall */
|
|
:focus-visible {
|
|
outline: 2px solid var(--accent);
|
|
outline-offset: 2px;
|
|
border-radius: 4px;
|
|
}
|
|
button:focus-visible, [role="button"]:focus-visible, a:focus-visible {
|
|
outline-offset: 3px;
|
|
}
|
|
input:focus-visible, textarea:focus-visible, select:focus-visible {
|
|
outline: none;
|
|
}
|
|
|
|
/* Theme crossfade — beim Dark/Light switch, Hauptflächen + Text faden ihre Farben.
|
|
Sparingly: nur background-color und color bekommen eine Transition. */
|
|
html.trek-theme-transitioning,
|
|
html.trek-theme-transitioning body,
|
|
html.trek-theme-transitioning *:not(img):not(video):not(canvas):not([class*="trek-skeleton"]):not(.leaflet-layer) {
|
|
transition:
|
|
background-color 320ms cubic-bezier(0.23, 1, 0.32, 1),
|
|
color 320ms cubic-bezier(0.23, 1, 0.32, 1),
|
|
border-color 320ms cubic-bezier(0.23, 1, 0.32, 1),
|
|
fill 320ms cubic-bezier(0.23, 1, 0.32, 1) !important;
|
|
}
|
|
|
|
/* Touch-Geräte: iOS-Tap-Highlight weg (wir haben eigenes Press-Feedback) */
|
|
@media (hover: none) {
|
|
button, [role="button"], a {
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
}
|
|
html, body {
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
/* Tabular-nums global für Time/Date/Currency/Counter */
|
|
time, .tabular-nums, [data-tabular],
|
|
input[type="number"], input[type="time"], input[type="date"], input[type="datetime-local"] {
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
/* Wenn Element explizit ease-in-out nutzt (z.B. Accordions), nicht überschreiben.
|
|
Tailwind setzt ease-in-out via eigener Klasse — die gewinnt durch letzte Deklaration. */
|
|
|
|
/* Press-Scale für clickbare Divs (Cards, Tiles) — sanfter als Buttons */
|
|
[data-press]:active {
|
|
transform: scale(0.985);
|
|
transition-duration: 80ms;
|
|
}
|
|
|
|
/* ── Popover/Dropdown Enter-Animationen ─────────────────────────
|
|
Emil: Popovers sollen von ihrem Trigger aus scalen, nicht vom Center.
|
|
Start bei scale(0.95) — nichts in der echten Welt poppt aus dem Nichts. */
|
|
@keyframes trek-menu-enter {
|
|
from { opacity: 0; transform: scale(0.95) translateY(-4px); }
|
|
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
}
|
|
@keyframes trek-popover-enter {
|
|
from { opacity: 0; transform: scale(0.96); }
|
|
to { opacity: 1; transform: scale(1); }
|
|
}
|
|
@keyframes trek-modal-enter {
|
|
from { opacity: 0; transform: scale(0.97); }
|
|
to { opacity: 1; transform: scale(1); }
|
|
}
|
|
@keyframes trek-backdrop-enter {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
@keyframes trek-toast-enter {
|
|
from { opacity: 0; transform: translateY(8px) scale(0.96); }
|
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
}
|
|
@keyframes trek-progress-fill {
|
|
from { width: 0%; }
|
|
to { width: var(--trek-progress-to, 0%); }
|
|
}
|
|
|
|
/* Pie-Chart Reveal — rotate + fade-in, gibt dem Kreisdiagramm ein "Draw"-Gefühl */
|
|
@keyframes trek-pie-reveal {
|
|
from { opacity: 0; transform: rotate(-90deg) scale(0.85); }
|
|
to { opacity: 1; transform: rotate(0deg) scale(1); }
|
|
}
|
|
.trek-pie-reveal {
|
|
animation: trek-pie-reveal 900ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
|
transform-origin: center;
|
|
will-change: transform, opacity;
|
|
}
|
|
|
|
/* Bar-Chart Reveal — horizontaler Fill von links */
|
|
@keyframes trek-bar-fill {
|
|
from { transform: scaleX(0); }
|
|
to { transform: scaleX(1); }
|
|
}
|
|
.trek-bar-fill {
|
|
animation: trek-bar-fill 700ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
|
transform-origin: left center;
|
|
will-change: transform;
|
|
}
|
|
|
|
/* Page-Transition — subtiler Fade-Up beim Mount */
|
|
@keyframes trek-page-enter {
|
|
from { opacity: 0; transform: translateY(6px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.trek-page-enter {
|
|
animation: trek-page-enter 220ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
|
}
|
|
|
|
/* Skeleton shimmer — ein fließender Gradient-Strip überquert den Platzhalter */
|
|
@keyframes trek-shimmer {
|
|
from { background-position: -200% 0; }
|
|
to { background-position: 200% 0; }
|
|
}
|
|
.trek-skeleton {
|
|
background: linear-gradient(
|
|
90deg,
|
|
var(--bg-tertiary) 0%,
|
|
var(--bg-hover) 50%,
|
|
var(--bg-tertiary) 100%
|
|
);
|
|
background-size: 200% 100%;
|
|
animation: trek-shimmer 1.6s linear infinite;
|
|
border-radius: 8px;
|
|
color: transparent;
|
|
user-select: none;
|
|
}
|
|
.dark .trek-skeleton {
|
|
background: linear-gradient(
|
|
90deg,
|
|
rgba(255,255,255,0.04) 0%,
|
|
rgba(255,255,255,0.08) 50%,
|
|
rgba(255,255,255,0.04) 100%
|
|
);
|
|
background-size: 200% 100%;
|
|
}
|
|
.trek-menu-enter {
|
|
animation: trek-menu-enter 200ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
transform-origin: top right;
|
|
will-change: transform, opacity;
|
|
}
|
|
.trek-menu-enter-left {
|
|
animation: trek-menu-enter 200ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
transform-origin: top left;
|
|
will-change: transform, opacity;
|
|
}
|
|
.trek-popover-enter {
|
|
animation: trek-popover-enter 180ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
will-change: transform, opacity;
|
|
}
|
|
.trek-modal-enter {
|
|
animation: trek-modal-enter 220ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
will-change: transform, opacity;
|
|
}
|
|
|
|
/* Mobile-Drawer-Feel — Modal slidet von unten rein, wird unten am Screen angedockt */
|
|
@keyframes trek-drawer-enter {
|
|
from { opacity: 0; transform: translateY(100%); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
@media (max-width: 639px) {
|
|
.trek-modal-enter {
|
|
animation: trek-drawer-enter 320ms cubic-bezier(0.32, 0.72, 0, 1);
|
|
border-bottom-left-radius: 0 !important;
|
|
border-bottom-right-radius: 0 !important;
|
|
margin-top: auto !important;
|
|
align-self: flex-end;
|
|
}
|
|
}
|
|
.trek-backdrop-enter {
|
|
animation: trek-backdrop-enter 180ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
}
|
|
.trek-toast-enter {
|
|
animation: trek-toast-enter 260ms cubic-bezier(0.23, 1, 0.32, 1);
|
|
will-change: transform, opacity;
|
|
}
|
|
|
|
/* Stagger-Helpers für Listen — Enter-Animation mit Offset */
|
|
@keyframes trek-fade-up {
|
|
from { opacity: 0; transform: translateY(6px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.trek-stagger > * {
|
|
animation: trek-fade-up 280ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
|
}
|
|
.trek-stagger > *:nth-child(1) { animation-delay: 0ms; }
|
|
.trek-stagger > *:nth-child(2) { animation-delay: 40ms; }
|
|
.trek-stagger > *:nth-child(3) { animation-delay: 80ms; }
|
|
.trek-stagger > *:nth-child(4) { animation-delay: 120ms; }
|
|
.trek-stagger > *:nth-child(5) { animation-delay: 160ms; }
|
|
.trek-stagger > *:nth-child(6) { animation-delay: 200ms; }
|
|
.trek-stagger > *:nth-child(7) { animation-delay: 240ms; }
|
|
.trek-stagger > *:nth-child(8) { animation-delay: 280ms; }
|
|
.trek-stagger > *:nth-child(n+9) { animation-delay: 320ms; }
|
|
|
|
/* Reduced motion — Emil's Accessibility-Regel: fewer and gentler, not zero */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.trek-menu-enter, .trek-menu-enter-left, .trek-popover-enter,
|
|
.trek-modal-enter, .trek-toast-enter, .trek-stagger > * {
|
|
animation: trek-backdrop-enter 120ms ease-out;
|
|
}
|
|
.trek-skeleton {
|
|
animation: none;
|
|
background: var(--bg-tertiary);
|
|
}
|
|
button:not(:disabled):not([data-no-press]):active,
|
|
[role="button"]:not([aria-disabled="true"]):not([data-no-press]):active,
|
|
[data-press]:active {
|
|
transform: none;
|
|
}
|
|
/* Parallax & lift disablen */
|
|
.group:hover img,
|
|
.group:hover .cover-img { transform: none !important; }
|
|
*:hover { translate: none !important; }
|
|
}
|
|
|
|
/* ── Design tokens ─────────────────────────────── */
|
|
:root {
|
|
/* Easing curves — stärker als die CSS-Defaults, siehe easing.dev */
|
|
--ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
|
|
--ease-in-out-quint: cubic-bezier(0.77, 0, 0.175, 1);
|
|
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
|
|
|
|
--safe-top: env(safe-area-inset-top, 0px);
|
|
--nav-h: 0px;
|
|
--bottom-nav-h: 0px;
|
|
--font-system: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif;
|
|
--sp-1: 4px;
|
|
--sp-2: 8px;
|
|
--sp-3: 12px;
|
|
--sp-4: 16px;
|
|
--sp-6: 24px;
|
|
--radius-sm: 8px;
|
|
--radius-md: 12px;
|
|
--radius-lg: 16px;
|
|
--radius-xl: 20px;
|
|
--shadow-card: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
|
|
--shadow-elevated: 0 4px 16px rgba(0,0,0,0.1);
|
|
|
|
/* Theme colors */
|
|
--bg-primary: #ffffff;
|
|
--bg-secondary: #f8fafc;
|
|
--bg-tertiary: #f1f5f9;
|
|
--bg-elevated: rgba(250,250,250,0.82);
|
|
--bg-card: #ffffff;
|
|
--bg-input: #ffffff;
|
|
--bg-hover: rgba(0,0,0,0.03);
|
|
--bg-selected: #e2e8f0;
|
|
--text-primary: #111827;
|
|
--text-secondary: #374151;
|
|
--text-muted: #6b7280;
|
|
--text-faint: #9ca3af;
|
|
--border-primary: #e5e7eb;
|
|
--border-secondary: #f3f4f6;
|
|
--border-faint: rgba(0,0,0,0.06);
|
|
--accent: #111827;
|
|
--accent-text: #ffffff;
|
|
--sidebar-bg: rgba(250,250,250,0.82);
|
|
--sidebar-shadow: 0 4px 32px rgba(0,0,0,0.10), 0 0 0 1px rgba(0,0,0,0.06);
|
|
--tooltip-bg: rgba(255,255,255,0.96);
|
|
--scrollbar-track: #f1f5f9;
|
|
--scrollbar-thumb: #d1d5db;
|
|
--scrollbar-hover: #9ca3af;
|
|
|
|
/* Journey design tokens */
|
|
--journal-bg: #FAFAFA;
|
|
--journal-card: #FFFFFF;
|
|
--journal-border: #E4E4E7;
|
|
--journal-accent: #6366F1;
|
|
--journal-text: #09090B;
|
|
--journal-muted: #71717A;
|
|
--journal-faint: #A1A1AA;
|
|
--mood-amazing: #E8654A;
|
|
--mood-good: #EF9F27;
|
|
--mood-neutral: #94928C;
|
|
--mood-tired: #6B9BD2;
|
|
--mood-rough: #9B8EC4;
|
|
}
|
|
|
|
@media (max-width: 767px) {
|
|
:root { --bottom-nav-h: calc(84px + env(safe-area-inset-bottom, 0px)); }
|
|
}
|
|
|
|
@media (min-width: 768px) {
|
|
:root { --nav-h: calc(56px + env(safe-area-inset-top, 0px)); }
|
|
}
|
|
|
|
.dark {
|
|
--bg-primary: #121215;
|
|
--bg-secondary: #1a1a1e;
|
|
--bg-tertiary: #1c1c21;
|
|
--bg-elevated: rgba(19,19,22,0.82);
|
|
--bg-card: #131316;
|
|
--bg-input: #1c1c21;
|
|
--bg-hover: rgba(255,255,255,0.06);
|
|
--bg-selected: rgba(255,255,255,0.1);
|
|
--text-primary: #f4f4f5;
|
|
--text-secondary: #d4d4d8;
|
|
--text-muted: #a1a1aa;
|
|
--text-faint: #71717a;
|
|
--border-primary: #27272a;
|
|
--border-secondary: #1c1c21;
|
|
--border-faint: rgba(255,255,255,0.07);
|
|
--accent: #e4e4e7;
|
|
--accent-text: #09090b;
|
|
--sidebar-bg: rgba(19,19,22,0.82);
|
|
--sidebar-shadow: 0 4px 32px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.05);
|
|
--tooltip-bg: rgba(19,19,22,0.96);
|
|
--scrollbar-track: #131316;
|
|
--scrollbar-thumb: #3f3f46;
|
|
--scrollbar-hover: #52525b;
|
|
|
|
/* Journey design tokens (dark) */
|
|
--journal-bg: #09090B;
|
|
--journal-card: #18181B;
|
|
--journal-border: #27272A;
|
|
--journal-accent: #818CF8;
|
|
--journal-text: #FAFAFA;
|
|
--journal-muted: #A1A1AA;
|
|
--journal-faint: #52525B;
|
|
--mood-amazing: #f28a6e;
|
|
--mood-good: #f5b84d;
|
|
--mood-neutral: #9a9a94;
|
|
--mood-tired: #6db3f0;
|
|
--mood-rough: #a9a3f0;
|
|
}
|
|
|
|
body {
|
|
font-family: var(--font-system);
|
|
background-color: var(--bg-primary);
|
|
color: var(--text-primary);
|
|
transition: background-color 0.2s, color 0.2s;
|
|
}
|
|
|
|
/* ── Marker cluster custom styling ────────────── */
|
|
.marker-cluster-wrapper {
|
|
background: transparent !important;
|
|
border: none !important;
|
|
}
|
|
|
|
.marker-cluster-custom {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 50%;
|
|
background: #111827;
|
|
border: 2.5px solid rgba(255, 255, 255, 0.9);
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25), 0 0 0 2px rgba(17, 24, 39, 0.15);
|
|
cursor: pointer;
|
|
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
}
|
|
|
|
.marker-cluster-custom:hover {
|
|
transform: scale(1.1);
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35), 0 0 0 3px rgba(17, 24, 39, 0.2);
|
|
}
|
|
|
|
.marker-cluster-custom span {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif;
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
color: #ffffff;
|
|
line-height: 1;
|
|
}
|
|
|
|
/* Hide default markercluster styles we don't need */
|
|
.marker-cluster-small,
|
|
.marker-cluster-medium,
|
|
.marker-cluster-large {
|
|
background: transparent !important;
|
|
}
|
|
.marker-cluster-small div,
|
|
.marker-cluster-medium div,
|
|
.marker-cluster-large div {
|
|
background: transparent !important;
|
|
}
|
|
|
|
/* ── Leaflet z-index ───────────────────────────── */
|
|
.leaflet-container {
|
|
z-index: 0;
|
|
}
|
|
.leaflet-pane {
|
|
z-index: 0 !important;
|
|
}
|
|
.leaflet-top, .leaflet-bottom {
|
|
z-index: 1 !important;
|
|
}
|
|
|
|
/* ── iOS-style map tooltip ─────────────────────── */
|
|
.leaflet-tooltip.map-tooltip {
|
|
background: var(--tooltip-bg);
|
|
backdrop-filter: blur(8px);
|
|
-webkit-backdrop-filter: blur(8px);
|
|
border: none;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
|
padding: 5px 10px;
|
|
font-family: var(--font-system);
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
pointer-events: none;
|
|
color: var(--text-primary);
|
|
}
|
|
.leaflet-tooltip.map-tooltip::before,
|
|
.leaflet-tooltip-left.map-tooltip::before,
|
|
.leaflet-tooltip-top.map-tooltip::before {
|
|
display: none;
|
|
}
|
|
|
|
/* Scrollbars — styled on desktop, hidden on mobile */
|
|
::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
::-webkit-scrollbar-button {
|
|
display: none;
|
|
height: 0;
|
|
width: 0;
|
|
}
|
|
::-webkit-scrollbar-track {
|
|
background: var(--scrollbar-track);
|
|
border-radius: 3px;
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
background: var(--scrollbar-thumb);
|
|
border-radius: 3px;
|
|
}
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: var(--scrollbar-hover);
|
|
}
|
|
|
|
@media (max-width: 767px) {
|
|
* { scrollbar-width: none; }
|
|
::-webkit-scrollbar { width: 0; height: 0; }
|
|
}
|
|
|
|
.route-info-pill { background: none !important; border: none !important; box-shadow: none !important; width: auto !important; height: auto !important; margin: 0 !important; }
|
|
.chat-scroll { overflow-y: auto !important; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
|
|
.chat-scroll::-webkit-scrollbar { width: 0; background: transparent; }
|
|
|
|
|
|
/* Einheitliche Formular-Inputs */
|
|
.form-input {
|
|
width: 100%;
|
|
border: 1px solid var(--border-primary);
|
|
border-radius: 10px;
|
|
padding: 8px 14px;
|
|
font-size: 13px;
|
|
font-family: inherit;
|
|
outline: none;
|
|
box-sizing: border-box;
|
|
color: var(--text-primary);
|
|
background: var(--bg-input);
|
|
transition: border-color 0.15s;
|
|
}
|
|
.form-input:focus {
|
|
border-color: var(--text-faint);
|
|
}
|
|
.form-input::placeholder {
|
|
color: var(--text-faint);
|
|
}
|
|
|
|
/* Brand images: no save/copy/drag */
|
|
img[alt="TREK"] {
|
|
pointer-events: none;
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
-webkit-user-drag: none;
|
|
-webkit-touch-callout: none;
|
|
}
|
|
|
|
/* Weiche Übergänge */
|
|
.transition-smooth {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
|
|
|
|
/* Tagesliste */
|
|
.day-list-item {
|
|
transition: background-color 0.15s ease;
|
|
}
|
|
|
|
.day-list-item:hover {
|
|
background-color: var(--bg-secondary);
|
|
}
|
|
|
|
.day-list-item.active {
|
|
background-color: #4f46e5;
|
|
color: white;
|
|
}
|
|
|
|
.scroll-container {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
|
}
|
|
|
|
/* ── Dark-Mode: Tailwind-Klassen ─────────────── */
|
|
.dark .bg-slate-50 { background-color: #131316 !important; }
|
|
.dark .bg-slate-100 { background-color: #1c1c21 !important; }
|
|
.dark .bg-white { background-color: #09090b !important; }
|
|
.dark .bg-gray-50 { background-color: #131316 !important; }
|
|
.dark .bg-gray-100 { background-color: #1c1c21 !important; }
|
|
.dark .text-slate-900, .dark .text-gray-900, .dark .text-slate-800 { color: #f4f4f5 !important; }
|
|
.dark .text-slate-700, .dark .text-gray-700 { color: #d4d4d8 !important; }
|
|
.dark .text-slate-600, .dark .text-gray-600 { color: #a1a1aa !important; }
|
|
.dark .text-slate-500, .dark .text-gray-500 { color: #a1a1aa !important; }
|
|
.dark .text-slate-400, .dark .text-gray-400 { color: #71717a !important; }
|
|
.dark .border-slate-200, .dark .border-gray-200, .dark .border-slate-300 { border-color: #27272a !important; }
|
|
.dark .border-gray-100, .dark .border-slate-100 { border-color: #1c1c21 !important; }
|
|
.dark .hover\:bg-slate-50:hover, .dark .hover\:bg-gray-50:hover { background-color: #1c1c21 !important; }
|
|
.dark .bg-slate-50\/60 { background-color: transparent !important; }
|
|
.dark .divide-slate-100 > :not([hidden]) ~ :not([hidden]) { border-color: #27272a !important; }
|
|
.dark .bg-slate-100 { background-color: #27272a !important; }
|
|
.dark .bg-slate-900 { background-color: #e4e4e7 !important; color: #09090b !important; }
|
|
.dark .hover\:bg-slate-700:hover { background-color: #d4d4d8 !important; color: #09090b !important; }
|
|
.dark input, .dark textarea, .dark select {
|
|
background-color: #1c1c21;
|
|
color: #f4f4f5;
|
|
border-color: #27272a;
|
|
}
|
|
.dark input::placeholder, .dark textarea::placeholder { color: #71717a; }
|
|
.dark .bg-emerald-50 { background-color: rgba(16,185,129,0.15) !important; }
|
|
.dark .bg-red-50 { background-color: rgba(239,68,68,0.15) !important; }
|
|
|
|
/* Ladebildschirm */
|
|
.dark .min-h-screen { background-color: var(--bg-primary) !important; }
|
|
|
|
/* Modal-Hintergrund */
|
|
.dark .modal-backdrop { background: rgba(0,0,0,0.6); }
|
|
|
|
/* ── Dark: Fallback für Komponenten die noch nicht auf CSS-Variablen umgestellt sind ── */
|
|
.dark {
|
|
color-scheme: dark;
|
|
}
|
|
|
|
|
|
/* Toast-Animationen */
|
|
@keyframes slideUp {
|
|
from { transform: translateY(100%); }
|
|
to { transform: translateY(0); }
|
|
}
|
|
|
|
@keyframes slide-in-right {
|
|
from { transform: translateX(100%); opacity: 0; }
|
|
to { transform: translateX(0); opacity: 1; }
|
|
}
|
|
|
|
@keyframes slide-out-right {
|
|
from { transform: translateX(0); opacity: 1; }
|
|
to { transform: translateX(100%); opacity: 0; }
|
|
}
|
|
|
|
.toast-enter {
|
|
animation: slide-in-right 0.3s ease-out forwards;
|
|
}
|
|
|
|
.toast-exit {
|
|
animation: slide-out-right 0.3s ease-in forwards;
|
|
}
|
|
|
|
/* Modal-Hintergrund */
|
|
.modal-backdrop {
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
/* Fortschrittsbalken */
|
|
@keyframes progress-fill {
|
|
from { width: 0; }
|
|
to { width: var(--progress); }
|
|
}
|
|
|
|
/* Anmeldeseiten-Gradient */
|
|
.auth-gradient {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
}
|
|
|
|
/* Bildanzeige-Overlay */
|
|
.lightbox-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(0, 0, 0, 0.95);
|
|
z-index: 1000;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
/* Markdown in Collab Notes */
|
|
.collab-note-md strong, .collab-note-md-full strong { font-weight: 700 !important; }
|
|
.collab-note-md em, .collab-note-md-full em { font-style: italic !important; }
|
|
.collab-note-md h1, .collab-note-md h2, .collab-note-md h3 { font-weight: 700 !important; margin: 0; }
|
|
.collab-note-md-full h1 { font-size: 1.3em !important; font-weight: 700 !important; margin: 0.8em 0 0.3em; }
|
|
.collab-note-md-full h2 { font-size: 1.15em !important; font-weight: 700 !important; margin: 0.8em 0 0.3em; }
|
|
.collab-note-md-full h3 { font-size: 1em !important; font-weight: 700 !important; margin: 0.8em 0 0.3em; }
|
|
.collab-note-md p, .collab-note-md-full p { margin: 0 0 0.3em; }
|
|
.collab-note-md ul, .collab-note-md-full ul { list-style-type: disc !important; padding-left: 1.4em !important; margin: 0.2em 0; }
|
|
.collab-note-md ol, .collab-note-md-full ol { list-style-type: decimal !important; padding-left: 1.4em !important; margin: 0.2em 0; }
|
|
.collab-note-md li, .collab-note-md-full li { display: list-item !important; margin: 0.1em 0; }
|
|
.collab-note-md code, .collab-note-md-full code { font-size: 0.9em; padding: 1px 5px; border-radius: 4px; background: var(--bg-secondary); }
|
|
.collab-note-md-full pre { padding: 10px 12px; border-radius: 8px; background: var(--bg-secondary); overflow-x: auto; margin: 0.5em 0; }
|
|
.collab-note-md-full pre code { padding: 0; background: none; }
|
|
.collab-note-md a, .collab-note-md-full a { color: #3b82f6; text-decoration: underline; word-break: break-all; }
|
|
.collab-note-md blockquote, .collab-note-md-full blockquote { border-left: 3px solid var(--border-primary); padding-left: 12px; margin: 0.5em 0; color: var(--text-muted); }
|
|
.collab-note-md-full table { border-collapse: collapse; width: 100%; margin: 0.5em 0; }
|
|
.collab-note-md-full th, .collab-note-md-full td { border: 1px solid var(--border-primary); padding: 4px 8px; font-size: 0.9em; }
|
|
.collab-note-md-full hr { border: none; border-top: 1px solid var(--border-primary); margin: 0.8em 0; }
|