diff --git a/app/emails/frontend/emails.html b/app/emails/frontend/emails.html
index 6dbd463..72985a6 100644
--- a/app/emails/frontend/emails.html
+++ b/app/emails/frontend/emails.html
@@ -379,6 +379,26 @@
word-break: break-word;
}
+ .email-html-body {
+ max-width: 100%;
+ overflow-x: hidden;
+ }
+
+ .email-html-iframe {
+ width: 100%;
+ min-height: 520px;
+ height: min(72vh, 980px);
+ border: 1px solid rgba(0,0,0,0.08);
+ border-radius: 10px;
+ background: #ffffff;
+ display: block;
+ }
+
+ [data-bs-theme="dark"] .email-html-iframe {
+ background: #111827;
+ border-color: rgba(255,255,255,0.16);
+ }
+
.email-body pre,
.email-html-body,
.email-html-body * {
@@ -388,14 +408,28 @@
}
.email-html-body table {
- display: block;
- overflow-x: auto;
- width: 100% !important;
+ display: table;
+ overflow-x: visible;
+ width: max-content !important;
+ min-width: 100% !important;
max-width: 100% !important;
table-layout: auto !important;
border-collapse: collapse;
}
+ .email-table-scroll {
+ width: 100%;
+ max-width: 100%;
+ overflow-x: auto;
+ overflow-y: hidden;
+ -webkit-overflow-scrolling: touch;
+ margin-bottom: 0.5rem;
+ }
+
+ .email-table-scroll > table {
+ margin-bottom: 0;
+ }
+
.email-html-body tbody,
.email-html-body thead,
.email-html-body tfoot,
@@ -407,11 +441,21 @@
.email-html-body td,
.email-html-body th {
+ min-width: 0 !important;
white-space: normal !important;
word-break: break-word !important;
overflow-wrap: anywhere !important;
}
+ .email-html-body [width],
+ .email-html-body [style*="width:"],
+ .email-html-body [style*="width: "],
+ .email-html-body [style*="min-width:"],
+ .email-html-body [style*="min-width: "] {
+ max-width: 100% !important;
+ box-sizing: border-box !important;
+ }
+
.email-html-body img,
.email-html-body video,
.email-html-body iframe {
@@ -2226,45 +2270,102 @@ function renderEmailDetail(email) {
- ${email.body_html ? `
` :
+ ${email.body_html ? `
` :
`
${escapeHtml(email.body_text || 'Ingen indhold')}`}
`;
- // If HTML, inject it as innerHTML after rendering
+
+ // If HTML, render inside sandboxed iframe so mail CSS cannot affect app layout.
if (email.body_html) {
- const htmlDiv = pane.querySelector('.email-html-body');
- if (htmlDiv) {
- htmlDiv.innerHTML = email.body_html;
- normalizeEmailHtmlLayout(htmlDiv);
+ const frame = pane.querySelector('.email-html-iframe');
+ if (frame) {
+ frame.srcdoc = buildIsolatedEmailSrcdoc(email.body_html);
}
}
}
-function normalizeEmailHtmlLayout(container) {
- if (!container) return;
+function buildIsolatedEmailSrcdoc(rawHtml) {
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(String(rawHtml || ''), 'text/html');
- const tables = container.querySelectorAll('table');
- tables.forEach((table) => {
- table.style.maxWidth = '100%';
- table.style.width = '100%';
- table.style.tableLayout = 'auto';
- table.removeAttribute('width');
- });
+ doc.querySelectorAll('script, base, meta[http-equiv="refresh"]').forEach((el) => el.remove());
- const cells = container.querySelectorAll('td, th');
- cells.forEach((cell) => {
- cell.style.whiteSpace = 'normal';
- cell.style.wordBreak = 'break-word';
- cell.style.overflowWrap = 'anywhere';
- });
+ doc.querySelectorAll('*').forEach((el) => {
+ Array.from(el.attributes).forEach((attr) => {
+ if (/^on/i.test(attr.name)) {
+ el.removeAttribute(attr.name);
+ }
+ });
- const images = container.querySelectorAll('img, iframe, video');
- images.forEach((el) => {
- el.style.maxWidth = '100%';
- if (el.tagName === 'IMG' || el.tagName === 'VIDEO') {
- el.style.height = 'auto';
+ if (el.hasAttribute('width')) {
+ el.removeAttribute('width');
+ }
+
+ if (el.tagName === 'A') {
+ el.setAttribute('target', '_blank');
+ el.setAttribute('rel', 'noopener noreferrer');
+ }
+ });
+
+ const bodyHtml = (doc.body && doc.body.innerHTML) ? doc.body.innerHTML : String(rawHtml || '');
+
+ return `
+
+
+
+
+
+
+${bodyHtml}
+`;
}
function renderEmailAnalysis(email) {
diff --git a/app/modules/sag/templates/detail.html b/app/modules/sag/templates/detail.html
index fb266cc..49bdeb7 100644
--- a/app/modules/sag/templates/detail.html
+++ b/app/modules/sag/templates/detail.html
@@ -864,11 +864,11 @@
/* Forslag 1: Opgavebeskrivelse + kommentarspor (venstre side) */
.narrative-description {
- border: 1px solid rgba(15, 76, 117, 0.16);
- background: linear-gradient(180deg, rgba(15, 76, 117, 0.06), rgba(15, 76, 117, 0.02));
+ border: 1px solid rgba(15, 76, 117, 0.22);
+ background: linear-gradient(165deg, rgba(15, 76, 117, 0.11), rgba(15, 76, 117, 0.04));
border-radius: 12px;
padding: 1.1rem 1.1rem 1rem;
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.52), 0 3px 10px rgba(15, 76, 117, 0.06);
}
#beskrivelse-section {
@@ -885,21 +885,26 @@
font-weight: 800;
letter-spacing: 0.06em;
text-transform: uppercase;
- color: var(--text-secondary);
+ color: color-mix(in srgb, var(--accent) 68%, #2f3a45);
margin-bottom: 0.55rem;
}
+ .case-left-section-title i {
+ color: var(--accent);
+ }
+
.case-left-panel {
- border: 1px solid rgba(0, 0, 0, 0.09);
+ border: 1px solid rgba(15, 76, 117, 0.18);
border-radius: 12px;
- background: var(--bg-card);
+ background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 4%, var(--bg-card)), var(--bg-card));
padding: 0.9rem;
+ box-shadow: 0 2px 8px rgba(15, 76, 117, 0.06);
}
#beskrivelse-history-wrap {
- border: 1px solid rgba(0, 0, 0, 0.09);
+ border: 1px solid rgba(15, 76, 117, 0.18);
border-radius: 12px;
- background: rgba(0, 0, 0, 0.02);
+ background: color-mix(in srgb, var(--accent) 6%, var(--bg-card));
padding: 0.75rem 0.85rem;
}
@@ -909,9 +914,9 @@
}
#beskrivelse-comments-wrap {
- border: 1px solid rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(15, 76, 117, 0.2);
border-radius: 12px;
- background: var(--bg-card);
+ background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 3%, var(--bg-card)), var(--bg-card));
padding: 0.95rem;
}
@@ -930,20 +935,21 @@
}
.comment-thread {
- border: 1px solid rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(15, 76, 117, 0.2);
border-radius: 10px;
padding: 0.65rem;
max-height: 360px;
overflow-y: auto;
- background: var(--bg-body);
+ background: color-mix(in srgb, var(--accent) 3%, var(--bg-body));
}
.comment-item {
- border: 1px solid rgba(0, 0, 0, 0.08);
+ border: 1px solid rgba(15, 76, 117, 0.16);
border-radius: 10px;
background: var(--bg-card);
padding: 0.55rem 0.65rem;
margin-bottom: 0.5rem;
+ box-shadow: 0 1px 4px rgba(15, 76, 117, 0.05);
}
.comment-item:last-child {
@@ -1020,9 +1026,9 @@
.comment-quick-reply-box {
margin-top: 0.75rem;
- border: 1px solid rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(15, 76, 117, 0.2);
border-radius: 10px;
- background: var(--bg-card);
+ background: color-mix(in srgb, var(--accent) 3%, var(--bg-card));
padding: 0.6rem;
}
@@ -1162,13 +1168,31 @@
}
[data-bs-theme="dark"] .narrative-description {
- border-color: rgba(117, 194, 239, 0.24);
- background: linear-gradient(180deg, rgba(117, 194, 239, 0.14), rgba(117, 194, 239, 0.06));
+ border-color: rgba(117, 194, 239, 0.32);
+ background: linear-gradient(180deg, rgba(117, 194, 239, 0.2), rgba(117, 194, 239, 0.08));
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 4px 12px rgba(5, 18, 30, 0.28);
+ }
+
+ [data-bs-theme="dark"] .case-left-section-title {
+ color: #d4e8f8;
+ }
+
+ [data-bs-theme="dark"] .case-left-section-title i {
+ color: #8fc3e8;
+ }
+
+ [data-bs-theme="dark"] .case-left-panel,
+ [data-bs-theme="dark"] #beskrivelse-history-wrap,
+ [data-bs-theme="dark"] #beskrivelse-comments-wrap {
+ border-color: rgba(117, 194, 239, 0.28);
+ background: linear-gradient(180deg, rgba(117, 194, 239, 0.08), rgba(17, 24, 33, 0.94));
}
[data-bs-theme="dark"] .comment-thread,
- [data-bs-theme="dark"] .comment-item {
- border-color: rgba(255, 255, 255, 0.14);
+ [data-bs-theme="dark"] .comment-item,
+ [data-bs-theme="dark"] .comment-quick-reply-box {
+ border-color: rgba(117, 194, 239, 0.24);
+ background: rgba(20, 30, 41, 0.86);
}
.card[data-module].module-empty-compact {
@@ -1802,9 +1826,9 @@
}
.case-tabs-topbar.topbar-primary {
- grid-template-columns: repeat(8, minmax(130px, 1fr));
- background: linear-gradient(140deg, rgba(15,76,117,0.08), rgba(15,76,117,0.01));
- border: 1px solid rgba(15,76,117,0.22);
+ grid-template-columns: minmax(86px, 0.55fr) minmax(220px, 1.7fr) repeat(6, minmax(120px, 1fr));
+ background: #0f4c75;
+ border: 1px solid #0b3a59;
border-radius: 0;
box-shadow: none;
margin-bottom: 1rem;
@@ -1813,7 +1837,7 @@
.topbar-primary .case-tabs-topbar-item {
background: transparent;
border: none;
- border-left: 1px solid rgba(15,76,117,0.2);
+ border-left: 1px solid rgba(255,255,255,0.24);
border-radius: 0;
padding: 0.45rem 0.7rem;
}
@@ -1823,16 +1847,26 @@
}
.topbar-primary .case-tabs-topbar-label {
- color: color-mix(in srgb, var(--accent) 75%, #2f3a45);
- opacity: 0.95;
- font-size: 0.62rem;
+ color: rgba(255,255,255,0.88);
+ opacity: 1;
+ font-size: 0.72rem;
letter-spacing: 0.1em;
}
.topbar-primary .case-tabs-topbar-value {
- font-size: 1.02rem;
+ font-size: 1.12rem;
font-weight: 750;
- color: var(--accent);
+ color: #ffffff;
+ }
+
+ .topbar-primary .field-case-id .case-tabs-topbar-value {
+ font-size: 0.96rem;
+ font-weight: 700;
+ letter-spacing: 0.01em;
+ }
+
+ .topbar-primary .field-case-id {
+ padding-right: 0.45rem;
}
.topbar-company-row {
@@ -1849,12 +1883,21 @@
white-space: nowrap;
}
+ .topbar-primary .topbar-company-name {
+ color: #ffffff !important;
+ font-size: 1.18rem;
+ font-weight: 800;
+ line-height: 1.15;
+ letter-spacing: 0.01em;
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
+ }
+
.topbar-company-contact {
margin-top: 0.22rem;
- font-size: 0.72rem;
+ font-size: 0.8rem;
line-height: 1.2;
- color: color-mix(in srgb, var(--accent) 58%, #475569);
- opacity: 0.95;
+ color: rgba(255,255,255,0.88);
+ opacity: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -1886,24 +1929,43 @@
}
.topbar-primary .case-inline-select {
- background: rgba(255,255,255,0.88);
- border-color: rgba(15,76,117,0.3);
+ background: rgba(255,255,255,0.14);
+ border-color: rgba(255,255,255,0.36);
box-shadow: none;
border-radius: 4px;
font-weight: 700;
- color: var(--accent);
+ color: #ffffff;
}
.topbar-primary .topbar-next-meta {
margin-top: 0.12rem;
- font-size: 0.7rem;
- color: color-mix(in srgb, var(--accent) 55%, #4b5563);
- opacity: 0.95;
+ font-size: 0.78rem;
+ color: rgba(255,255,255,0.8);
+ opacity: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
+ .topbar-primary .topbar-secondary-action {
+ border-color: rgba(255,255,255,0.36);
+ background: rgba(255,255,255,0.12);
+ color: #ffffff;
+ font-size: 0.88rem;
+ }
+
+ .topbar-primary .topbar-secondary-action:hover,
+ .topbar-primary .topbar-secondary-action:focus-visible {
+ background: rgba(255,255,255,0.22);
+ color: #ffffff;
+ }
+
+ .topbar-primary .case-tabs-topbar-label i,
+ .topbar-primary .topbar-next-meta i,
+ .topbar-primary .case-tabs-topbar-value i {
+ color: rgba(255,255,255,0.9);
+ }
+
.back-link {
display: inline-flex;
align-items: center;
@@ -1945,23 +2007,34 @@
}
[data-bs-theme="dark"] .case-tabs-topbar.topbar-primary {
- background: linear-gradient(135deg, rgba(70,120,160,0.2), rgba(70,120,160,0.06));
- border-color: rgba(120,170,210,0.35);
+ background: #0f4c75;
+ border-color: #75a7cc;
}
[data-bs-theme="dark"] .topbar-primary .case-tabs-topbar-item {
- border-left-color: rgba(120,170,210,0.25);
+ border-left-color: rgba(255,255,255,0.28);
}
[data-bs-theme="dark"] .topbar-primary .case-tabs-topbar-label,
[data-bs-theme="dark"] .topbar-primary .case-tabs-topbar-value {
- color: #b8d9f1;
+ color: #ffffff;
}
[data-bs-theme="dark"] .topbar-primary .case-inline-select {
- background: rgba(20,35,48,0.7);
- border-color: rgba(120,170,210,0.4);
- color: #d9ebf7;
+ background: rgba(255,255,255,0.14);
+ border-color: rgba(255,255,255,0.4);
+ color: #ffffff;
+ }
+
+ .card[data-module] {
+ border-width: 2px !important;
+ border-color: rgba(15, 76, 117, 0.28) !important;
+ box-shadow: 0 4px 12px rgba(15, 76, 117, 0.10);
+ }
+
+ [data-bs-theme="dark"] .card[data-module] {
+ border-color: rgba(117, 167, 204, 0.45) !important;
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.28);
}
[data-bs-theme="dark"] .topbar-company-edit-btn {
@@ -1973,6 +2046,11 @@
color: #b8d9f1;
}
+ [data-bs-theme="dark"] .topbar-primary .topbar-company-name {
+ color: #ffffff !important;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
+ }
+
[data-bs-theme="dark"] .right-module-card {
border-color: rgba(140, 182, 219, 0.25);
box-shadow: 0 4px 16px rgba(5, 22, 40, 0.45);
@@ -1997,6 +2075,56 @@
minmax(150px, 1.1fr) /* Deadline (1 knap) */
minmax(120px, 0.85fr) /* AnyDesk */
minmax(140px, 1fr) /* Dokumenter */;
+ align-items: stretch;
+ background: linear-gradient(180deg, rgba(15, 76, 117, 0.10), rgba(15, 76, 117, 0.04));
+ border: 1px solid rgba(15, 76, 117, 0.30);
+ border-radius: 10px;
+ padding: 0.42rem 0.5rem;
+ }
+
+ .case-tabs-topbar.topbar-secondary .case-tabs-topbar-item {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ height: 100%;
+ background: rgba(255, 255, 255, 0.82);
+ border: 1px solid rgba(15, 76, 117, 0.24);
+ border-left: 1px solid rgba(15, 76, 117, 0.24);
+ border-radius: 8px;
+ }
+
+ .case-tabs-topbar.topbar-secondary .case-tabs-topbar-item:first-child {
+ border-left: 1px solid rgba(15, 76, 117, 0.24);
+ }
+
+ .case-tabs-topbar.topbar-secondary .case-tabs-topbar-label {
+ color: #1c425c;
+ opacity: 1;
+ }
+
+ .case-tabs-topbar.topbar-secondary .case-tabs-topbar-value {
+ color: #0f2f45;
+ font-weight: 700;
+ }
+
+ .case-tabs-topbar.topbar-secondary .case-inline-select {
+ background: #ffffff;
+ border: 1px solid rgba(15, 76, 117, 0.34);
+ color: #0f2f45;
+ font-weight: 700;
+ }
+
+ .case-tabs-topbar.topbar-secondary .topbar-secondary-action {
+ border-color: rgba(15, 76, 117, 0.34);
+ background: #ffffff;
+ color: #0f2f45;
+ }
+
+ .case-tabs-topbar.topbar-secondary .topbar-secondary-action:hover,
+ .case-tabs-topbar.topbar-secondary .topbar-secondary-action:focus-visible {
+ background: rgba(15, 76, 117, 0.12);
+ border-color: rgba(15, 76, 117, 0.55);
+ color: #0b2535;
}
.case-tabs-topbar-item {
@@ -2226,6 +2354,31 @@
background: rgba(20, 27, 38, 0.78);
}
+ [data-bs-theme="dark"] .case-tabs-topbar.topbar-secondary {
+ background: linear-gradient(180deg, rgba(117, 194, 239, 0.18), rgba(117, 194, 239, 0.08));
+ border-color: rgba(117, 194, 239, 0.36);
+ }
+
+ [data-bs-theme="dark"] .case-tabs-topbar.topbar-secondary .case-tabs-topbar-item {
+ background: rgba(15, 24, 34, 0.9);
+ border-color: rgba(117, 194, 239, 0.32);
+ }
+
+ [data-bs-theme="dark"] .case-tabs-topbar.topbar-secondary .case-tabs-topbar-label {
+ color: #cfe6f7;
+ }
+
+ [data-bs-theme="dark"] .case-tabs-topbar.topbar-secondary .case-tabs-topbar-value {
+ color: #f2f8fe;
+ }
+
+ [data-bs-theme="dark"] .case-tabs-topbar.topbar-secondary .case-inline-select,
+ [data-bs-theme="dark"] .case-tabs-topbar.topbar-secondary .topbar-secondary-action {
+ background: rgba(19, 30, 42, 0.92);
+ border-color: rgba(117, 194, 239, 0.38);
+ color: #eef6fd;
+ }
+
.case-add-side-backdrop {
@@ -2462,7 +2615,7 @@
-
-
-
- Tilbage til sager
-
-
+
+
@@ -11779,13 +11928,6 @@
return;
}
- // Moduler med indhold skal altid vises.
- if (hasContent) {
- setVisibility(true);
- el.classList.remove('module-empty-compact');
- return;
- }
-
// HVIS specifik præference deaktiverer den - Skjul den! Uanset content.
if (pref === false) {
setVisibility(false);
@@ -11800,6 +11942,13 @@
return;
}
+ // Moduler med indhold vises automatisk, når der ikke er et eksplicit brugervalg.
+ if (hasContent) {
+ setVisibility(true);
+ el.classList.remove('module-empty-compact');
+ return;
+ }
+
// Default logic - ingen content: se på layout defaults
if (standardModuleSet.has(moduleName)) {
setVisibility(true);
diff --git a/app/shared/frontend/base.html b/app/shared/frontend/base.html
index ddbc536..469f945 100644
--- a/app/shared/frontend/base.html
+++ b/app/shared/frontend/base.html
@@ -109,6 +109,16 @@
scrollbar-width: none;
}
+ .global-bottom-bar .bb-zone-left .bb-back-btn {
+ position: sticky;
+ left: 0;
+ z-index: 3;
+ background: var(--bg-card);
+ border-color: rgba(var(--text-primary-rgb), 0.2);
+ margin-right: 0.2rem;
+ flex: 0 0 auto;
+ }
+
.global-bottom-bar .bb-zone-left::-webkit-scrollbar {
display: none;
}
@@ -1047,6 +1057,10 @@