Files
Calendarr/frontend/css/app.css
Scarriffle 64d499647d fix: Stufenförmige Monatsgrenze – auch waagerechte Linie unter Vormonats-Tagen
Die Trennlinie hat jetzt eine 'Stufen'-Form: unten unter den letzten
Tagen des Vormonats in derselben Zeile, dann links runter zum 1. des
neuen Monats, dann oben über die ersten Tage des neuen Monats.

So ist die Monatsgrenze visuell vollständig umrandet.
2026-05-09 17:12:57 +02:00

1630 lines
59 KiB
CSS

/* ═══════════════════════════════════════════════════════
Calendarr — Dark-Mode-first CSS
═══════════════════════════════════════════════════════ */
/* ── Variables ─────────────────────────────────────────── */
:root {
--primary: #4285f4;
--primary-dim: rgba(66,133,244,.15);
--accent: #ea4335;
--today-color: #4285f4;
--bg-app: #0e0e14;
--bg-topbar: #18181f;
--bg-sidebar: #18181f;
--bg-surface: #22222c;
--bg-hover: #2a2a38;
--bg-active: #32324a;
--text-1: #e8e8f0;
--text-2: #9090aa;
--text-3: #55556a;
--border: #2e2e40;
--border-light: #242438;
--scrollbar: #30303c;
--topbar-h: 64px;
--sidebar-w: 256px;
--shadow: 0 2px 12px rgba(0,0,0,.45);
--shadow-lg: 0 8px 28px rgba(0,0,0,.55);
--radius: 8px;
--radius-sm: 4px;
--transition: .15s ease;
}
/* ── Reset ──────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; }
body {
font-family: 'Google Sans', 'Roboto', system-ui, sans-serif;
background: var(--bg-app);
color: var(--text-1);
font-size: 14px;
line-height: 1.5;
}
input, select, textarea, button { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }
a { color: var(--primary); text-decoration: none; }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 3px; }
/* ── Utilities ──────────────────────────────────────────── */
.hidden { display: none !important; }
.flex { display: flex; }
.flex-col { display: flex; flex-direction: column; }
.gap-8 { gap: 8px; }
/* ── Buttons ────────────────────────────────────────────── */
.btn {
display: inline-flex; align-items: center; gap: 6px;
padding: 8px 16px; border-radius: 20px;
font-weight: 500; transition: background var(--transition), color var(--transition);
white-space: nowrap;
}
.btn-primary {
background: var(--primary);
color: #fff;
}
.btn-primary:hover { filter: brightness(1.12); }
.btn-secondary {
background: var(--bg-surface);
color: var(--text-1);
border: 1px solid var(--border);
}
.btn-secondary:hover { background: var(--bg-hover); }
.btn-ghost { color: var(--primary); }
.btn-ghost:hover { background: var(--primary-dim); }
.btn-danger { background: var(--accent); color: #fff; }
.btn-danger:hover { filter: brightness(1.1); }
.btn-full { width: 100%; justify-content: center; }
.btn-fab {
display: flex; align-items: center; gap: 10px;
padding: 12px 20px; border-radius: 24px;
background: var(--bg-surface);
color: var(--text-1);
font-weight: 600;
box-shadow: var(--shadow);
margin: 16px 12px 8px;
transition: background var(--transition), box-shadow var(--transition);
}
.btn-fab:hover { background: var(--bg-hover); box-shadow: var(--shadow-lg); }
.icon-btn {
display: inline-flex; align-items: center; justify-content: center;
width: 40px; height: 40px; border-radius: 50%;
color: var(--text-2); transition: background var(--transition);
flex-shrink: 0;
}
.icon-btn svg { width: 20px; height: 20px; fill: currentColor; }
.icon-btn:hover { background: var(--bg-hover); color: var(--text-1); }
/* ── Auth Screens ───────────────────────────────────────── */
.auth-screen {
position: fixed; inset: 0;
display: flex; align-items: center; justify-content: center;
background: var(--bg-app);
z-index: 1000;
}
.auth-card {
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 40px;
width: 100%; max-width: 400px;
box-shadow: var(--shadow-lg);
}
.auth-logo {
display: flex; align-items: center; gap: 10px;
margin-bottom: 24px;
}
.auth-logo .logo-icon { display: block; color: var(--primary); }
.auth-logo h1 { font-size: 24px; font-weight: 600; color: var(--text-1); margin: 0; }
.auth-tagline { font-size: 12px; color: var(--text-3); margin: 2px 0 0; }
.auth-card h2 { font-size: 18px; margin-bottom: 4px; }
.auth-sub { color: var(--text-2); margin-bottom: 24px; }
.impressum-link {
position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
background: none; border: none; cursor: pointer;
font-size: 12px; color: var(--text-3);
transition: color var(--transition); white-space: nowrap;
}
.impressum-link:hover { color: var(--text-1); }
/* ── Forms ──────────────────────────────────────────────── */
.form-group {
display: flex; flex-direction: column; gap: 6px;
margin-bottom: 16px;
}
.form-group label { color: var(--text-2); font-size: 12px; font-weight: 500; text-transform: uppercase; letter-spacing: .5px; }
.form-group input, .form-group select, .form-group textarea {
background: var(--bg-app);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 10px 12px;
color: var(--text-1);
outline: none;
transition: border-color var(--transition);
width: 100%;
}
.form-group input:focus, .form-group select:focus, .form-group textarea:focus {
border-color: var(--primary);
}
.form-group textarea { resize: vertical; }
/* ── Date/time input dark mode ──────────────────────────── */
.form-group input[type="datetime-local"],
.form-group input[type="date"] {
color-scheme: dark;
}
.form-group input[type="datetime-local"]::-webkit-calendar-picker-indicator,
.form-group input[type="date"]::-webkit-calendar-picker-indicator {
filter: invert(0.8);
opacity: 0.7;
cursor: pointer;
}
.form-row {
display: flex; gap: 12px; margin-bottom: 16px; align-items: center;
}
.form-group.half { flex: 1; margin-bottom: 0; }
.form-error {
background: rgba(234,67,53,.15);
border: 1px solid rgba(234,67,53,.4);
border-radius: var(--radius-sm);
padding: 10px 12px;
color: #f28b82;
margin-bottom: 12px;
}
.input-title {
font-size: 20px !important; font-weight: 500;
background: transparent !important;
border: none !important;
border-bottom: 2px solid var(--border) !important;
border-radius: 0 !important;
padding: 8px 0 !important;
margin-bottom: 8px;
}
.input-title:focus { border-bottom-color: var(--primary) !important; }
.toggle-label {
display: flex; align-items: center; gap: 8px;
cursor: pointer; color: var(--text-1);
}
.toggle-label input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--primary); }
.color-input {
width: 52px; height: 40px; padding: 3px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--bg-surface);
cursor: pointer;
outline: none;
}
.color-input::-webkit-color-swatch-wrapper { padding: 2px; }
.color-input::-webkit-color-swatch { border-radius: 3px; border: none; }
.color-row { display: flex; align-items: center; gap: 10px; }
.color-label { font-size: 12px; color: var(--text-2); font-family: monospace; }
/* ── Color Picker ───────────────────────────────────────── */
.color-picker { display: flex; gap: 8px; flex-wrap: wrap; }
.color-swatch {
width: 28px; height: 28px; border-radius: 50%; cursor: pointer;
border: 3px solid transparent;
transition: border-color var(--transition), transform var(--transition);
}
.color-swatch:hover { transform: scale(1.15); }
.color-swatch.active { border-color: var(--text-1); }
.ev-color-row { display: flex; align-items: center; gap: 8px; }
.ev-color-hex {
flex: 1; height: 36px; padding: 0 10px;
background: var(--bg-hover); border: 1px solid var(--border);
border-radius: var(--radius-sm); color: var(--text-1);
font-family: 'Roboto Mono', monospace; font-size: 13px;
}
.ev-color-hex:focus { outline: none; border-color: var(--primary); }
.ev-color-preview {
width: 36px; height: 36px; border-radius: var(--radius-sm);
border: 1px solid var(--border); cursor: pointer;
flex-shrink: 0; transition: box-shadow var(--transition);
}
.ev-color-preview:hover { box-shadow: 0 0 0 2px var(--primary); }
/* ── Gradient Color Picker (Dark) ──────────────────────── */
.gcp {
position: fixed; z-index: 600;
width: 252px; padding: 16px;
background: var(--bg-surface); border: 1px solid var(--border);
border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.gcp-sv {
display: block; width: 100%; height: 160px;
border-radius: var(--radius-sm); cursor: crosshair;
}
.gcp-sv-cursor {
position: absolute; width: 14px; height: 14px;
border: 2px solid #fff; border-radius: 50%;
box-shadow: 0 0 0 1px rgba(0,0,0,.4), inset 0 0 0 1px rgba(0,0,0,.3);
transform: translate(-50%, -50%); pointer-events: none;
}
.gcp-hue-track {
position: relative; margin-top: 12px; height: 14px; cursor: pointer;
}
.gcp-hue {
display: block; width: 100%; height: 14px;
border-radius: 7px; cursor: pointer;
}
.gcp-hue-thumb {
position: absolute; top: 50%; width: 18px; height: 18px;
border: 2px solid #fff; border-radius: 50%;
box-shadow: 0 0 0 1px rgba(0,0,0,.3), 0 1px 4px rgba(0,0,0,.4);
transform: translate(-50%, -50%); pointer-events: none;
background: transparent;
}
.gcp-bottom {
display: flex; align-items: center; gap: 10px; margin-top: 12px;
}
.gcp-preview {
width: 36px; height: 36px; border-radius: var(--radius-sm);
border: 1px solid var(--border); flex-shrink: 0;
}
.gcp-hex {
flex: 1; height: 36px; padding: 0 10px;
background: var(--bg-hover); border: 1px solid var(--border);
border-radius: var(--radius-sm); color: var(--text-1);
font-family: 'Roboto Mono', monospace; font-size: 13px;
outline: none;
}
.gcp-hex:focus { border-color: var(--primary); }
.gcp-select {
display: block; width: 100%; margin-top: 12px;
padding: 8px 0; background: var(--primary); color: #fff;
border: none; border-radius: var(--radius-sm);
font-weight: 600; font-size: 13px; cursor: pointer;
transition: opacity var(--transition);
}
.gcp-select:hover { opacity: .85; }
/* ── Top Bar ────────────────────────────────────────────── */
.topbar {
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
height: var(--topbar-h);
background: var(--bg-topbar);
border-bottom: 1px solid var(--border);
display: flex; align-items: center;
padding: 0 8px;
gap: 8px;
}
.topbar-left { display: flex; align-items: center; gap: 4px; width: var(--sidebar-w); flex-shrink: 0; }
.topbar-logo { display: flex; align-items: center; gap: 8px; user-select: none; }
.topbar-logo span:first-child { font-size: 22px; }
.logo-text { font-size: 20px; font-weight: 400; color: var(--text-1); }
.topbar-center { display: flex; align-items: center; gap: 4px; flex: 1; }
.view-title { font-size: 20px; font-weight: 400; color: var(--text-1); white-space: nowrap; padding-left: 8px; }
.topbar-right { display: flex; align-items: center; gap: 4px; }
.view-switcher { display: flex; background: var(--bg-surface); border-radius: 20px; overflow: hidden; border: 1px solid var(--border); }
.view-btn {
padding: 6px 14px; font-size: 13px; font-weight: 500;
color: var(--text-2);
transition: background var(--transition), color var(--transition);
border-radius: 20px;
}
.view-btn:hover { background: var(--bg-hover); color: var(--text-1); }
.view-btn.active { background: var(--primary-dim); color: var(--primary); }
.user-menu-wrapper { position: relative; }
.user-avatar {
width: 34px; height: 34px; border-radius: 50%;
background: var(--primary);
display: flex; align-items: center; justify-content: center;
font-weight: 600; font-size: 14px; color: #fff;
cursor: pointer; user-select: none; flex-shrink: 0;
overflow: hidden; position: relative;
}
.user-dropdown {
position: absolute; top: 42px; right: 0;
background: var(--bg-surface); border: 1px solid var(--border);
border-radius: var(--radius); min-width: 180px;
box-shadow: 0 8px 24px rgba(0,0,0,.4); z-index: 200;
overflow: hidden;
}
.dropdown-user {
padding: 12px 16px; font-size: 13px; font-weight: 600;
color: var(--text-1); border-bottom: 1px solid var(--border);
}
.dropdown-item {
display: flex; align-items: center; gap: 10px;
width: 100%; padding: 10px 16px; border: none;
background: none; color: var(--text-2); font-size: 13px;
cursor: pointer; transition: background var(--transition);
}
.dropdown-item:hover { background: var(--bg-hover); color: var(--text-1); }
.dropdown-item svg { flex-shrink: 0;
}
/* ── Layout ─────────────────────────────────────────────── */
#app {
display: flex; flex-direction: column; height: 100vh;
}
.content-wrapper {
margin-top: var(--topbar-h);
display: flex; flex: 1; overflow: hidden; height: calc(100vh - var(--topbar-h));
}
.sidebar {
width: var(--sidebar-w);
background: var(--bg-sidebar);
border-right: 1px solid var(--border);
flex-shrink: 0;
overflow-y: auto;
overflow-x: hidden;
transition: transform var(--transition);
}
.sidebar.collapsed { transform: translateX(calc(-1 * var(--sidebar-w))); margin-right: calc(-1 * var(--sidebar-w)); }
.sidebar-inner { padding-bottom: 8px; }
.sidebar-copyright {
display: block; width: 100%;
padding: 10px 16px 12px;
font-size: 11px; color: var(--text-3);
text-align: center; cursor: pointer;
background: none; border: none; border-top: 1px solid var(--border);
transition: color var(--transition);
white-space: nowrap;
position: sticky; bottom: 0;
background: var(--bg-sidebar);
}
.sidebar-copyright:hover { color: var(--text-1); }
.main-view { flex: 1; overflow: hidden; display: flex; flex-direction: column; }
#view-container { flex: 1; display: flex; flex-direction: column; min-height: 0; }
/* ── Mini Calendar ──────────────────────────────────────── */
.mini-cal { padding: 12px 16px; }
.mini-cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.mini-title { font-size: 13px; font-weight: 500; color: var(--text-1); }
.mini-btn { width: 28px; height: 28px; font-size: 18px; color: var(--text-2); }
.mini-btn:hover { color: var(--text-1); background: var(--bg-hover); }
.mini-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; }
.mini-dow { font-size: 11px; color: var(--text-3); padding: 2px 0; font-weight: 500; }
.mini-cal-days { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; }
.mini-day {
font-size: 12px; padding: 3px 0; border-radius: 50%;
cursor: pointer; transition: background var(--transition);
color: var(--text-2); width: 28px; height: 28px;
display: flex; align-items: center; justify-content: center;
margin: 1px auto; position: relative;
}
.mini-day:hover { background: var(--bg-hover); color: var(--text-1); }
.mini-day.other-month { color: var(--text-3); }
.mini-day.today {
background: var(--today-color);
color: #fff; font-weight: 700;
}
.mini-day.selected:not(.today) { background: var(--primary-dim); color: var(--primary); font-weight: 600; }
.mini-day.has-events::after {
content: ''; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%);
width: 4px; height: 4px; border-radius: 50%; background: var(--primary);
}
.mini-day.today.has-events::after { background: #fff; }
/* ── Calendar List ──────────────────────────────────────── */
.cal-list { padding: 8px 0; }
.cal-list-header {
display: flex; align-items: center; justify-content: space-between;
padding: 8px 16px;
font-size: 12px; font-weight: 600; text-transform: uppercase;
letter-spacing: .5px; color: var(--text-2);
}
.add-cal-dropdown-wrap { position: relative; }
.add-cal-dropdown {
position: absolute; top: 100%; right: 0; z-index: 200;
min-width: 180px; padding: 4px 0;
background: var(--bg-surface); border: 1px solid var(--border);
border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.add-cal-dropdown button {
display: block; width: 100%; padding: 8px 14px;
text-align: left; font-size: 13px; color: var(--text-1);
background: none; border: none; cursor: pointer;
}
.add-cal-dropdown button:hover { background: var(--bg-hover); }
.cal-item {
display: flex; align-items: center; gap: 10px;
padding: 6px 16px; cursor: pointer;
transition: background var(--transition);
border-radius: 0 20px 20px 0;
margin-right: 12px;
}
.cal-item:hover { background: var(--bg-hover); }
.cal-item-dot {
width: 14px; height: 14px; border-radius: 3px; flex-shrink: 0; cursor: pointer;
}
.cal-item-dot:hover { outline: 2px solid var(--text-2); outline-offset: 1px; }
.cal-item input[type=checkbox] { accent-color: var(--primary); width: 14px; height: 14px; }
.cal-item-name { font-size: 13px; flex: 1; min-width: 0; color: var(--text-1); cursor: default; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-item-remove { flex-shrink: 0; }
.cal-rename-input {
font-size: 13px; flex: 1; color: var(--text-1);
background: var(--bg-app); border: 1px solid var(--primary);
border-radius: var(--radius-sm); padding: 2px 6px;
outline: none;
}
.cal-account-name { font-size: 11px; color: var(--text-3); padding: 4px 16px 2px; font-weight: 500; }
.cal-item-remove { opacity: 0; }
.cal-item:hover .cal-item-remove { opacity: 1; }
/* ── Month View ─────────────────────────────────────────── */
.month-view { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.month-header {
display: grid; grid-template-columns: 38px repeat(7, 1fr);
border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.month-kw-header {
padding: 8px 0; text-align: center;
font-size: 13px; font-weight: 700; text-transform: uppercase;
letter-spacing: .3px; color: var(--text-3);
border-right: 1px solid var(--border-light);
}
.month-dow {
padding: 8px 0; text-align: center;
font-size: 11px; font-weight: 600; text-transform: uppercase;
letter-spacing: .5px; color: var(--text-2);
}
.month-kw-cell {
position: absolute; left: 0; top: 0; bottom: 0; width: 38px;
display: flex; align-items: flex-start; justify-content: center;
padding-top: 6px;
font-size: 13px; color: var(--text-3); font-weight: 700;
border-right: 1px solid var(--border-light);
cursor: default; user-select: none; z-index: 1;
background: var(--bg-app);
}
/* Full-height column divs — click target + border */
.month-col {
flex: 1; border-right: 1px solid var(--border);
cursor: pointer; transition: background var(--transition);
padding: 4px 4px 0; min-width: 0;
}
.month-col:last-child { border-right: none; }
.month-col:hover { background: var(--bg-hover); }
.month-col.today { background: rgba(66,133,244,.08); }
.month-col.month-selected { background: var(--primary-dim); }
.month-col.month-selected .cell-day { border: 2px solid var(--primary); color: var(--primary); font-weight: 700; }
.month-col.month-selected .cell-day.today { background: var(--today-color); color: #fff; border: none; }
.month-col.other-month .cell-day { color: var(--text-3); }
.cell-day {
font-size: 12px; font-weight: 500; color: var(--text-2);
width: 26px; height: 26px;
display: flex; align-items: center; justify-content: center;
border-radius: 50%; flex-shrink: 0;
}
.cell-day.today { background: var(--today-color); color: #fff; font-weight: 700; }
/* Month boundary marker: thicker line + month abbreviation on the 1st */
.month-col {
position: relative; /* anchor for divider pseudo-elements */
}
.month-col.first-of-month {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0;
padding-top: 8px;
}
/* Dividers via pseudo-elements so they render above events (z-index 2) */
.month-col.month-divider-left::before {
content: '';
position: absolute;
left: 0; top: 0; bottom: 0;
width: 3px;
background: var(--month-divider-color, #7090c0);
z-index: 4;
pointer-events: none;
}
.month-col.month-divider-top::after {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
background: var(--month-divider-color, #7090c0);
z-index: 4;
pointer-events: none;
}
/* Bottom divider on the previous-month cells in the same row as the change.
Uses ::before because these cells never have month-divider-left. */
.month-col.month-divider-bottom::before {
content: '';
position: absolute;
bottom: 0; left: 0; right: 0;
height: 3px;
background: var(--month-divider-color, #7090c0);
z-index: 4;
pointer-events: none;
}
.month-row.month-divider-top {
position: relative;
}
.month-row.month-divider-top::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
background: var(--month-divider-color, #7090c0);
z-index: 4;
pointer-events: none;
}
.month-marker {
font-size: 14px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: .5px;
color: var(--month-label-color, #7090c0);
line-height: 1;
padding: 0 2px;
margin-bottom: 2px;
position: relative;
z-index: 3; /* above events overlay (z-index 2) */
}
/* Make sure the day number stays visible above events */
.cell-day {
position: relative;
z-index: 3;
}
/* Push events overlay down when row contains a first-of-month cell so the
day "1" (which sits below the month marker) isn't hidden by event bars */
.month-row.has-month-marker .month-events-overlay {
top: 56px;
}
/* Events overlay — pointer-events:none so clicks pass to columns */
.month-events-overlay {
position: absolute; top: 30px; left: 0; right: 0; bottom: 0;
pointer-events: none; overflow: hidden; z-index: 2;
}
.month-more {
position: absolute;
font-size: 11px; color: var(--text-2); padding: 0 4px;
cursor: pointer; font-weight: 500;
pointer-events: all;
white-space: nowrap; overflow: hidden;
}
.month-more:hover { color: var(--primary); }
/* ── Week / Day Views ───────────────────────────────────── */
.week-view, .day-view { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: scroll; }
.week-head-sticky {
flex-shrink: 0; position: sticky; top: 0; z-index: 10;
background: var(--bg-app);
}
.week-header-row {
display: flex; border-bottom: 1px solid var(--border);
}
/* KW badge in week view header gutter */
.week-kw-badge {
font-size: 14px; font-weight: 700; color: var(--text-3);
display: flex; align-items: flex-end; justify-content: center;
padding-bottom: 6px;
text-transform: uppercase; letter-spacing: .3px;
user-select: none;
}
.week-time-gutter {
width: 56px; flex-shrink: 0;
display: flex; flex-direction: column; align-items: stretch;
}
.week-day-header {
flex: 1; padding: 8px 4px; text-align: center;
border-left: 1px solid var(--border); cursor: pointer;
transition: background var(--transition);
}
.week-day-header:hover { background: var(--bg-hover); }
.week-day-header .day-name {
font-size: 11px; font-weight: 600; text-transform: uppercase;
letter-spacing: .5px; color: var(--text-2);
}
.week-day-header .day-num {
font-size: 22px; font-weight: 400; color: var(--text-2);
width: 44px; height: 44px;
display: flex; align-items: center; justify-content: center;
border-radius: 50%; margin: 2px auto;
}
.week-day-header.today .day-num {
background: var(--today-color);
color: #fff; font-weight: 700;
}
.week-day-header.today .day-name { color: var(--today-color); }
/* All-day row */
.week-allday-row { display: flex; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.allday-gutter { width: 56px; flex-shrink: 0; display: flex; align-items: flex-start; justify-content: flex-end; padding: 6px 6px 0; font-size: 10px; color: var(--text-3); }
.allday-cols-wrap { flex: 1; position: relative; display: flex; }
.allday-col-bg { flex: 1; border-left: 1px solid var(--border); }
.allday-spans-layer { position: absolute; inset: 0; pointer-events: none; }
.allday-span {
position: absolute;
height: 18px; line-height: 18px;
font-size: 11px; font-weight: 500;
padding: 0 6px; border-radius: 3px;
cursor: pointer; pointer-events: all;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.allday-span:hover { filter: brightness(1.12); }
.allday-span.past { opacity: .45; }
.allday-span.continues-left { border-top-left-radius: 0; border-bottom-left-radius: 0; padding-left: 3px; }
.allday-span.continues-right { border-top-right-radius: 0; border-bottom-right-radius: 0; padding-right: 3px; }
.allday-span.multiday-timed { opacity: .88; border-left: 3px solid rgba(255,255,255,.4); }
.col-span-tint { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
/* Time grid */
.week-time-area { display: flex; flex-shrink: 0; }
.week-time-col { width: 56px; flex-shrink: 0; position: relative; }
.time-label {
height: var(--hour-h, 60px); display: flex; align-items: flex-start; justify-content: flex-end;
padding-right: 8px; padding-top: 6px;
font-size: 10px; color: var(--text-3);
}
.week-days-col { flex: 1; display: flex; position: relative; }
.week-day-col {
flex: 1; border-left: 1px solid var(--border);
position: relative;
min-height: calc(var(--hour-h, 60px) * 24);
}
.hour-line {
position: absolute; left: 0; right: 0;
border-top: 1px solid var(--border-light);
height: var(--hour-h, 60px);
}
.hour-line:first-child { border-top: none; }
.half-line {
position: absolute; left: 0; right: 0;
border-top: 1px dashed var(--border-light);
top: calc(var(--hour-h, 60px) / 2);
}
/* Current time indicator */
.now-line {
position: absolute; left: 0; right: 0;
border-top: 2px solid var(--accent);
z-index: 5; pointer-events: none;
}
.now-dot {
position: absolute; left: -5px; top: -5px;
width: 10px; height: 10px; border-radius: 50%;
background: var(--accent);
}
/* Timed events */
.timed-event {
position: absolute; border-radius: 4px;
padding: 2px 4px; cursor: pointer; overflow: hidden;
font-size: 11px; font-weight: 500;
border-left: 3px solid rgba(0,0,0,.25);
transition: filter var(--transition);
z-index: 3;
}
.timed-event:hover { filter: brightness(1.12); z-index: 4; }
.timed-event.past { opacity: .45; }
.timed-event .ev-time { font-size: 10px; opacity: .85; }
.timed-event .ev-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.timed-event .ev-loc { font-size: 10px; opacity: .75; white-space: nowrap; overflow: hidden; }
/* Day view specifics */
.day-view .week-day-col { flex: 1; }
/* ── Quarter View ───────────────────────────────────────── */
.quarter-view {
display: flex;
gap: 16px;
padding: 16px;
flex: 1;
min-height: 0;
box-sizing: border-box;
overflow-y: auto;
}
.qtr-month {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
background: var(--bg-2);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
}
.qtr-month-name {
font-size: 13px;
font-weight: 600;
color: var(--text-1);
padding: 10px 12px 8px;
border-bottom: 1px solid var(--border);
letter-spacing: .3px;
}
.qtr-month-grid { padding: 6px 8px 8px; }
.qtr-header {
display: grid;
grid-template-columns: repeat(7, 1fr);
margin-bottom: 2px;
}
.qtr-dow {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
color: var(--text-3);
text-align: center;
padding: 3px 0;
}
.qtr-cells {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: repeat(6, auto);
}
.qtr-cell {
padding: 3px 2px;
text-align: center;
cursor: pointer;
border-radius: 4px;
min-height: 36px;
}
.qtr-cell:hover { background: var(--bg-hover); }
.qtr-cell.today .qtr-day-num {
background: var(--today-color, var(--primary));
color: #fff;
border-radius: 50%;
}
.qtr-day-num {
font-size: 12px;
font-weight: 500;
color: var(--text-2);
width: 22px;
height: 22px;
line-height: 22px;
margin: 0 auto 2px;
}
.qtr-cell.other-month .qtr-day-num { color: var(--text-3); opacity: .45; }
.qtr-cell.today .qtr-day-num { color: #fff; }
.qtr-dots {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 2px;
min-height: 6px;
}
.qtr-dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
flex-shrink: 0;
cursor: pointer;
}
.qtr-dot.past { opacity: .45; }
.qtr-dot-more {
font-size: 9px;
color: var(--text-3);
line-height: 6px;
}
/* ── Agenda View ────────────────────────────────────────── */
.agenda-view { padding: 16px; flex: 1; overflow-y: auto; min-height: 0; }
.agenda-day { margin-bottom: 16px; }
.agenda-date {
font-size: 13px; font-weight: 600; color: var(--text-2);
padding: 8px 0 4px;
border-bottom: 1px solid var(--border);
margin-bottom: 8px;
display: flex; align-items: center; gap: 10px;
}
.agenda-date-num {
font-size: 22px; font-weight: 300; color: var(--text-1);
width: 44px; text-align: center;
}
.agenda-date-label { display: flex; flex-direction: column; }
.agenda-date-label .wd { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--text-2); }
.agenda-date-label .mo { font-size: 13px; color: var(--text-2); }
.agenda-date.today .agenda-date-num { color: var(--today-color); font-weight: 600; }
.agenda-event {
display: flex; align-items: flex-start; gap: 12px;
padding: 8px 12px; border-radius: var(--radius-sm);
cursor: pointer; transition: background var(--transition);
margin-left: 54px; margin-bottom: 4px;
}
.agenda-event:hover { background: var(--bg-hover); }
.agenda-event.past { opacity: .45; }
.agenda-ev-color { width: 10px; height: 10px; border-radius: 50%; margin-top: 4px; flex-shrink: 0; }
.agenda-ev-info { flex: 1; }
.agenda-ev-title { font-size: 14px; color: var(--text-1); }
.agenda-ev-meta { font-size: 12px; color: var(--text-2); }
.agenda-empty { text-align: center; padding: 48px; color: var(--text-3); font-size: 15px; }
/* ── Modals ─────────────────────────────────────────────── */
.modal-overlay {
position: fixed; inset: 0; z-index: 500;
background: rgba(0,0,0,.6);
display: flex; align-items: center; justify-content: center;
padding: 16px;
}
.modal-card {
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius);
width: 100%;
max-height: 90vh; overflow-y: auto;
box-shadow: var(--shadow-lg);
}
.modal-header {
display: flex; align-items: center;
padding: 16px 20px; border-bottom: 1px solid var(--border);
gap: 8px;
}
.modal-header h3 { font-size: 18px; font-weight: 500; flex: 1; }
.modal-close { font-size: 24px; }
.modal-body { padding: 20px; }
.modal-body p { margin: 0 0 14px; font-size: 14px; color: var(--text-1); }
.modal-body p:last-child { margin-bottom: 0; }
.modal-body a { color: var(--primary); text-decoration: none; }
.modal-body a:hover { text-decoration: underline; }
.modal-footer {
display: flex; align-items: center; gap: 8px;
padding: 12px 20px; border-top: 1px solid var(--border);
}
/* ── Recurrence UI ─────────────────────────────────────── */
.rec-weekdays { display: flex; gap: 4px; margin-top: 8px; }
.rec-day-btn {
width: 36px; height: 36px; border-radius: 50%;
border: 1px solid var(--border); background: var(--bg-card);
color: var(--text-2); cursor: pointer; font-size: 12px;
display: flex; align-items: center; justify-content: center;
transition: background var(--transition), color var(--transition);
}
.rec-day-btn:hover { background: var(--bg-hover); }
.rec-day-btn.active { background: var(--primary); color: #fff; border-color: var(--primary); }
/* ── Day Context Menu ──────────────────────────────────── */
.cal-context-menu {
position: fixed; z-index: 1000;
background: var(--bg-surface); border: 1px solid var(--border);
border-radius: var(--radius-sm); box-shadow: 0 4px 16px rgba(0,0,0,.5);
min-width: 180px; padding: 4px 0;
}
.ctx-item {
padding: 8px 16px; font-size: 13px; color: var(--text-1); cursor: pointer;
}
.ctx-item:hover { background: var(--bg-hover); }
/* ── Event Popup ────────────────────────────────────────── */
.event-popup {
position: fixed; z-index: 600;
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius);
width: 300px;
box-shadow: var(--shadow-lg);
}
.popup-header {
display: flex; align-items: center; gap: 8px;
padding: 12px 16px; border-bottom: 1px solid var(--border);
}
.popup-color-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
.popup-header h4 { flex: 1; font-size: 15px; font-weight: 500; }
.popup-action, .popup-close { width: 32px; height: 32px; font-size: 16px; }
.popup-body { padding: 12px 16px; }
.popup-time, .popup-location, .popup-calendar { font-size: 13px; color: var(--text-2); margin-bottom: 6px; }
.popup-description { font-size: 13px; color: var(--text-1); margin-bottom: 6px; white-space: pre-wrap; }
.popup-copy-menu {
border-top: 1px solid var(--border);
padding: 4px 0;
}
.popup-copy-label {
font-size: 11px; font-weight: 600; text-transform: uppercase;
letter-spacing: .5px; color: var(--text-3);
padding: 4px 14px 6px;
}
.popup-copy-item {
display: flex; align-items: center; gap: 9px;
padding: 7px 14px; cursor: pointer; font-size: 13px; color: var(--text-1);
}
.popup-copy-item:hover { background: var(--bg-hover); }
.popup-copy-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.popup-copy-edit-toggle {
display: flex; align-items: center; gap: 8px;
padding: 6px 14px 8px;
font-size: 12px; color: var(--text-2);
cursor: pointer;
border-bottom: 1px solid var(--border);
margin-bottom: 4px;
}
.popup-copy-edit-toggle input[type="checkbox"] { margin: 0; cursor: pointer; }
/* ── Settings Page ──────────────────────────────────────── */
#modal-settings.modal-overlay {
align-items: stretch; justify-content: stretch; padding: 0; background: var(--bg-app);
}
.settings-page-card {
width: 100%; height: 100%;
display: flex; flex-direction: column;
background: var(--bg-app); overflow: hidden;
}
.settings-page-header {
display: flex; align-items: center; gap: 8px;
padding: 14px 20px; border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.settings-page-header h3 { font-size: 16px; font-weight: 600; color: var(--text-1); margin: 0; }
.settings-page-body {
display: flex; flex: 1; overflow: hidden;
}
.settings-nav {
width: 200px; flex-shrink: 0;
border-right: 1px solid var(--border);
padding: 12px 8px;
display: flex; flex-direction: column; gap: 2px;
}
.settings-nav-btn {
display: block; width: 100%; text-align: left;
padding: 9px 14px; border-radius: var(--radius-sm);
font-size: 14px; color: var(--text-2);
background: none; border: none; cursor: pointer;
transition: background .15s, color .15s;
}
.settings-nav-btn:hover { background: var(--bg-hover); color: var(--text-1); }
.settings-nav-btn.active { background: var(--primary-dim); color: var(--primary); font-weight: 600; }
.settings-panels {
flex: 1; overflow-y: auto; padding: 24px 28px;
}
.settings-panel { display: none; }
.settings-panel.active { display: block; }
/* Panel typography */
.panel-title {
font-size: 14px; font-weight: 600; color: var(--text-1); margin: 0 0 4px;
}
.panel-desc {
font-size: 12px; color: var(--text-3); margin: 0 0 12px;
}
/* Contrast / option selectors — segmented pill */
.contrast-selector {
display: inline-flex;
border: 1px solid var(--border);
border-radius: 20px;
overflow: hidden;
background: var(--bg-surface);
}
.contrast-btn {
display: flex; flex-direction: column; align-items: center; gap: 4px;
padding: 8px 14px; min-width: 64px;
background: transparent; border: none;
border-right: 1px solid var(--border);
cursor: pointer; color: var(--text-2);
transition: background var(--transition), color var(--transition);
}
.contrast-btn:last-child { border-right: none; }
.contrast-btn:hover { background: var(--bg-hover); color: var(--text-1); }
.contrast-btn.active { background: var(--primary); color: #fff; }
.contrast-btn span { font-size: 18px; font-weight: 700; line-height: 1; }
.contrast-btn.active span { color: #fff !important; }
.contrast-lbl { font-size: 11px; white-space: nowrap; }
.contrast-btn.active .contrast-lbl { color: #fff; }
.line-preview {
display: block; width: 36px; height: 0;
border-top: 2px solid; border-radius: 1px;
margin: 4px 0;
}
.hour-preview {
font-size: 14px; line-height: 1; color: var(--text-2);
}
.contrast-btn.active .hour-preview { color: #fff; }
/* ── Settings (legacy) ──────────────────────────────────── */
.settings-section { margin-bottom: 28px; }
.settings-section h4 { font-size: 14px; font-weight: 600; color: var(--text-1); margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
.badge-admin {
font-size: 10px; padding: 2px 6px;
background: rgba(66,133,244,.2); color: var(--primary);
border-radius: 10px; font-weight: 600;
}
.users-list-item {
display: flex; align-items: center; justify-content: space-between;
padding: 8px 0; border-bottom: 1px solid var(--border-light);
}
.users-list-item .uname { font-weight: 500; }
.users-list-item .uemail { font-size: 12px; color: var(--text-2); }
.users-list-item .ubadge { font-size: 11px; color: var(--text-3); background: var(--bg-hover); padding: 2px 6px; border-radius: 10px; }
/* ── Profile ───────────────────────────────────────────── */
.profile-avatar-section {
display: flex; align-items: center; gap: 20px;
margin-bottom: 28px; padding-bottom: 20px;
border-bottom: 1px solid var(--border);
}
.profile-avatar {
width: 80px; height: 80px; border-radius: 50%;
background: var(--primary); display: flex;
align-items: center; justify-content: center;
font-size: 32px; font-weight: 700; color: #fff;
flex-shrink: 0; overflow: hidden; position: relative;
}
.profile-avatar img {
width: 100%; height: 100%; object-fit: cover;
position: absolute; inset: 0;
}
.profile-avatar-actions { display: flex; flex-direction: column; gap: 6px; }
.profile-username { font-size: 18px; font-weight: 600; color: var(--text-1); }
.btn-sm { padding: 6px 14px; font-size: 12px; }
.input-disabled { opacity: .5; cursor: not-allowed; }
.text-muted { font-size: 13px; color: var(--text-2); margin-bottom: 12px; }
.text-success { font-size: 13px; color: #34a853; margin-bottom: 12px; font-weight: 500; }
.totp-qr-wrapper {
display: flex; justify-content: center;
margin: 16px 0; padding: 16px;
background: #fff; border-radius: var(--radius);
width: fit-content;
}
.totp-qr-wrapper img { width: 200px; height: 200px; }
.totp-secret-row {
display: flex; align-items: center; gap: 8px;
background: var(--bg-app); border: 1px solid var(--border);
border-radius: var(--radius-sm); padding: 8px 12px;
}
.totp-secret-row code {
font-family: monospace; font-size: 14px; color: var(--text-1);
word-break: break-all; flex: 1;
}
.profile-cal-item {
display: flex; align-items: center; gap: 10px;
padding: 8px 0; border-bottom: 1px solid var(--border-light);
}
.profile-cal-dot {
width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0;
}
.profile-cal-name { font-size: 13px; color: var(--text-1); }
.profile-cal-account { font-size: 11px; color: var(--text-3); }
/* ── Avatar Crop ───────────────────────────────────────── */
.crop-container { max-height: 400px; overflow: hidden; background: #000; }
.crop-container img { display: block; max-width: 100%; }
/* ── Toast ──────────────────────────────────────────────── */
.toast {
position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
background: var(--bg-surface); border: 1px solid var(--border);
border-radius: 24px; padding: 10px 24px;
font-size: 14px; color: var(--text-1);
box-shadow: var(--shadow-lg); z-index: 9999;
transition: opacity .3s;
}
.toast.error { border-color: rgba(234,67,53,.5); background: rgba(234,67,53,.15); color: #f28b82; }
/* ── Loading Spinner ────────────────────────────────────── */
.spinner {
width: 32px; height: 32px; border: 3px solid var(--border);
border-top-color: var(--primary); border-radius: 50%;
animation: spin .7s linear infinite; margin: 32px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading-view { display: flex; justify-content: center; align-items: center; height: 200px; }
/* ── Accounts Panel ──────────────────────────────────────── */
.accounts-section { margin-bottom: 24px; }
.accounts-section-heading {
font-size: 11px; font-weight: 600; text-transform: uppercase;
letter-spacing: .5px; color: var(--text-3);
padding: 0 0 8px;
border-bottom: 1px solid var(--border-light);
margin-bottom: 10px;
}
.accounts-section-empty {
font-size: 13px; color: var(--text-3); padding: 4px 0; display: block;
}
.accounts-row {
display: flex; align-items: center;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid var(--border-light);
}
.accounts-row:last-child { border-bottom: none; }
.accounts-row-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.accounts-row-name { font-size: 13px; color: var(--text-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.accounts-row-sub { font-size: 11px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.accounts-row-actions { display: flex; gap: 6px; flex-shrink: 0; margin-left: 8px; }
.accounts-local-dot {
width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; display: inline-block;
}
/* ── Month View (spanning bars) ─────────────────────────── */
.month-body {
display: flex; flex-direction: column; flex: 1; overflow: hidden;
}
.month-row {
display: flex; flex: 1; position: relative; min-height: 100px;
border-bottom: 1px solid var(--border);
}
.month-row:last-child { border-bottom: none; }
/* row-right: flex row containing 7 full-height column divs + events overlay */
.month-row-right {
margin-left: 38px; display: flex; flex: 1; position: relative; min-width: 0;
}
.month-span-event {
position: absolute;
height: 18px; line-height: 18px;
border-radius: 3px; padding: 0 6px;
font-size: 11px; font-weight: 500;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
cursor: pointer; color: #fff;
transition: filter var(--transition);
box-sizing: border-box;
pointer-events: all;
}
.month-span-event:hover { filter: brightness(1.15); }
.month-span-event.past { opacity: .45; }
.month-span-event.continues-left {
border-top-left-radius: 0; border-bottom-left-radius: 0; padding-left: 3px;
}
.month-span-event.continues-right {
border-top-right-radius: 0; border-bottom-right-radius: 0; padding-right: 3px;
}
/* ── Responsive ─────────────────────────────────────────── */
@media (max-width: 768px) {
:root { --sidebar-w: 0px; }
.sidebar { position: fixed; left: 0; top: var(--topbar-h); bottom: 0; z-index: 200; width: 256px; transform: translateX(-100%); }
.sidebar.open { transform: translateX(0); }
.topbar-left { width: auto; }
.view-switcher .view-btn { padding: 6px 8px; font-size: 12px; }
.logo-text { display: none; }
.view-title { font-size: 16px; }
}
/* ── Custom Date/Time Display Field ─────────────────────── */
.dt-display {
display: flex; align-items: center; justify-content: space-between;
background: var(--bg-app);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 10px 12px;
color: var(--text-1);
cursor: pointer;
transition: border-color var(--transition);
user-select: none;
min-height: 42px;
}
.dt-display:hover, .dt-display:focus { border-color: var(--primary); outline: none; }
.dt-display-text { font-size: 14px; }
.dt-display-icon { color: var(--text-3); flex-shrink: 0; margin-left: 6px; }
/* ── Date/Time Picker Card ───────────────────────────────── */
.dtp-overlay {
position: fixed; inset: 0; z-index: 700;
}
.dtp-card {
position: fixed; z-index: 701;
background: var(--bg-surface);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow-lg);
padding: 16px;
width: 272px;
user-select: none;
}
/* Calendar header */
.dtp-cal-header {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: 10px;
}
.dtp-month-label {
font-size: 14px; font-weight: 600; color: var(--text-1);
}
.dtp-nav-btn {
background: none; border: none; cursor: pointer;
color: var(--text-2); font-size: 22px; line-height: 1;
padding: 2px 6px; border-radius: var(--radius-sm);
transition: background var(--transition), color var(--transition);
}
.dtp-nav-btn:hover { background: var(--bg-hover); color: var(--text-1); }
/* Day-of-week headers */
.dtp-grid {
display: grid; grid-template-columns: repeat(7, 1fr);
gap: 2px; margin-bottom: 4px;
}
.dtp-dow {
text-align: center; font-size: 11px; font-weight: 600;
color: var(--text-3); padding: 4px 0; text-transform: uppercase;
}
/* Day cells */
.dtp-day {
display: flex; align-items: center; justify-content: center;
height: 34px; border-radius: 6px;
font-size: 13px; font-weight: 500; color: var(--text-1);
cursor: pointer; transition: background var(--transition);
}
.dtp-day:hover { background: var(--bg-hover); }
.dtp-day.other { color: var(--text-3); }
.dtp-day.other:hover { background: var(--bg-hover); }
.dtp-day.today { color: var(--primary); font-weight: 700; }
.dtp-day.selected {
background: var(--primary) !important;
color: #fff !important; font-weight: 700;
}
/* Time picker */
.dtp-time-row {
display: flex; align-items: center; justify-content: center;
gap: 4px; margin: 12px 0 8px;
border-top: 1px solid var(--border-light);
padding-top: 12px;
}
.dtp-colon {
font-size: 22px; font-weight: 600; color: var(--text-2);
padding: 0 2px; line-height: 1;
align-self: center;
}
.dtp-tc-wrap {
position: relative; width: 64px;
}
.dtp-tc {
height: calc(3 * 40px); /* 120px = 3 visible items */
overflow-y: scroll;
scroll-snap-type: y mandatory;
scrollbar-width: none;
padding: 40px 0; /* top/bottom padding so first/last can center */
box-sizing: content-box;
}
.dtp-tc::-webkit-scrollbar { display: none; }
.dtp-ti {
height: 40px; line-height: 40px;
text-align: center; font-size: 20px; font-weight: 500;
scroll-snap-align: center;
border-radius: 8px;
cursor: pointer;
color: var(--text-2);
transition: background .1s, color .1s;
}
.dtp-ti:hover { color: var(--text-1); }
.dtp-ti.selected {
background: var(--primary);
color: #fff;
}
/* Actions */
.dtp-actions {
display: flex; justify-content: flex-end; gap: 8px;
margin-top: 12px; padding-top: 10px;
border-top: 1px solid var(--border-light);
}
/* ── Mobile / PWA additions ─────────────────────────────────
Additive only — does not modify any existing rules above. */
/* Backdrop element exists in DOM but is hidden by default on desktop */
.sidebar-backdrop { display: none; }
/* Mobile-only UI elements: hidden on desktop ───────────── */
.view-mobile-wrapper { position: relative; display: none; }
.settings-nav-toggle { display: none; }
.settings-nav-backdrop { display: none; }
.dropdown-item-mobile-only { display: none; }
.create-fab { display: none; }
/* View-title spans: visual space between main and year on desktop */
.view-title-year { margin-left: 6px; }
@media (max-width: 768px) {
html, body { overflow-x: hidden; max-width: 100vw; }
/* ── Sidebar slides in as overlay on mobile ─────────────── */
.sidebar {
position: fixed;
top: var(--topbar-h);
left: 0;
bottom: 0;
width: min(85vw, 320px);
z-index: 600;
transform: translateX(-100%);
transition: transform .25s ease;
box-shadow: var(--shadow-lg);
margin-right: 0 !important;
}
body.sidebar-open .sidebar { transform: translateX(0); }
/* Neutralize the desktop .collapsed shift on mobile so the JS toggle
never creates a second hidden state to fight with .sidebar-open */
.sidebar.collapsed { transform: translateX(-100%); margin-right: 0 !important; }
body.sidebar-open .sidebar.collapsed { transform: translateX(0); }
.sidebar-backdrop {
display: block;
position: fixed;
inset: 0;
background: rgba(0,0,0,.55);
z-index: 500;
opacity: 0;
pointer-events: none;
transition: opacity .2s ease;
}
body.sidebar-open .sidebar-backdrop {
opacity: 1;
pointer-events: auto;
}
/* ── Topbar tightening + scrollable view switcher ────────── */
.topbar { padding: 0 8px; gap: 4px; }
.topbar-left { width: auto; flex-shrink: 0; }
.topbar-center {
min-width: 0;
overflow: hidden;
}
.topbar-center .view-title {
font-size: 14px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.topbar-right {
min-width: 0;
/* no overflow:hidden — would clip the user dropdown on tap */
}
.view-switcher {
overflow-x: auto;
overflow-y: hidden;
flex-wrap: nowrap;
max-width: 100%;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
}
.view-switcher::-webkit-scrollbar { display: none; }
.view-switcher .view-btn { flex: 0 0 auto; }
/* ── 44px minimum tap targets ────────────────────────────── */
.icon-btn {
min-width: 44px;
min-height: 44px;
}
.btn { min-height: 44px; }
.view-switcher .view-btn { min-height: 40px; }
/* ── Month view: events keep text, just smaller ──────────── */
.month-span-event {
height: 14px !important;
line-height: 14px !important;
padding: 0 4px !important;
font-size: 9px !important;
font-weight: 500;
}
.month-more {
font-size: 9px;
padding: 0 2px;
}
.cell-day { font-size: 11px; }
/* ── Week view collapses to single day on mobile when today
is in the visible week. Falls back to default 7-col layout
for other weeks (use day view there). ──────────────────── */
.week-header-row:has(.week-day-header.today) .week-day-header:not(.today) { display: none; }
.week-header-row:has(.week-day-header.today) .week-day-header.today { flex: 1 1 100%; width: 100%; }
.week-days-col:has(.week-day-col.today) .week-day-col:not(.today) { display: none; }
.week-days-col:has(.week-day-col.today) .week-day-col.today { flex: 1 1 100%; width: 100%; }
.week-allday-row:has(.week-day-col.today) .week-day-col:not(.today) { display: none; }
/* ── Modals: full-screen on mobile ───────────────────────── */
.modal-overlay { padding: 0; }
.modal-card {
max-width: 100% !important;
width: 100% !important;
height: 100%;
max-height: 100%;
border-radius: 0;
display: flex;
flex-direction: column;
}
.modal-body {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.modal-footer { flex-shrink: 0; }
/* Settings page modal: also full-screen */
.settings-page-card {
max-width: 100% !important;
width: 100% !important;
height: 100%;
max-height: 100%;
border-radius: 0;
}
/* ── Misc safety: prevent overflow on flex topbar items ──── */
.main-view { width: 100%; min-width: 0; }
#view-container { max-width: 100%; overflow-x: hidden; }
/* ── Long-press / text-selection / image-save fixes ──────── */
/* Calendar UI shouldn't be selectable on touch — long-press
should reach our handlers, not trigger iOS text selection. */
.topbar, .sidebar, .main-view,
.month-view, .month-row, .month-col, .cell-day, .month-events-overlay, .month-span-event,
.week-view, .day-view, .week-day-col, .week-day-header, .week-allday-row,
.quarter-view, .agenda-view,
.view-switcher, .view-btn, .btn, .icon-btn, .user-avatar, .user-dropdown, .dropdown-item {
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
}
/* Faster taps, no double-tap zoom on interactive elements */
.icon-btn, .btn, .view-btn, .user-avatar, .month-col, .week-day-col, .dropdown-item,
.sidebar-copyright, .impressum-link, .modal-close, [data-modal] {
touch-action: manipulation;
}
/* Avatar long-press: don't show "Save Image" — taps reach parent */
.user-avatar img {
-webkit-touch-callout: none;
pointer-events: none;
}
/* ── Calendar weeks (KW) shown as a small bubble, not a column ── */
.month-header {
grid-template-columns: repeat(7, 1fr) !important;
}
.month-kw-header { display: none !important; }
.month-row-right {
margin-left: 0 !important;
}
.month-kw-cell {
position: absolute;
/* Bottom-left: away from the day-number (top-left) */
left: 3px; bottom: 3px;
top: auto; right: auto;
width: auto; height: auto;
padding: 1px 6px;
background: var(--bg-active);
border: none !important;
border-radius: 10px;
font-size: 9px; font-weight: 600;
color: var(--text-2);
z-index: 5;
display: inline-flex;
align-items: center;
pointer-events: none;
}
/* ── Status-bar safe area inside full-screen modals (PWA) ── */
.modal-card .modal-header,
.settings-page-header {
padding-top: calc(16px + env(safe-area-inset-top, 0px));
}
.modal-footer,
.settings-page-body {
padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}
/* ── Topbar: hide desktop view-switcher + settings, show
mobile view-toggle and let the title breathe ──────────── */
.topbar .view-switcher { display: none; }
.topbar #btn-settings { display: none; }
.view-mobile-wrapper { display: inline-block; }
.dropdown-item-mobile-only { display: flex; }
/* Heute-Button bleibt im Topbar-Center, kompakter Stil für Mobile */
.topbar #btn-today {
padding: 6px 10px;
font-size: 13px;
min-height: 36px;
flex-shrink: 0;
}
/* Sidebar create-button: auf Mobile durch den runden FAB ersetzt */
#btn-create-event { display: none; }
/* Floating action button — bottom-right round button */
.create-fab {
display: flex;
position: fixed;
bottom: calc(20px + env(safe-area-inset-bottom, 0px));
right: 20px;
width: 56px; height: 56px;
border-radius: 50%;
background: var(--primary);
color: #fff;
align-items: center;
justify-content: center;
box-shadow: 0 4px 14px rgba(0,0,0,.5);
z-index: 450;
transition: filter var(--transition), transform var(--transition);
-webkit-tap-highlight-color: transparent;
touch-action: manipulation;
}
.create-fab:active { transform: scale(.95); }
.create-fab:hover { filter: brightness(1.1); }
/* The title is the most important info — let it grow */
.topbar-center { flex: 1; min-width: 0; }
.topbar-center .view-title {
font-size: 15px;
font-weight: 500;
padding-left: 4px;
flex: 1;
line-height: 1.1;
display: flex;
flex-direction: column;
align-items: flex-start;
overflow: hidden;
}
.view-title-main {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100%;
}
.view-title-year {
font-size: 11px;
font-weight: 400;
color: var(--text-2);
line-height: 1.1;
margin-left: 0;
}
.topbar-left { gap: 0; }
.topbar-right { gap: 0; }
/* Event-Popup: Buttons kompakt halten, kein 44px-Override ───── */
.event-popup .icon-btn {
min-width: 32px !important;
min-height: 32px !important;
width: 32px;
height: 32px;
}
.event-popup .popup-header { gap: 2px; padding: 10px 12px; }
.event-popup { width: min(92vw, 340px); max-width: 92vw; }
/* Monatsansicht: Startzeit ausblenden — nur Titel anzeigen ──── */
.month-event-time { display: none; }
/* ── Settings modal: nav becomes a slide-in overlay ──────── */
.settings-nav-toggle { display: inline-flex !important; }
.settings-page-body { position: relative; }
.settings-nav {
position: absolute;
top: 0; left: 0; bottom: 0;
width: min(75vw, 280px);
z-index: 50;
background: var(--bg-app);
border-right: 1px solid var(--border);
transform: translateX(-100%);
transition: transform .25s ease;
box-shadow: var(--shadow-lg);
}
.settings-page-card.nav-open .settings-nav {
transform: translateX(0);
}
.settings-nav-backdrop {
display: block;
position: absolute; inset: 0;
background: rgba(0,0,0,.5);
z-index: 40;
opacity: 0;
pointer-events: none;
transition: opacity .2s ease;
}
.settings-page-card.nav-open .settings-nav-backdrop {
opacity: 1;
pointer-events: auto;
}
.settings-panels { padding: 16px; }
/* Modal headers: tighter on mobile */
.modal-header { padding: 12px 16px; }
.modal-body { padding: 16px; }
.modal-footer { padding: 12px 16px; }
}
/* iOS notch / home-indicator safe areas (PWA standalone) */
@supports (padding: env(safe-area-inset-top)) {
.topbar {
padding-top: env(safe-area-inset-top);
height: calc(var(--topbar-h) + env(safe-area-inset-top));
}
.sidebar { padding-bottom: env(safe-area-inset-bottom); }
/* The main content sits below the (now taller) topbar and must not
extend behind the home indicator at the bottom. */
.content-wrapper {
margin-top: calc(var(--topbar-h) + env(safe-area-inset-top));
height: calc(100vh - var(--topbar-h) - env(safe-area-inset-top) - env(safe-area-inset-bottom));
}
/* On mobile the slide-in sidebar also needs to start below the larger topbar */
@media (max-width: 768px) {
.sidebar { top: calc(var(--topbar-h) + env(safe-area-inset-top)); }
}
}