Files
matrix/landing/index.html
T
Lotus CIandClaude Opus 5.5 090a394782
Lint / Shell (shellcheck) (push) Successful in 18s
Lint / JS (eslint) (push) Successful in 11s
Lint / Landing page is rendered (matrix (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Successful in 1m5s
Lint / Secret scan (gitleaks) (push) Successful in 10s
landing: structured feature groups, single-source comparison table (#11)
- The ~1,800-word "our fork adds" paragraph becomes seven titled groups
  (Calls & Voice, Messaging, Media & Links, Privacy & Security, Look &
  Feel, Desktop App, Rooms & Moderation), one short line per feature,
  with a link to LOTUS_FEATURES.md instead of duplicating the changelog.
- The comparison table lives in landing/data/comparison.json (converted
  losslessly: all 71 rows render with identical cell text) and the
  feature groups in landing/data/features.json. landing/build.py renders
  them between <!-- BEGIN/END --> markers; everything else stays
  hand-edited.
- CSS moved to landing/style.css and inlined by build.py (the LXC 139
  deploy copies index.html only, so a linked stylesheet wouldn't ship).
  The fork paragraph's 16 repeated inline styles are gone.
- Visible "Client comparison last reviewed <date>" stamp from
  comparison.json, replacing the stale "June 2026 (latest)" title.
- CI: `landing-fresh` fails if index.html doesn't match its sources.

Page is ~1,850 px shorter on desktop and ~2,500 px on phones; no
horizontal overflow at 1280 px or Pixel 7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 22:15:27 -04:00

1530 lines
82 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lotus Guild Matrix</title>
<!-- BEGIN:styles -->
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: #0a0a0a;
color: #e0e0e0;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px 16px 40px;
}
body::before {
content: '';
position: fixed;
top: 50%;
left: 50%;
width: 900px;
height: 900px;
transform: translate(-50%, -50%);
background: radial-gradient(circle, rgba(152, 0, 0, 0.07) 0%, transparent 65%);
pointer-events: none;
z-index: 0;
}
.container {
position: relative;
z-index: 1;
text-align: center;
width: 100%;
max-width: 900px;
}
.logo {
width: 140px;
height: 140px;
margin: 0 auto 28px;
border-radius: 50%;
filter: drop-shadow(0 0 24px rgba(152, 0, 0, 0.35));
animation: float 6s ease-in-out infinite;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
h1 {
font-size: 2rem;
font-weight: 300;
letter-spacing: 0.15em;
text-transform: uppercase;
color: #fff;
margin-bottom: 4px;
}
h1 span { color: #980000; font-weight: 600; }
.subtitle {
font-size: 0.85rem;
color: #555;
letter-spacing: 0.3em;
text-transform: uppercase;
margin-bottom: 36px;
}
/* ─── Cards / Panels ─── */
.card {
background: linear-gradient(145deg, rgba(22,22,22,0.95), rgba(14,14,14,0.98));
border: 1px solid rgba(152,0,0,0.2);
border-radius: 16px;
padding: 32px;
max-width: 560px;
margin: 0 auto;
}
.card h2 {
font-size: 0.9rem;
font-weight: 500;
color: #980000;
text-transform: uppercase;
letter-spacing: 0.15em;
margin-bottom: 20px;
}
/* ─── Steps ─── */
.steps { list-style: none; text-align: left; margin-bottom: 28px; }
.steps li {
display: flex;
align-items: flex-start;
gap: 14px;
padding: 12px 0;
border-bottom: 1px solid rgba(255,255,255,0.04);
}
.steps li:last-child { border-bottom: none; }
.step-num {
flex-shrink: 0;
width: 28px; height: 28px;
background: rgba(152,0,0,0.12);
border: 1px solid rgba(152,0,0,0.35);
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-size: 0.8rem; font-weight: 600; color: #c44;
}
.step-text { padding-top: 3px; font-size: 0.95rem; line-height: 1.5; color: #bbb; }
.step-text strong { color: #e0e0e0; }
.homeserver {
display: inline-block;
background: rgba(152,0,0,0.1);
border: 1px solid rgba(152,0,0,0.25);
color: #e88;
font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
font-size: 0.85rem;
padding: 3px 10px;
border-radius: 6px;
}
a { color: #c44; text-decoration: none; }
.step-text a, .option-block a {
border-bottom: 1px solid rgba(204,68,68,0.3);
transition: border-color 0.2s;
}
.step-text a:hover, .option-block a:hover { border-bottom-color: #c44; }
/* ─── Or divider ─── */
.or-divider {
display: flex; align-items: center; gap: 10px;
margin: 4px 0 10px 42px;
color: #444; font-size: 0.78rem; letter-spacing: 0.1em; text-transform: uppercase;
}
.or-divider::before, .or-divider::after {
content: ''; flex: 1; height: 1px; background: rgba(255,255,255,0.06);
}
.option-block {
margin-left: 42px;
padding: 12px 14px;
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.06);
border-radius: 8px;
text-align: left; font-size: 0.88rem; color: #888; line-height: 1.5;
}
.divider { height: 1px; background: rgba(152,0,0,0.15); margin: 24px 0; }
/* ─── Tags ─── */
.tag {
font-size: 0.65rem;
background: rgba(255,255,255,0.08);
border: 1px solid rgba(255,255,255,0.1);
padding: 2px 8px; border-radius: 4px;
text-transform: uppercase; letter-spacing: 0.05em; color: #bbb;
white-space: nowrap;
}
.tag.voice { background: rgba(0,180,120,0.2); border-color: rgba(0,180,120,0.4); color: #5effc4; }
.tag.beta { background: rgba(255,180,0,0.15); border-color: rgba(255,180,0,0.3); color: #ffcc55; }
.tag.dev { background: rgba(160,80,255,0.15); border-color: rgba(160,80,255,0.3); color: #cc88ff; }
.tag.rust { background: rgba(80,140,255,0.15); border-color: rgba(80,140,255,0.3); color: #88aaff; }
.tag.warn { background: rgba(255,140,0,0.15); border-color: rgba(255,140,0,0.3); color: #ffaa44; }
.tag.dim { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,0.08); color: #666; }
/* ─── Featured client ─── */
.client-featured { margin-bottom: 16px; }
.client-featured a {
display: flex; flex-direction: column; align-items: center; gap: 6px;
background: linear-gradient(135deg, rgba(152,0,0,0.25), rgba(120,0,0,0.15));
border: 1px solid rgba(152,0,0,0.55);
color: #fff; text-decoration: none;
padding: 18px 24px; border-radius: 12px;
transition: all 0.25s ease;
box-shadow: 0 0 20px rgba(152,0,0,0.1);
}
.client-featured a:hover {
background: linear-gradient(135deg, rgba(152,0,0,0.38), rgba(120,0,0,0.25));
border-color: rgba(152,0,0,0.8);
box-shadow: 0 0 32px rgba(152,0,0,0.25);
transform: translateY(-2px);
}
.client-name { font-size: 1.15rem; font-weight: 600; letter-spacing: 0.05em; }
.client-desc { font-size: 0.82rem; color: #ccc; }
.tag-row { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; margin-top: 2px; }
/* Also-available note */
.also-available {
font-size: 0.78rem; color: #555; margin-top: 8px; line-height: 1.6;
}
.also-available a { color: #666; border-bottom: 1px solid rgba(102,102,102,0.3); transition: color 0.2s; }
.also-available a:hover { color: #999; }
/* ─── Space join ─── */
.space-join {
margin-top: 20px; padding: 16px 20px;
background: rgba(152,0,0,0.06);
border: 1px solid rgba(152,0,0,0.2); border-radius: 10px;
}
.space-join p { font-size: 0.82rem; color: #666; margin-bottom: 10px; }
.space-join a {
display: inline-block;
background: rgba(152,0,0,0.15);
border: 1px solid rgba(152,0,0,0.35);
color: #c44; text-decoration: none;
padding: 8px 20px; border-radius: 8px; font-size: 0.88rem;
transition: all 0.25s ease;
}
.space-join a:hover { background: rgba(152,0,0,0.25); color: #fff; }
/* ─── Secondary client cards ─── */
.clients-section h3 {
font-size: 0.8rem; font-weight: 500; color: #666;
text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 14px;
}
.client-group { margin-bottom: 18px; }
.client-group-label {
font-size: 0.75rem; color: #555;
text-transform: uppercase; letter-spacing: 0.1em;
margin-bottom: 8px;
}
.client-cards { display: flex; flex-direction: column; gap: 8px; }
.client-card {
display: flex; flex-direction: column; gap: 6px;
background: rgba(255,255,255,0.025);
border: 1px solid rgba(255,255,255,0.06);
border-radius: 10px; padding: 12px 14px; text-align: left;
transition: border-color 0.2s;
}
.client-card:hover { border-color: rgba(152,0,0,0.3); }
.client-card-top {
display: flex; align-items: center;
justify-content: space-between; gap: 10px; flex-wrap: wrap;
}
.client-card-name {
font-size: 0.95rem; font-weight: 600; color: #e0e0e0;
text-decoration: none;
border-bottom: 1px solid rgba(204,68,68,0.2);
transition: color 0.2s, border-color 0.2s;
}
.client-card-name:hover { color: #c44; border-bottom-color: #c44; }
.client-card-tags { display: flex; gap: 5px; flex-wrap: wrap; }
.client-card-desc { font-size: 0.8rem; color: #666; line-height: 1.45; }
/* ─── Comparison table ─── */
.comparison-section {
margin-top: 32px;
background: linear-gradient(145deg, rgba(22,22,22,0.95), rgba(14,14,14,0.98));
border: 1px solid rgba(152,0,0,0.2);
border-radius: 16px;
overflow: hidden;
}
.comparison-title {
font-size: 0.78rem; font-weight: 500; color: #980000;
text-transform: uppercase; letter-spacing: 0.15em;
padding: 16px 20px 12px;
border-bottom: 1px solid rgba(152,0,0,0.1);
}
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table {
width: 100%; border-collapse: collapse;
font-size: 0.78rem; min-width: 760px;
}
thead tr { border-bottom: 1px solid rgba(152,0,0,0.15); }
th {
padding: 10px 8px; text-align: center;
font-size: 0.7rem; font-weight: 600;
color: #888; text-transform: uppercase; letter-spacing: 0.08em;
background: rgba(255,255,255,0.02);
}
th:first-child { text-align: left; padding-left: 16px; min-width: 140px; }
th.ours { color: #c66; }
th small { display: block; font-size: 0.6rem; font-weight: 400; color: #555; margin-top: 2px; text-transform: none; letter-spacing: 0; }
tr { border-bottom: 1px solid rgba(255,255,255,0.03); }
tr:last-child { border-bottom: none; }
tr.section-header td {
background: rgba(152,0,0,0.06);
color: #770000; font-weight: 600;
font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.12em;
padding: 6px 8px 5px 16px; text-align: left;
}
td {
padding: 8px 8px; text-align: center; vertical-align: middle;
color: #888; line-height: 1.3;
}
td:first-child {
text-align: left; padding-left: 16px;
color: #aaa; font-size: 0.78rem;
}
td small { display: block; font-size: 0.68rem; color: #555; margin-top: 1px; }
.yes { color: #5effc4; font-size: 1rem; }
.part { color: #ffcc55; font-size: 0.9rem; }
.no { color: #444; font-size: 1rem; }
/* highlight our hosted client column */
th.ours, td.ours { background: rgba(152,0,0,0.04); }
/* ─── Legend ─── */
.legend {
display: flex; gap: 18px; justify-content: center; flex-wrap: wrap;
padding: 10px 16px 14px;
border-top: 1px solid rgba(255,255,255,0.04);
font-size: 0.72rem; color: #555;
}
.legend span { display: flex; align-items: center; gap: 5px; }
/* ─── Security note ─── */
.security-note {
margin: 0 20px 16px;
padding: 10px 14px;
background: rgba(80,140,255,0.04);
border: 1px solid rgba(80,140,255,0.12);
border-radius: 8px;
font-size: 0.76rem; color: #556; line-height: 1.55; text-align: left;
}
.security-note strong { color: #88aaff; }
.all-clients { margin-top: 14px; }
.all-clients a {
font-size: 0.78rem; color: #555;
border-bottom: 1px solid rgba(85,85,85,0.3);
transition: color 0.2s, border-color 0.2s;
}
.all-clients a:hover { color: #888; border-bottom-color: #888; }
/* ─── Server info ─── */
.server-info {
margin-top: 24px;
background: linear-gradient(145deg, rgba(22,22,22,0.95), rgba(14,14,14,0.98));
border: 1px solid rgba(152,0,0,0.2);
border-radius: 12px; overflow: hidden;
}
.server-info-title {
font-size: 0.78rem; font-weight: 500; color: #980000;
text-transform: uppercase; letter-spacing: 0.15em;
padding: 14px 20px 10px;
border-bottom: 1px solid rgba(152,0,0,0.1);
}
.info-grid { display: grid; grid-template-columns: 1fr 1fr; }
.info-item {
padding: 12px 18px;
border-bottom: 1px solid rgba(255,255,255,0.03);
border-right: 1px solid rgba(255,255,255,0.03);
text-align: left;
}
.info-item:nth-child(even) { border-right: none; }
.info-item:nth-last-child(-n+2) { border-bottom: none; }
.info-label { font-size: 0.7rem; color: #555; text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 3px; }
.info-value { font-size: 0.88rem; color: #ccc; }
.privacy-strip {
padding: 10px 18px;
border-top: 1px solid rgba(152,0,0,0.1);
display: flex; gap: 18px; justify-content: center; flex-wrap: wrap;
}
.privacy-badge { font-size: 0.75rem; color: #5effc4; display: flex; align-items: center; gap: 5px; }
.privacy-badge::before { content: '✓'; font-weight: 700; }
/* ─── Legal / contact / footer ─── */
.legal-note {
margin-top: 24px; padding: 12px 18px;
background: rgba(255,255,255,0.02);
border: 1px solid rgba(255,255,255,0.05);
border-radius: 8px; font-size: 0.75rem; color: #444;
line-height: 1.6; text-align: left;
}
.legal-note a { color: #555; border-bottom: 1px solid rgba(85,85,85,0.3); }
.legal-note a:hover { color: #888; }
.contact {
margin-top: 24px; padding: 16px;
background: linear-gradient(145deg, rgba(22,22,22,0.95), rgba(14,14,14,0.98));
border: 1px solid rgba(152,0,0,0.2);
border-radius: 12px; text-align: center;
}
.footer {
margin-top: 20px; font-size: 0.72rem; color: #383838;
letter-spacing: 0.04em;
display: flex; justify-content: center; gap: 14px; flex-wrap: wrap;
}
.footer a { color: #444; transition: color 0.2s; }
.footer a:hover { color: #777; }
/* ─── Sticky first table column (all screen sizes) ─── */
td:first-child {
position: sticky;
left: 0;
z-index: 1;
background: #0d0d0d;
}
th:first-child {
position: sticky;
left: 0;
z-index: 2;
background: #111;
}
tr.section-header td {
/* section headers span full width — override sticky bg */
position: static;
background: rgba(152,0,0,0.06);
}
/* Scroll hint — visible only on mobile via JS class */
.scroll-hint {
display: none;
font-size: 0.72rem;
color: #3a3a3a;
padding: 0 16px 10px;
letter-spacing: 0.05em;
}
/* ─── Tablet (≤ 700px) ─── */
@media (max-width: 700px) {
body { align-items: flex-start; }
}
/* ─── Mobile (≤ 540px) ─── */
@media (max-width: 540px) {
body { padding: 20px 12px 40px; }
.logo { width: 100px; height: 100px; margin-bottom: 20px; }
h1 { font-size: 1.5rem; letter-spacing: 0.1em; }
.subtitle { font-size: 0.78rem; letter-spacing: 0.18em; margin-bottom: 26px; }
.card { padding: 22px 16px; }
.step-text { font-size: 0.88rem; }
.homeserver { font-size: 0.75rem; word-break: break-all; }
.or-divider, .option-block { margin-left: 0; }
.client-card-top { flex-direction: column; align-items: flex-start; gap: 6px; }
.client-card-desc { font-size: 0.79rem; }
.client-card-tags { gap: 4px; }
.also-available { font-size: 0.75rem; }
/* Table */
.scroll-hint { display: block; }
table { font-size: 0.71rem; min-width: 620px; }
th { padding: 8px 5px; font-size: 0.6rem; }
th:first-child { min-width: 100px; padding-left: 10px; }
td { padding: 7px 5px; }
td:first-child { font-size: 0.71rem; padding-left: 10px; }
td small, th small { font-size: 0.58rem; }
.yes { font-size: 0.88rem; }
.part { font-size: 0.82rem; }
.no { font-size: 0.88rem; }
.comparison-title { font-size: 0.7rem; padding: 12px 14px 8px; letter-spacing: 0.1em; }
.security-note { margin: 10px 12px 4px; font-size: 0.71rem; }
.legend { padding: 8px 12px 12px; gap: 12px; font-size: 0.68rem; }
/* Server info */
.server-info-title { font-size: 0.7rem; padding: 12px 14px 8px; }
.info-item { padding: 10px 14px; }
.info-label { font-size: 0.65rem; }
.info-value { font-size: 0.82rem; }
.privacy-strip { flex-direction: column; align-items: center; gap: 8px; padding: 10px 14px; }
.privacy-badge { font-size: 0.71rem; }
/* Legal / footer */
.legal-note { font-size: 0.72rem; padding: 11px 14px; }
.contact { padding: 14px; }
.footer { gap: 8px; font-size: 0.68rem; }
}
/* ─── Very small (≤ 380px) ─── */
@media (max-width: 380px) {
h1 { font-size: 1.3rem; }
.logo { width: 84px; height: 84px; }
.card { padding: 18px 12px; }
table { font-size: 0.66rem; min-width: 580px; }
th { font-size: 0.55rem; padding: 7px 4px; }
td { padding: 6px 4px; }
td:first-child { font-size: 0.66rem; min-width: 90px; }
}
/* ── Fork feature groups (matrix #11) ── */
.fork-intro { font-size: 0.82rem; color: #888; margin: 14px 0 8px; line-height: 1.5; }
.fork-features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 10px;
margin: 0 0 12px;
}
.fork-group {
background: rgba(255,255,255,0.02);
border: 1px solid rgba(255,255,255,0.06);
border-radius: 8px;
padding: 10px 12px;
}
.fork-group { text-align: left; }
.fork-group h4 { text-align: center; margin: 0 0 6px; font-size: 0.8rem; color: #c66; letter-spacing: 0.02em; }
.fork-group ul { margin: 0; padding-left: 16px; }
.fork-group li { font-size: 0.74rem; color: #999; line-height: 1.45; margin: 3px 0; }
.fork-more { font-size: 0.76rem; color: #777; margin: 0 0 6px; }
.fork-more a { color: #888; border-bottom: 1px solid rgba(136,136,136,0.3); }
.hs-inline { font-size: 0.8em; color: #e88; }
.reviewed { font-size: 0.7rem; color: #666; text-align: center; margin: -4px 0 10px; }
</style>
<!-- END:styles -->
</head>
<body>
<div class="container">
<img class="logo" src="https://photos.lotusguild.org/api/assets/3c4eb2da-0d06-407f-bdb7-c9e4cf795f0a/thumbnail?key=4aoZxX5-FHE3m_Ywwz1uGo3iNW53kmFztxfUw91PdOgphPNxayLFicNuxPvit1OYTpY&size=preview&c=jUqDBQAWF9iId3J%2FyAeIcIAICEd4d3BzSA%3D%3D" alt="Lotus Guild">
<h1><span>Lotus</span> Guild</h1>
<p class="subtitle">Private Communications</p>
<!-- ── How to Join ── -->
<div class="card">
<h2>How to Join</h2>
<ol class="steps">
<li>
<span class="step-num">1</span>
<span class="step-text">Open <a href="https://chat.lotusguild.org" target="_blank" rel="noopener">chat.lotusguild.org</a> &mdash; your homeserver is pre-configured</span>
</li>
<li>
<span class="step-num">2</span>
<span class="step-text">Register with a <strong>token from Jared</strong> &mdash; <code class="homeserver">@jared:matrix.lotusguild.org</code></span>
</li>
<li>
<span class="step-num">3</span>
<span class="step-text">Join the <a href="https://matrix.to/#/!-1ZBnAH-JiCOV8MGSKN77zDGTuI3pgSdy8Unu_DrDyc?via=matrix.lotusguild.org&via=matrix.org" target="_blank" rel="noopener">Lotus Guild Space</a> to access all rooms</span>
</li>
</ol>
<div class="or-divider">or join from another server</div>
<div class="option-block">
Already have a Matrix account? Sign up free at <a href="https://app.element.io/#/register?hs_url=https://mozilla.modular.im" target="_blank" rel="noopener">mozilla.org</a> or <a href="https://app.element.io/#/register" target="_blank" rel="noopener">matrix.org</a>, then <a href="https://matrix.to/#/!-1ZBnAH-JiCOV8MGSKN77zDGTuI3pgSdy8Unu_DrDyc?via=matrix.lotusguild.org&via=matrix.org" target="_blank" rel="noopener">join our space</a>.
</div>
<div class="divider"></div>
<!-- ── Recommended client ── -->
<div class="clients-section">
<h3>Recommended Client</h3>
<div class="client-featured">
<a href="https://chat.lotusguild.org" target="_blank" rel="noopener">
<span class="client-name">Lotus Guild Chat</span>
<span class="client-desc">Hosted Cinny &mdash; homeserver pre-configured, no setup</span>
<span class="tag-row">
<span class="tag dim">Desktop &amp; Web</span>
<span class="tag dev">Lotus Fork</span>
<span class="tag voice">Voice &amp; Video Rooms</span>
<span class="tag">Discord-like UI</span>
</span>
</a>
</div>
<p class="fork-intro">Our Lotus Guild fork of Cinny adds:</p>
<!-- BEGIN:features -->
<div class="fork-features">
<div class="fork-group">
<h4>Calls &amp; Voice</h4>
<ul>
<li>Voice rooms with our own Element Call fork on a self-hosted LiveKit SFU</li>
<li>Push-to-talk and push-to-deafen, with system-wide hotkeys on the Windows app (work while a game has focus)</li>
<li>On-device noise suppression: Off, browser-native, or ML (RNNoise, Speex, DTLN, DeepFilterNet&nbsp;3)</li>
<li>In-call soundboard with your own clips, synced across your devices</li>
<li>Incoming-call ring with Answer/Decline, join/leave sounds, draggable picture-in-picture window</li>
<li>Screenshare fullscreen and audio mute; per-user mic/screenshare bitrate and framerate caps</li>
<li>Server-enforced room limits and permissions (max participants, audio-only, no screenshare) for every Matrix client</li>
<li>AFK auto-mute after a configurable idle time</li>
</ul>
</div>
<div class="fork-group">
<h4>Messaging</h4>
<ul>
<li>Threads with a side panel, unread chips and per-thread notification overrides</li>
<li>Voice messages with 0.75&times;&ndash;2&times; playback (MSC3245, E2EE)</li>
<li>Polls, message scheduling (MSC4140), forwarding, captions and location sharing</li>
<li>Pinned messages, saved messages/bookmarks and private notes on people, synced across devices</li>
<li>Who-reacted viewer, read receipt avatars, quick reactions on hover</li>
<li>GIF picker (Giphy), custom emoji &amp; sticker packs, math/LaTeX (KaTeX)</li>
<li>On-device message translation: text never leaves your machine, works in encrypted rooms</li>
</ul>
</div>
<div class="fork-group">
<h4>Media &amp; Links</h4>
<ul>
<li>Click-to-play inline embeds: YouTube, Vimeo, Twitch, TikTok, X, Instagram, Reddit, Bluesky, Spotify, SoundCloud, Apple Music, Tidal and more</li>
<li>Rich link cards for GitHub, Steam, Wikipedia, IMDb, npm and others; animated GIF previews</li>
<li>Media gallery for every image, video and file shared in a room</li>
<li>Optional image compression, folder drag-and-drop upload</li>
</ul>
</div>
<div class="fork-group">
<h4>Privacy &amp; Security</h4>
<ul>
<li>Private read receipts, hide typing, hide online status</li>
<li>Tracking-parameter stripping (utm_*, fbclid, YouTube si= and ~40 more), on your device</li>
<li>Opt-in on-device search index for encrypted rooms, wiped on logout</li>
<li>Device verification fixes (cross-client emoji SAS) and a per-member session panel</li>
</ul>
</div>
<div class="fork-group">
<h4>Look &amp; Feel</h4>
<ul>
<li>Lotus Terminal theme, night-light filter, glassmorphism sidebar</li>
<li>Animated chat backgrounds and 11 seasonal overlays (all respect reduced motion)</li>
<li>99 animated avatar decorations, visible to other Lotus users (MSC4133)</li>
<li>Custom status with emoji and auto-clear, Discord-style presence rings</li>
<li>Settings sync across devices (theme, layout, notification and privacy preferences)</li>
</ul>
</div>
<div class="fork-group">
<h4>Desktop App</h4>
<ul>
<li>Windows, macOS and Linux (Tauri)</li>
<li>Rich Windows notifications with inline reply; Focus Assist sync</li>
<li>Taskbar call controls, jump list and upload progress; tray with call status</li>
<li>Stays awake during calls, reconnects on network changes, updates itself</li>
</ul>
</div>
<div class="fork-group">
<h4>Rooms &amp; Moderation</h4>
<ul>
<li>Knock-to-join with an admin approve/deny panel and live pending-count badge</li>
<li>Invite links with QR codes, favourites, room filter, room history export (txt/json/html)</li>
<li>Room activity &amp; mod log, stats panel, server ACL editor, policy-list viewer</li>
</ul>
</div>
</div>
<!-- END:features -->
<p class="fork-more">Full list in <a href="https://code.lotusguild.org/LotusGuild/cinny/src/branch/lotus/LOTUS_FEATURES.md" target="_blank" rel="noopener">LOTUS_FEATURES.md</a>.</p>
<p class="also-available">Prefer the unmodified upstream? <a href="https://cinny.in" target="_blank" rel="noopener">cinny.in</a> works with our homeserver &mdash; set it to <code class="hs-inline">matrix.lotusguild.org</code>.</p>
<div class="space-join">
<p>Already signed in? Jump straight into the community:</p>
<a href="https://matrix.to/#/!-1ZBnAH-JiCOV8MGSKN77zDGTuI3pgSdy8Unu_DrDyc?via=matrix.lotusguild.org&via=matrix.org" target="_blank" rel="noopener">Join Lotus Guild Space &rarr;</a>
</div>
<div class="divider"></div>
<!-- ── Other clients ── -->
<div class="clients-section">
<h3>Other Clients</h3>
<div class="client-group">
<p class="client-group-label">Web &amp; Desktop &mdash; Official Cinny</p>
<div class="client-cards">
<div class="client-card">
<div class="client-card-top">
<a href="https://cinny.in" target="_blank" rel="noopener" class="client-card-name">Cinny</a>
<div class="client-card-tags">
<span class="tag dim">Web</span>
<span class="tag dim">Desktop</span>
</div>
</div>
<p class="client-card-desc">The upstream open-source Cinny client. Same Discord-like UI and best-in-class space navigation as Lotus Chat, but without our custom additions (no GIF picker, no call ring notification, no PiP window, no message forwarding). Set homeserver to <code style="font-size:0.85em;color:#e88;background:rgba(152,0,0,0.08);padding:1px 5px;border-radius:4px;">matrix.lotusguild.org</code>.</p>
</div>
</div>
</div>
<div class="client-group">
<p class="client-group-label">Mobile &mdash; iOS &amp; Android</p>
<div class="client-cards">
<div class="client-card">
<div class="client-card-top">
<a href="https://element.io/element-x" target="_blank" rel="noopener" class="client-card-name">Element X</a>
<div class="client-card-tags">
<span class="tag dim">iOS</span>
<span class="tag dim">Android</span>
<span class="tag rust">Rust SDK</span>
<span class="tag voice">Voice, Video &amp; Screenshare</span>
</div>
</div>
<p class="client-card-desc">Fastest Matrix client &mdash; instant load via Sliding Sync. Native MatrixRTC calls (voice-only + video), screenshare, DM voice calls, live location sharing, media captions. Full space create &amp; management. Rust encryption (Vodozemac).</p>
</div>
<div class="client-card">
<div class="client-card-top">
<a href="https://fluffychat.im/" target="_blank" rel="noopener" class="client-card-name">FluffyChat</a>
<div class="client-card-tags">
<span class="tag dim">iOS</span>
<span class="tag dim">Android</span>
<span class="tag dim">Desktop</span>
<span class="tag dim">Web</span>
<span class="tag dim">Dart SDK</span>
<span class="tag warn">Calls Experimental</span>
</div>
</div>
<p class="client-card-desc">Simple, beginner-friendly, fully cross-platform. Dart SDK with Vodozemac encryption. Unique: supports image captions (text + image as one event). Voice/video calls are experimental &mdash; reliability varies by homeserver and platform.</p>
</div>
</div>
</div>
<div class="client-group">
<p class="client-group-label">Discord-like &mdash; Android, Windows, macOS &amp; Linux</p>
<div class="client-cards">
<div class="client-card">
<div class="client-card-top">
<a href="https://commet.chat/" target="_blank" rel="noopener" class="client-card-name">Commet</a>
<div class="client-card-tags">
<span class="tag dim">Android</span>
<span class="tag dim">Windows</span>
<span class="tag dim">macOS</span>
<span class="tag dim">Linux</span>
<span class="tag beta">Beta</span>
<span class="tag voice">Voice &amp; Video</span>
</div>
</div>
<p class="client-card-desc">Most Discord-like client overall. Multi-account support, built-in GIF search (privacy proxy &mdash; uploads to homeserver), shared calendars &amp; photo albums, polls, screenshare on browsers &amp; Android. Available on Android, Windows, macOS, Linux, and Web. Active development &mdash; iOS planned.</p>
</div>
</div>
</div>
<div class="client-group">
<p class="client-group-label">Desktop &mdash; Windows, macOS &amp; Linux</p>
<div class="client-cards">
<div class="client-card">
<div class="client-card-top">
<a href="https://element.io/download" target="_blank" rel="noopener" class="client-card-name">Element</a>
<div class="client-card-tags">
<span class="tag dim">Windows</span>
<span class="tag dim">macOS</span>
<span class="tag dim">Linux</span>
<span class="tag dim">Web</span>
<span class="tag voice">Voice, Video &amp; Screenshare</span>
</div>
</div>
<p class="client-card-desc">Most feature-complete Matrix client &mdash; every spec feature including polls, widgets, threads, screenshare. Heavier on resources. Encrypted message search on desktop only (not web).</p>
</div>
<div class="client-card">
<div class="client-card-top">
<a href="https://nheko-reborn.github.io/" target="_blank" rel="noopener" class="client-card-name">Nheko</a>
<div class="client-card-tags">
<span class="tag dim">Windows</span>
<span class="tag dim">macOS</span>
<span class="tag dim">Linux</span>
<span class="tag voice">Voice &amp; Video</span>
</div>
</div>
<p class="client-card-desc">Native C++/Qt client &mdash; lightest desktop option, no Electron. Deep KDE/Plasma integration. No threads, no mobile or web. Best for Linux power users who want minimal resource usage.</p>
</div>
</div>
</div>
<p class="all-clients"><a href="https://matrix.org/ecosystem/clients/" target="_blank" rel="noopener">View all Matrix clients &rarr;</a></p>
</div>
</div>
</div><!-- end .card -->
<!-- ── Feature Comparison Table ── -->
<div class="comparison-section">
<p class="comparison-title">Client Feature Comparison</p>
<p class="reviewed"><!-- BEGIN:reviewed -->
Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
<!-- END:reviewed --></p>
<p class="scroll-hint" id="scrollHint">← swipe to compare →</p>
<div class="table-wrap">
<!-- BEGIN:comparison -->
<table>
<thead>
<tr>
<th></th>
<th class="ours">Lotus Chat<small>chat.lotusguild.org<br>Our Cinny fork</small></th>
<th>Cinny<small>cinny.in<br>Official</small></th>
<th>Element X<small>iOS &amp; Android</small></th>
<th>FluffyChat<small>All platforms</small></th>
<th>Commet<small>Android / Win / macOS / Linux</small></th>
<th>Element<small>Web &amp; Desktop</small></th>
<th>Nheko<small>Desktop only</small></th>
</tr>
</thead>
<tbody>
<tr class="section-header"><td colspan="8">Platform</td></tr>
<tr>
<td>iOS</td>
<td class="ours"><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Android</td>
<td class="ours"><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Desktop app</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>Cinny Desktop</small></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>Win, macOS &amp; Linux</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Web browser</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Performance</td>
<td class="ours">Light</td>
<td>Light</td>
<td>Very fast<small>Sliding Sync</small></td>
<td>Moderate</td>
<td>Moderate</td>
<td>Heavy<small>Electron / JS</small></td>
<td>Light<small>Native C++</small></td>
</tr>
<tr class="section-header"><td colspan="8">Desktop App</td></tr>
<tr>
<td>Native rich notifications (click&rarr;open, inline reply)</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Windows Jump List (recent rooms)</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Taskbar + volume-flyout call controls</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Focus Assist &rarr; auto Do-Not-Disturb</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Stay awake during calls</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Recursive folder drag-drop upload</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr class="section-header"><td colspan="8">Security &amp; Encryption</td></tr>
<tr>
<td>E2EE</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Vodozemac encryption<small>stronger crypto track record</small></td>
<td class="ours"><span class="no">✗</span><small>js-sdk</small></td>
<td><span class="no">✗</span><small>js-sdk</small></td>
<td><span class="yes">✓</span><small>Rust SDK</small></td>
<td><span class="yes">✓</span><small>dart-sdk</small></td>
<td><span class="yes">✓</span><small>dart-sdk</small></td>
<td><span class="no">✗</span><small>js-sdk, migrating</small></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Device verification</td>
<td class="ours"><span class="yes">✓</span><small>SAS emoji, cross-client requests show inline card</small></td>
<td><span class="part">~</span><small>cross-client requests<br>may show unsupported</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
</tr>
<tr class="section-header"><td colspan="8">Voice &amp; Video</td></tr>
<tr>
<td>Voice &amp; video calls</td>
<td class="ours"><span class="yes">✓</span><small>rooms &amp; DMs, group calls,<br>screenshare via Element Call</small></td>
<td><span class="part">~</span><small>Element Call embed;<br>no ring notification</small></td>
<td><span class="yes">✓</span><small>MatrixRTC</small></td>
<td><span class="part">~</span><small>experimental, varies<br>by homeserver</small></td>
<td><span class="part">~</span><small>1:1 + group,<br>no E2EE voice rooms</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Screenshare</td>
<td class="ours"><span class="yes">✓</span><small>via Element Call; fullscreen button,<br>independent audio mute</small></td>
<td><span class="yes">✓</span><small>via Element Call embed</small></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>XDG portals &amp; native</small></td>
</tr>
<tr>
<td>Noise suppression<small>filter background noise from mic</small></td>
<td class="ours"><span class="yes">✓</span><small>3 tiers: off / browser-native /<br>on-device ML (RNNoise, Speex,<br>DTLN, DeepFilterNet&nbsp;3),<br>works on self-hosted SFU</small></td>
<td><span class="part">~</span><small>browser-native<br>via Element Call</small></td>
<td><span class="part">~</span><small>browser-native</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>browser-native;<br>ML only on LiveKit Cloud</small></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Push-to-Talk<small>hold key to transmit</small></td>
<td class="ours"><span class="yes">✓</span><small>configurable hold key,<br>PTT badge in call bar;<br>M = push-to-deafen;<br>system-wide on Windows desktop</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>AFK auto-mute<small>silence mic after idle timeout</small></td>
<td class="ours"><span class="yes">✓</span><small>1–30 min timeout,<br>toast notification</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Voice channel user limit<small>admin-set max participants</small></td>
<td class="ours"><span class="yes">✓</span><small>per-room cap,<br>server-enforced<br>for all clients</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Call join/leave sounds<small>cue when others come &amp; go</small></td>
<td class="ours"><span class="yes">✓</span><small>3 styles,<br>Web Audio synth</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Group calls</td>
<td class="ours"><span class="yes">✓</span><small>via Element Call embed</small></td>
<td><span class="yes">✓</span><small>via Element Call embed</small></td>
<td><span class="yes">✓</span><small>MatrixRTC</small></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>no E2EE voice rooms</small></td>
<td><span class="yes">✓</span></td>
<td><span class="part">~</span><small>partial</small></td>
</tr>
<tr>
<td>Incoming call notification<small>ring + Answer/Decline</small></td>
<td class="ours"><span class="yes">✓</span><small>DMs &amp; group chats;<br>ring tone, auto-dismiss</small></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>native push</small></td>
<td><span class="part">~</span><small>experimental</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>desktop</small></td>
<td><span class="part">~</span><small>partial</small></td>
</tr>
<tr class="section-header"><td colspan="8">Core Features</td></tr>
<tr>
<td>Spaces</td>
<td class="ours"><span class="yes">✓</span><small>best-in-class sub-space nav</small></td>
<td><span class="yes">✓</span><small>best-in-class sub-space nav</small></td>
<td><span class="yes">✓</span><small>dedicated spaces tab,<br>full management</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>Discord-like categories</small></td>
<td><span class="yes">✓</span><small>sub-spaces clunky</small></td>
<td><span class="part">~</span><small>limited</small></td>
</tr>
<tr>
<td>Threads</td>
<td class="ours"><span class="yes">✓</span><small>side panel + Slack-style per-thread notifications</small></td>
<td><span class="part">~</span><small>basic, no dedicated view</small></td>
<td><span class="part">~</span><small>Labs flag</small></td>
<td><span class="no">✗</span><small>shows as regular messages</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Polls</td>
<td class="ours"><span class="yes">✓</span><small>create, vote &amp; display;<br>single or multiple choice</small></td>
<td><span class="part">~</span><small>display only</small></td>
<td><span class="yes">✓</span><small>create, vote &amp; end</small></td>
<td><span class="yes">✓</span><small>added v2.3.0</small></td>
<td><span class="yes">✓</span><small>added v0.4.2</small></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Voice messages<small>record &amp; play</small></td>
<td class="ours"><span class="yes">✓</span><small>record &amp; play, E2EE;<br>0.75×/1×/1.5×/2× speed</small></td>
<td><span class="part">~</span><small>playback only</small></td>
<td><span class="yes">✓</span><small>record, play, variable speed,<br>reply with voice</small></td>
<td><span class="yes">✓</span><small>record &amp; play,<br>pause support</small></td>
<td><span class="part">~</span><small>playback confirmed;<br>recording unclear</small></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Pinned messages</td>
<td class="ours"><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>dedicated pins view</small></td>
<td><span class="part">~</span><small>view only</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Custom emoji &amp; stickers</td>
<td class="ours"><span class="yes">✓</span><small>best-in-class</small></td>
<td><span class="yes">✓</span></td>
<td><span class="part">~</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>bulk upload, Signal packs</small></td>
<td><span class="part">~</span><small>sometimes shows mxc:// URLs</small></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>GIF search / picker</td>
<td class="ours"><span class="yes">✓</span><small>Giphy, Terminal TDS themed,<br>click-outside to close</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>privacy proxy,<br>uploads to homeserver</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Message search (encrypted)</td>
<td class="ours"><span class="yes">✓</span><small>local cache scan; load-more<br>buttons extend history per room</small></td>
<td><span class="part">~</span><small>server search only;<br>no E2EE support</small></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>cache scan only</small></td>
<td><span class="yes">✓</span><small>client-side; auto-fetches +<br>decrypts history during search</small></td>
<td><span class="part">~</span><small>desktop only, not web</small></td>
<td><span class="part">~</span><small>local DB scan</small></td>
</tr>
<tr>
<td>Widgets</td>
<td class="ours"><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr class="section-header"><td colspan="8">UX &amp; Extras</td></tr>
<tr>
<td>Multi-account</td>
<td class="ours"><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>supported but clunky</small></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span><small>CLI profiles only</small></td>
</tr>
<tr>
<td>Image captions<small>(text + image as one event)</small></td>
<td class="ours"><span class="yes">✓</span><small>caption field on<br>image &amp; video upload</small></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>scrollable captions<br>on media (v26.04.2)</small></td>
<td><span class="yes">✓</span><small>unique feature</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span></td>
</tr>
<tr>
<td>Discord-like UI</td>
<td class="ours"><span class="yes">✓</span><small>best-in-class for web</small></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span><small>WhatsApp/Telegram style</small></td>
<td><span class="yes">✓</span><small>most Discord-like overall</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Shared calendars &amp; albums</td>
<td class="ours"><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>unique to Commet</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Night Light / Blue Light Filter<small>warm overlay, adjustable intensity</small></td>
<td class="ours"><span class="yes">✓</span><small>5–80% intensity slider,<br>Settings → Appearance</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Animated chat backgrounds<small>CSS-only, GPU-accelerated</small></td>
<td class="ours"><span class="yes">✓</span><small>5 animated wallpapers (rain,<br>stars, grid pulse, aurora,<br>fireflies); pause toggle</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Deleted message visibility<small>(redacted events)</small></td>
<td class="ours"><span class="yes">✓</span><small>"Message deleted" with reason<br>if provided</small></td>
<td><span class="no">✗</span><small>redacted messages hidden</small></td>
<td><span class="yes">✓</span><small>"Message deleted"<br>placeholder shown</small></td>
<td><span class="yes">✓</span><small>shows redaction notice</small></td>
<td><span class="yes">✓</span><small>shows redaction notice</small></td>
<td><span class="yes">✓</span><small>"Message deleted"<br>placeholder shown</small></td>
<td><span class="yes">✓</span><small>shows redaction notice</small></td>
</tr>
<tr>
<td>Location sharing</td>
<td class="ours"><span class="part">~</span><small>map embed view +<br>static share button</small></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>live &amp; static,<br>map rendering</small></td>
<td><span class="part">~</span><small>basic static</small></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Message forwarding</td>
<td class="ours"><span class="yes">✓</span><small>forward to any room</small></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>via share menu</small></td>
<td><span class="yes">✓</span></td>
<td><span class="part">~</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Per-message read receipts<small>who read each message</small></td>
<td class="ours"><span class="yes">✓</span><small>avatar pill below message,<br>click for list + timestamps</small></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>avatar thumbnails</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>avatar row below message</small></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Who reacted<small>see who reacted with each emoji</small></td>
<td class="ours"><span class="yes">✓</span><small>hover tooltip with names;<br>right-click for full avatar modal</small></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>tap reaction chip</small></td>
<td><span class="part">~</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>tooltip + click for list</small></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Edit history viewer<small>see all prior versions of an edited message</small></td>
<td class="ours"><span class="yes">✓</span><small>click "(edited)" label → modal<br>with all versions + timestamps</small></td>
<td><span class="no">✗</span><small>label shown, not clickable</small></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Custom status message<small>shown below username</small></td>
<td class="ours"><span class="yes">✓</span><small>emoji picker, auto-clear timer<br>(30 min – 7 days), 64-char limit</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>via profile settings</small></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Online presence tracking<small>idle/away auto-detection</small></td>
<td class="ours"><span class="yes">✓</span><small>online on start, idle after 10 min,<br>unavailable when tab hidden,<br>offline on close; hide-status toggle</small></td>
<td><span class="part">~</span><small>manual AFK only; auto idle<br>detection PR open, unmerged</small></td>
<td><span class="part">~</span><small>basic online/offline only</small></td>
<td><span class="part">~</span><small>basic online/offline only</small></td>
<td><span class="part">~</span><small>inactivity monitor shipped Oct 2025;<br>no tab/close detection confirmed</small></td>
<td><span class="part">~</span><small>3-min idle timer (shipped Nov 2023);<br>no tab detection, no offline on close,<br>no user-facing hide toggle</small></td>
<td><span class="part">~</span><small>basic online/offline only</small></td>
</tr>
<tr>
<td>Media Gallery<small>browse room images/videos/files</small></td>
<td class="ours"><span class="yes">✓</span><small>right-side drawer;<br>Images/Videos/Files tabs</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Sidebar room filter<small>filter by name in real time</small></td>
<td class="ours"><span class="yes">✓</span><small>Home &amp; DMs tabs</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Favorite rooms<small>starred section in sidebar</small></td>
<td class="ours"><span class="yes">✓</span><small>m.favourite tag, syncs<br>across devices</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>favourites section</small></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Invite link + QR code</td>
<td class="ours"><span class="yes">✓</span><small>matrix.to URL + QR code<br>in invite modal &amp; room settings</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Custom notification sounds<small>per-category sound selector</small></td>
<td class="ours"><span class="yes">✓</span><small>per-category sound selector; ▶ preview</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Notification quiet hours<small>silence notifs in a time window</small></td>
<td class="ours"><span class="yes">✓</span><small>silence all notifs in a time window; overnight support</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Room sort order<small>sort sidebar rooms by activity, name, or unread</small></td>
<td class="ours"><span class="yes">✓</span><small>Recent / A→Z / Unread First</small></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>sort by activity only</small></td>
<td><span class="part">~</span><small>alphabetical only</small></td>
<td><span class="yes">✓</span><small>multiple sort options</small></td>
<td><span class="part">~</span><small>limited</small></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Push notifications</td>
<td class="ours"><span class="part">~</span><small>web push only</small></td>
<td><span class="part">~</span><small>web push only</small></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span></td>
<td><span class="yes">✓</span><small>desktop</small></td>
<td><span class="yes">✓</span></td>
</tr>
<tr>
<td>Export room history<small>download messages as file</small></td>
<td class="ours"><span class="yes">✓</span><small>txt/json/html, date range,<br>E2EE-aware</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span><small>has export</small></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Message scheduling<small>send later with datetime picker</small></td>
<td class="ours"><span class="yes">✓</span><small>MSC4140, datetime picker,<br>cancel tray above composer</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>partial / labs</small></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Message bookmarks / saved messages</td>
<td class="ours"><span class="yes">✓</span><small>right-click bookmark,<br>sidebar panel, syncs across devices</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="yes">✓</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Collapsible long messages<small>auto-collapse &gt;20 lines</small></td>
<td class="ours"><span class="yes">✓</span><small>"Read more" toggle,<br>threshold configurable</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Inline GIF preview<small>Giphy / Tenor links auto-embed</small></td>
<td class="ours"><span class="yes">✓</span><small>via homeserver proxy,<br>no direct CDN contact</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Presence avatar border ring<small>colored ring shows online status</small></td>
<td class="ours"><span class="yes">✓</span><small>green/yellow/red ring;<br>timeline, members, mentions</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Room emoji prefix<small>🎮 renders larger in sidebar</small></td>
<td class="ours"><span class="yes">✓</span><small>1.15× size; emoji picker<br>in all name inputs</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>Quick emoji reactions on hover<small>1-click react, no menu needed</small></td>
<td class="ours"><span class="yes">✓</span><small>3 recent emoji in hover bar;<br>dismisses emoji picker</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="part">~</span><small>hover bar, no recents</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>In-app notification toasts<small>TDS-styled, when window focused</small></td>
<td class="ours"><span class="yes">✓</span><small>slides in bottom-right;<br>4 s auto-dismiss, click to jump</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
<tr>
<td>On-device message translation<small>read foreign messages in your language</small></td>
<td class="ours"><span class="yes">✓</span><small>100% on-device browser AI;<br>works in E2EE rooms, no cloud;<br>Chromium desktop &amp; Lotus app</small></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
<td><span class="no">✗</span></td>
</tr>
</tbody>
</table>
<!-- END:comparison -->
</div><!-- table-wrap -->
<div class="security-note" style="margin:14px 16px 6px;">
<strong>Encryption architecture:</strong> Element X uses the native <strong>matrix-rust-sdk</strong> with Vodozemac. FluffyChat and Commet use <strong>matrix-dart-sdk</strong>, which also wraps Vodozemac for its crypto &mdash; all three benefit from Vodozemac's stronger security track record over the older JavaScript SDK. Cinny and Element Web/Desktop currently use <strong>matrix-js-sdk</strong>; Element is actively migrating to the Rust SDK. Clients using Vodozemac were not affected by historical js-sdk vulnerabilities.
</div>
<div class="legend">
<span><span class="yes">✓</span> Full support</span>
<span><span class="part">~</span> Partial / experimental</span>
<span><span class="no">✗</span> Not supported</span>
</div>
</div><!-- comparison-section -->
<!-- ── Server Details ── -->
<div class="server-info">
<p class="server-info-title">Server Details</p>
<div class="info-grid">
<div class="info-item">
<div class="info-label">Access</div>
<div class="info-value">Invite-only</div>
</div>
<div class="info-item">
<div class="info-label">Max Upload</div>
<div class="info-value">200 MB / file</div>
</div>
<div class="info-item">
<div class="info-label">Message History</div>
<div class="info-value">Kept indefinitely</div>
</div>
<div class="info-item">
<div class="info-label">Media Retention</div>
<div class="info-value">3 yr local &middot; 1 yr remote</div>
</div>
<div class="info-item">
<div class="info-label">Federation</div>
<div class="info-value">Fully federated</div>
</div>
<div class="info-item">
<div class="info-label">Minimum Age</div>
<div class="info-value">13+ (COPPA)</div>
</div>
</div>
<div class="privacy-strip">
<span class="privacy-badge">No ads or tracking</span>
<span class="privacy-badge">No data sold</span>
<span class="privacy-badge">E2EE &mdash; server cannot read encrypted rooms</span>
</div>
</div>
<div class="legal-note">
This service is provided "as-is" with no uptime guarantee. Not for emergency use &mdash; do not use to contact emergency services (e.g. 911). Use is governed by our <a href="https://wiki.lotusguild.org/en/Legal/terms-of-service" target="_blank" rel="noopener">Terms of Service</a> and <a href="https://wiki.lotusguild.org/en/Legal/privacy-policy" target="_blank" rel="noopener">Privacy Policy</a>. Governing law: State of Ohio, United States.
</div>
<div class="contact">
<p style="font-size:0.85rem;color:#777;margin-bottom:4px;">Questions or need a registration token?</p>
<p>Reach out to <code class="homeserver">@jared:matrix.lotusguild.org</code></p>
</div>
<p class="footer">
<a href="https://wiki.lotusguild.org/en/Services/service-matrix" target="_blank" rel="noopener">Wiki &amp; Setup Guide</a>
<span>&middot;</span>
<a href="https://wiki.lotusguild.org/en/Legal/privacy-policy" target="_blank" rel="noopener">Privacy Policy</a>
<span>&middot;</span>
<a href="https://wiki.lotusguild.org/en/Legal/terms-of-service" target="_blank" rel="noopener">Terms of Service</a>
<span>&middot;</span>
<span>Powered by Matrix &middot; E2E Encrypted</span>
</p>
</div><!-- container -->
<script>
// Show scroll hint only on touch devices; hide once table is scrolled
if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
var hint = document.getElementById('scrollHint');
if (hint) hint.style.display = 'block';
var wrap = hint && hint.nextElementSibling;
if (wrap) wrap.addEventListener('scroll', function hide() {
hint.style.display = 'none';
wrap.removeEventListener('scroll', hide);
}, { passive: true });
}
</script>
</body>
</html>