Files
Calendarr/frontend/css/app.css
Guido Schmit 94cbe4e7fb feat: Spanning event bars, wheel nav, dark datetime picker, segmented settings UI
- Month view: Multi-day events render as continuous Google Calendar-style
  spanning bars across days/weeks using a greedy lane-packing algorithm.
  Timed multi-day events no longer repeat per day.
- Mouse wheel / trackpad scrolls week-by-week in month view, day/week in
  other views (debounced, prevents default page scroll).
- datetime-local/date inputs now use color-scheme:dark so the native
  browser picker opens in dark mode; calendar icon styled to match.
- Contrast/hour-height selectors redesigned as connected segmented pill
  controls instead of individual tiles.
- Hidden calendars list gains proper padding and separator lines.
- "Google Konten" settings panel renamed "Konten" and expanded to show
  CalDAV, local calendars, iCal subscriptions, and Google accounts in
  one unified panel with sync/disconnect actions.
- New i18n keys added for accounts panel in both de and en.
2026-04-07 21:20:42 +02:00

950 lines
37 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ═══════════════════════════════════════════════════════
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: auto; display: flex; flex-direction: column; }
#view-container { flex: 1; display: flex; flex-direction: column; }
/* ── 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; height: 100%; }
.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);
}
.month-cell {
flex: 1;
border-right: 1px solid var(--border);
padding: 4px 4px 0;
cursor: pointer;
transition: background var(--transition);
min-width: 0;
}
.month-cell:last-child { border-right: none; }
.month-cell:hover { background: var(--bg-hover); }
.month-cell.today { background: rgba(66,133,244,.08); }
.month-cell.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-more {
position: absolute;
font-size: 11px; color: var(--text-2); padding: 0 4px;
cursor: pointer; font-weight: 500;
}
.month-more:hover { color: var(--primary); }
/* ── Week / Day Views ───────────────────────────────────── */
.week-view, .day-view { display: flex; flex-direction: column; height: 100%; }
.week-header-row {
display: flex; border-bottom: 1px solid var(--border);
flex-shrink: 0; background: var(--bg-app);
position: sticky; top: 0; z-index: 10;
}
/* 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; min-height: 28px; }
.allday-gutter { width: 56px; flex-shrink: 0; display: flex; align-items: center; justify-content: flex-end; padding-right: 6px; font-size: 10px; color: var(--text-3); }
.allday-cols { display: flex; flex: 1; }
.allday-col { flex: 1; border-left: 1px solid var(--border); padding: 2px; }
.allday-event {
font-size: 11px; font-weight: 500; padding: 2px 6px;
border-radius: 3px; margin-bottom: 2px; cursor: pointer;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Time grid */
.week-body { display: flex; flex: 1; overflow-y: auto; position: relative; }
.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; }
/* ── Agenda View ────────────────────────────────────────── */
.agenda-view { padding: 16px; }
.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);
}
/* ── 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; }
/* ── 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: 0;
border-bottom: 1px solid var(--border);
}
.month-row:last-child { border-bottom: none; }
.month-row-right {
margin-left: 38px; display: flex; flex-direction: column; flex: 1; min-width: 0;
}
.month-day-strip {
display: flex; flex-shrink: 0;
}
.month-events-area {
position: relative; flex: 1;
min-height: 72px; /* 3 lanes × 22px + 6px padding */
overflow: hidden;
}
.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;
z-index: 2;
}
.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; }
}