Add Logbuch: project update blog with admin, media and API
Public archive with sidebar navigation, project pages, month archive, search and entry pages with image blocks. Admin area for brands, projects, post types, users, api clients, media and the entry editor with drag and drop images, preview per audience, scheduling and publish checks. Read and write API with bearer tokens, audience scoping, idempotent creation, OpenAPI document and editorial guide. Magic link login with configurable allowed domains, whole app behind the session gate. 456 tests including design rule checks.
This commit is contained in:
@@ -0,0 +1,546 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Logbuch</title>
|
||||
<style>
|
||||
:root {
|
||||
--paper: #eff0ec;
|
||||
--surface: #fbfbf9;
|
||||
--ink: #191c20;
|
||||
--ink-2: #4a4f56;
|
||||
--ink-3: #868b92;
|
||||
--rule: #d8d9d2;
|
||||
--red: #c43a22;
|
||||
--blue: #2b4a9b;
|
||||
--shot-1: #dcdcd5;
|
||||
--shot-2: #c9cac2;
|
||||
|
||||
--font-display: "Futura", "Avenir Next Condensed", "Avenir Next", system-ui, sans-serif;
|
||||
--font-body: "Charter", "Iowan Old Style", Palatino, Georgia, serif;
|
||||
--font-mono: "SF Mono", ui-monospace, Menlo, monospace;
|
||||
|
||||
--margin-col: 6rem;
|
||||
--gap: 1.5rem;
|
||||
--maxw: 63rem;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--paper: #15171a;
|
||||
--surface: #1c1f23;
|
||||
--ink: #e9e8e3;
|
||||
--ink-2: #a8adb4;
|
||||
--ink-3: #73787f;
|
||||
--rule: #2c3036;
|
||||
--red: #e46045;
|
||||
--blue: #8aa6ee;
|
||||
--shot-1: #2a2e34;
|
||||
--shot-2: #383d45;
|
||||
}
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--paper: #15171a;
|
||||
--surface: #1c1f23;
|
||||
--ink: #e9e8e3;
|
||||
--ink-2: #a8adb4;
|
||||
--ink-3: #73787f;
|
||||
--rule: #2c3036;
|
||||
--red: #e46045;
|
||||
--blue: #8aa6ee;
|
||||
--shot-1: #2a2e34;
|
||||
--shot-2: #383d45;
|
||||
}
|
||||
|
||||
:root[data-theme="light"] {
|
||||
--paper: #eff0ec;
|
||||
--surface: #fbfbf9;
|
||||
--ink: #191c20;
|
||||
--ink-2: #4a4f56;
|
||||
--ink-3: #868b92;
|
||||
--rule: #d8d9d2;
|
||||
--red: #c43a22;
|
||||
--blue: #2b4a9b;
|
||||
--shot-1: #dcdcd5;
|
||||
--shot-2: #c9cac2;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--paper);
|
||||
color: var(--ink);
|
||||
font-family: var(--font-body);
|
||||
font-size: 1rem;
|
||||
line-height: 1.6;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
h1, h2, h3, .label, .btn, .badge, .stamp { font-family: var(--font-display); }
|
||||
.label, .meta, .num { font-family: var(--font-mono); }
|
||||
a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: 0.15em; }
|
||||
:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
|
||||
::-webkit-scrollbar { width: 0.5rem; height: 0.5rem; }
|
||||
::-webkit-scrollbar-thumb { background: var(--ink-3); border-radius: 1rem; }
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
|
||||
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 1.5rem; }
|
||||
|
||||
/* Kopfleiste */
|
||||
.bar {
|
||||
position: sticky; top: 0; z-index: 5;
|
||||
display: flex; align-items: center; gap: 1rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: color-mix(in srgb, var(--paper) 88%, transparent);
|
||||
backdrop-filter: blur(8px);
|
||||
border-bottom: 1px solid var(--rule);
|
||||
}
|
||||
.mark {
|
||||
font-family: var(--font-display);
|
||||
font-size: 0.95rem; font-weight: 500;
|
||||
letter-spacing: 0.42em; text-transform: uppercase;
|
||||
margin-right: auto;
|
||||
}
|
||||
.mark span { color: var(--red); }
|
||||
.btn {
|
||||
font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase;
|
||||
padding: 0.45rem 0.8rem; border: 1px solid var(--rule);
|
||||
background: var(--surface); color: var(--ink); border-radius: 0.125rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn:hover { border-color: var(--ink-3); }
|
||||
.btn--primary { background: var(--ink); color: var(--paper); border-color: var(--ink); }
|
||||
.btn--primary:hover { background: var(--red); border-color: var(--red); }
|
||||
|
||||
/* Formularkopf */
|
||||
.masthead { padding: 3.5rem 0 2.5rem; }
|
||||
.masthead h1 {
|
||||
font-size: clamp(2.5rem, 7vw, 4.5rem);
|
||||
font-weight: 500; line-height: 0.95; letter-spacing: -0.01em;
|
||||
margin: 0 0 0.5rem;
|
||||
}
|
||||
.masthead p {
|
||||
margin: 0 0 2.25rem; max-width: 34rem;
|
||||
color: var(--ink-2); font-size: 1.0625rem;
|
||||
}
|
||||
.fields { display: grid; gap: 0.4rem; }
|
||||
.field { display: flex; align-items: baseline; gap: 0.6rem; font-size: 0.75rem; }
|
||||
.field .label { color: var(--ink-3); letter-spacing: 0.16em; text-transform: uppercase; white-space: nowrap; }
|
||||
.field .leader { flex: 1; border-bottom: 1px dotted var(--rule); }
|
||||
.field .val { font-family: var(--font-mono); color: var(--ink-2); text-align: right; }
|
||||
|
||||
/* Filterzeile */
|
||||
.filters { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 1.75rem 0 0.5rem; }
|
||||
.chip {
|
||||
display: inline-flex; align-items: center; gap: 0.45rem;
|
||||
font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.06em;
|
||||
padding: 0.35rem 0.65rem; border: 1px solid var(--rule); border-radius: 1rem;
|
||||
background: transparent; color: var(--ink-2); cursor: pointer;
|
||||
}
|
||||
.chip[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
|
||||
.chip i { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--dot, var(--ink-3)); }
|
||||
|
||||
/* Logbuch-Schiene */
|
||||
.log { position: relative; padding: 1rem 0 3rem; }
|
||||
.log::before {
|
||||
content: ""; position: absolute; top: 0; bottom: 0;
|
||||
left: calc(var(--margin-col) - 0.5rem); width: 1px;
|
||||
background: color-mix(in srgb, var(--red) 45%, transparent);
|
||||
}
|
||||
.entry {
|
||||
display: grid; grid-template-columns: var(--margin-col) 1fr; gap: var(--gap);
|
||||
padding: 1.75rem 0; border-bottom: 1px solid var(--rule);
|
||||
animation: rise 0.5s both cubic-bezier(0.22, 0.61, 0.36, 1);
|
||||
animation-delay: calc(var(--i, 0) * 60ms);
|
||||
}
|
||||
.entry:last-child { border-bottom: 0; }
|
||||
@keyframes rise { from { opacity: 0; transform: translateY(0.5rem); } }
|
||||
@media (prefers-reduced-motion: reduce) { .entry { animation: none; } }
|
||||
|
||||
.entry .rail { position: relative; text-align: right; }
|
||||
.entry .rail::after {
|
||||
content: ""; position: absolute; right: -0.75rem; top: 0.45rem;
|
||||
width: 0.5rem; height: 0.5rem;
|
||||
border: 1px solid var(--red); background: var(--paper);
|
||||
transition: background 0.15s;
|
||||
}
|
||||
.entry:hover .rail::after { background: var(--red); }
|
||||
.entry--unread .rail::after { background: var(--red); }
|
||||
.entry .date { display: block; font-family: var(--font-mono); font-size: 0.8125rem; color: var(--ink); }
|
||||
.entry .year, .entry .num { display: block; font-family: var(--font-mono); font-size: 0.6875rem; color: var(--ink-3); }
|
||||
.entry .num { margin-top: 0.5rem; }
|
||||
|
||||
.head { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.5rem; }
|
||||
.badge {
|
||||
font-size: 0.625rem; letter-spacing: 0.16em; text-transform: uppercase;
|
||||
padding: 0.2rem 0.45rem; border: 1px solid currentColor; color: var(--ink-2);
|
||||
}
|
||||
.badge--feature { color: var(--blue); }
|
||||
.badge--breaking { color: var(--red); }
|
||||
.stamp {
|
||||
margin-left: auto; transform: rotate(-5deg);
|
||||
font-size: 0.6875rem; letter-spacing: 0.22em; text-transform: uppercase;
|
||||
color: var(--red); border: 0.125rem solid var(--red); padding: 0.15rem 0.5rem;
|
||||
opacity: 0.85;
|
||||
}
|
||||
.entry h2 { margin: 0 0 0.5rem; font-size: 1.375rem; font-weight: 500; line-height: 1.2; }
|
||||
.entry--lead h2 { font-size: clamp(1.75rem, 3.6vw, 2.5rem); }
|
||||
.entry p { margin: 0; color: var(--ink-2); max-width: 40rem; }
|
||||
.foot {
|
||||
display: flex; align-items: center; gap: 0.75rem; margin-top: 0.9rem;
|
||||
font-family: var(--font-mono); font-size: 0.6875rem; color: var(--ink-3);
|
||||
}
|
||||
.foot .proj { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--ink-2); }
|
||||
.foot .proj i { width: 0.5rem; height: 0.5rem; background: var(--dot); }
|
||||
.foot .sep { color: var(--rule); }
|
||||
|
||||
/* Bildplatzhalter */
|
||||
.shots { display: flex; gap: 0.5rem; margin-top: 1rem; }
|
||||
.shot {
|
||||
position: relative; overflow: hidden;
|
||||
background: var(--surface); border: 1px solid var(--rule); border-radius: 0.1875rem;
|
||||
flex: 1; aspect-ratio: 16 / 10;
|
||||
}
|
||||
.shot--wide { aspect-ratio: 21 / 9; }
|
||||
.shot::before {
|
||||
content: ""; position: absolute; inset: 0.5rem 0.5rem auto; height: 0.375rem;
|
||||
background: var(--shot-2); border-radius: 0.125rem;
|
||||
}
|
||||
.shot--table::after {
|
||||
content: ""; position: absolute; inset: 1.4rem 0.5rem 0.5rem;
|
||||
background:
|
||||
linear-gradient(var(--shot-1) 0 0) 0 0 / 62% 0.3rem no-repeat,
|
||||
linear-gradient(var(--shot-1) 0 0) 0 0.75rem / 88% 0.3rem no-repeat,
|
||||
linear-gradient(var(--shot-1) 0 0) 0 1.5rem / 45% 0.3rem no-repeat,
|
||||
linear-gradient(var(--shot-1) 0 0) 0 2.25rem / 74% 0.3rem no-repeat,
|
||||
linear-gradient(var(--shot-1) 0 0) 0 3rem / 55% 0.3rem no-repeat;
|
||||
}
|
||||
.shot--chart::after {
|
||||
content: ""; position: absolute; inset: auto 0.5rem 0.5rem; height: 55%;
|
||||
background:
|
||||
linear-gradient(var(--shot-2) 0 0) 0 100% / 12% 40% no-repeat,
|
||||
linear-gradient(var(--shot-2) 0 0) 22% 100% / 12% 72% no-repeat,
|
||||
linear-gradient(var(--shot-2) 0 0) 44% 100% / 12% 55% no-repeat,
|
||||
linear-gradient(var(--shot-2) 0 0) 66% 100% / 12% 90% no-repeat,
|
||||
linear-gradient(var(--shot-2) 0 0) 88% 100% / 12% 30% no-repeat;
|
||||
}
|
||||
.shot--map::after {
|
||||
content: ""; position: absolute; inset: 1.4rem 0.5rem 0.5rem;
|
||||
background:
|
||||
radial-gradient(circle 0.15rem, var(--red) 98%, transparent) 18% 30% / 100% 100% no-repeat,
|
||||
radial-gradient(circle 0.15rem, var(--red) 98%, transparent) 42% 62% / 100% 100% no-repeat,
|
||||
radial-gradient(circle 0.15rem, var(--red) 98%, transparent) 71% 24% / 100% 100% no-repeat,
|
||||
radial-gradient(circle 0.15rem, var(--shot-2) 98%, transparent) 58% 80% / 100% 100% no-repeat,
|
||||
radial-gradient(circle 0.15rem, var(--shot-2) 98%, transparent) 86% 58% / 100% 100% no-repeat,
|
||||
linear-gradient(var(--shot-1) 0 0) 0 45% / 100% 1px no-repeat;
|
||||
}
|
||||
|
||||
/* Archiv */
|
||||
.section-label {
|
||||
display: flex; align-items: center; gap: 1rem; margin: 0 0 1.25rem;
|
||||
font-family: var(--font-display); font-size: 0.7rem;
|
||||
letter-spacing: 0.24em; text-transform: uppercase; color: var(--ink-3);
|
||||
}
|
||||
.section-label::after { content: ""; flex: 1; height: 1px; background: var(--rule); }
|
||||
.archive { padding: 2.5rem 0; border-top: 1px solid var(--rule); }
|
||||
.year { display: grid; grid-template-columns: 4rem 1fr; gap: var(--gap); margin-bottom: 1.25rem; }
|
||||
.year > .label { font-family: var(--font-mono); font-size: 0.8125rem; color: var(--ink-3); }
|
||||
.months { display: flex; flex-wrap: wrap; gap: 0.375rem; }
|
||||
.month {
|
||||
display: flex; align-items: baseline; gap: 0.4rem;
|
||||
padding: 0.3rem 0.55rem; border: 1px solid var(--rule); border-radius: 0.125rem;
|
||||
font-family: var(--font-mono); font-size: 0.7rem; color: var(--ink-2);
|
||||
background: transparent; cursor: pointer;
|
||||
}
|
||||
.month:hover { border-color: var(--red); color: var(--ink); }
|
||||
.month b { font-weight: 400; color: var(--ink-3); font-size: 0.625rem; }
|
||||
|
||||
/* In-App-Vorschau */
|
||||
.inapp { padding: 2.5rem 0 4rem; border-top: 1px solid var(--rule); }
|
||||
.inapp .hint { color: var(--ink-2); max-width: 34rem; margin: 0 0 1.5rem; font-size: 0.9375rem; }
|
||||
.panel {
|
||||
max-width: 24rem; background: var(--surface);
|
||||
border: 1px solid var(--rule); border-radius: 0.25rem;
|
||||
box-shadow: 0 1.5rem 3rem -1.5rem color-mix(in srgb, var(--ink) 25%, transparent);
|
||||
overflow: hidden;
|
||||
}
|
||||
.panel header {
|
||||
display: flex; align-items: center; gap: 0.5rem;
|
||||
padding: 0.75rem 0.875rem; border-bottom: 1px solid var(--rule);
|
||||
font-family: var(--font-display); font-size: 0.8125rem;
|
||||
}
|
||||
.panel header .count {
|
||||
font-family: var(--font-mono); font-size: 0.625rem;
|
||||
background: var(--red); color: #fff; padding: 0.1rem 0.35rem; border-radius: 1rem;
|
||||
}
|
||||
.panel header .close { margin-left: auto; color: var(--ink-3); font-family: var(--font-mono); }
|
||||
.panel ul { list-style: none; margin: 0; padding: 0; max-height: 15rem; overflow-y: auto; }
|
||||
.panel li { padding: 0.75rem 0.875rem; border-bottom: 1px solid var(--rule); }
|
||||
.panel li:last-child { border-bottom: 0; }
|
||||
.panel li .meta { font-size: 0.625rem; color: var(--ink-3); letter-spacing: 0.06em; }
|
||||
.panel li strong { display: block; font-family: var(--font-display); font-weight: 500; font-size: 0.9375rem; margin: 0.2rem 0; }
|
||||
.panel li p { margin: 0; font-size: 0.8125rem; color: var(--ink-2); }
|
||||
.panel footer { display: flex; gap: 0.5rem; padding: 0.75rem 0.875rem; border-top: 1px solid var(--rule); }
|
||||
|
||||
footer.site {
|
||||
padding: 1.5rem 0 3rem; border-top: 1px solid var(--rule);
|
||||
display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center;
|
||||
font-family: var(--font-mono); font-size: 0.6875rem; color: var(--ink-3);
|
||||
}
|
||||
footer.site .mark { font-size: 0.7rem; letter-spacing: 0.3em; margin-right: auto; color: var(--ink-2); }
|
||||
|
||||
@media (max-width: 46rem) {
|
||||
.log::before { display: none; }
|
||||
.entry { grid-template-columns: 1fr; gap: 0.6rem; }
|
||||
.entry .rail { display: flex; gap: 0.75rem; text-align: left; }
|
||||
.entry .rail::after { display: none; }
|
||||
.entry .date, .entry .year, .entry .num { display: inline; }
|
||||
.entry .num { margin: 0; }
|
||||
.year { grid-template-columns: 1fr; gap: 0.5rem; }
|
||||
.field .val { text-align: left; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="bar">
|
||||
<div class="mark">Log<span>b</span>uch</div>
|
||||
<button class="btn" id="theme" aria-label="Farbmodus wechseln">Hell / Dunkel</button>
|
||||
<button class="btn btn--primary">Eintrag schreiben</button>
|
||||
</div>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
<section class="masthead">
|
||||
<h1>Was zuletzt<br>passiert ist.</h1>
|
||||
<p>Alle zwei Wochen halten wir pro Projekt fest, was fertig geworden ist. Mit Bildern, in ganzen Sätzen, ohne Ticketnummern-Kauderwelsch.</p>
|
||||
|
||||
<div class="fields">
|
||||
<div class="field"><span class="label">Flotte</span><span class="leader"></span><span class="val">NYO · Pocket Rocket · Tajo · Aliens Exist</span></div>
|
||||
<div class="field"><span class="label">Zeitraum</span><span class="leader"></span><span class="val">01.01.2026 - 30.07.2026</span></div>
|
||||
<div class="field"><span class="label">Einträge</span><span class="leader"></span><span class="val">142 gesamt, 6 in den letzten 14 Tagen</span></div>
|
||||
<div class="field"><span class="label">Stand</span><span class="leader"></span><span class="val">30.07.2026, 09:14</span></div>
|
||||
</div>
|
||||
|
||||
<div class="filters">
|
||||
<button class="chip" aria-pressed="true">Alle Projekte</button>
|
||||
<button class="chip" aria-pressed="false" style="--dot:#2e7d5b"><i></i>Trakk</button>
|
||||
<button class="chip" aria-pressed="false" style="--dot:#2b4a9b"><i></i>MTA360</button>
|
||||
<button class="chip" aria-pressed="false" style="--dot:#b4761a"><i></i>MTA Telematik</button>
|
||||
<button class="chip" aria-pressed="false" style="--dot:#6b4ba8"><i></i>Orbit</button>
|
||||
<button class="chip" aria-pressed="false" style="--dot:#a33b6a"><i></i>Pulsar</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<main class="log">
|
||||
|
||||
<article class="entry entry--lead entry--unread" style="--i:0">
|
||||
<div class="rail">
|
||||
<span class="date">30.07.</span>
|
||||
<span class="year">2026</span>
|
||||
<span class="num">0142</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="head">
|
||||
<span class="badge badge--feature">Feature</span>
|
||||
<span class="stamp">Neu</span>
|
||||
</div>
|
||||
<h2>Regel-Engine: Bedingung trifft Aktion</h2>
|
||||
<p>Tickets reagieren jetzt selbst. Du setzt eine Bedingung und hängst eine Aktion daran: Status ändern, zuweisen, Nachricht schicken. Läuft über den Event-Bus im Worker, ohne Cronjobs.</p>
|
||||
<div class="shots">
|
||||
<div class="shot shot--wide shot--table"></div>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<span class="proj" style="--dot:#2e7d5b"><i></i>Trakk</span>
|
||||
<span class="sep">/</span>
|
||||
<span>3 Bilder</span>
|
||||
<span class="sep">/</span>
|
||||
<span>Paul</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="entry entry--unread" style="--i:1">
|
||||
<div class="rail">
|
||||
<span class="date">29.07.</span>
|
||||
<span class="year">2026</span>
|
||||
<span class="num">0141</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="head"><span class="badge">Verbesserung</span></div>
|
||||
<h2>Spalten per Rechtsklick verwalten</h2>
|
||||
<p>Rechtsklick auf eine Kopfzeile öffnet das Spaltenmenü: sortieren, anpinnen, ausblenden, Breite zurücksetzen. Wer das nicht mag, schaltet es in den Einstellungen ab.</p>
|
||||
<div class="shots">
|
||||
<div class="shot shot--table"></div>
|
||||
<div class="shot shot--chart"></div>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<span class="proj" style="--dot:#2b4a9b"><i></i>MTA360</span>
|
||||
<span class="sep">/</span>
|
||||
<span>2 Bilder</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="entry entry--unread" style="--i:2">
|
||||
<div class="rail">
|
||||
<span class="date">28.07.</span>
|
||||
<span class="year">2026</span>
|
||||
<span class="num">0140</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="head"><span class="badge badge--feature">Feature</span></div>
|
||||
<h2>10.000 Tracker auf einer Karte</h2>
|
||||
<p>Positionen kommen gebündelt aus TimescaleDB, Geofences werden serverseitig geprüft. Die Karte bleibt bei voller Flotte flüssig.</p>
|
||||
<div class="shots">
|
||||
<div class="shot shot--map"></div>
|
||||
<div class="shot shot--chart"></div>
|
||||
<div class="shot shot--table"></div>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<span class="proj" style="--dot:#b4761a"><i></i>MTA Telematik</span>
|
||||
<span class="sep">/</span>
|
||||
<span>3 Bilder</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="entry" style="--i:3">
|
||||
<div class="rail">
|
||||
<span class="date">25.07.</span>
|
||||
<span class="year">2026</span>
|
||||
<span class="num">0139</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="head"><span class="badge">Fix</span></div>
|
||||
<h2>SLA-Uhr zählt Feiertage nicht mehr mit</h2>
|
||||
<p>Reaktionszeiten liefen über Wochenenden und Feiertage weiter und lösten falsche Eskalationen aus. Der Kalender pro Kunde gilt jetzt auch für die Uhr.</p>
|
||||
<div class="foot">
|
||||
<span class="proj" style="--dot:#2e7d5b"><i></i>Trakk</span>
|
||||
<span class="sep">/</span>
|
||||
<span>gelesen</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="entry" style="--i:4">
|
||||
<div class="rail">
|
||||
<span class="date">23.07.</span>
|
||||
<span class="year">2026</span>
|
||||
<span class="num">0138</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="head"><span class="badge badge--breaking">Breaking</span></div>
|
||||
<h2>Lokale Tabellen-Konfigurationen werden nicht mehr gelesen</h2>
|
||||
<p>Ansichten liegen jetzt vollständig in der Datenbank. Wer noch eine Konfiguration im Browser hatte, sieht die Standardansicht und legt seine Ansicht einmal neu an.</p>
|
||||
<div class="foot">
|
||||
<span class="proj" style="--dot:#2b4a9b"><i></i>MTA360</span>
|
||||
<span class="sep">/</span>
|
||||
<span>gelesen</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="entry" style="--i:5">
|
||||
<div class="rail">
|
||||
<span class="date">21.07.</span>
|
||||
<span class="year">2026</span>
|
||||
<span class="num">0137</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="head"><span class="badge">Info</span></div>
|
||||
<h2>Ein Eingang für alle Kommentare</h2>
|
||||
<p>Kommentare aus Instagram, LinkedIn und Facebook landen in einem Eingang, Antworten gehen von dort zurück.</p>
|
||||
<div class="foot">
|
||||
<span class="proj" style="--dot:#6b4ba8"><i></i>Orbit</span>
|
||||
<span class="sep">/</span>
|
||||
<span>gelesen</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
<section class="archive">
|
||||
<h2 class="section-label">Archiv</h2>
|
||||
<div class="year">
|
||||
<span class="label">2026</span>
|
||||
<div class="months">
|
||||
<button class="month">Jan <b>14</b></button>
|
||||
<button class="month">Feb <b>11</b></button>
|
||||
<button class="month">Mär <b>18</b></button>
|
||||
<button class="month">Apr <b>21</b></button>
|
||||
<button class="month">Mai <b>19</b></button>
|
||||
<button class="month">Jun <b>23</b></button>
|
||||
<button class="month">Jul <b>16</b></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="year">
|
||||
<span class="label">2025</span>
|
||||
<div class="months">
|
||||
<button class="month">Okt <b>6</b></button>
|
||||
<button class="month">Nov <b>9</b></button>
|
||||
<button class="month">Dez <b>5</b></button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="inapp">
|
||||
<h2 class="section-label">In der Anwendung</h2>
|
||||
<p class="hint">Dieselben Einträge holt sich jede App über die API und zeigt sie im eigenen Design. Gelesen wird pro Nutzer der jeweiligen App gemerkt.</p>
|
||||
<div class="panel">
|
||||
<header>
|
||||
Was ist neu in Trakk
|
||||
<span class="count">3</span>
|
||||
<span class="close">Esc</span>
|
||||
</header>
|
||||
<ul>
|
||||
<li>
|
||||
<span class="meta">30.07. · Feature</span>
|
||||
<strong>Regel-Engine: Bedingung trifft Aktion</strong>
|
||||
<p>Tickets reagieren jetzt selbst, ohne Cronjobs.</p>
|
||||
</li>
|
||||
<li>
|
||||
<span class="meta">25.07. · Fix</span>
|
||||
<strong>SLA-Uhr zählt Feiertage nicht mehr mit</strong>
|
||||
<p>Keine falschen Eskalationen über Wochenenden.</p>
|
||||
</li>
|
||||
<li>
|
||||
<span class="meta">18.07. · Verbesserung</span>
|
||||
<strong>Anhänge direkt im Ticket</strong>
|
||||
<p>Dateien landen per Drag & Drop im Verlauf.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<footer>
|
||||
<button class="btn btn--primary">Alles gelesen</button>
|
||||
<button class="btn">Im Logbuch öffnen</button>
|
||||
</footer>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="site">
|
||||
<span class="mark">Logbuch</span>
|
||||
<span>Spaceport Adventures</span>
|
||||
<span class="sep">/</span>
|
||||
<span>Entwurf 30.07.2026</span>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const root = document.documentElement
|
||||
document.getElementById('theme').addEventListener('click', () => {
|
||||
const dark = getComputedStyle(root).getPropertyValue('--paper').trim() === '#15171a'
|
||||
root.dataset.theme = dark ? 'light' : 'dark'
|
||||
})
|
||||
document.querySelectorAll('.chip').forEach(chip => {
|
||||
chip.addEventListener('click', () => {
|
||||
document.querySelectorAll('.chip').forEach(c => c.setAttribute('aria-pressed', 'false'))
|
||||
chip.setAttribute('aria-pressed', 'true')
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user