diff --git a/frontend/css/app.css b/frontend/css/app.css
index 8afa9f7..7dcbab3 100644
--- a/frontend/css/app.css
+++ b/frontend/css/app.css
@@ -2148,6 +2148,8 @@ a { color: var(--primary); text-decoration: none; }
/* Group emoji + icon picker */
.group-emoji { flex: 0 0 auto; font-size: 16px; cursor: pointer; line-height: 1; }
.cal-shared-flag { flex: 0 0 auto; font-size: 12px; opacity: .8; }
+/* Read-only (shared with me) indicator: a struck-through pencil. */
+.cal-readonly-flag { color: var(--text-3); opacity: .7; margin-left: 2px; }
.group-icon-picker { display: flex; flex-wrap: wrap; gap: 6px; }
.group-icon-opt {
width: 38px; height: 38px;
diff --git a/frontend/js/calendar.js b/frontend/js/calendar.js
index 6819fc0..7456abe 100644
--- a/frontend/js/calendar.js
+++ b/frontend/js/calendar.js
@@ -733,7 +733,7 @@ function renderCalendarList() {
// (e.g. Guido's "Persönlich" appears as "Guido"); the original calendar
// name stays in the sub-label so it's still identifiable.
entries.push({ key: `local:${cal.id}`, source: 'local', dataId: `data-cal-id="${cal.id}"`,
- name: cal.shared_by || cal.name, color: cal.color, enabled: cal.enabled,
+ name: cal.shared_by || cal.name, color: cal.color, enabled: cal.enabled, readOnly,
sourceLabel: `${t('shared_with_me')} · ${cal.name}${readOnly ? ' · ' + t('perm_read') : ''}`, remove: null });
});
// Group calendars (owned by the creator or reached via membership) — shown so
@@ -793,6 +793,7 @@ function renderCalendarList() {
${e.isGroupCal ? `${groupIconSvg(e.groupIcon || 'people', 13)}` : ''}
${e.groupVisible ? `${shareIconSvg(state.settings?.share_calendar_icon || 'share', 13)}` : ''}
${escHtml(e.name)}
+ ${e.readOnly ? `` : ''}
${e.reminders ? `` : ''}
${e.remove ? `` : ''}
`
@@ -956,6 +957,12 @@ function renderCalendarList() {
e.stopPropagation();
const item = nameEl.closest('.cal-item');
const source = nameEl.dataset.source;
+ // Can't rename a calendar shared with me — only the owner may. Renaming
+ // would just 403 on save, so don't even start editing.
+ if (source === 'local') {
+ const cal = state.localCalendars.find(c => c.id === parseInt(item?.dataset.calId));
+ if (cal && cal.owned === false) return;
+ }
const currentName = nameEl.textContent;
const input = document.createElement('input');
input.type = 'text';
diff --git a/frontend/js/version.js b/frontend/js/version.js
index 90af8b3..5815c84 100644
--- a/frontend/js/version.js
+++ b/frontend/js/version.js
@@ -1,2 +1,2 @@
// Increment APP_VERSION with every code change
-export const APP_VERSION = 'v71';
+export const APP_VERSION = 'v72';