/* ═══════════════════════════════════════════════════════ Calendarr — Dark-Mode-first CSS ═══════════════════════════════════════════════════════ */ /* ── Variables ─────────────────────────────────────────── */ :root { --primary: #4285f4; --primary-dim: rgba(66,133,244,.15); --accent: #ea4335; --today-color: #4285f4; /* Layered surfaces — subtly cool-tinted, slightly more depth between layers so panels read via elevation instead of hard table-like 1px borders */ --bg-app: #0c0c13; --bg-topbar: #14141d; --bg-sidebar: #14141d; --bg-surface: #1d1d2a; --bg-2: #16161f; /* used by quarter month cards */ --bg-card: #1d1d2a; /* used by recurrence day buttons */ --bg-hover: #262636; --bg-active: #31314f; --text-1: #e8e8f0; --text-2: #9090aa; --text-3: #55556a; --border: #2e2e40; --border-light: #242438; --scrollbar: #36364a; --topbar-h: 64px; --sidebar-w: 256px; --shadow-sm: 0 1px 3px rgba(0,0,0,.30); --shadow: 0 6px 20px rgba(0,0,0,.40); --shadow-lg: 0 16px 44px rgba(0,0,0,.55); --radius-lg: 20px; --radius: 14px; --radius-sm: 9px; --transition: .18s cubic-bezier(.4, 0, .2, 1); --ring: 0 0 0 3px var(--primary-dim); } /* ── Reset ──────────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; overflow: hidden; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', system-ui, sans-serif; background: var(--bg-app); color: var(--text-1); font-size: 14px; line-height: 1.5; letter-spacing: .1px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; } 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), box-shadow var(--transition), transform var(--transition), filter var(--transition); white-space: nowrap; } .btn:active { transform: translateY(1px); } .btn:focus-visible { outline: none; box-shadow: var(--ring); } .btn-primary { background: var(--primary); background: linear-gradient(135deg, var(--primary), color-mix(in srgb, var(--primary) 80%, #14141d)); color: #fff; box-shadow: 0 2px 10px var(--primary-dim); } .btn-primary:hover { filter: brightness(1.10); box-shadow: 0 5px 18px var(--primary-dim); } .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), color var(--transition), transform 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); } .icon-btn:active { transform: scale(.92); } .icon-btn:focus-visible { outline: none; box-shadow: var(--ring); } /* ── 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: 13px; font-weight: 500; letter-spacing: 0; } .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), box-shadow var(--transition); width: 100%; } .form-group input:focus, .form-group select:focus, .form-group textarea:focus { border-color: var(--primary); box-shadow: var(--ring); } .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-light); box-shadow: var(--shadow-sm); 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; gap: 2px; padding: 3px; background: var(--bg-surface); border-radius: 22px; border: 1px solid var(--border-light); } .view-btn { padding: 6px 14px; font-size: 13px; font-weight: 500; color: var(--text-2); transition: background var(--transition), color var(--transition), box-shadow var(--transition); border-radius: 18px; } .view-btn:hover { background: var(--bg-hover); color: var(--text-1); } .view-btn:focus-visible { outline: none; box-shadow: var(--ring); } .view-btn.active { background: var(--primary-dim); color: var(--primary); font-weight: 600; box-shadow: inset 0 0 0 1px var(--primary-dim); } .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-light); 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: center; justify-content: center; 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: color-mix(in srgb, var(--today-color) 9%, transparent); } .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: 0 0 2px 4px; 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: center; justify-content: center; 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: 6px; 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: 7px; 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-light); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); transition: box-shadow var(--transition), transform var(--transition); } .qtr-month:hover { box-shadow: var(--shadow); transform: translateY(-2px); } .qtr-month-name { font-size: 13px; font-weight: 600; color: var(--text-1); padding: 10px 12px 8px; border-bottom: 1px solid var(--border-light); 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(8,8,14,.55); -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px); display: flex; align-items: center; justify-content: center; padding: 16px; } .modal-card { background: var(--bg-surface); border: 1px solid var(--border-light); border-radius: var(--radius); width: 100%; max-height: 90vh; overflow-y: auto; box-shadow: var(--shadow-lg); animation: card-in .2s cubic-bezier(.4, 0, .2, 1); } @keyframes card-in { from { opacity: 0; transform: translateY(8px) scale(.985); } to { opacity: 1; transform: none; } } @media (prefers-reduced-motion: reduce) { .modal-card { animation: none; } } .modal-header { display: flex; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--border-light); gap: 8px; } .modal-header h3 { font-size: 18px; font-weight: 600; flex: 1; letter-spacing: -.2px; } .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: 14px 20px; border-top: 1px solid var(--border-light); } /* ── 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-light); border-radius: var(--radius); width: 340px; box-shadow: var(--shadow-lg); overflow: hidden; animation: card-in .16s cubic-bezier(.4, 0, .2, 1); } @media (prefers-reduced-motion: reduce) { .event-popup { animation: none; } } .popup-header { display: flex; align-items: flex-start; gap: 10px; padding: 14px 12px 12px 16px; border-bottom: 1px solid var(--border-light); } .popup-color-dot { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; margin-top: 5px; } .popup-header h4 { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; padding-top: 1px; } .popup-action, .popup-close { width: 30px; height: 30px; font-size: 16px; flex-shrink: 0; } .popup-close { margin-left: 2px; } .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: var(--primary-dim); 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: 6px; 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)); } } }