upload
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><style>
|
||||
html{font-family:Arial,sans-serif;font-size:8px;color:{{ data.design.muted_color }};margin:0 14mm;-webkit-print-color-adjust:exact}body{margin:0}.footer{border-top:1px solid {{ data.design.primary_color }}33;padding-top:2.5mm;display:flex;justify-content:space-between}.page{font-weight:700;color:{{ data.design.primary_color }}}
|
||||
</style></head><body><div class="footer"><span>{{ data.customer.name }} · {{ data.report.period.label }} · {{ data._theme.name }}</span><span class="page">Seite <span class="pageNumber"></span> / <span class="totalPages"></span></span></div></body></html>
|
||||
@@ -0,0 +1,68 @@
|
||||
{% macro logo(data, class_name='logo') -%}
|
||||
<div class="{{ class_name }}">
|
||||
{% if data.customer.logo_data_uri %}<img src="{{ data.customer.logo_data_uri }}" alt="Logo">{% else %}{{ data.customer.logo_text }}{% endif %}
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro kpis(data) -%}
|
||||
<div class="kpis">
|
||||
<article class="kpi"><div class="kpi-label">Umsatz</div><div class="kpi-value">{{ data.metrics.revenue|currency_de(data.metrics.currency) }}</div><div class="kpi-delta {{ 'up' if data.metrics.comparison.revenue_delta_pct >= 0 else 'down' }}">{{ data.metrics.comparison.revenue_delta_pct|delta_de(1, '%') }}</div></article>
|
||||
<article class="kpi"><div class="kpi-label">Auslastung</div><div class="kpi-value">{{ data.metrics.occupancy_rate|percent_de }}</div><div class="kpi-delta {{ 'up' if data.metrics.comparison.occupancy_delta_pp >= 0 else 'down' }}">{{ data.metrics.comparison.occupancy_delta_pp|delta_de(1, 'PP') }}</div></article>
|
||||
<article class="kpi"><div class="kpi-label">Ø Tagespreis</div><div class="kpi-value">{{ data.metrics.adr|currency_de(data.metrics.currency) }}</div><div class="kpi-delta {{ 'up' if data.metrics.comparison.adr_delta_pct >= 0 else 'down' }}">{{ data.metrics.comparison.adr_delta_pct|delta_de(1, '%') }}</div></article>
|
||||
<article class="kpi"><div class="kpi-label">Buchungen</div><div class="kpi-value">{{ data.metrics.bookings|number_de(0) }}</div><div class="kpi-delta {{ 'up' if data.metrics.comparison.bookings_delta >= 0 else 'down' }}">{{ data.metrics.comparison.bookings_delta|delta_de(0, '') }} Buchungen</div></article>
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro facts(data) -%}
|
||||
<div class="facts">
|
||||
<div class="fact"><span>RevPAR</span><strong>{{ data.metrics.revpar|currency_de(data.metrics.currency) }}</strong></div>
|
||||
<div class="fact"><span>Verkaufte Nächte</span><strong>{{ data.metrics.nights_sold|number_de(0) }}</strong></div>
|
||||
<div class="fact"><span>Ø Aufenthalt</span><strong>{{ data.metrics.average_stay|number_de(1) }} Nächte</strong></div>
|
||||
<div class="fact"><span>Stornoquote</span><strong>{{ data.metrics.cancellation_rate|percent_de }}</strong></div>
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro trend_bars(data) -%}
|
||||
<div class="trend-bars">
|
||||
{% for item in data.trends %}
|
||||
<div class="trend-row">
|
||||
<div class="trend-label">{{ item.label }}</div>
|
||||
<div class="trend-track"><div class="trend-revenue" style="width:{{ item.revenue_bar }}%"></div><div class="trend-occ" style="width:{{ item.occupancy_bar }}%"></div></div>
|
||||
<div class="trend-num">{{ item.revenue|currency_de(data.metrics.currency) }}</div>
|
||||
<div class="trend-num">{{ item.occupancy_rate|percent_de }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro trend_table(data) -%}
|
||||
<table class="trend-table">
|
||||
<thead><tr><th>Monat</th><th>Umsatz</th><th>Auslastung</th><th>Ø Tagespreis</th></tr></thead>
|
||||
<tbody>{% for item in data.trends %}<tr><td>{{ item.label }}</td><td>{{ item.revenue|currency_de(data.metrics.currency) }}</td><td>{{ item.occupancy_rate|percent_de }}</td><td>{{ item.adr|currency_de(data.metrics.currency) }}</td></tr>{% endfor %}</tbody>
|
||||
</table>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro developments(data) -%}
|
||||
<div class="developments">
|
||||
{% for item in data.content.developments %}
|
||||
<article class="development {{ item.impact }}"><div class="impact"></div><div><h3>{{ item.title }}</h3><p>{{ item.text }}</p></div></article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro recommendations(data) -%}
|
||||
<div class="recommendations">
|
||||
{% for item in data.content.recommendations|sort(attribute='priority') %}
|
||||
<article class="recommendation"><div class="priority">{{ item.priority }}</div><div><div class="category">{{ item.category }}</div><h3>{{ item.title }}</h3><p><strong>Begründung:</strong> {{ item.reason }}</p><p><strong>Massnahme:</strong> {{ item.action }}</p><p class="effect"><strong>Erwarteter Effekt:</strong> {{ item.expected_effect }}</p></div></article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro outlook(data) -%}
|
||||
<section class="outlook"><div class="kicker">Ausblick</div><h2>{{ data.content.outlook.headline }}</h2><p>{{ data.content.outlook.text }}</p></section>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro notes(data) -%}
|
||||
{% if data.content.data_quality_notes %}<section class="notes"><strong>Hinweise zur Datengrundlage</strong><ul>{% for note in data.content.data_quality_notes %}<li>{{ note }}</li>{% endfor %}</ul></section>{% endif %}
|
||||
<div class="legal">{{ data.legal_note }}</div>
|
||||
{%- endmacro %}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
html { font-family: Arial, sans-serif; font-size: 8px; color: #737b80; margin: 0 16mm; -webkit-print-color-adjust: exact; }
|
||||
body { margin: 0; }
|
||||
.footer { border-top: 1px solid #cfd6da; padding-top: 3mm; display: flex; justify-content: space-between; }
|
||||
.page { color: {{ data.design.primary_color }}; font-weight: 700; }
|
||||
</style>
|
||||
</head>
|
||||
<body><div class="footer"><span>{{ data.customer.name }} · Vertraulich</span><span class="page">{{ data.report.period.label }} · <span class="pageNumber"></span>/<span class="totalPages"></span></span></div></body>
|
||||
</html>
|
||||
@@ -0,0 +1,124 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Monatsreport {{ data.report.period.label }} - {{ data.customer.name }}</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: {{ data.design.primary_color }};
|
||||
--accent: {{ data.design.accent_color }};
|
||||
--text: {{ data.design.text_color }};
|
||||
--muted: {{ data.design.muted_color }};
|
||||
--surface: {{ data.design.surface_color }};
|
||||
--line: #cfd6da;
|
||||
--positive: #236a4f;
|
||||
--negative: #9d3e3e;
|
||||
}
|
||||
@page { size: A4; margin: 15mm 16mm 19mm; }
|
||||
* { box-sizing: border-box; }
|
||||
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||
body { margin: 0; font-family: {{ data.design.font_family }}, Georgia, serif; color: var(--text); font-size: 9.5pt; line-height: 1.5; }
|
||||
h1, h2, h3, p { margin-top: 0; }
|
||||
h1 { font-size: 25pt; font-weight: 500; line-height: 1.12; margin-bottom: 2mm; }
|
||||
h2 { font-size: 15pt; font-weight: 600; color: var(--primary); margin-bottom: 3mm; }
|
||||
h3 { font-size: 10.5pt; margin-bottom: 1mm; }
|
||||
p { margin-bottom: 3mm; }
|
||||
.sans { font-family: Arial, sans-serif; }
|
||||
.header { border-top: 2.5mm solid var(--primary); padding-top: 7mm; margin-bottom: 8mm; display: grid; grid-template-columns: 1fr auto; gap: 8mm; }
|
||||
.brand { text-align: right; font-family: Arial, sans-serif; font-size: 8pt; color: var(--muted); }
|
||||
.brand strong { display: block; color: var(--primary); font-size: 10pt; margin-bottom: 1mm; }
|
||||
.period { font-family: Arial, sans-serif; text-transform: uppercase; letter-spacing: 1.4px; color: var(--accent); font-size: 8pt; font-weight: 700; }
|
||||
.meta { display: flex; gap: 6mm; color: var(--muted); font-family: Arial, sans-serif; font-size: 7.5pt; }
|
||||
.rule-heading { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4mm; margin: 7mm 0 3mm; }
|
||||
.rule-heading h2 { margin: 0; white-space: nowrap; }
|
||||
.rule { height: .25mm; background: var(--line); }
|
||||
.summary { padding: 5mm 0 5mm 5mm; border-left: 1.2mm solid var(--accent); break-inside: avoid; }
|
||||
.summary h2 { color: var(--text); }
|
||||
.summary p { margin: 0; }
|
||||
.kpis { display: grid; grid-template-columns: repeat(4,1fr); border: .25mm solid var(--line); break-inside: avoid; }
|
||||
.kpi { padding: 4mm; border-right: .25mm solid var(--line); min-height: 28mm; }
|
||||
.kpi:last-child { border-right: 0; }
|
||||
.kpi-label { font-family: Arial, sans-serif; font-size: 7pt; text-transform: uppercase; letter-spacing: .8px; color: var(--muted); }
|
||||
.kpi-value { color: var(--primary); font-size: 15pt; font-weight: 600; margin: 2.5mm 0 1mm; white-space: nowrap; }
|
||||
.kpi-delta { font-family: Arial, sans-serif; font-size: 7pt; color: var(--muted); }
|
||||
.facts { display: grid; grid-template-columns: repeat(4,1fr); background: var(--surface); padding: 3mm 4mm; font-family: Arial, sans-serif; font-size: 7.5pt; }
|
||||
.facts strong { display: block; color: var(--primary); font-size: 9pt; margin-top: .5mm; }
|
||||
table { width: 100%; border-collapse: collapse; break-inside: avoid; font-family: Arial, sans-serif; font-size: 7.6pt; }
|
||||
th { text-align: left; color: var(--muted); font-size: 6.8pt; text-transform: uppercase; letter-spacing: .7px; padding: 2.5mm; border-bottom: .5mm solid var(--primary); }
|
||||
td { padding: 2.5mm; border-bottom: .25mm solid var(--line); }
|
||||
td.num, th.num { text-align: right; }
|
||||
.developments { columns: 2; column-gap: 6mm; }
|
||||
.development { break-inside: avoid; padding: 0 0 3mm 4mm; margin-bottom: 3mm; border-left: .8mm solid var(--line); }
|
||||
.development.positive { border-left-color: var(--positive); }
|
||||
.development.negative { border-left-color: var(--negative); }
|
||||
.development p { margin: 0; }
|
||||
.recommendation { break-inside: avoid; display: grid; grid-template-columns: 10mm 1fr; gap: 4mm; padding: 4mm 0; border-bottom: .25mm solid var(--line); }
|
||||
.recommendation:last-child { border-bottom: 0; }
|
||||
.number { width: 9mm; height: 9mm; border: .4mm solid var(--primary); color: var(--primary); display: flex; align-items: center; justify-content: center; align-self: start; border-radius: 50%; font-family: Arial, sans-serif; font-weight: 700; }
|
||||
.category { color: var(--accent); font-family: Arial, sans-serif; font-size: 7pt; text-transform: uppercase; letter-spacing: .8px; font-weight: 700; }
|
||||
.recommendation p { margin-bottom: 1.7mm; }
|
||||
.outlook { margin-top: 6mm; padding: 5mm; background: var(--surface); border-top: 1mm solid var(--primary); break-inside: avoid; }
|
||||
.outlook p { margin: 0; }
|
||||
.notes { font-family: Arial, sans-serif; font-size: 7pt; color: var(--muted); margin-top: 4mm; }
|
||||
.notes ul { margin: 1mm 0; padding-left: 4mm; }
|
||||
.legal { font-family: Arial, sans-serif; font-size: 6.6pt; color: var(--muted); margin-top: 4mm; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="header">
|
||||
<div>
|
||||
<div class="period">{{ data.report.period.label }}</div>
|
||||
<h1>Monatsreport</h1>
|
||||
<div class="meta"><span>{{ data.customer.property_name }}</span><span>{{ data.customer.location }}</span><span>{{ data.report.generated_at|date_de }}</span></div>
|
||||
</div>
|
||||
<div class="brand"><strong>{{ data.customer.name }}</strong>{{ data.customer.contact_line }}</div>
|
||||
</header>
|
||||
|
||||
<section class="summary">
|
||||
<div class="period">Kurzfazit</div>
|
||||
<h2>{{ data.content.summary.headline }}</h2>
|
||||
<p>{{ data.content.summary.text }}</p>
|
||||
</section>
|
||||
|
||||
<div class="rule-heading"><h2>Kennzahlen</h2><div class="rule"></div></div>
|
||||
<section class="kpis">
|
||||
<div class="kpi"><div class="kpi-label">Umsatz</div><div class="kpi-value">{{ data.metrics.revenue|currency_de(data.metrics.currency) }}</div><div class="kpi-delta">{{ data.metrics.comparison.revenue_delta_pct|delta_de(1, '%') }}</div></div>
|
||||
<div class="kpi"><div class="kpi-label">Auslastung</div><div class="kpi-value">{{ data.metrics.occupancy_rate|percent_de }}</div><div class="kpi-delta">{{ data.metrics.comparison.occupancy_delta_pp|delta_de(1, 'PP') }}</div></div>
|
||||
<div class="kpi"><div class="kpi-label">Ø Tagespreis</div><div class="kpi-value">{{ data.metrics.adr|currency_de(data.metrics.currency) }}</div><div class="kpi-delta">{{ data.metrics.comparison.adr_delta_pct|delta_de(1, '%') }}</div></div>
|
||||
<div class="kpi"><div class="kpi-label">Buchungen</div><div class="kpi-value">{{ data.metrics.bookings|number_de(0) }}</div><div class="kpi-delta">{{ data.metrics.comparison.bookings_delta|delta_de(0, '') }} Buchungen</div></div>
|
||||
</section>
|
||||
<section class="facts">
|
||||
<div>RevPAR<strong>{{ data.metrics.revpar|currency_de(data.metrics.currency) }}</strong></div>
|
||||
<div>Verkaufte Nächte<strong>{{ data.metrics.nights_sold|number_de(0) }}</strong></div>
|
||||
<div>Ø Aufenthalt<strong>{{ data.metrics.average_stay|number_de(1) }} Nächte</strong></div>
|
||||
<div>Stornoquote<strong>{{ data.metrics.cancellation_rate|percent_de }}</strong></div>
|
||||
</section>
|
||||
|
||||
<div class="rule-heading"><h2>Monatsverlauf</h2><div class="rule"></div></div>
|
||||
<table>
|
||||
<thead><tr><th>Monat</th><th class="num">Umsatz</th><th class="num">Auslastung</th><th class="num">Ø Tagespreis</th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in data.trends %}<tr><td>{{ item.label }}</td><td class="num">{{ item.revenue|currency_de(data.metrics.currency) }}</td><td class="num">{{ item.occupancy_rate|percent_de }}</td><td class="num">{{ item.adr|currency_de(data.metrics.currency) }}</td></tr>{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="rule-heading"><h2>Wichtige Entwicklungen</h2><div class="rule"></div></div>
|
||||
<section class="developments">
|
||||
{% for item in data.content.developments %}<article class="development {{ item.impact }}"><h3>{{ item.title }}</h3><p>{{ item.text }}</p></article>{% endfor %}
|
||||
</section>
|
||||
|
||||
<div class="rule-heading"><h2>Empfehlungen</h2><div class="rule"></div></div>
|
||||
<section>
|
||||
{% for item in data.content.recommendations|sort(attribute='priority') %}
|
||||
<article class="recommendation">
|
||||
<div class="number">{{ item.priority }}</div>
|
||||
<div><div class="category">{{ item.category }}</div><h3>{{ item.title }}</h3><p><strong>Begründung:</strong> {{ item.reason }}</p><p><strong>Massnahme:</strong> {{ item.action }}</p><p><strong>Erwarteter Effekt:</strong> {{ item.expected_effect }}</p></div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
|
||||
<section class="outlook"><div class="period">Ausblick</div><h2>{{ data.content.outlook.headline }}</h2><p>{{ data.content.outlook.text }}</p></section>
|
||||
{% if data.content.data_quality_notes %}<section class="notes"><strong>Hinweise zur Datengrundlage</strong><ul>{% for note in data.content.data_quality_notes %}<li>{{ note }}</li>{% endfor %}</ul></section>{% endif %}
|
||||
<div class="legal">{{ data.legal_note }}</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#d8e0e5;--pos:#25745b;--neg:#a84444}@page{size:A4;margin:12mm 13mm 19mm}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:9pt/1.46 {{data.design.font_family}},Arial,sans-serif;background:#fff}h1,h2,h3,p{margin-top:0}h1{font-size:24pt;margin:0;line-height:1.05}h2{font-size:13.5pt;margin-bottom:3mm}h3{font-size:10pt;margin-bottom:1mm}p{margin-bottom:2.5mm}.header{background:linear-gradient(125deg,var(--p),var(--s));color:#fff;border-radius:3mm;padding:7mm;margin-bottom:5mm;display:grid;grid-template-columns:1fr auto;gap:8mm;break-inside:avoid}.header-left{display:flex;gap:4mm;align-items:center}.logo{width:14mm;height:14mm;background:#fff;color:var(--p);border-radius:2mm;display:flex;align-items:center;justify-content:center;font-weight:900;overflow:hidden}.logo img{width:100%;height:100%;object-fit:contain;padding:1mm}.brand{font-weight:700}.sub{font-size:7.5pt;opacity:.78}.header-right{text-align:right}.period{font-size:11pt;font-weight:800}.kicker,.kpi-label,.category{font-size:6.8pt;text-transform:uppercase;letter-spacing:.9px;font-weight:800;color:var(--m)}.header .kicker{color:#ffffffb8}.summary{display:grid;grid-template-columns:1fr 42mm;gap:4mm;margin-bottom:5mm}.summary-main{padding:5mm;border:1px solid var(--line);border-radius:2mm}.summary-main h2{font-size:15pt}.summary-score{background:var(--bg);border-radius:2mm;padding:4mm;display:flex;flex-direction:column;justify-content:center;text-align:center}.summary-score strong{font-size:20pt;color:var(--p)}.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:3mm;margin-bottom:3mm}.kpi{padding:4mm;background:var(--bg);border-top:1.2mm solid var(--p);min-height:29mm;break-inside:avoid}.kpi-value{font-size:15pt;font-weight:800;color:var(--p);margin:2mm 0;white-space:nowrap}.kpi-delta{font-size:7pt}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:grid;grid-template-columns:repeat(4,1fr);gap:3mm;margin-bottom:6mm}.fact{border:1px solid var(--line);padding:2.5mm 3mm}.fact span{display:block;font-size:6.8pt;color:var(--m)}.fact strong{display:block;margin-top:.5mm}.grid{display:grid;grid-template-columns:1.18fr .82fr;gap:5mm;align-items:start;break-before:page;break-inside:avoid}.panel{border:1px solid var(--line);border-radius:2mm;padding:4mm;margin-bottom:5mm;break-inside:avoid}.panel-head{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--line);padding-bottom:2mm;margin-bottom:3mm}.panel-head h2{margin:0}.trend-bars{display:grid;gap:2mm}.trend-row{display:grid;grid-template-columns:17mm 1fr 27mm 21mm;gap:2mm;align-items:center;font-size:7.2pt}.trend-label{font-weight:700}.trend-track{height:4mm;background:#e7ecef;position:relative;border-radius:1mm;overflow:hidden}.trend-revenue{height:100%;background:var(--p)}.trend-occ{height:1.2mm;background:var(--a);position:absolute;bottom:0;left:0}.trend-num{text-align:right}.developments{display:grid;gap:2.5mm}.development{display:grid;grid-template-columns:2mm 1fr;gap:2.5mm;padding-bottom:2.5mm;border-bottom:1px solid var(--line);break-inside:avoid}.impact{background:var(--m)}.positive .impact{background:var(--pos)}.negative .impact{background:var(--neg)}.development p{margin:0}.recommendations{display:grid;gap:3mm}.recommendation{display:grid;grid-template-columns:8mm 1fr;gap:3mm;background:var(--bg);padding:3.5mm;break-inside:avoid}.priority{width:7mm;height:7mm;border-radius:50%;background:var(--p);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800}.recommendation p{margin-bottom:1.4mm}.effect{border-top:1px solid #00000010;padding-top:1.5mm}.outlook{padding:5mm;background:var(--p);color:#fff;border-radius:2mm;break-inside:avoid}.outlook .kicker{color:#ffffffb8}.outlook h2{margin-bottom:1.5mm}.outlook p{margin:0}.notes{font-size:6.8pt;color:var(--m);margin-top:4mm}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font-size:6.3pt;color:var(--m);margin-top:2mm}
|
||||
</style></head><body>
|
||||
<header class="header"><div class="header-left">{{ui.logo(data)}}<div><div class="brand">{{data.customer.name}}</div><div class="sub">{{data.customer.property_name}} · {{data.customer.location}}</div></div></div><div class="header-right"><div class="kicker">Performance Dashboard</div><div class="period">{{data.report.period.label}}</div><div class="sub">Erstellt {{data.report.generated_at|date_de}}</div></div></header>
|
||||
<section class="summary"><div class="summary-main"><div class="kicker">Management Summary</div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></div><div class="summary-score"><span class="kicker">Status</span><strong>{% if data.content.summary.rating=='positive' %}↑{% elif data.content.summary.rating=='watch' %}!{% else %}•{% endif %}</strong><span>{{data.content.summary.rating}}</span></div></section>
|
||||
{{ui.kpis(data)}}{{ui.facts(data)}}
|
||||
<div class="grid"><div><section class="panel"><div class="panel-head"><h2>Monatsverlauf</h2><span class="kicker">{{data.report.period.comparison_label}}</span></div>{{ui.trend_bars(data)}}</section><section class="panel"><div class="panel-head"><h2>Wichtige Entwicklungen</h2></div>{{ui.developments(data)}}</section></div><div><section class="panel"><div class="panel-head"><h2>Prioritäten</h2></div>{{ui.recommendations(data)}}</section>{{ui.outlook(data)}}</div></div>
|
||||
{{ui.notes(data)}}
|
||||
</body></html>
|
||||
@@ -0,0 +1,11 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#cfcac1;--pos:#2e7259;--neg:#9a4747}@page{size:A4;margin:14mm 16mm 19mm}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:9.6pt/1.55 {{data.design.font_family}},Georgia,serif}h1,h2,h3,p{margin-top:0}h1{font-size:38pt;line-height:.94;font-weight:500;letter-spacing:-1.5px;margin:0}h2{font-size:17pt;font-weight:500;margin-bottom:3mm}h3{font-size:11pt;margin-bottom:1mm}p{margin-bottom:3mm}.mast{display:grid;grid-template-columns:1fr auto;align-items:center;border-top:2mm solid var(--p);border-bottom:1px solid var(--line);padding:4mm 0;margin-bottom:9mm}.brand{font:700 8pt Arial,sans-serif;text-transform:uppercase;letter-spacing:1.2px}.issue{text-align:right;font:7pt Arial,sans-serif;color:var(--m)}.issue strong{display:block;color:var(--p);font-size:10pt}.hero{display:grid;grid-template-columns:1.1fr .9fr;gap:10mm;align-items:end;margin-bottom:8mm}.logo{width:13mm;height:13mm;border:1px solid var(--p);float:left;margin-right:3mm;display:flex;align-items:center;justify-content:center;font:800 9pt Arial,sans-serif;color:var(--p);overflow:hidden}.logo img{width:100%;height:100%;object-fit:contain;padding:1mm}.deck{border-top:1mm solid var(--a);padding-top:4mm}.deck .kicker,.kicker,.kpi-label,.category{font:700 6.8pt/1.2 Arial,sans-serif;text-transform:uppercase;letter-spacing:1px;color:var(--m)}.deck h2{font-size:16pt}.deck p{margin:0}.kpis{display:grid;grid-template-columns:repeat(4,1fr);margin:8mm 0 4mm;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}.kpi{padding:4mm 4mm 4mm 0}.kpi+.kpi{border-left:1px solid var(--line);padding-left:4mm}.kpi-value{font-size:16pt;color:var(--p);margin:2mm 0;white-space:nowrap}.kpi-delta{font:7pt Arial,sans-serif}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:flex;justify-content:space-between;gap:4mm;font:7pt Arial,sans-serif;color:var(--m);margin-bottom:9mm}.fact strong{color:var(--t);margin-left:1mm}.headline{display:flex;align-items:center;gap:4mm;margin:7mm 0 4mm}.headline h2{margin:0;white-space:nowrap}.headline:after{content:"";height:1px;background:var(--line);flex:1}.trend-table{width:100%;border-collapse:collapse;font:7.5pt Arial,sans-serif;break-inside:avoid}.trend-table th{text-align:left;text-transform:uppercase;letter-spacing:.7px;color:var(--m);font-size:6.5pt;border-bottom:1mm solid var(--p);padding:2mm}.trend-table td{padding:2.2mm;border-bottom:1px solid var(--line)}.trend-table th:not(:first-child),.trend-table td:not(:first-child){text-align:right}.editorial-grid{display:grid;grid-template-columns:1fr 1fr;gap:8mm;align-items:start;break-before:page;break-inside:avoid}.developments{columns:1}.development{display:grid;grid-template-columns:2mm 1fr;gap:3mm;margin-bottom:4mm;break-inside:avoid}.impact{background:var(--m)}.positive .impact{background:var(--pos)}.negative .impact{background:var(--neg)}.development p{margin:0}.recommendations{display:grid;gap:4mm}.recommendation{border-top:1px solid var(--line);padding-top:3mm;display:grid;grid-template-columns:8mm 1fr;gap:3mm;break-inside:avoid}.priority{font-size:20pt;color:var(--a);line-height:1}.recommendation p{margin-bottom:1.4mm}.effect{font-style:italic}.outlook{margin-top:8mm;background:var(--bg);padding:6mm;border-left:1.2mm solid var(--p);break-inside:avoid}.outlook h2{margin-bottom:2mm}.outlook p{margin:0}.notes{font:6.8pt Arial,sans-serif;color:var(--m);margin-top:4mm}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font:6.3pt Arial,sans-serif;color:var(--m);margin-top:2mm}
|
||||
</style></head><body>
|
||||
<header class="mast"><div class="brand">{{data.customer.name}} · Monthly Review</div><div class="issue"><strong>{{data.report.period.label}}</strong>{{data.customer.location}}</div></header>
|
||||
<section class="hero"><div><div>{{ui.logo(data)}}<div class="kicker">{{data.customer.property_name}}</div></div><h1>Monatsreport</h1></div><div class="deck"><div class="kicker">Analyse des Monats</div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></div></section>
|
||||
{{ui.kpis(data)}}{{ui.facts(data)}}
|
||||
<div class="headline"><h2>Zahlen im Verlauf</h2></div>{{ui.trend_table(data)}}
|
||||
<div class="editorial-grid"><section><div class="headline"><h2>Entwicklungen</h2></div>{{ui.developments(data)}}</section><section><div class="headline"><h2>Empfehlungen</h2></div>{{ui.recommendations(data)}}</section></div>
|
||||
{{ui.outlook(data)}}{{ui.notes(data)}}
|
||||
</body></html>
|
||||
@@ -0,0 +1,12 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#cbd2ce;--pos:#247159;--neg:#9e4545}@page{size:A4;margin:13mm 14mm 19mm}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:8.7pt/1.45 {{data.design.font_family}},"Courier New",monospace}h1,h2,h3,p{margin-top:0}h1{font-size:24pt;letter-spacing:-1px;margin:0}h2{font-size:12pt;margin-bottom:3mm;text-transform:uppercase;letter-spacing:.6px}h3{font-size:9.3pt;margin-bottom:1mm}p{margin-bottom:2.3mm}.header{border:1px solid var(--p);display:grid;grid-template-columns:1fr 62mm;margin-bottom:5mm}.header-main{padding:5mm}.header-meta{background:var(--p);color:#fff;padding:5mm}.brandline{display:flex;align-items:center;gap:3mm;margin-bottom:4mm}.logo{width:10mm;height:10mm;border:1px solid var(--p);display:flex;align-items:center;justify-content:center;font-weight:800;overflow:hidden}.logo img{width:100%;height:100%;object-fit:contain;padding:.8mm}.label,.kicker,.kpi-label,.category{font-size:6.5pt;text-transform:uppercase;letter-spacing:.8px;color:var(--m);font-weight:700}.header-meta .label{color:#ffffffad}.header-meta strong{display:block;font-size:13pt;margin:1mm 0 4mm}.summary{border:1px solid var(--line);padding:4mm;margin-bottom:4mm;display:grid;grid-template-columns:26mm 1fr;gap:4mm}.summary-code{font-size:18pt;color:var(--a);font-weight:800}.summary h2{font-size:13pt;text-transform:none}.summary p{margin:0}.kpis{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line);margin-bottom:0}.kpi{padding:3.5mm;border-right:1px solid var(--line)}.kpi:last-child{border-right:0}.kpi-value{font-size:13pt;font-weight:800;color:var(--p);margin:2mm 0;white-space:nowrap}.kpi-delta{font-size:6.7pt}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line);border-top:0;margin-bottom:6mm}.fact{padding:2.5mm 3.5mm;border-right:1px solid var(--line)}.fact:last-child{border-right:0}.fact span{display:block;font-size:6.4pt;color:var(--m)}.fact strong{display:block;margin-top:.5mm}.block{margin-bottom:6mm}.block-head{display:flex;justify-content:space-between;align-items:center;background:var(--bg);border-left:1.2mm solid var(--p);padding:2.5mm 3mm;margin-bottom:2mm}.block-head h2{margin:0}.trend-table{width:100%;border-collapse:collapse;font-size:7.3pt}.trend-table th,.trend-table td{padding:2mm;border:1px solid var(--line)}.trend-table th{text-align:left;background:var(--bg);color:var(--m);font-size:6.3pt;text-transform:uppercase}.trend-table th:not(:first-child),.trend-table td:not(:first-child){text-align:right}.analysis-table{width:100%;border-collapse:collapse}.analysis-table td{border-bottom:1px solid var(--line);padding:3mm 2mm;vertical-align:top}.analysis-table td:first-child{width:7mm;font-weight:800;color:var(--a)}.analysis-table td:nth-child(2){width:42mm;font-weight:800}.analysis-table p{margin:0}.recommendations{display:grid;gap:0;border-top:1px solid var(--line)}.recommendation{display:grid;grid-template-columns:10mm 1fr;gap:3mm;border-bottom:1px solid var(--line);padding:3mm 0;break-inside:avoid}.priority{font-size:14pt;color:var(--p);font-weight:800}.recommendation p{margin-bottom:1.2mm}.effect{background:var(--bg);padding:1.5mm}.outlook{border:1px solid var(--p);padding:4mm;break-inside:avoid}.outlook h2{text-transform:none}.outlook p{margin:0}.notes{font-size:6.5pt;color:var(--m);margin-top:3mm}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font-size:6pt;color:var(--m);margin-top:2mm}.developments{display:none}
|
||||
</style></head><body>
|
||||
<header class="header"><div class="header-main"><div class="brandline">{{ui.logo(data)}}<div><strong>{{data.customer.name}}</strong><div class="label">{{data.customer.property_name}} / {{data.customer.location}}</div></div></div><h1>MONATSREPORT</h1></div><div class="header-meta"><div class="label">Berichtsperiode</div><strong>{{data.report.period.label}}</strong><div class="label">Erstellt</div><div>{{data.report.generated_at|date_de}}</div><div class="label" style="margin-top:3mm">Template</div><div>{{data._theme.id}}</div></div></header>
|
||||
<section class="summary"><div class="summary-code">00</div><div><div class="kicker">Executive Summary</div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></div></section>
|
||||
{{ui.kpis(data)}}{{ui.facts(data)}}
|
||||
<section class="block"><div class="block-head"><h2>01 / Monatsverlauf</h2><span class="label">Vergleich {{data.report.period.comparison_label}}</span></div>{{ui.trend_table(data)}}</section>
|
||||
<section class="block"><div class="block-head"><h2>02 / Entwicklungen</h2><span class="label">Analyse</span></div><table class="analysis-table">{% for item in data.content.developments %}<tr><td>{{'%02d'|format(loop.index)}}</td><td>{{item.title}}</td><td><p>{{item.text}}</p></td></tr>{% endfor %}</table></section>
|
||||
<section class="block"><div class="block-head"><h2>03 / Massnahmenliste</h2><span class="label">Priorisiert</span></div>{{ui.recommendations(data)}}</section>
|
||||
{{ui.outlook(data)}}{{ui.notes(data)}}
|
||||
</body></html>
|
||||
@@ -0,0 +1,11 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#d7dce2;--pos:#24725a;--neg:#a24048}@page{size:A4;margin:12mm 14mm 19mm}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:9.1pt/1.47 {{data.design.font_family}},Arial,sans-serif}h1,h2,h3,p{margin-top:0}h1{font-size:39pt;line-height:.88;letter-spacing:-2px;margin:0;text-transform:uppercase}h2{font-size:16pt;line-height:1.08;margin-bottom:3mm}h3{font-size:10.5pt;margin-bottom:1mm}p{margin-bottom:2.6mm}.cover{display:grid;grid-template-columns:1fr 53mm;min-height:73mm;margin-bottom:6mm;break-inside:avoid}.cover-main{background:var(--p);color:#fff;padding:7mm;position:relative;overflow:hidden}.cover-main:after{content:"";position:absolute;width:60mm;height:60mm;border:10mm solid #ffffff0f;border-radius:50%;right:-24mm;bottom:-30mm}.cover-side{background:var(--a);padding:6mm 5mm;display:flex;flex-direction:column;justify-content:space-between;color:var(--t)}.logo{width:14mm;height:14mm;background:#fff;color:var(--p);display:flex;align-items:center;justify-content:center;font-weight:900;overflow:hidden}.logo img{width:100%;height:100%;object-fit:contain;padding:1mm}.brand{margin-top:4mm;font-weight:800}.location{font-size:7.5pt;opacity:.76}.cover-title{position:absolute;left:7mm;bottom:7mm;z-index:1}.cover-title .kicker{color:#ffffffb8}.issue-num{font-size:36pt;font-weight:900;line-height:1;color:var(--p)}.issue-label{font-size:7pt;text-transform:uppercase;letter-spacing:1px;font-weight:800}.kicker,.kpi-label,.category{font-size:6.7pt;text-transform:uppercase;letter-spacing:1.1px;font-weight:900;color:var(--m)}.summary{display:grid;grid-template-columns:52mm 1fr;gap:6mm;padding:5mm 0;border-bottom:1px solid var(--line);margin-bottom:5mm}.summary-mark{font-size:22pt;font-weight:900;color:var(--a);line-height:1}.summary h2{font-size:17pt}.summary p{margin:0}.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:2mm;margin-bottom:3mm}.kpi{padding:4mm;background:var(--bg);border-bottom:1.2mm solid var(--p);min-height:29mm}.kpi:nth-child(2n){border-bottom-color:var(--a)}.kpi-value{font-size:16pt;font-weight:900;margin:2mm 0;color:var(--p);white-space:nowrap}.kpi-delta{font-size:7pt}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:grid;grid-template-columns:repeat(4,1fr);gap:2mm;margin-bottom:7mm}.fact{padding:2.2mm 3mm;border:1px solid var(--line)}.fact span{display:block;font-size:6.7pt;color:var(--m)}.fact strong{display:block;margin-top:.7mm}.section-head{display:grid;grid-template-columns:13mm 1fr;gap:3mm;align-items:center;margin:7mm 0 3mm}.section-no{font-size:18pt;font-weight:900;color:var(--a)}.section-head h2{margin:0;border-bottom:1px solid var(--line);padding-bottom:2mm}.trend-bars{display:grid;gap:2mm}.trend-row{display:grid;grid-template-columns:18mm 1fr 28mm 22mm;gap:2.5mm;align-items:center;font-size:7.4pt}.trend-label{font-weight:800}.trend-track{height:5mm;background:var(--bg);position:relative;overflow:hidden}.trend-revenue{height:100%;background:var(--p)}.trend-occ{height:1.3mm;background:var(--a);position:absolute;left:0;bottom:0}.trend-num{text-align:right}.feature-grid{display:grid;grid-template-columns:1fr 1fr;gap:5mm;break-before:page;break-inside:avoid}.developments,.recommendations{display:grid;gap:3mm}.development{background:var(--bg);padding:3.5mm;break-inside:avoid;border-top:1mm solid var(--m)}.development.positive{border-top-color:var(--pos)}.development.negative{border-top-color:var(--neg)}.development{display:grid;grid-template-columns:0 1fr;gap:0}.development .impact{display:none}.development p{margin:0}.recommendation{display:grid;grid-template-columns:9mm 1fr;gap:3mm;border:1px solid var(--line);padding:3.5mm;break-inside:avoid}.priority{font-size:19pt;font-weight:900;color:var(--a)}.recommendation p{margin-bottom:1.3mm}.effect{color:var(--p);font-weight:600}.outlook{margin-top:7mm;background:linear-gradient(110deg,var(--p),var(--s));color:#fff;padding:6mm;break-inside:avoid}.outlook .kicker{color:#ffffffb8}.outlook p{margin:0}.notes{font-size:6.8pt;color:var(--m);margin-top:4mm}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font-size:6.2pt;color:var(--m);margin-top:2mm}
|
||||
</style></head><body>
|
||||
<section class="cover"><div class="cover-main">{{ui.logo(data)}}<div class="brand">{{data.customer.name}}</div><div class="location">{{data.customer.property_name}} · {{data.customer.location}}</div><div class="cover-title"><div class="kicker">Performance / Strategie / Ausblick</div><h1>Monats<br>report</h1></div></div><div class="cover-side"><div><div class="issue-label">Ausgabe</div><div class="issue-num">{{'%02d'|format(data.report.period.month)}}</div></div><div><div class="issue-label">Zeitraum</div><strong>{{data.report.period.label}}</strong><div class="location">{{data.report.generated_at|date_de}}</div></div></div></section>
|
||||
<section class="summary"><div><div class="summary-mark">“</div><div class="kicker">Kurzfazit</div></div><div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></div></section>
|
||||
{{ui.kpis(data)}}{{ui.facts(data)}}
|
||||
<div class="section-head"><div class="section-no">01</div><h2>Monatsverlauf</h2></div>{{ui.trend_bars(data)}}
|
||||
<div class="feature-grid"><section><div class="section-head"><div class="section-no">02</div><h2>Entwicklungen</h2></div>{{ui.developments(data)}}</section><section><div class="section-head"><div class="section-no">03</div><h2>Empfehlungen</h2></div>{{ui.recommendations(data)}}</section></div>
|
||||
{{ui.outlook(data)}}{{ui.notes(data)}}
|
||||
</body></html>
|
||||
@@ -0,0 +1,11 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#d9dfdf;--pos:#27745b;--neg:#a54a4a}@page{size:A4;margin:14mm 15mm 19mm}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:9.3pt/1.52 {{data.design.font_family}},Arial,sans-serif}h1,h2,h3,p{margin-top:0}h1{font-size:36pt;line-height:.98;letter-spacing:-1.7px;margin:0}h2{font-size:15pt;line-height:1.15;margin-bottom:3mm}h3{font-size:10.5pt;margin-bottom:1mm}p{margin-bottom:3mm}.top{display:flex;justify-content:space-between;align-items:flex-start;border-top:1.8mm solid var(--p);padding-top:6mm;margin-bottom:12mm}.brand{display:flex;gap:3mm;align-items:center}.logo{width:11mm;height:11mm;border:1px solid var(--p);display:flex;align-items:center;justify-content:center;font-weight:800;color:var(--p);overflow:hidden}.logo img{width:100%;height:100%;object-fit:contain;padding:1mm}.brand strong{display:block}.micro,.kicker,.kpi-label,.category{font:700 7pt/1.2 Arial,sans-serif;text-transform:uppercase;letter-spacing:1.1px;color:var(--m)}.period{text-align:right;color:var(--p);font-weight:700}.hero{display:grid;grid-template-columns:1fr 68mm;gap:10mm;align-items:end;margin-bottom:11mm}.hero-note{border-left:1mm solid var(--a);padding-left:5mm}.hero-note h2{font-size:14pt}.hero-note p{margin:0}.kpis{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid var(--line);border-bottom:1px solid var(--line);margin-bottom:5mm}.kpi{padding:5mm 4mm 4mm 0}.kpi+.kpi{border-left:1px solid var(--line);padding-left:4mm}.kpi-value{font-size:16pt;font-weight:700;color:var(--p);white-space:nowrap;margin:2mm 0}.kpi-delta{font-size:7.5pt;color:var(--m)}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:grid;grid-template-columns:repeat(4,1fr);gap:6mm;margin-bottom:10mm}.fact span{display:block;color:var(--m);font-size:7.3pt}.fact strong{display:block;margin-top:1mm}.section{margin-bottom:9mm}.section-title{display:grid;grid-template-columns:auto 1fr;gap:4mm;align-items:center;margin-bottom:4mm}.section-title h2{margin:0}.rule{height:1px;background:var(--line)}.trend-bars{border-top:1px solid var(--line)}.trend-row{display:grid;grid-template-columns:18mm 1fr 28mm 22mm;gap:3mm;align-items:center;padding:2.2mm 0;border-bottom:1px solid var(--line);font-size:7.7pt}.trend-label{font-weight:700}.trend-track{height:3.5mm;background:var(--bg);position:relative}.trend-revenue{height:100%;background:var(--p)}.trend-occ{height:1mm;background:var(--a);position:absolute;bottom:0;left:0}.trend-num{text-align:right}.content-grid{display:grid;grid-template-columns:1fr 1.1fr;gap:9mm;break-before:page;break-inside:avoid}.developments,.recommendations{display:grid;gap:4mm}.development{display:grid;grid-template-columns:2mm 1fr;gap:3mm;break-inside:avoid}.impact{width:1.3mm;background:var(--m)}.positive .impact{background:var(--pos)}.negative .impact{background:var(--neg)}.development p{margin:0}.recommendation{display:grid;grid-template-columns:8mm 1fr;gap:3mm;break-inside:avoid;padding-bottom:4mm;border-bottom:1px solid var(--line)}.priority{font-size:17pt;color:var(--a);font-weight:700}.recommendation p{margin-bottom:1.5mm}.effect{color:var(--p)}.outlook{margin-top:8mm;padding:6mm 0;border-top:1.2mm solid var(--p);border-bottom:1px solid var(--line);break-inside:avoid}.outlook p{margin:0}.notes{margin-top:4mm;font-size:7pt;color:var(--m)}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font-size:6.5pt;color:var(--m);margin-top:3mm}
|
||||
</style></head><body>
|
||||
<header class="top"><div class="brand">{{ui.logo(data)}}<div><strong>{{data.customer.name}}</strong><div class="micro">{{data.customer.property_name}}</div></div></div><div class="period">{{data.report.period.label}}<div class="micro">{{data.customer.location}}</div></div></header>
|
||||
<section class="hero"><div><div class="kicker">Monatliche Performance</div><h1>Monats-<br>report</h1></div><div class="hero-note"><div class="kicker">Kurzfazit</div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></div></section>
|
||||
{{ui.kpis(data)}}{{ui.facts(data)}}
|
||||
<section class="section"><div class="section-title"><h2>Monatsverlauf</h2><div class="rule"></div></div>{{ui.trend_bars(data)}}</section>
|
||||
<div class="content-grid"><section><div class="section-title"><h2>Entwicklungen</h2><div class="rule"></div></div>{{ui.developments(data)}}</section><section><div class="section-title"><h2>Empfehlungen</h2><div class="rule"></div></div>{{ui.recommendations(data)}}</section></div>
|
||||
{{ui.outlook(data)}}{{ui.notes(data)}}
|
||||
</body></html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
html { font-family: Arial, sans-serif; font-size: 8px; color: #718087; margin: 0 14mm; -webkit-print-color-adjust: exact; }
|
||||
body { margin: 0; }
|
||||
.footer { width: 100%; padding-top: 3mm; border-top: 1px solid #dfe5e8; display: flex; justify-content: space-between; align-items: center; }
|
||||
.page { font-weight: 700; color: {{ data.design.primary_color }}; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="footer">
|
||||
<span>{{ data.customer.name }} · {{ data.report.period.label }} · Template {{ data.report.template_version }}</span>
|
||||
<span class="page">Seite <span class="pageNumber"></span> / <span class="totalPages"></span></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,373 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Monatsreport {{ data.report.period.label }} - {{ data.customer.name }}</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: {{ data.design.primary_color }};
|
||||
--secondary: {{ data.design.secondary_color }};
|
||||
--accent: {{ data.design.accent_color }};
|
||||
--text: {{ data.design.text_color }};
|
||||
--muted: {{ data.design.muted_color }};
|
||||
--surface: {{ data.design.surface_color }};
|
||||
--line: #dfe5e8;
|
||||
--positive: #207a5a;
|
||||
--neutral: #667680;
|
||||
--negative: #b14949;
|
||||
--watch: #9a6815;
|
||||
}
|
||||
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 13mm 14mm 18mm 14mm;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||
body {
|
||||
margin: 0;
|
||||
color: var(--text);
|
||||
font-family: {{ data.design.font_family }}, Arial, sans-serif;
|
||||
font-size: 9.3pt;
|
||||
line-height: 1.48;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
h1, h2, h3, p { margin-top: 0; }
|
||||
h1 { font-size: 27pt; line-height: 1.08; letter-spacing: -0.6px; margin-bottom: 2mm; }
|
||||
h2 { font-size: 14.5pt; line-height: 1.2; margin-bottom: 4mm; }
|
||||
h3 { font-size: 10.8pt; line-height: 1.25; margin-bottom: 1.5mm; }
|
||||
p { margin-bottom: 3mm; }
|
||||
|
||||
.cover {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 67mm;
|
||||
padding: 9mm;
|
||||
border-radius: 5mm;
|
||||
color: #fff;
|
||||
background: linear-gradient(128deg, var(--primary), var(--secondary));
|
||||
margin-bottom: 7mm;
|
||||
break-inside: avoid;
|
||||
}
|
||||
.cover::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 92mm;
|
||||
height: 92mm;
|
||||
right: -27mm;
|
||||
top: -42mm;
|
||||
border: 12mm solid rgba(255,255,255,.08);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.cover-top { display: flex; align-items: center; justify-content: space-between; gap: 8mm; position: relative; z-index: 1; }
|
||||
.brand { display: flex; align-items: center; gap: 4mm; }
|
||||
.logo {
|
||||
width: 15mm; height: 15mm; border-radius: 4mm;
|
||||
background: rgba(255,255,255,.96); color: var(--primary);
|
||||
display: flex; align-items: center; justify-content: center; font-size: 15pt; font-weight: 800;
|
||||
box-shadow: 0 2mm 5mm rgba(0,0,0,.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
.logo img { width: 100%; height: 100%; object-fit: contain; padding: 1.6mm; }
|
||||
.brand-name { font-size: 11pt; font-weight: 700; }
|
||||
.brand-sub { font-size: 8pt; opacity: .82; }
|
||||
.period-chip {
|
||||
padding: 2.2mm 4mm; border-radius: 99mm;
|
||||
border: .25mm solid rgba(255,255,255,.38);
|
||||
background: rgba(255,255,255,.12); font-size: 8.3pt; font-weight: 700;
|
||||
}
|
||||
.cover-main { position: relative; z-index: 1; margin-top: 13mm; max-width: 142mm; }
|
||||
.eyebrow { text-transform: uppercase; letter-spacing: 1.7px; font-size: 7.2pt; font-weight: 800; opacity: .78; margin-bottom: 2.2mm; }
|
||||
.cover-meta { display: flex; flex-wrap: wrap; gap: 3mm 8mm; font-size: 8.4pt; opacity: .88; }
|
||||
|
||||
.section { margin-bottom: 7mm; }
|
||||
.section-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: 5mm; margin-bottom: 3.5mm; }
|
||||
.section-heading h2 { margin: 0; }
|
||||
.section-kicker { font-size: 7.3pt; font-weight: 800; color: var(--muted); text-transform: uppercase; letter-spacing: 1.2px; margin-bottom: 1mm; }
|
||||
|
||||
.summary {
|
||||
display: grid; grid-template-columns: 10mm 1fr; gap: 4mm;
|
||||
padding: 5mm; border-radius: 3mm; background: var(--surface);
|
||||
border-left: 1.5mm solid var(--accent); break-inside: avoid;
|
||||
}
|
||||
.summary-icon {
|
||||
width: 9mm; height: 9mm; border-radius: 50%;
|
||||
display: flex; align-items: center; justify-content: center; align-self: start; color: #fff; font-weight: 900; margin-top: .5mm;
|
||||
}
|
||||
.summary-icon.positive { background: var(--positive); }
|
||||
.summary-icon.neutral { background: var(--neutral); }
|
||||
.summary-icon.watch { background: var(--watch); }
|
||||
.summary h2 { font-size: 14pt; margin-bottom: 2mm; }
|
||||
.summary p { margin-bottom: 0; }
|
||||
|
||||
.kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 3mm; }
|
||||
.kpi-card {
|
||||
min-height: 31mm; padding: 4mm; border: .25mm solid var(--line);
|
||||
border-radius: 3mm; break-inside: avoid; background: #fff;
|
||||
}
|
||||
.kpi-label { font-size: 7.3pt; text-transform: uppercase; letter-spacing: .8px; color: var(--muted); font-weight: 800; }
|
||||
.kpi-value { font-size: 16pt; font-weight: 800; color: var(--primary); line-height: 1.15; margin: 3mm 0 1.5mm; white-space: nowrap; }
|
||||
.kpi-delta { font-size: 7.6pt; color: var(--muted); }
|
||||
.delta-positive { color: var(--positive); font-weight: 700; }
|
||||
.delta-negative { color: var(--negative); font-weight: 700; }
|
||||
|
||||
.detail-strip {
|
||||
display: grid; grid-template-columns: repeat(4, 1fr); gap: 0;
|
||||
border: .25mm solid var(--line); border-radius: 3mm; overflow: hidden; margin-top: 3mm;
|
||||
}
|
||||
.detail-item { padding: 3mm 4mm; border-right: .25mm solid var(--line); }
|
||||
.detail-item:last-child { border-right: 0; }
|
||||
.detail-label { font-size: 7.2pt; color: var(--muted); }
|
||||
.detail-value { font-weight: 800; margin-top: .8mm; }
|
||||
|
||||
.trend-panel {
|
||||
border: .25mm solid var(--line); border-radius: 3mm; padding: 5mm;
|
||||
break-inside: avoid;
|
||||
}
|
||||
.trend-legend { display: flex; gap: 5mm; font-size: 7.4pt; color: var(--muted); }
|
||||
.legend-dot { width: 2.2mm; height: 2.2mm; border-radius: 50%; display: inline-block; margin-right: 1.2mm; }
|
||||
.legend-revenue { background: var(--primary); }
|
||||
.legend-occ { background: var(--accent); }
|
||||
.trend-grid { display: block; margin-top: 3mm; }
|
||||
.trend-row { display: grid; grid-template-columns: 20mm 1fr 25mm 25mm; align-items: center; gap: 2mm; margin-top: 2mm; }
|
||||
.trend-label { font-weight: 700; font-size: 8pt; }
|
||||
.bar-track { height: 4mm; border-radius: 99mm; background: #edf1f3; overflow: hidden; position: relative; }
|
||||
.bar { height: 100%; border-radius: inherit; }
|
||||
.bar-revenue { background: var(--primary); }
|
||||
.bar-occ { background: var(--accent); height: 1.5mm; position: absolute; left: 0; bottom: 0; }
|
||||
.trend-number { text-align: right; font-size: 7.7pt; font-variant-numeric: tabular-nums; }
|
||||
|
||||
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 5mm; align-items: start; }
|
||||
.development-list { display: grid; gap: 3mm; }
|
||||
.development {
|
||||
border: .25mm solid var(--line); border-radius: 3mm; padding: 4mm;
|
||||
break-inside: avoid;
|
||||
}
|
||||
.development-top { display: flex; align-items: center; gap: 2mm; margin-bottom: 1.5mm; }
|
||||
.impact-dot { width: 2.5mm; height: 2.5mm; border-radius: 50%; flex: 0 0 auto; }
|
||||
.impact-dot.positive { background: var(--positive); }
|
||||
.impact-dot.neutral { background: var(--neutral); }
|
||||
.impact-dot.negative { background: var(--negative); }
|
||||
.development p { margin: 0; color: #35434a; }
|
||||
|
||||
.recommendations { display: grid; gap: 3.5mm; }
|
||||
.recommendation {
|
||||
display: grid; grid-template-columns: 11mm 1fr; gap: 4mm;
|
||||
padding: 4.5mm; border-radius: 3mm; background: var(--surface);
|
||||
border: .25mm solid #d7e1e2;
|
||||
break-inside: avoid;
|
||||
}
|
||||
.priority {
|
||||
width: 10mm; height: 10mm; border-radius: 3mm; background: var(--primary); color: #fff;
|
||||
display: flex; align-items: center; justify-content: center; align-self: start; font-weight: 900; font-size: 12pt;
|
||||
}
|
||||
.category { color: var(--primary); font-size: 7.2pt; font-weight: 900; text-transform: uppercase; letter-spacing: .8px; }
|
||||
.recommendation h3 { font-size: 11.3pt; margin: .8mm 0 2mm; }
|
||||
.recommendation p { margin-bottom: 2mm; }
|
||||
.recommendation p:last-child { margin-bottom: 0; }
|
||||
.action-line { padding-top: 2mm; border-top: .25mm solid rgba(0,0,0,.08); }
|
||||
|
||||
.outlook {
|
||||
padding: 5mm; color: #fff; border-radius: 3mm;
|
||||
background: linear-gradient(115deg, var(--primary), var(--secondary));
|
||||
break-inside: avoid;
|
||||
}
|
||||
.outlook h2 { margin-bottom: 2mm; }
|
||||
.outlook p { margin: 0; opacity: .94; }
|
||||
|
||||
.notes {
|
||||
margin-top: 4mm; padding: 3.5mm 4mm; border-radius: 2mm;
|
||||
background: #f7f8f9; color: var(--muted); font-size: 7.5pt;
|
||||
break-inside: avoid;
|
||||
}
|
||||
.notes ul { margin: 1.5mm 0 0; padding-left: 4mm; }
|
||||
.notes li { margin-bottom: .8mm; }
|
||||
.legal { margin-top: 4mm; color: var(--muted); font-size: 6.9pt; }
|
||||
|
||||
.page-break { break-before: page; }
|
||||
.avoid { break-inside: avoid; }
|
||||
|
||||
@media print {
|
||||
.section:last-child { margin-bottom: 0; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<section class="cover">
|
||||
<div class="cover-top">
|
||||
<div class="brand">
|
||||
<div class="logo">
|
||||
{% if data.customer.logo_data_uri %}
|
||||
<img src="{{ data.customer.logo_data_uri }}" alt="Logo">
|
||||
{% else %}
|
||||
{{ data.customer.logo_text }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<div class="brand-name">{{ data.customer.name }}</div>
|
||||
<div class="brand-sub">{{ data.customer.property_name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="period-chip">{{ data.report.period.label }}</div>
|
||||
</div>
|
||||
<div class="cover-main">
|
||||
<div class="eyebrow">Performance & Handlungsempfehlungen</div>
|
||||
<h1>Monatsreport</h1>
|
||||
<div class="cover-meta">
|
||||
<span>{{ data.customer.location }}</span>
|
||||
<span>Erstellt am {{ data.report.generated_at|date_de }}</span>
|
||||
<span>Version {{ data.report.report_version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="summary">
|
||||
<div class="summary-icon {{ data.content.summary.rating }}">
|
||||
{% if data.content.summary.rating == 'positive' %}↑{% elif data.content.summary.rating == 'watch' %}!{% else %}•{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<div class="section-kicker">Kurzfazit</div>
|
||||
<h2>{{ data.content.summary.headline }}</h2>
|
||||
<p>{{ data.content.summary.text }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<div class="section-kicker">Kennzahlen</div>
|
||||
<h2>Der Monat auf einen Blick</h2>
|
||||
</div>
|
||||
<div class="section-kicker">Vergleich: {{ data.report.period.comparison_label }}</div>
|
||||
</div>
|
||||
<div class="kpi-grid">
|
||||
<article class="kpi-card">
|
||||
<div class="kpi-label">Umsatz</div>
|
||||
<div class="kpi-value">{{ data.metrics.revenue|currency_de(data.metrics.currency) }}</div>
|
||||
<div class="kpi-delta {% if data.metrics.comparison.revenue_delta_pct >= 0 %}delta-positive{% else %}delta-negative{% endif %}">
|
||||
{{ data.metrics.comparison.revenue_delta_pct|delta_de(1, '%') }}
|
||||
</div>
|
||||
</article>
|
||||
<article class="kpi-card">
|
||||
<div class="kpi-label">Auslastung</div>
|
||||
<div class="kpi-value">{{ data.metrics.occupancy_rate|percent_de }}</div>
|
||||
<div class="kpi-delta {% if data.metrics.comparison.occupancy_delta_pp >= 0 %}delta-positive{% else %}delta-negative{% endif %}">
|
||||
{{ data.metrics.comparison.occupancy_delta_pp|delta_de(1, 'PP') }}
|
||||
</div>
|
||||
</article>
|
||||
<article class="kpi-card">
|
||||
<div class="kpi-label">Ø Tagespreis</div>
|
||||
<div class="kpi-value">{{ data.metrics.adr|currency_de(data.metrics.currency) }}</div>
|
||||
<div class="kpi-delta {% if data.metrics.comparison.adr_delta_pct >= 0 %}delta-positive{% else %}delta-negative{% endif %}">
|
||||
{{ data.metrics.comparison.adr_delta_pct|delta_de(1, '%') }}
|
||||
</div>
|
||||
</article>
|
||||
<article class="kpi-card">
|
||||
<div class="kpi-label">Buchungen</div>
|
||||
<div class="kpi-value">{{ data.metrics.bookings|number_de(0) }}</div>
|
||||
<div class="kpi-delta {% if data.metrics.comparison.bookings_delta >= 0 %}delta-positive{% else %}delta-negative{% endif %}">
|
||||
{{ data.metrics.comparison.bookings_delta|delta_de(0, '') }} Buchungen
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div class="detail-strip">
|
||||
<div class="detail-item"><div class="detail-label">RevPAR</div><div class="detail-value">{{ data.metrics.revpar|currency_de(data.metrics.currency) }}</div></div>
|
||||
<div class="detail-item"><div class="detail-label">Verkaufte Nächte</div><div class="detail-value">{{ data.metrics.nights_sold|number_de(0) }}</div></div>
|
||||
<div class="detail-item"><div class="detail-label">Ø Aufenthaltsdauer</div><div class="detail-value">{{ data.metrics.average_stay|number_de(1) }} Nächte</div></div>
|
||||
<div class="detail-item"><div class="detail-label">Stornoquote</div><div class="detail-value">{{ data.metrics.cancellation_rate|percent_de }}</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<div class="section-kicker">Verlauf</div>
|
||||
<h2>Entwicklung der letzten Monate</h2>
|
||||
</div>
|
||||
<div class="trend-legend">
|
||||
<span><i class="legend-dot legend-revenue"></i> Umsatz</span>
|
||||
<span><i class="legend-dot legend-occ"></i> Auslastung</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="trend-panel">
|
||||
<div class="trend-grid">
|
||||
{% for item in data.trends %}
|
||||
<div class="trend-row">
|
||||
<div class="trend-label">{{ item.label }}</div>
|
||||
<div class="bar-track">
|
||||
<div class="bar bar-revenue" style="width: {{ item.revenue_bar }}%"></div>
|
||||
<div class="bar bar-occ" style="width: {{ item.occupancy_bar }}%"></div>
|
||||
</div>
|
||||
<div class="trend-number">{{ item.revenue|currency_de(data.metrics.currency) }}</div>
|
||||
<div class="trend-number">{{ item.occupancy_rate|percent_de }}</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<div class="section-kicker">Analyse</div>
|
||||
<h2>Wichtige Entwicklungen</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="two-col">
|
||||
{% for item in data.content.developments %}
|
||||
<article class="development">
|
||||
<div class="development-top"><span class="impact-dot {{ item.impact }}"></span><h3>{{ item.title }}</h3></div>
|
||||
<p>{{ item.text }}</p>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<div class="section-kicker">Naechste Schritte</div>
|
||||
<h2>Priorisierte Empfehlungen</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="recommendations">
|
||||
{% for item in data.content.recommendations|sort(attribute='priority') %}
|
||||
<article class="recommendation">
|
||||
<div class="priority">{{ item.priority }}</div>
|
||||
<div>
|
||||
<div class="category">{{ item.category }}</div>
|
||||
<h3>{{ item.title }}</h3>
|
||||
<p><strong>Warum:</strong> {{ item.reason }}</p>
|
||||
<p class="action-line"><strong>Massnahme:</strong> {{ item.action }}</p>
|
||||
<p><strong>Erwarteter Effekt:</strong> {{ item.expected_effect }}</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="outlook">
|
||||
<div class="section-kicker" style="color: rgba(255,255,255,.7)">Ausblick</div>
|
||||
<h2>{{ data.content.outlook.headline }}</h2>
|
||||
<p>{{ data.content.outlook.text }}</p>
|
||||
</div>
|
||||
{% if data.content.data_quality_notes %}
|
||||
<div class="notes">
|
||||
<strong>Hinweise zur Datengrundlage</strong>
|
||||
<ul>
|
||||
{% for note in data.content.data_quality_notes %}<li>{{ note }}</li>{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="legal">{{ data.legal_note }}</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#d6d6d6;--pos:#25745a;--neg:#a43d43}@page{size:A4;margin:11mm 13mm 19mm}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:9pt/1.42 {{data.design.font_family}},Arial,sans-serif}h1,h2,h3,p{margin-top:0}h1{font-size:43pt;line-height:.8;letter-spacing:-2.8px;text-transform:uppercase;margin:0}h2{font-size:17pt;line-height:1.05;margin-bottom:3mm}h3{font-size:10pt;margin-bottom:1mm}p{margin-bottom:2.5mm}.cover{background:var(--p);color:#fff;min-height:79mm;padding:7mm;position:relative;overflow:hidden;margin-bottom:4mm;break-inside:avoid}.cover:after{content:"{{'%02d'|format(data.report.period.month)}}";position:absolute;right:-4mm;bottom:-17mm;font-size:90pt;line-height:1;font-weight:900;color:#ffffff10}.top{display:flex;justify-content:space-between;align-items:flex-start;position:relative;z-index:1}.brand{display:flex;gap:3mm;align-items:center}.logo{width:13mm;height:13mm;background:#fff;color:var(--p);display:flex;align-items:center;justify-content:center;font-weight:900;overflow:hidden}.logo img{width:100%;height:100%;object-fit:contain;padding:1mm}.brand-name{font-weight:900}.small{font-size:7pt;opacity:.74}.period{background:var(--a);color:var(--t);padding:2.5mm 4mm;font-weight:900}.title{position:absolute;left:7mm;bottom:7mm;z-index:1}.kicker,.kpi-label,.category{font-size:6.6pt;text-transform:uppercase;letter-spacing:1px;font-weight:900;color:var(--m)}.cover .kicker{color:#ffffffad}.summary{display:grid;grid-template-columns:48mm 1fr;background:var(--a);padding:5mm;margin-bottom:4mm}.summary-label{font-size:22pt;font-weight:900;text-transform:uppercase;line-height:.9}.summary h2{font-size:16pt}.summary p{margin:0}.kpis{display:grid;grid-template-columns:1fr 1fr;gap:3mm;margin-bottom:3mm}.kpi{min-height:34mm;padding:4mm;border:1px solid var(--t);position:relative}.kpi:nth-child(1),.kpi:nth-child(4){background:var(--t);color:#fff}.kpi:nth-child(1) .kpi-label,.kpi:nth-child(4) .kpi-label{color:#ffffffaa}.kpi-value{font-size:25pt;font-weight:900;line-height:1;color:var(--p);margin:2mm 0}.kpi:nth-child(1) .kpi-value,.kpi:nth-child(4) .kpi-value{color:var(--a)}.kpi-delta{font-size:7pt}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:grid;grid-template-columns:repeat(4,1fr);gap:0;background:var(--bg);margin-bottom:6mm}.fact{padding:3mm;border-right:1px solid var(--line)}.fact:last-child{border-right:0}.fact span{display:block;font-size:6.5pt;color:var(--m)}.fact strong{display:block;margin-top:.5mm}.section-title{display:flex;align-items:baseline;gap:4mm;border-bottom:2mm solid var(--p);margin:7mm 0 3mm}.section-title .num{font-size:24pt;font-weight:900;color:var(--a)}.section-title h2{margin:0 0 1mm;text-transform:uppercase}.trend-bars{display:grid;gap:2mm}.trend-row{display:grid;grid-template-columns:17mm 1fr 28mm 22mm;gap:2.5mm;align-items:center;font-size:7.2pt}.trend-label{font-weight:900}.trend-track{height:5mm;background:var(--bg);position:relative;border:1px solid var(--t)}.trend-revenue{height:100%;background:var(--p)}.trend-occ{height:1.4mm;background:var(--a);position:absolute;left:0;bottom:0}.trend-num{text-align:right}.content{display:grid;grid-template-columns:1fr 1fr;gap:5mm;break-before:page;break-inside:avoid}.developments,.recommendations{display:grid;gap:3mm}.development{display:grid;grid-template-columns:3mm 1fr;gap:3mm;border-bottom:1px solid var(--line);padding-bottom:3mm;break-inside:avoid}.impact{background:var(--m)}.positive .impact{background:var(--pos)}.negative .impact{background:var(--neg)}.development p{margin:0}.recommendation{display:grid;grid-template-columns:10mm 1fr;gap:3mm;border:1px solid var(--t);padding:3mm;break-inside:avoid}.priority{font-size:22pt;font-weight:900;color:var(--a)}.recommendation p{margin-bottom:1.2mm}.effect{border-top:1px solid var(--line);padding-top:1.3mm}.outlook{margin-top:6mm;background:var(--t);color:#fff;padding:5mm;break-inside:avoid}.outlook .kicker{color:var(--a)}.outlook p{margin:0}.notes{font-size:6.7pt;color:var(--m);margin-top:3mm}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font-size:6.1pt;color:var(--m);margin-top:2mm}
|
||||
</style></head><body>
|
||||
<section class="cover"><div class="top"><div class="brand">{{ui.logo(data)}}<div><div class="brand-name">{{data.customer.name}}</div><div class="small">{{data.customer.property_name}} · {{data.customer.location}}</div></div></div><div class="period">{{data.report.period.label}}</div></div><div class="title"><div class="kicker">Performance / Analyse / Aktionen</div><h1>Monats<br>report</h1></div></section>
|
||||
<section class="summary"><div class="summary-label">Der<br>Monat</div><div><div class="kicker">Kurzfazit</div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></div></section>
|
||||
{{ui.kpis(data)}}{{ui.facts(data)}}
|
||||
<div class="section-title"><span class="num">01</span><h2>Monatsverlauf</h2></div>{{ui.trend_bars(data)}}
|
||||
<div class="content"><section><div class="section-title"><span class="num">02</span><h2>Entwicklungen</h2></div>{{ui.developments(data)}}</section><section><div class="section-title"><span class="num">03</span><h2>Aktionen</h2></div>{{ui.recommendations(data)}}</section></div>
|
||||
{{ui.outlook(data)}}{{ui.notes(data)}}
|
||||
</body></html>
|
||||
@@ -0,0 +1,7 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#d8e0df;--pos:#28765b;--neg:#a54b4b}@page{size:A4;margin:0 13mm 18mm 0}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:9.1pt/1.48 {{data.design.font_family}},Arial,sans-serif}h1,h2,h3,p{margin-top:0}h1{font-size:25pt;line-height:1.05;margin-bottom:2mm}h2{font-size:14pt;margin-bottom:3mm}h3{font-size:10.2pt;margin-bottom:1mm}p{margin-bottom:2.7mm}.page{display:grid;grid-template-columns:45mm 1fr;min-height:279mm}.side{background:linear-gradient(180deg,var(--p),var(--s));color:#fff;padding:13mm 7mm 10mm 8mm}.main{padding:13mm 0 0 9mm}.logo{width:15mm;height:15mm;background:#fff;color:var(--p);border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:900;overflow:hidden;margin-bottom:5mm}.logo img{width:100%;height:100%;object-fit:contain;padding:1.3mm}.brand{font-weight:800;font-size:11pt}.side-sub{font-size:7.5pt;opacity:.78;margin-top:1mm}.side-period{margin:18mm 0 10mm}.side-period strong{font-size:18pt;display:block;line-height:1.05}.kicker,.kpi-label,.category{font:800 6.8pt/1.2 Arial,sans-serif;text-transform:uppercase;letter-spacing:1px;color:var(--m)}.side .kicker{color:#ffffffb0}.side-facts{display:grid;gap:4mm;border-top:1px solid #ffffff40;padding-top:5mm}.side-fact span{font-size:7pt;opacity:.7;display:block}.side-fact strong{font-size:11pt}.side-outlook{margin-top:13mm;border-top:1px solid #ffffff40;padding-top:5mm}.side-outlook h3{font-size:11pt}.side-outlook p{font-size:7.6pt;opacity:.88}.intro{margin-bottom:6mm}.intro h1{color:var(--p)}.summary{border-left:1.4mm solid var(--a);padding:1mm 0 1mm 5mm;margin:5mm 0 6mm}.summary h2{font-size:14.5pt}.summary p{margin:0}.kpis{display:grid;grid-template-columns:1fr 1fr;gap:3mm;margin-bottom:5mm}.kpi{background:var(--bg);padding:4mm;border-radius:2mm;break-inside:avoid}.kpi-value{font-size:17pt;font-weight:800;color:var(--p);margin:2mm 0}.kpi-delta{font-size:7pt}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:none}.section{margin:6mm 0}.section-head{display:flex;align-items:center;gap:3mm;margin-bottom:3mm}.section-head h2{margin:0;white-space:nowrap}.line{height:1px;background:var(--line);width:100%}.trend-bars{display:grid;gap:2mm}.trend-row{display:grid;grid-template-columns:16mm 1fr 27mm 21mm;gap:2mm;align-items:center;font-size:7.2pt}.trend-label{font-weight:700}.trend-track{height:3.7mm;background:var(--bg);position:relative}.trend-revenue{height:100%;background:var(--p)}.trend-occ{height:1mm;background:var(--a);position:absolute;bottom:0;left:0}.trend-num{text-align:right}.developments{columns:2;column-gap:5mm}.development{display:grid;grid-template-columns:2mm 1fr;gap:2.5mm;break-inside:avoid;margin-bottom:3mm}.impact{background:var(--m)}.positive .impact{background:var(--pos)}.negative .impact{background:var(--neg)}.development p{margin:0}.recommendations{display:grid;gap:3mm}.recommendation{display:grid;grid-template-columns:9mm 1fr;gap:3mm;padding:3.5mm 0;border-top:1px solid var(--line);break-inside:avoid}.priority{font-size:18pt;font-weight:800;color:var(--a)}.recommendation p{margin-bottom:1.3mm}.effect{color:var(--p)}.outlook{display:none}.notes{font-size:6.8pt;color:var(--m);margin-top:4mm}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font-size:6.2pt;color:var(--m);margin-top:2mm}
|
||||
</style></head><body><div class="page">
|
||||
<aside class="side">{{ui.logo(data)}}<div class="brand">{{data.customer.name}}</div><div class="side-sub">{{data.customer.property_name}}<br>{{data.customer.location}}</div><div class="side-period"><div class="kicker">Monatsreport</div><strong>{{data.report.period.label}}</strong><div class="side-sub">Version {{data.report.report_version}}</div></div><div class="side-facts"><div class="side-fact"><span>RevPAR</span><strong>{{data.metrics.revpar|currency_de(data.metrics.currency)}}</strong></div><div class="side-fact"><span>Verkaufte Nächte</span><strong>{{data.metrics.nights_sold|number_de(0)}}</strong></div><div class="side-fact"><span>Ø Aufenthalt</span><strong>{{data.metrics.average_stay|number_de(1)}}</strong></div><div class="side-fact"><span>Stornoquote</span><strong>{{data.metrics.cancellation_rate|percent_de}}</strong></div></div><div class="side-outlook"><div class="kicker">Ausblick</div><h3>{{data.content.outlook.headline}}</h3><p>{{data.content.outlook.text}}</p></div></aside>
|
||||
<main class="main"><section class="intro"><div class="kicker">Performance & Handlungsempfehlungen</div><h1>Der Monat<br>im Überblick</h1></section><section class="summary"><div class="kicker">Kurzfazit</div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></section>{{ui.kpis(data)}}
|
||||
<section class="section"><div class="section-head"><h2>Monatsverlauf</h2><div class="line"></div></div>{{ui.trend_bars(data)}}</section><section class="section"><div class="section-head"><h2>Entwicklungen</h2><div class="line"></div></div>{{ui.developments(data)}}</section><section class="section"><div class="section-head"><h2>Empfehlungen</h2><div class="line"></div></div>{{ui.recommendations(data)}}</section>{{ui.notes(data)}}</main></div></body></html>
|
||||
@@ -0,0 +1,11 @@
|
||||
{% import '_shared/macros.html.j2' as ui %}
|
||||
<!doctype html><html lang="de"><head><meta charset="utf-8"><title>{{ data._theme.name }} - {{ data.customer.name }}</title><style>
|
||||
:root{--p:{{data.design.primary_color}};--s:{{data.design.secondary_color}};--a:{{data.design.accent_color}};--t:{{data.design.text_color}};--m:{{data.design.muted_color}};--bg:{{data.design.surface_color}};--line:#d9dfdf;--pos:#28745a;--neg:#a74646}@page{size:A4;margin:12mm 14mm 19mm}*{box-sizing:border-box}html{-webkit-print-color-adjust:exact;print-color-adjust:exact}body{margin:0;color:var(--t);font:9.2pt/1.48 {{data.design.font_family}},Arial,sans-serif}h1,h2,h3,p{margin-top:0}h1{font-size:31pt;line-height:.98;margin:0}h2{font-size:15pt;margin-bottom:3mm}h3{font-size:10.3pt;margin-bottom:1mm}p{margin-bottom:2.6mm}.cover{display:grid;grid-template-columns:1fr 1fr;min-height:68mm;margin-bottom:6mm;break-inside:avoid}.cover-left{background:var(--p);color:#fff;padding:7mm;display:flex;flex-direction:column;justify-content:space-between}.cover-right{background:var(--bg);padding:7mm;display:flex;flex-direction:column;justify-content:space-between}.brand{display:flex;align-items:center;gap:3mm}.logo{width:13mm;height:13mm;background:#fff;color:var(--p);display:flex;align-items:center;justify-content:center;font-weight:900;overflow:hidden}.logo img{width:100%;height:100%;object-fit:contain;padding:1mm}.brand-name{font-weight:800}.small{font-size:7.3pt;opacity:.76}.kicker,.kpi-label,.category{font-size:6.7pt;text-transform:uppercase;letter-spacing:1px;font-weight:800;color:var(--m)}.cover-left .kicker{color:#ffffffb8}.period{font-size:18pt;color:var(--p);font-weight:800}.summary h2{font-size:15pt}.summary p{margin:0}.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:3mm;margin-bottom:3mm}.kpi{padding:4mm;border-left:1mm solid var(--p);background:#fff;border-top:1px solid var(--line);border-right:1px solid var(--line);border-bottom:1px solid var(--line)}.kpi:nth-child(even){border-left-color:var(--a)}.kpi-value{font-size:15.5pt;font-weight:800;color:var(--p);margin:2mm 0;white-space:nowrap}.kpi-delta{font-size:7pt}.up{color:var(--pos)}.down{color:var(--neg)}.facts{display:grid;grid-template-columns:repeat(4,1fr);background:var(--bg);padding:3mm 4mm;margin-bottom:7mm}.fact span{display:block;font-size:6.7pt;color:var(--m)}.fact strong{display:block;margin-top:.5mm}.band{display:grid;grid-template-columns:40mm 1fr;gap:6mm;margin:7mm 0;break-inside:avoid}.band-title{background:var(--p);color:#fff;padding:5mm;min-height:30mm}.band-title.alt{background:var(--a);color:var(--t)}.band-title h2{margin:0}.trend-bars{display:grid;gap:2mm}.trend-row{display:grid;grid-template-columns:18mm 1fr 28mm 22mm;gap:2.5mm;align-items:center;font-size:7.3pt}.trend-label{font-weight:700}.trend-track{height:4mm;background:var(--bg);position:relative}.trend-revenue{height:100%;background:var(--p)}.trend-occ{height:1.2mm;background:var(--a);position:absolute;bottom:0;left:0}.trend-num{text-align:right}.developments{display:grid;grid-template-columns:1fr 1fr;gap:3mm}.development{display:grid;grid-template-columns:2mm 1fr;gap:3mm;border:1px solid var(--line);padding:3.5mm;break-inside:avoid}.impact{background:var(--m)}.positive .impact{background:var(--pos)}.negative .impact{background:var(--neg)}.development p{margin:0}.recommendations{display:grid;gap:3mm}.recommendation{display:grid;grid-template-columns:9mm 1fr;gap:3mm;border-bottom:1px solid var(--line);padding:0 0 3mm;break-inside:avoid}.priority{font-size:18pt;font-weight:800;color:var(--a)}.recommendation p{margin-bottom:1.3mm}.effect{color:var(--p)}.outlook{margin-top:7mm;display:grid;grid-template-columns:38mm 1fr;background:var(--bg);padding:5mm;break-inside:avoid}.outlook .kicker{align-self:start;color:var(--p)}.outlook h2{margin-bottom:2mm}.outlook p{margin:0}.notes{font-size:6.8pt;color:var(--m);margin-top:4mm}.notes ul{margin:1mm 0;padding-left:4mm}.legal{font-size:6.2pt;color:var(--m);margin-top:2mm}
|
||||
</style></head><body>
|
||||
<section class="cover"><div class="cover-left"><div class="brand">{{ui.logo(data)}}<div><div class="brand-name">{{data.customer.name}}</div><div class="small">{{data.customer.property_name}}</div></div></div><div><div class="kicker">Performance & Strategie</div><h1>Monatsreport</h1></div></div><div class="cover-right"><div><div class="kicker">Berichtszeitraum</div><div class="period">{{data.report.period.label}}</div><div class="small">{{data.customer.location}} · {{data.report.generated_at|date_de}}</div></div><div class="summary"><div class="kicker">Kurzfazit</div><h2>{{data.content.summary.headline}}</h2><p>{{data.content.summary.text}}</p></div></div></section>
|
||||
{{ui.kpis(data)}}{{ui.facts(data)}}
|
||||
<section class="band"><div class="band-title"><div class="kicker">01</div><h2>Monatsverlauf</h2></div><div>{{ui.trend_bars(data)}}</div></section>
|
||||
<section class="band"><div class="band-title alt"><div class="kicker">02</div><h2>Entwicklungen</h2></div><div>{{ui.developments(data)}}</div></section>
|
||||
<section class="band"><div class="band-title"><div class="kicker">03</div><h2>Empfehlungen</h2></div><div>{{ui.recommendations(data)}}</div></section>
|
||||
{{ui.outlook(data)}}{{ui.notes(data)}}
|
||||
</body></html>
|
||||
Reference in New Issue
Block a user