From 8ddfa7e713cc7b7ad4f4b10c460bda05475e6d88 Mon Sep 17 00:00:00 2001 From: Saramanda9988 <2074730050@qq.com> Date: Wed, 31 Dec 2025 13:36:10 +0800 Subject: [PATCH] feat: Update report templates and improved layout --- .../retro_futurism/image_template.html | 2 +- .../retro_futurism/pdf_template.html | 794 +++++++++--------- 2 files changed, 391 insertions(+), 405 deletions(-) diff --git a/src/reports/templates/retro_futurism/image_template.html b/src/reports/templates/retro_futurism/image_template.html index f811e4f..b23309c 100644 --- a/src/reports/templates/retro_futurism/image_template.html +++ b/src/reports/templates/retro_futurism/image_template.html @@ -786,7 +786,7 @@

- QQ群日常活动分析报告,基于消息统计与AI分析生成 + Daily activity analysis report, generated based on message statistics and AI analysis

diff --git a/src/reports/templates/retro_futurism/pdf_template.html b/src/reports/templates/retro_futurism/pdf_template.html index 4933d11..f049873 100644 --- a/src/reports/templates/retro_futurism/pdf_template.html +++ b/src/reports/templates/retro_futurism/pdf_template.html @@ -29,16 +29,21 @@ } :root { - --c-main: #B2653B; + /* Palette */ --c-bg: #F5EDDC; - --c-dark: #181818; - --c-grid: rgba(186, 133, 48, 0.2); - --c-accent-1: #5C7F71; - --c-accent-2: #802520; - --c-accent-3: #BA8530; + --c-text: #181818; + --c-accent: #B2653B; + + --c-dec-1: #5C7F71; + --c-dec-2: #802520; + --c-dec-3: #BA8530; + + --c-grid: rgba(24, 24, 24, 0.08); + + /* Fonts */ --font-display: "Oswald", "Oswald-Fallback", Impact, "Arial Black", sans-serif; - --font-body: "Noto Sans SC", "NotoSans-Fallback", "Microsoft YaHei", "PingFang SC", sans-serif; --font-mono: "JetBrains Mono", "JetBrains-Fallback", Consolas, Monaco, "Courier New", monospace; + --font-body: "Noto Sans SC", "NotoSans-Fallback", "Microsoft YaHei", "PingFang SC", sans-serif; } * { @@ -47,131 +52,90 @@ body { margin: 0; - background: linear-gradient(180deg, #f8f2e5, #efe1ca 65%, #fbf5ea); + background-color: var(--c-bg); + color: var(--c-text); font-family: var(--font-body); - color: var(--c-dark); - min-height: 100vh; - } - - body::before { - content: ""; - position: fixed; - inset: 0; + /* Grid Background */ background-image: linear-gradient(var(--c-grid) 1px, transparent 1px), linear-gradient(90deg, var(--c-grid) 1px, transparent 1px); - background-size: 72px 72px; - opacity: 0.4; - pointer-events: none; + background-size: 40px 40px; + min-height: 100vh; + overflow-x: hidden; } - body::after { - content: ""; - position: fixed; - inset: 0; - background: - radial-gradient(circle at 12% 10%, rgba(92, 127, 113, 0.25), transparent 45%), - radial-gradient(circle at 80% 15%, rgba(128, 37, 32, 0.2), transparent 40%), - linear-gradient(90deg, rgba(178, 101, 59, 0.08), transparent 55%); - opacity: 0.7; - pointer-events: none; - } - - .scanlines { - position: fixed; - inset: 0; - pointer-events: none; - background-image: linear-gradient(rgba(24, 24, 24, 0.08) 50%, transparent 50%); - background-size: 100% 5px; - mix-blend-mode: multiply; - opacity: 0.35; - } - - .report-shell { + /* Layout Container */ + .layout { + width: 100%; + max-width: 1600px; + margin: 0 auto; + padding: 60px 40px; position: relative; - width: min(1100px, calc(100% - 48px)); - margin: 48px auto 80px; - background: linear-gradient(180deg, rgba(255, 255, 255, 0.95), rgba(246, 232, 210, 0.98)); - border-left: 16px solid var(--c-main); - border-right: 2px solid rgba(24, 24, 24, 0.08); - box-shadow: 0 40px 80px rgba(0, 0, 0, 0.25); - overflow: hidden; - padding-bottom: 60px; + border-left: 1px solid var(--c-text); + border-right: 1px solid var(--c-text); + background: + linear-gradient(90deg, transparent 0%, transparent 98%, var(--c-accent) 98%, var(--c-accent) 100%); + background-size: 100% 100%; + min-height: 100vh; } - .report-shell::before { - content: ""; - position: absolute; - top: 0; - right: -50px; - width: 180px; - height: 100%; - background: linear-gradient(180deg, rgba(24, 24, 24, 0), rgba(178, 101, 59, 0.1), rgba(24, 24, 24, 0)); - } - - .color-strip { + /* Decorative Color Bar */ + .color-bar { display: flex; flex-direction: row; gap: 0; - margin-bottom: 24px; + margin-bottom: 20px; } - .color-strip span { - width: 80px; - height: 6px; + .c-block { + width: 70px; + height: 5px; } - .strip-1 { - background: var(--c-accent-1); + .cb-1 { background: var(--c-dec-1); } + .cb-2 { background: var(--c-dec-2); } + .cb-3 { background: var(--c-dec-3); } + + /* Header */ + header { + margin-bottom: 60px; + position: relative; } - .strip-2 { - background: var(--c-accent-2); - } - - .strip-3 { - background: var(--c-accent-3); - } - - header.hero { - display: grid; - grid-template-columns: 2.2fr 1fr; - gap: 40px; - padding: 80px 64px 40px 64px; - } - - .hero-label { + .header-meta { font-family: var(--font-mono); - letter-spacing: 0.3rem; - font-size: 0.78rem; + font-size: 0.75rem; + color: var(--c-text); + opacity: 0.65; + margin-bottom: 12px; + letter-spacing: 0.15rem; text-transform: uppercase; - color: rgba(24, 24, 24, 0.65); - margin-bottom: 14px; } - .hero-title { + h1 { font-family: var(--font-display); - font-size: clamp(3rem, 6vw, 4.8rem); - text-transform: uppercase; + font-size: 4.5rem; line-height: 0.9; - margin: 0 0 18px; - letter-spacing: 0.1rem; + margin: 0 0 20px; + text-transform: uppercase; + letter-spacing: -0.1rem; + color: var(--c-text); } - .hero-title .accent { - color: var(--c-main); + h1 .highlight { + color: var(--c-accent); } - .hero-icons { + .header-icons { display: flex; - gap: 20px; - margin-top: 24px; + gap: 18px; + margin-top: 20px; align-items: center; } - .hero-icon { - width: 42px; - height: 42px; + .header-icon { + width: 38px; + height: 38px; display: flex; align-items: center; justify-content: center; @@ -179,34 +143,36 @@ background: rgba(178, 101, 59, 0.08); } - .hero-icon svg { - width: 22px; - height: 22px; - fill: var(--c-dark); + .header-icon svg { + width: 20px; + height: 20px; + fill: var(--c-text); } - .hero-brief { - max-width: 460px; - color: rgba(24, 24, 24, 0.7); + .header-brief { + max-width: 500px; + color: rgba(24, 24, 24, 0.8); line-height: 1.6; - margin: 0; + margin-bottom: 24px; + font-size: 0.95rem; + font-weight: 400; } - .hero-meta { + .header-meta-row { display: flex; - gap: 24px; - margin-top: 28px; - font-family: var(--font-mono); + gap: 30px; } - .hero-meta .meta-block { - border-left: 4px solid var(--c-main); - padding-left: 14px; + .meta-block { + padding-left: 16px; + border-left: 3px solid var(--c-accent); } .meta-label { - font-size: 0.72rem; - letter-spacing: 0.2rem; + font-family: var(--font-mono); + font-size: 0.75rem; + font-weight: 500; + letter-spacing: 0.15rem; text-transform: uppercase; color: rgba(24, 24, 24, 0.5); } @@ -214,25 +180,31 @@ .meta-value { display: block; margin-top: 4px; - color: var(--c-dark); + color: var(--c-text); + font-family: var(--font-mono); + font-size: 0.9rem; + font-weight: 400; } + /* CRT Console */ .crt-console { - background: #181818; + background: var(--c-text); color: var(--c-bg); - padding: 24px; - border-radius: 6px; - border: 1px solid rgba(245, 237, 220, 0.25); - box-shadow: inset 0 0 25px rgba(0, 0, 0, 0.5); - min-height: 280px; + padding: 20px 24px; + font-family: var(--font-mono); + font-size: 0.85rem; + line-height: 1.6; position: relative; + overflow: hidden; + grid-column: span 12; + border-radius: 6px; } .crt-header { display: flex; align-items: center; gap: 8px; - margin-bottom: 20px; + margin-bottom: 16px; } .crt-btn { @@ -242,66 +214,88 @@ flex-shrink: 0; } - .crt-btn-1 { background: var(--c-accent-1); } - .crt-btn-2 { background: var(--c-accent-2); } - .crt-btn-3 { background: var(--c-accent-3); } + .crt-btn-1 { background: var(--c-dec-1); } + .crt-btn-2 { background: var(--c-dec-2); } + .crt-btn-3 { background: var(--c-dec-3); } .crt-title { margin-left: 12px; - font-family: var(--font-mono); - letter-spacing: 0.22rem; - font-size: 0.68rem; - color: var(--c-main); + font-size: 0.65rem; + letter-spacing: 0.2rem; + color: var(--c-accent); text-transform: uppercase; } .crt-label { - font-family: var(--font-mono); - font-size: 0.78rem; - letter-spacing: 0.28rem; + font-size: 0.7rem; + letter-spacing: 0.2rem; text-transform: uppercase; color: rgba(245, 237, 220, 0.7); } .crt-value { font-family: var(--font-display); - font-size: 3rem; - color: var(--c-main); - margin: 12px 0; + font-size: 2.5rem; + color: var(--c-accent); + margin: 8px 0; } .crt-sub { - font-size: 0.9rem; + font-size: 0.8rem; color: rgba(245, 237, 220, 0.8); - margin-bottom: 4px; } - .section-shell { - padding: 0 64px; - } - - .stat-grid { + /* Grid System */ + .grid-container { display: grid; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); - gap: 18px; - margin-bottom: 18px; + grid-template-columns: repeat(12, 1fr); + gap: 20px; + margin-bottom: 60px; } - .stat-card { - background: rgba(255, 255, 255, 0.9); - border: 1px solid rgba(24, 24, 24, 0.12); + /* Section Labels */ + .section-label { + grid-column: span 12; + font-family: var(--font-display); + font-size: 1.8rem; + text-transform: uppercase; + border-bottom: 2px solid var(--c-text); + padding-bottom: 8px; + margin-bottom: 20px; + display: flex; + justify-content: space-between; + align-items: flex-end; + letter-spacing: 0.1rem; + } + + .section-label span { + background: var(--c-text); + color: var(--c-bg); + padding: 2px 10px; + font-size: 0.75rem; + font-family: var(--font-mono); + vertical-align: middle; + letter-spacing: 0.15rem; + } + + /* Stat Box */ + .stat-box { + grid-column: span 3; + border: 1px solid var(--c-text); padding: 20px; - box-shadow: inset 0 0 0 1px rgba(24, 24, 24, 0.05); - min-height: 140px; position: relative; + background: rgba(255, 255, 255, 0.5); border-radius: 6px; } - .stat-card::after { - content: ""; + .stat-box::before { + content: ''; position: absolute; - inset: 18px; - border: 1px dashed rgba(24, 24, 24, 0.08); + top: 4px; + left: 4px; + right: 4px; + bottom: 4px; + border: 1px solid var(--c-grid); pointer-events: none; } @@ -309,165 +303,139 @@ font-family: var(--font-mono); font-size: 0.8rem; font-weight: 500; - letter-spacing: 0.2rem; text-transform: uppercase; - color: rgba(24, 24, 24, 0.55); + color: var(--c-dec-1); + margin-bottom: 10px; + display: block; + letter-spacing: 0.15rem; } .stat-value { font-family: var(--font-display); - font-size: 2.8rem; + font-size: 3rem; + color: var(--c-accent); line-height: 1; - color: var(--c-main); - margin: 16px 0 8px; } .stat-note { - font-size: 0.95rem; - color: rgba(24, 24, 24, 0.75); + font-size: 0.85rem; + color: rgba(24, 24, 24, 0.7); + margin-top: 8px; font-weight: 400; } - .module { - margin: 36px 0; - padding: 32px 32px 40px; - border-left: 5px solid rgba(178, 101, 59, 0.6); - background: linear-gradient(180deg, rgba(255, 255, 255, 0.95), rgba(245, 237, 220, 0.85)); - box-shadow: 0 12px 30px rgba(0, 0, 0, 0.08); + /* Content Box (for topics, titles, quotes) */ + .content-box { + grid-column: span 12; + border: 1px solid var(--c-text); + padding: 24px; + background: rgba(255, 255, 255, 0.5); position: relative; + border-radius: 6px; } - .module::after { - content: ""; + .content-box::before { + content: ''; position: absolute; - inset: 16px; - border: 1px solid rgba(24, 24, 24, 0.06); + top: 6px; + left: 6px; + right: 6px; + bottom: 6px; + border: 1px solid var(--c-grid); pointer-events: none; } - .module-heading { - display: flex; - justify-content: space-between; - align-items: flex-end; - margin-bottom: 18px; - } - - .module-kicker { + /* Activity Chart */ + .activity-wrapper { font-family: var(--font-mono); - font-size: 0.75rem; - letter-spacing: 0.3rem; - text-transform: uppercase; - color: rgba(24, 24, 24, 0.55); - margin-bottom: 6px; - } - - .module-title { - margin: 0; - font-family: var(--font-display); - font-size: 2.2rem; - letter-spacing: 0.1rem; - } - - .module-tag { - font-family: var(--font-mono); - font-size: 0.75rem; - letter-spacing: 0.3rem; - background: var(--c-dark); - color: var(--c-bg); - padding: 6px 14px; - border-radius: 30px; - } - - .activity-panel { - background: #fff5eb; - padding: 20px; - border: 1px solid rgba(24, 24, 24, 0.08); - } - - .activity-board { - display: flex; - flex-direction: column; - gap: 12px; + font-size: 0.85rem; } .activity-row { display: grid; - grid-template-columns: 80px 1fr 70px; + grid-template-columns: 60px 1fr 50px; align-items: center; gap: 12px; - font-family: var(--font-mono); - color: rgba(24, 24, 24, 0.6); + padding: 8px 0; + border-bottom: 1px solid var(--c-grid); + } + + .activity-row:last-child { + border-bottom: none; } .activity-hour { letter-spacing: 0.1rem; + color: rgba(24, 24, 24, 0.6); } .activity-meter { background: rgba(24, 24, 24, 0.08); - height: 10px; - border-radius: 20px; + height: 8px; + border-radius: 2px; overflow: hidden; - border: 1px solid rgba(24, 24, 24, 0.1); } .activity-bar { height: 100%; width: var(--pct, 10%); - background: linear-gradient(90deg, rgba(178, 101, 59, 0.8), rgba(178, 101, 59, 0.3)); - position: relative; + background: var(--c-accent); } .activity-count { text-align: right; + color: rgba(24, 24, 24, 0.6); } - .topic-stack { + /* Topic List */ + .topic-list { display: flex; flex-direction: column; gap: 16px; + padding: 0; + width: 100%; } - .topic-card { + .topic-item { display: grid; grid-template-columns: 16px 1fr; gap: 16px; padding: 16px; padding-left: 20px; - background: rgba(255, 255, 255, 0.9); - border: 1px solid rgba(24, 24, 24, 0.12); + background: rgba(255, 255, 255, 0.5); + border: 1px solid var(--c-text); position: relative; border-radius: 6px; } - .topic-card::before { + .topic-item::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; - background: var(--c-accent-1); + background: var(--c-dec-1); border-radius: 6px 0 0 6px; } - .topic-card::after { + .topic-item::after { content: ''; position: absolute; left: 4px; top: 0; bottom: 0; width: 4px; - background: var(--c-accent-2); + background: var(--c-dec-2); } - .topic-card .color-third { + .topic-item .color-third { position: absolute; left: 8px; top: 0; bottom: 0; width: 4px; - background: var(--c-accent-3); + background: var(--c-dec-3); border-radius: 0 6px 6px 0; } @@ -482,7 +450,7 @@ .topic-icon svg { width: 14px; height: 14px; - fill: var(--c-main); + fill: var(--c-accent); } .topic-content { @@ -495,15 +463,15 @@ margin: 0; font-size: 1.15rem; font-weight: 500; - letter-spacing: 0.04rem; - color: var(--c-dark); + letter-spacing: 0.05rem; + color: var(--c-text); } .topic-meta { font-family: var(--font-mono); font-size: 0.8rem; font-weight: 600; - letter-spacing: 0.16rem; + letter-spacing: 0.15rem; color: rgba(24, 24, 24, 0.7); text-transform: uppercase; } @@ -515,40 +483,49 @@ font-weight: 400; } + /* User Title Grid */ .title-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); - gap: 18px; - margin-top: 20px; + grid-template-columns: repeat(2, 1fr); + gap: 20px; } - .title-card { - display: grid; - grid-template-columns: 72px 1fr; - column-gap: 18px; + .title-item { + border: 1px solid var(--c-text); padding: 18px; - border: 1px solid rgba(24, 24, 24, 0.12); - background: rgba(255, 255, 255, 0.9); position: relative; + background: rgba(255, 255, 255, 0.5); border-radius: 6px; } + .title-header { + display: flex; + align-items: center; + gap: 14px; + margin-bottom: 12px; + } + + .title-info { + display: flex; + flex-direction: column; + gap: 8px; + } + .title-avatar { - width: 72px; - height: 72px; + width: 52px; + height: 52px; border-radius: 50%; overflow: hidden; - border: 1px solid rgba(24, 24, 24, 0.12); + border: 1px solid var(--c-text); background: rgba(24, 24, 24, 0.08); - grid-row: 1 / span 3; - align-self: center; + flex-shrink: 0; } .title-avatar img { width: 100%; height: 100%; object-fit: cover; - filter: grayscale(35%) contrast(110%); + filter: grayscale(50%) contrast(110%); } .title-avatar-fallback { @@ -558,25 +535,11 @@ align-items: center; justify-content: center; font-family: var(--font-mono); - font-size: 0.78rem; - letter-spacing: 0.25rem; + font-size: 0.7rem; + letter-spacing: 0.15rem; color: rgba(24, 24, 24, 0.5); } - .title-header { - display: flex; - align-items: center; - gap: 14px; - margin-bottom: 12px; - grid-column: 2; - } - - .title-info { - display: flex; - flex-direction: column; - gap: 8px; - } - .title-name { font-weight: 600; font-size: 1.1rem; @@ -603,7 +566,7 @@ font-weight: 600; letter-spacing: 0.15rem; text-transform: uppercase; - color: var(--c-main); + color: var(--c-accent); background: rgba(178, 101, 59, 0.15); padding: 3px 10px; font-size: 0.75rem; @@ -611,7 +574,6 @@ } .title-reason { - grid-column: 2; margin: 8px 0 0; font-size: 0.95rem; color: rgba(24, 24, 24, 0.8); @@ -619,52 +581,55 @@ font-weight: 400; } - .quote-stack { + /* Quote List */ + .quote-list { display: flex; flex-direction: column; gap: 16px; + padding: 0; + width: 100%; } - .quote-card { + .quote-item { display: grid; grid-template-columns: 16px 1fr; gap: 16px; padding: 16px; padding-left: 20px; - background: rgba(255, 255, 255, 0.9); - border: 1px solid rgba(24, 24, 24, 0.12); + background: rgba(255, 255, 255, 0.5); + border: 1px solid var(--c-text); position: relative; border-radius: 6px; } - .quote-card::before { + .quote-item::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; - background: var(--c-accent-1); + background: var(--c-dec-1); border-radius: 6px 0 0 6px; } - .quote-card::after { + .quote-item::after { content: ''; position: absolute; left: 4px; top: 0; bottom: 0; width: 4px; - background: var(--c-accent-2); + background: var(--c-dec-2); } - .quote-card .color-third { + .quote-item .color-third { position: absolute; left: 8px; top: 0; bottom: 0; width: 4px; - background: var(--c-accent-3); + background: var(--c-dec-3); border-radius: 0 6px 6px 0; } @@ -679,12 +644,12 @@ .quote-icon svg { width: 14px; height: 14px; - fill: var(--c-main); + fill: var(--c-accent); } .quote-content { font-size: 1.05rem; - color: var(--c-dark); + color: var(--c-text); margin: 0 0 8px; line-height: 1.6; font-weight: 400; @@ -694,7 +659,7 @@ font-family: var(--font-mono); font-size: 0.8rem; font-weight: 600; - letter-spacing: 0.2rem; + letter-spacing: 0.15rem; color: rgba(24, 24, 24, 0.7); text-transform: uppercase; } @@ -706,6 +671,23 @@ font-weight: 400; } + /* Footer */ + footer { + margin-top: 60px; + border-top: 3px solid var(--c-text); + padding-top: 16px; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 20px; + font-family: var(--font-mono); + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.15rem; + color: rgba(24, 24, 24, 0.6); + } + .footer-tokens { display: flex; gap: 24px; @@ -714,166 +696,170 @@ .footer-author { font-family: var(--font-mono); font-size: 0.7rem; - color: var(--c-main); + color: var(--c-accent); letter-spacing: 0.1rem; } - footer { - padding: 0 64px; - margin-top: 28px; - font-family: var(--font-mono); - font-size: 0.78rem; - letter-spacing: 0.25rem; - display: flex; - justify-content: space-between; - align-items: center; - flex-wrap: wrap; - gap: 20px; - color: rgba(24, 24, 24, 0.65); - } - + /* Responsive */ @media (max-width: 900px) { - header.hero { + .layout { + padding: 40px 24px; + } + + h1 { + font-size: 3rem; + } + + .stat-box { + grid-column: span 6; + } + + .title-grid { grid-template-columns: 1fr; } - .report-shell { - width: calc(100% - 24px); - margin: 24px auto 60px; - } - - .section-shell { - padding: 0 32px; - } - - footer { - padding: 0 32px; - } - - .module { - padding: 24px; - } - - .stat-grid { - grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + .header-meta-row { + flex-direction: column; + gap: 16px; } } -
-
-
-
-
- - - +
+
+
+
+
+
+
+
System Report // {{current_date}}
+

Daily
Analysis
Export

+
+
+ + +
-
Instruction Catalogue // Retro Futurism Export
-

Left Aligned
Daily Report

-
-
- - - -
-
- - - -
-
- - - -
+
+ + +
-

- 利用网格与留白塑造复古终端的秩序感,配合 #B2653B 主色的橙铜质感, - 打造一份兼容当代阅读体验的指令式日报。 -

-
-
-
Report Date
- {{current_date}} -
-
-
Generated At
- {{current_datetime}} -
+
+ + +
+

+ Daily activity analysis report, generated based on message statistics and AI analysis +

+
+
+
Generated At
+ {{current_datetime}} +
+
+
Peak Window
+ {{most_active_period}} +
+
+
+ + +
+
+ Messages +
{{message_count}}
+
累计消息数量
+
+ +
+ Participants +
{{participant_count}}
+
参与者计数
+
+ +
+ Characters +
{{total_characters}}
+
文本总字数
+
+ +
+ Emoji +
{{emoji_count}}
+
表情符号统计
+
+
+ + +
- CRT CHANNEL
-
Peak Window
+
Peak Activity Window
{{most_active_period}}
-
活跃序列 SCAN
-
消息流强度 {{message_count}}
+
活跃序列 SCAN // 消息流强度 {{message_count}}
-
+
-
-
-
-
Messages
-
{{message_count}}
-
累计消息数量
-
-
-
Participants
-
{{participant_count}}
-
参与者计数
-
-
-
Characters
-
{{total_characters}}
-
文本总字数
-
-
-
Emoji Count
-
{{emoji_count}}
-
表情符号统计
-
-
-
- -
-
-
-
Activity Spectrum
-

Hourly Broadcast

-
-
GRID-01
-
-
+ + +
+
+
{{hourly_chart_html}}
-
+
+ -
+ +
+ Thread Matrix TOPICS_MODULE +
+
{{topics_html}} - {{titles_html}} +
+ + +
+ Operator Registry TITLES_MODULE +
+
+
+
+ {{titles_html}} +
+
+
+ + +
+ Golden Lines QUOTES_MODULE +
+
{{quotes_html}}
- +