From 709c0022f0321e6bd5809c1adb669c28128397fe Mon Sep 17 00:00:00 2001
From: defnax <9952056+defnax@users.noreply.github.com>
Date: Thu, 30 Jul 2026 23:56:39 +0200
Subject: [PATCH] Improved Channels for Phone & Desktop
Fixed channels thumbnail layout issue
Added same comments design from boards to channels
---
webui-src/app/boards/board_kanban.js | 25 +-
webui-src/app/boards/board_view.js | 43 +-
webui-src/app/boards/boards_util.js | 17 +-
webui-src/app/channels/channel_view.js | 392 +-
webui-src/app/channels/channels_util.js | 4 +-
webui-src/app/people/people_util.js | 20 +-
webui-src/app/scss/pages/_board.scss | 17 +-
webui-src/app/scss/pages/_channel.scss | 110 +
webui-src/styles.css | 6098 +++++++++++++++++++++++
9 files changed, 6559 insertions(+), 167 deletions(-)
diff --git a/webui-src/app/boards/board_kanban.js b/webui-src/app/boards/board_kanban.js
index cbc742c..32c89ae 100644
--- a/webui-src/app/boards/board_kanban.js
+++ b/webui-src/app/boards/board_kanban.js
@@ -13,24 +13,15 @@ function numberValue(value) {
* Fallback SVG Thumbnail when no image is available
*/
const FallbackImage = () =>
- m(
- 'svg.board-card__placeholder-img',
- {
- xmlns: 'http://www.w3.org/2000/svg',
- viewBox: '0 0 24 24',
- fill: 'none',
- stroke: 'currentColor',
- strokeWidth: '1.5',
- strokeLinecap: 'round',
- strokeLinejoin: 'round',
- 'aria-hidden': 'true',
+ m('.board-card__placeholder-content', {
+ style: {
+ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
+ gap: '.3rem', color: '#64748b', fontSize: '.72rem', fontWeight: '600', textAlign: 'center',
},
- [
- m('rect', { x: '3', y: '3', width: '18', height: '18', rx: '2', ry: '2' }),
- m('circle', { cx: '8.5', cy: '8.5', r: '1.5' }),
- m('polyline', { points: '21 15 16 10 5 21' }),
- ]
- );
+ }, [
+ m('i.fas.fa-image[aria-hidden=true]', { style: { fontSize: '1.35rem' } }),
+ m('span', 'No image'),
+ ]);
/**
* Check if notes string contains non-whitespace text
diff --git a/webui-src/app/boards/board_view.js b/webui-src/app/boards/board_view.js
index 5229af1..9cc4041 100644
--- a/webui-src/app/boards/board_view.js
+++ b/webui-src/app/boards/board_view.js
@@ -3,6 +3,7 @@ const util = require('boards/boards_util');
const boardKanban = require('boards/board_kanban');
const rs = require('rswebui');
const peopleUtil = require('people/people_util');
+const chatEmoji = require('chat/chat_emoji');
const Data = util.Data;
function createboard() {
@@ -275,10 +276,13 @@ function PostView() {
let loadingComments = true;
let identities = [];
let authorId = null;
+ let voteIdentity = null;
let replyTo = null;
let composerText = '';
let submitting = false;
let submitError = '';
+ let notesExpanded = false;
+ let showEmojiPicker = false;
const expandedReplies = {};
const metaOf = (comment) => (comment && comment.mMeta) || {};
@@ -372,6 +376,7 @@ function PostView() {
peopleUtil.ownIds((ids) => {
identities = (ids || []).filter((id) => Number(id) !== 0);
authorId = identities[0] || null;
+ voteIdentity = identities[0] || null;
m.redraw();
});
},
@@ -384,6 +389,7 @@ function PostView() {
const title = meta.mMsgName || p.mMsgName || p.title || 'Post';
const notes = util.plainText(p.mNotes || p.mBody || p.notes || p.body || '');
+ const hasLongNotes = notes.length > 280;
const author = meta.mAuthorId ? meta.mAuthorId.substring(0, 10) : 'Unknown';
const publishTs = meta.mPublishTs || p.mPublishTs || null;
const dateStr = publishTs
@@ -425,26 +431,46 @@ function PostView() {
m('b', author),
dateStr ? m('span', ` • ${dateStr}`) : null,
]),
- notes ? m('p', { style: { whiteSpace: 'pre-wrap', margin: '1rem 0' } }, notes) : null,
+ notes ? m('.post-description.board-post-description', [
+ m('.post-description__text', { class: notesExpanded ? '' : 'post-description__text--collapsed', style: { whiteSpace: 'pre-wrap', maxHeight: notesExpanded ? 'none' : '4.5em', overflow: 'hidden', lineHeight: '1.5' } }, notes),
+ hasLongNotes ? m('button.post-description__toggle[type=button]', { onclick: () => { notesExpanded = !notesExpanded; } }, notesExpanded ? 'Show less' : '…more') : null,
+ ]) : null,
m('hr'),
m('.board-comments', [
- m('.board-comments__heading', [m('h3', `${comments.length} Comment${comments.length === 1 ? '' : 's'}`), m('span', [m('i.fas.fa-sort-amount-down'), ' Oldest first'])]),
+ m('.board-comments__heading', [
+ m('h3', `${comments.length} Comment${comments.length === 1 ? '' : 's'}`),
+ m('span', [m('i.fas.fa-sort-amount-down'), ' Oldest first']),
+ m('.board-comments__voter', [
+ m('label[for=board-comment-voter]', 'Voter identity'),
+ m('select#board-comment-voter', {
+ value: voteIdentity || '',
+ disabled: identities.length === 0,
+ onchange: (e) => { voteIdentity = e.target.value; },
+ }, identities.length
+ ? identities.map((id) => m('option', { value: id }, nameOf(id)))
+ : m('option', { value: '' }, 'Loading identities…')),
+ ]),
+ ]),
m('.board-comment-composer', [
m('.board-comment-avatar', initials(nameOf(authorId))),
m('.board-comment-composer__body', [
replyTo ? m('.board-comment-composer__replying', ['Replying to ', m('b', nameOf(metaOf(replyTo).mAuthorId)), m('button[type=button][aria-label=Cancel reply]', { onclick: () => { replyTo = null; composerText = ''; } }, m('i.fas.fa-times'))]) : null,
- identities.length > 1 ? m('select.board-comment-composer__identity', { value: authorId, onchange: (e) => { authorId = e.target.value; } }, identities.map((id) => m('option', { value: id }, nameOf(id)))) : null,
+ identities.length ? m('select.board-comment-composer__identity', { value: authorId, onchange: (e) => { authorId = e.target.value; } }, identities.map((id) => m('option', { value: id }, nameOf(id)))) : null,
m('textarea.board-comment-composer__input[rows=1][placeholder=Add a comment…]', { value: composerText, disabled: !authorId || submitting, oninput: (e) => { composerText = e.target.value; }, onkeydown: (e) => { if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') submitComment(forumId, msgId); } }),
!authorId ? m('p.board-comment-composer__hint', 'Create or select an identity to post a comment.') : null,
submitError ? m('p.board-comment-composer__error', submitError) : null,
m('.board-comment-composer__actions', [
+ m('.board-comment-composer__emoji', { style: { position: 'relative', marginRight: 'auto' } }, [
+ m('button[type=button][title=Insert emoji][aria-label=Insert emoji]', { style: { width: '32px', height: '32px', padding: '0', borderRadius: '50%', border: '0', boxShadow: 'none', background: showEmojiPicker ? '#e0f2fe' : 'transparent', color: '#475569', fontSize: '1.15rem' }, onclick: () => { showEmojiPicker = !showEmojiPicker; } }, m('i.fas.fa-smile')),
+ showEmojiPicker ? m('.board-comment-emoji-popover', { style: { position: 'absolute', zIndex: '20', top: '38px', left: '0', width: '250px', maxHeight: '180px', overflowY: 'auto', padding: '.5rem', display: 'grid', gridTemplateColumns: 'repeat(8, 1fr)', gap: '.2rem', background: '#fff', border: '1px solid #cbd5e1', borderRadius: '8px', boxShadow: '0 8px 20px rgba(0,0,0,.16)' } }, chatEmoji.EMOJI_DATA.Smileys.slice(0, 48).map((emoji) => m('button[type=button]', { style: { width: '28px', height: '28px', padding: '0', border: '0', boxShadow: 'none', background: 'transparent', fontSize: '1.1rem' }, onclick: () => { composerText += emoji; showEmojiPicker = false; } }, emoji))) : null,
+ ]),
composerText || replyTo ? m('button.board-comment-composer__cancel[type=button]', { onclick: () => { composerText = ''; replyTo = null; submitError = ''; } }, 'Cancel') : null,
m('button.board-comment-composer__submit[type=button]', { disabled: !composerText.trim() || !authorId || submitting, onclick: () => submitComment(forumId, msgId) }, submitting ? 'Posting…' : 'Comment')
])
])
]),
loadingComments ? m('.board-comments__status', [m('i.fas.fa-spinner.fa-spin'), ' Loading comments…'])
- : comments.length === 0 ? m('.board-comments__empty', [m('i.far.fa-comment'), m('p', 'No comments yet. Start the conversation.')])
+ : comments.length === 0 ? m('.board-comments__empty', [m('i.fas.fa-comment'), m('p', 'No comments yet. Start the conversation.')])
: m('.board-comments__list', treeOfComments().map((node) => renderComment(node, 0))),
]),
]),
@@ -468,7 +494,14 @@ function PostView() {
]),
m('p.board-comment__text', textOf(comment)),
m('.board-comment__actions', [
- m('span.board-comment__like', [m('i.far.fa-thumbs-up'), ' Like']),
+ m('button[type=button]', {
+ disabled: !voteIdentity,
+ onclick: () => util.voteForPost(forumId, key, util.GXS_VOTE_UP, voteIdentity),
+ }, [m('i.fas.fa-thumbs-up'), ` ${comment.mUpVotes || 0}`]),
+ m('button[type=button]', {
+ disabled: !voteIdentity,
+ onclick: () => util.voteForPost(forumId, key, util.GXS_VOTE_DOWN, voteIdentity),
+ }, m('i.fas.fa-thumbs-down')),
m('button[type=button]', { onclick: () => { replyTo = comment; composerText = ''; submitError = ''; } }, 'Reply')
]),
repliesCount ? m('button.board-comment__replies-toggle[type=button]', {
diff --git a/webui-src/app/boards/boards_util.js b/webui-src/app/boards/boards_util.js
index 7002920..74225b7 100644
--- a/webui-src/app/boards/boards_util.js
+++ b/webui-src/app/boards/boards_util.js
@@ -245,15 +245,18 @@ function popupmessage(message) {
);
}
-async function voteForPost(postGrpId, postMsgId, voteType) {
+async function voteForPost(postGrpId, postMsgId, voteType, voterId = null) {
try {
- const resId = await rs.rsJsonApiRequest('/rsIdentity/getOwnIds', {});
- const ownIds = (resId && resId.body && resId.body.ids) ? resId.body.ids : [];
- if (ownIds.length === 0) {
- alert('No identity found to vote.');
- return false;
+ let authorId = voterId;
+ if (!authorId) {
+ const resId = await rs.rsJsonApiRequest('/rsIdentity/getOwnIds', {});
+ const ownIds = (resId && resId.body && resId.body.ids) ? resId.body.ids : [];
+ if (ownIds.length === 0) {
+ alert('No identity found to vote.');
+ return false;
+ }
+ authorId = ownIds[0];
}
- const authorId = ownIds[0];
const res = await rs.rsJsonApiRequest('/rsPosted/voteForPost', {
postGrpId: postGrpId,
diff --git a/webui-src/app/channels/channel_view.js b/webui-src/app/channels/channel_view.js
index 81adda2..0ca79df 100644
--- a/webui-src/app/channels/channel_view.js
+++ b/webui-src/app/channels/channel_view.js
@@ -7,6 +7,7 @@ const peopleUtil = require('people/people_util');
const sha1 = require('channels/sha1');
const fileUtil = require('files/files_util');
const fileDown = require('files/files_downloads');
+const chatEmoji = require('chat/chat_emoji');
const filesUploadHashes = {
// figure out a better way later.
@@ -14,6 +15,29 @@ const filesUploadHashes = {
Thumbnail: [],
};
+function channelThumbnailSrc(post) {
+ const thumbnail = post && (post.mThumbnail || post.thumbnail || post.mImage);
+ const base64 = thumbnail && thumbnail.mData && thumbnail.mData.base64
+ ? thumbnail.mData.base64
+ : typeof thumbnail === 'string'
+ ? thumbnail
+ : thumbnail && thumbnail.base64;
+ if (!base64 || !String(base64).trim()) return '';
+ return String(base64).startsWith('data:') ? base64 : `data:image/png;base64,${base64}`;
+}
+
+const ChannelFallbackThumbnail = () => ({
+ view: (vnode) => m('.channel-post__placeholder', { style: {
+ display: vnode.attrs.hidden ? 'none' : 'flex', flex: '1 1 auto', minHeight: '0',
+ flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: '.35rem',
+ color: '#64748b', background: 'linear-gradient(135deg, #f8fafc, #dbe5f1)',
+ } }, [
+ m('i.fas.fa-image[aria-hidden=true]', { style: { fontSize: '1.35rem', color: '#64748b' } }),
+ m('span', { style: { fontSize: '2rem', fontWeight: '700', color: '#2563eb' } }, (vnode.attrs.title || 'Post').trim().slice(0, 1).toUpperCase()),
+ m('small', { style: { fontSize: '.72rem', fontWeight: '600' } }, 'No image'),
+ ]),
+});
+
async function parsefile(file, type) {
const fileSize = file.size;
const chunkSize = 1024 * 1024; // bytes
@@ -428,7 +452,14 @@ const ChannelView = () => {
m(
'.posts-container-card',
{
- style: 'display: ' + (plist[key].isSearched ? 'flex' : 'none'), // for search
+ style: {
+ display: plist[key].isSearched ? 'flex' : 'none', // for search
+ height: '240px',
+ minHeight: '0',
+ overflow: 'hidden',
+ flexDirection: 'column',
+ alignSelf: 'start',
+ },
onclick: () => {
m.route.set('/channels/:tab/:mGroupId/:mMsgId', {
tab: m.route.param().tab,
@@ -438,13 +469,19 @@ const ChannelView = () => {
},
},
[
- m('img', {
- src:
- plist[key].post.mThumbnail.mData.base64 === ''
- ? 'data/streaming.png'
- : 'data:image/png;base64,' + plist[key].post.mThumbnail.mData.base64,
- alt: 'No Thumbnail',
- }),
+ channelThumbnailSrc(plist[key].post)
+ ? [
+ m('img', {
+ src: channelThumbnailSrc(plist[key].post),
+ alt: plist[key].post.mMeta.mMsgName || 'Post thumbnail',
+ onerror: (e) => {
+ e.target.style.display = 'none';
+ if (e.target.nextSibling) e.target.nextSibling.style.display = 'flex';
+ },
+ }),
+ m(ChannelFallbackThumbnail, { title: plist[key].post.mMeta.mMsgName, hidden: true }),
+ ]
+ : m(ChannelFallbackThumbnail, { title: plist[key].post.mMeta.mMsgName }),
m('p', plist[key].post.mMeta.mMsgName),
]
),
@@ -665,20 +702,156 @@ function displaycomment() {
};
}
+/* Modern threaded comment experience for channel posts. */
+const ChannelComments = () => {
+ let replyTo = null;
+ let text = '';
+ let identity = null;
+ let submitting = false;
+ let error = '';
+ let showEmojiPicker = false;
+ const expandedReplies = {};
+
+ const metaOf = (comment) => (comment && comment.mMeta) || {};
+ const idOf = (comment) => metaOf(comment).mMsgId || comment.msgId;
+ const nameOf = (id) => rs.userList.username(id) || rs.userList.userMap[id] || `${String(id || 'Unknown').slice(0, 10)}…`;
+ const initials = (name) => String(name || '?').split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]).join('').toUpperCase();
+ const dateOf = (value) => {
+ const seconds = value && typeof value === 'object' ? value.xint64 : value;
+ return Number(seconds) ? new Date(Number(seconds) * 1000).toLocaleString() : '';
+ };
+
+ function tree(threadId) {
+ const nodes = {};
+ const roots = [];
+ Object.keys(Data.Comments[threadId] || {}).forEach((key) => {
+ const entry = Data.Comments[threadId][key];
+ const comment = entry.comment || entry;
+ if (idOf(comment)) nodes[idOf(comment)] = { comment, children: [] };
+ });
+ Object.keys(nodes).forEach((key) => {
+ const node = nodes[key];
+ const parent = metaOf(node.comment).mParentId;
+ if (parent && parent !== threadId && nodes[parent]) nodes[parent].children.push(node);
+ else roots.push(node);
+ });
+ const chronological = (a, b) => Number(metaOf(a.comment).mPublishTs && (metaOf(a.comment).mPublishTs.xint64 || metaOf(a.comment).mPublishTs)) - Number(metaOf(b.comment).mPublishTs && (metaOf(b.comment).mPublishTs.xint64 || metaOf(b.comment).mPublishTs));
+ roots.sort(chronological);
+ Object.keys(nodes).forEach((key) => nodes[key].children.sort(chronological));
+ return roots;
+ }
+
+ async function submit(vnode) {
+ const comment = text.trim();
+ if (!comment || !identity || submitting) return;
+ submitting = true;
+ error = '';
+ try {
+ const res = await rs.rsJsonApiRequest('/rsgxschannels/createCommentV2', {
+ channelId: vnode.attrs.channelId,
+ threadId: vnode.attrs.threadId,
+ comment,
+ authorId: identity,
+ parentId: replyTo ? idOf(replyTo) : vnode.attrs.threadId,
+ });
+ if (!res || !res.body || res.body.retval === false) {
+ error = (res && res.body && res.body.errorMessage) || 'Your comment could not be posted.';
+ return;
+ }
+ text = '';
+ replyTo = null;
+ await util.updatedisplaychannels(vnode.attrs.channelId);
+ } catch (submitError) {
+ console.warn('Channel comment submission failed', submitError);
+ error = 'Your comment could not be posted. Please try again.';
+ } finally {
+ submitting = false;
+ m.redraw();
+ }
+ }
+
+ function renderComment(node, vnode) {
+ const comment = node.comment;
+ const meta = metaOf(comment);
+ const id = idOf(comment);
+ const name = nameOf(meta.mAuthorId);
+ const votes = (Data.Votes[meta.mThreadId] && Data.Votes[meta.mThreadId][id]) || { upvotes: 0, downvotes: 0 };
+ const repliesExpanded = expandedReplies[id] === true;
+ return m('.board-comment', { key: id }, [
+ m('.board-comment-avatar', initials(name)),
+ m('.board-comment__content', [
+ m('.board-comment__header', [
+ m('.board-comment__meta', [m('b', name), dateOf(meta.mPublishTs) ? m('span', dateOf(meta.mPublishTs)) : null]),
+ m('button.board-comment__menu[type=button][aria-label=Comment options]', m('i.fas.fa-ellipsis-v')),
+ ]),
+ m('p.board-comment__text', comment.mComment || comment.comment || ''),
+ m('.board-comment__actions', [
+ m('button[type=button]', { disabled: !vnode.attrs.voteIdentity, onclick: () => addvote(util.GXS_VOTE_UP, vnode.attrs.channelId, vnode.attrs.threadId, vnode.attrs.voteIdentity, id) }, [m('i.fas.fa-thumbs-up'), ` ${votes.upvotes || 0}`]),
+ m('button[type=button]', { disabled: !vnode.attrs.voteIdentity, onclick: () => addvote(util.GXS_VOTE_DOWN, vnode.attrs.channelId, vnode.attrs.threadId, vnode.attrs.voteIdentity, id) }, m('i.fas.fa-thumbs-down')),
+ m('button[type=button]', { onclick: () => { replyTo = comment; text = ''; error = ''; } }, 'Reply'),
+ ]),
+ node.children.length ? m('button.board-comment__replies-toggle[type=button]', { 'aria-expanded': repliesExpanded, onclick: () => { expandedReplies[id] = !repliesExpanded; } }, [`${node.children.length} ${node.children.length === 1 ? 'reply' : 'replies'} `, m('i.fas', { class: repliesExpanded ? 'fa-chevron-up' : 'fa-chevron-down' })]) : null,
+ node.children.length && repliesExpanded ? m('.board-comment__replies', node.children.map((child) => renderComment(child, vnode))) : null,
+ ]),
+ ]);
+ }
+
+ return {
+ view: (vnode) => {
+ const identities = (vnode.attrs.identities || []).filter((id) => Number(id) !== 0);
+ if (!identity && identities.length) identity = identities[0];
+ const comments = tree(vnode.attrs.threadId);
+ return m('.board-comments.channel-comments', [
+ m('.board-comments__heading', [
+ m('h3', `${Object.keys(Data.Comments[vnode.attrs.threadId] || {}).length} Comment${Object.keys(Data.Comments[vnode.attrs.threadId] || {}).length === 1 ? '' : 's'}`),
+ m('span', [m('i.fas.fa-sort-amount-down'), ' Oldest first']),
+ m('.board-comments__voter', [
+ m('label[for=channel-comment-voter]', 'Voter identity'),
+ m('select#channel-comment-voter', {
+ value: vnode.attrs.voteIdentity || '',
+ disabled: identities.length === 0,
+ onchange: (e) => vnode.attrs.onVoteIdentity(e.target.value),
+ }, identities.length
+ ? identities.map((id) => m('option', { value: id }, nameOf(id)))
+ : m('option', { value: '' }, vnode.attrs.identitiesLoading ? 'Loading identities…' : 'No identity available')),
+ ]),
+ ]),
+ m('.board-comment-composer', [
+ m('.board-comment-avatar', initials(nameOf(identity))),
+ m('.board-comment-composer__body', [
+ replyTo ? m('.board-comment-composer__replying', ['Replying to ', m('b', nameOf(metaOf(replyTo).mAuthorId)), m('button[type=button][aria-label=Cancel reply]', { onclick: () => { replyTo = null; text = ''; } }, m('i.fas.fa-times'))]) : null,
+ identities.length ? m('select.board-comment-composer__identity', { value: identity, onchange: (e) => { identity = e.target.value; } }, identities.map((id) => m('option', { value: id }, nameOf(id)))) : null,
+ m('textarea.board-comment-composer__input[rows=1][placeholder=Add a comment…]', { value: text, disabled: !identity || submitting, oninput: (e) => { text = e.target.value; }, onkeydown: (e) => { if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') submit(vnode); } }),
+ !identity ? m('p.board-comment-composer__hint', vnode.attrs.identitiesLoading ? 'Loading identities…' : 'Create or select an identity to post a comment.') : null,
+ error ? m('p.board-comment-composer__error', error) : null,
+ m('.board-comment-composer__actions', [
+ m('.board-comment-composer__emoji', { style: { position: 'relative', marginRight: 'auto' } }, [
+ m('button[type=button][title=Insert emoji][aria-label=Insert emoji]', { style: { width: '32px', height: '32px', padding: '0', borderRadius: '50%', border: '0', boxShadow: 'none', background: showEmojiPicker ? '#e0f2fe' : 'transparent', color: '#475569', fontSize: '1.15rem' }, onclick: () => { showEmojiPicker = !showEmojiPicker; } }, m('i.fas.fa-smile')),
+ showEmojiPicker ? m('.board-comment-emoji-popover', { style: { position: 'absolute', zIndex: '20', top: '38px', left: '0', width: '250px', maxHeight: '180px', overflowY: 'auto', padding: '.5rem', display: 'grid', gridTemplateColumns: 'repeat(8, 1fr)', gap: '.2rem', background: '#fff', border: '1px solid #cbd5e1', borderRadius: '8px', boxShadow: '0 8px 20px rgba(0,0,0,.16)' } }, chatEmoji.EMOJI_DATA.Smileys.slice(0, 48).map((emoji) => m('button[type=button]', { style: { width: '28px', height: '28px', padding: '0', border: '0', boxShadow: 'none', background: 'transparent', fontSize: '1.1rem' }, onclick: () => { text += emoji; showEmojiPicker = false; } }, emoji))) : null,
+ ]),
+ text || replyTo ? m('button.board-comment-composer__cancel[type=button]', { onclick: () => { text = ''; replyTo = null; error = ''; } }, 'Cancel') : null,
+ m('button.board-comment-composer__submit[type=button]', { disabled: !text.trim() || !identity || submitting, onclick: () => submit(vnode) }, submitting ? 'Posting…' : 'Comment'),
+ ]),
+ ]),
+ ]),
+ comments.length ? m('.board-comments__list', comments.map((node) => renderComment(node, vnode))) : m('.board-comments__empty', [m('i.fas.fa-comment'), m('p', 'No comments yet. Start the conversation.')]),
+ ]);
+ },
+ };
+};
+
const PostView = () => {
let post = {};
- let topComments = {};
const filesInfo = {};
let voteIdentity;
let ownId;
+ let identitiesLoading = true;
+ let messageExpanded = false;
return {
oninit: async (v) => {
if (Data.Posts[v.attrs.channelId] && Data.Posts[v.attrs.channelId][v.attrs.msgId]) {
post = Data.Posts[v.attrs.channelId][v.attrs.msgId].post;
}
- if (Data.TopComments[v.attrs.msgId]) {
- topComments = Data.TopComments[v.attrs.msgId]; // get all the top level parent comments
- }
if (post) {
post.mFiles.map(async (file) => {
const res = await rs.rsJsonApiRequest('/rsfiles/alreadyHaveFile', {
@@ -696,10 +869,16 @@ const PostView = () => {
}
}
voteIdentity = ownId[0];
+ identitiesLoading = false;
});
fileDown.Downloads.loadStatus(); // for retrieving downloading files.
},
- view: (v) => [
+ view: (v) => {
+ const message = post.mMsg || '';
+ const messageText = String(message).replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
+ const hasEmbeddedImage = /
280 || hasEmbeddedImage;
+ return [
m(
'a[title=Back]',
{
@@ -713,7 +892,19 @@ const PostView = () => {
),
m('.widget__heading', m('h3', post.mMeta.mMsgName)),
m('.widget__body', [
- m('p', { style: { whiteSpace: 'normal' } }, m.trust(post.mMsg)),
+ message ? m('.post-description', [
+ m('.post-description__text', {
+ style: {
+ maxHeight: messageExpanded ? 'none' : '4.5em',
+ overflow: 'hidden',
+ lineHeight: '1.5',
+ },
+ }, m.trust(message)),
+ hasLongMessage ? m('button.post-description__toggle[type=button]', {
+ style: { marginTop: '.35rem', padding: '0', border: '0', boxShadow: 'none', background: 'transparent', color: '#0f172a', fontSize: '.85rem', fontWeight: '700' },
+ onclick: () => { messageExpanded = !messageExpanded; },
+ }, messageExpanded ? 'Show less' : '…more') : null,
+ ]) : null,
m('.file-section', [
m('h3', 'Files(' + post.mAttachmentCount + ')'),
m(
@@ -722,132 +913,77 @@ const PostView = () => {
'tbody',
post.mFiles.map((file) =>
m('tr', [
- m('td', file.mName),
- m('td', rs.formatBytes(file.mSize.xint64)),
- m(
- 'button',
- {
- style: { fontSize: '0.9em' },
- onclick: async () =>
- widget.popupMessage([
- m('p', 'Start Download?'),
- m(
- 'button',
- {
- onclick: async () => {
- if (filesInfo[file.mHash] && !filesInfo[file.mHash].retval) {
- const res = await rs.rsJsonApiRequest('/rsFiles/FileRequest', {
- fileName: file.mName,
- hash: file.mHash,
- flags: util.RS_FILE_REQ_ANONYMOUS_ROUTING,
- size: {
- xstr64: file.mSize.xstr64,
- },
- });
- res.body.retval === false
- ? widget.popupMessage([
- m('h3', 'Error'),
- m('hr'),
- m('p', res.body.errorMessage),
- ])
- : widget.popupMessage([
- m('h3', 'Success'),
- m('hr'),
- m('p', 'Download Started'),
- ]);
- m.redraw();
- }
+ m('td.channel-file__name[data-label=File name]', file.mName),
+ m('td.channel-file__size[data-label=Size]', rs.formatBytes(file.mSize.xint64)),
+ m('td.channel-file__action[data-label=Download]', [
+ m(
+ 'button',
+ {
+ style: { fontSize: '0.9em' },
+ onclick: async () =>
+ widget.popupMessage([
+ m('p', 'Start Download?'),
+ m(
+ 'button',
+ {
+ onclick: async () => {
+ if (filesInfo[file.mHash] && !filesInfo[file.mHash].retval) {
+ const res = await rs.rsJsonApiRequest('/rsFiles/FileRequest', {
+ fileName: file.mName,
+ hash: file.mHash,
+ flags: util.RS_FILE_REQ_ANONYMOUS_ROUTING,
+ size: {
+ xstr64: file.mSize.xstr64,
+ },
+ });
+ res.body.retval === false
+ ? widget.popupMessage([
+ m('h3', 'Error'),
+ m('hr'),
+ m('p', res.body.errorMessage),
+ ])
+ : widget.popupMessage([
+ m('h3', 'Success'),
+ m('hr'),
+ m('p', 'Download Started'),
+ ]);
+ m.redraw();
+ }
+ },
},
- },
- 'Start Download'
- ),
- ]),
- },
- filesInfo[file.mHash]
- ? filesInfo[file.mHash].retval
- ? 'Open File'
- : ['Download', m('i.fas.fa-download')]
- : 'Please Wait...'
- ),
- fileDown.list[file.mHash] && // using the file from files_util to display download.
- m(fileUtil.File, {
+ 'Start Download'
+ ),
+ ]),
+ },
+ filesInfo[file.mHash]
+ ? filesInfo[file.mHash].retval
+ ? 'Open File'
+ : ['Download ', m('i.fas.fa-download')]
+ : 'Please Wait...'
+ ),
+ fileDown.list[file.mHash] && m(fileUtil.File, {
info: fileDown.list[file.mHash],
direction: 'down',
transferred: fileDown.list[file.mHash].transfered.xint64,
parts: [],
}),
+ ]),
])
)
)
),
]),
- m('.comments-section', [
- m('h3', 'Comments'),
- m('.comments-section__menu', [
- m(
- 'button',
- {
- onclick: () => {
- widget.popupMessage(
- m(AddComment, {
- parent_comment: '',
- channelId: v.attrs.channelId,
- authorId: ownId,
- threadId: v.attrs.msgId,
- parentId: v.attrs.msgId,
- })
- );
- },
- },
- 'Add Comment'
- ),
- m('.comments-section__menu-id', [
- m('label[for=idtags', 'Voter ID: '),
- m(
- 'select[id=idtags]',
- {
- value: voteIdentity,
- onchange: (e) => {
- voteIdentity = ownId[e.target.selectedIndex];
- },
- },
- [
- ownId &&
- ownId.map((o) =>
- m(
- 'option',
- { value: o },
- `${rs.userList.userMap[o].toLocaleString()} (${o.slice(0, 8)}...)`
- )
- ),
- ]
- ),
- ]),
- ]),
- ]),
- m(
- util.CommentsTable,
- m(
- 'tbody',
- Object.keys(topComments).map((key, index) =>
- Data.Comments[topComments[key].mMeta.mThreadId] &&
- Data.Comments[topComments[key].mMeta.mThreadId][topComments[key].mMeta.mMsgId]
- ? m(displaycomment, {
- // calls the recursive function for all the parents.
- identity: ownId,
- voteIdentity,
- commentStruct:
- Data.Comments[topComments[key].mMeta.mThreadId][
- topComments[key].mMeta.mMsgId
- ],
- replyDepth: 0,
- })
- : ''
- )
- )
- ),
+ m(ChannelComments, {
+ channelId: v.attrs.channelId,
+ threadId: v.attrs.msgId,
+ identities: ownId,
+ voteIdentity,
+ identitiesLoading,
+ onVoteIdentity: (id) => { voteIdentity = id; },
+ }),
]),
- ],
+ ];
+ },
};
};
diff --git a/webui-src/app/channels/channels_util.js b/webui-src/app/channels/channels_util.js
index 9e272d8..022d94b 100644
--- a/webui-src/app/channels/channels_util.js
+++ b/webui-src/app/channels/channels_util.js
@@ -173,8 +173,8 @@ const FilesTable = () => {
return {
oninit: (v) => {},
view: (v) =>
- m('table.files', [
- m('tr', [m('th', 'File Name'), m('th', 'Size'), m('th', m('i.fas.fa-download'))]),
+ m('table.files.channel-files', [
+ m('thead', m('tr', [m('th', 'File Name'), m('th', 'Size'), m('th', m('i.fas.fa-download'))])),
v.children,
]),
};
diff --git a/webui-src/app/people/people_util.js b/webui-src/app/people/people_util.js
index c14e9a9..6a764ce 100644
--- a/webui-src/app/people/people_util.js
+++ b/webui-src/app/people/people_util.js
@@ -137,15 +137,21 @@ function sortIds(list) {
}
async function ownIds(consumer = () => { }, onlySigned = false) {
- await rs.rsJsonApiRequest('/rsIdentity/getOwnSignedIds', {}, (owns) => {
+ try {
+ const signedResponse = await rs.rsJsonApiRequest('/rsIdentity/getOwnSignedIds', {});
+ const signedIds = (signedResponse && signedResponse.body && signedResponse.body.ids) || [];
if (onlySigned) {
- consumer(sortIds(owns.ids));
- } else {
- rs.rsJsonApiRequest('/rsIdentity/getOwnPseudonimousIds', {}, (pseudo) => {
- if (pseudo.ids) consumer(sortIds(pseudo.ids.concat(owns.ids)));
- });
+ consumer(sortIds(signedIds));
+ return;
}
- });
+
+ const pseudonymousResponse = await rs.rsJsonApiRequest('/rsIdentity/getOwnPseudonimousIds', {});
+ const pseudonymousIds = (pseudonymousResponse && pseudonymousResponse.body && pseudonymousResponse.body.ids) || [];
+ consumer(sortIds(pseudonymousIds.concat(signedIds)));
+ } catch (error) {
+ console.warn('Unable to load own identities', error);
+ consumer([]);
+ }
}
const SearchBar = () => {
let searchString = '';
diff --git a/webui-src/app/scss/pages/_board.scss b/webui-src/app/scss/pages/_board.scss
index b47e628..b94937d 100644
--- a/webui-src/app/scss/pages/_board.scss
+++ b/webui-src/app/scss/pages/_board.scss
@@ -240,6 +240,8 @@
.board-comments__heading h3 { margin: 0; font-size: 1.15rem; }
.board-comments__heading span { color: #64748b; font-size: .8rem; font-weight: 600; }
.board-comments__heading i { margin-right: .35rem; }
+.board-comments__voter { display: inline-flex; align-items: center; gap: .4rem; margin-left: auto; color: #64748b; font-size: .75rem; font-weight: 600; white-space: nowrap; }
+.board-comments__voter select { max-width: 180px; padding: .25rem .4rem; font-size: .78rem; }
.board-comment-composer,
.board-comment {
@@ -355,7 +357,9 @@
.board-comments__empty i { font-size: 1.5rem; }
@media (max-width: 560px) {
- .board-comments__heading { justify-content: space-between; }
+ .board-comments__heading { flex-wrap: wrap; justify-content: space-between; gap: .5rem; }
+ .board-comments__voter { width: 100%; margin-left: 0; }
+ .board-comments__voter select { flex: 1; max-width: none; }
.board-comment-composer, .board-comment { gap: .6rem; }
.board-comment-avatar { flex-basis: 32px; width: 32px; height: 32px; font-size: .68rem; }
.board-comment__replies { padding-left: .6rem; }
@@ -604,6 +608,17 @@ button.board-card__vote-btn,
background: linear-gradient(135deg, #e2e8f0 0%, #cbd5e1 100%) !important;
}
+.board-card__placeholder-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: .3rem;
+ color: #64748b;
+ font-size: .72rem;
+ font-weight: 600;
+}
+.board-card__placeholder-content i { font-size: 1.35rem; }
+
.board-card--compact .board-card__placeholder-img {
width: 24px !important;
height: 24px !important;
diff --git a/webui-src/app/scss/pages/_channel.scss b/webui-src/app/scss/pages/_channel.scss
index 962f99d..0179a89 100644
--- a/webui-src/app/scss/pages/_channel.scss
+++ b/webui-src/app/scss/pages/_channel.scss
@@ -78,6 +78,116 @@ table {
}
}
}
+
+.posts-container-card .channel-post__placeholder {
+ flex: 1 1 auto;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: .35rem;
+ color: #64748b;
+ background: linear-gradient(135deg, #f8fafc, #dbe5f1);
+}
+.channel-post__placeholder i { font-size: 1.35rem; color: #64748b; }
+.channel-post__placeholder span { font-size: 2rem; font-weight: 700; color: #2563eb; }
+.channel-post__placeholder small { font-size: .72rem; font-weight: 600; }
+
+/* Compact YouTube-style post description with an opt-in expansion control. */
+.post-description {
+ margin: 1rem 0;
+ padding: .85rem 1rem;
+ border-radius: 10px;
+ background: #f1f5f9;
+ color: #1e293b;
+}
+.post-description__text { overflow-wrap: anywhere; line-height: 1.5; }
+.post-description__text > :first-child { margin-top: 0; }
+.post-description__text > :last-child { margin-bottom: 0; }
+.post-description__text--collapsed {
+ display: -webkit-box;
+ overflow: hidden;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+}
+.post-description__toggle {
+ margin-top: .35rem;
+ padding: 0 !important;
+ border: 0 !important;
+ box-shadow: none !important;
+ background: transparent !important;
+ color: #0f172a !important;
+ font-size: .85rem !important;
+ font-weight: 700 !important;
+}
+.post-description__toggle:hover { color: #2563eb !important; text-decoration: underline; }
+
+/* Keep image and generated-thumbnail cards the same size instead of stretching
+ * a sparse grid row to the full height of the Posts panel. */
+.posts-container { align-content: start; grid-auto-rows: 240px; }
+.posts-container-card { height: 240px; min-height: 0; overflow: hidden; }
+.posts-container-card > img,
+.posts-container-card > .channel-post__placeholder { min-height: 0; }
+
+@media (max-width: 700px) {
+ .posts-container { grid-auto-rows: 210px; gap: 1rem; }
+ .posts-container-card { height: 210px; }
+}
+
+/* Channel attachment table -> compact cards on phones. */
+@media (max-width: 700px) {
+ .file-section { margin-top: 1.25rem; }
+
+ table.channel-files,
+ table.channel-files tbody,
+ table.channel-files tr,
+ table.channel-files td {
+ display: block;
+ width: 100% !important;
+ box-sizing: border-box;
+ }
+
+ table.channel-files { padding: 0; table-layout: auto; }
+ table.channel-files thead { display: none; }
+
+ table.channel-files tr {
+ margin: 0 0 .7rem;
+ padding: .7rem;
+ border: 1px solid #dbe3ef;
+ border-radius: 8px;
+ background: #fff;
+ }
+
+ table.channel-files td {
+ min-width: 0;
+ padding: .25rem 0;
+ border: 0;
+ text-align: left;
+ }
+
+ table.channel-files td::before {
+ display: block;
+ margin-bottom: .1rem;
+ color: #64748b;
+ content: attr(data-label);
+ font-size: .72rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ }
+
+ table.channel-files .channel-file__name {
+ overflow-wrap: anywhere;
+ color: #0f172a;
+ font-weight: 600;
+ line-height: 1.35;
+ }
+
+ table.channel-files .channel-file__size { color: #475569; }
+ table.channel-files .channel-file__action { padding-top: .5rem; }
+ table.channel-files .channel-file__action > button { min-width: 116px; }
+ table.channel-files .channel-file__action .file-view { margin-top: .6rem; }
+}
/* #options{
width: 100px;
text-align: center;
diff --git a/webui-src/styles.css b/webui-src/styles.css
index e49f240..e1e6b1c 100644
--- a/webui-src/styles.css
+++ b/webui-src/styles.css
@@ -5978,3 +5978,6101 @@ button.red {
+
+/* =========================================================
+ Global Modal & Lightbox Overlay (#popupmessage)
+ ========================================================= */
+
+#popupmessage {
+ position: fixed !important;
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+ width: 100vw !important;
+ height: 100vh !important;
+ background-color: rgba(15, 23, 42, 0.75) !important;
+ backdrop-filter: blur(4px) !important;
+ z-index: 999999 !important;
+ display: none;
+ align-items: center !important;
+ justify-content: center !important;
+ box-sizing: border-box !important;
+}
+
+.popup {
+ position: fixed !important;
+ top: 50% !important;
+ left: 50% !important;
+ transform: translate(-50%, -50%) !important;
+ z-index: 1000000 !important;
+ max-width: 90vw !important;
+ max-height: 90vh !important;
+ display: flex !important;
+ flex-direction: column !important;
+ box-sizing: border-box !important;
+}
+
+.popup-content {
+ position: relative !important;
+ background: #ffffff !important;
+ border-radius: 12px !important;
+ padding: 1rem !important;
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.2) !important;
+ max-width: 90vw !important;
+ max-height: 90vh !important;
+ overflow: auto !important;
+ box-sizing: border-box !important;
+}
+
+.popup-content span.close {
+ position: absolute !important;
+ top: 0.5rem !important;
+ right: 0.75rem !important;
+ font-size: 1.75rem !important;
+ font-weight: 700 !important;
+ color: #64748b !important;
+ cursor: pointer !important;
+ line-height: 1 !important;
+ z-index: 10 !important;
+ transition: color 0.15s ease !important;
+}
+
+.popup-content span.close:hover {
+ color: #ef4444 !important;
+}
+
+.board-view-container {
+ display: flex !important;
+ flex-direction: column !important;
+ gap: 1rem !important;
+ width: 100% !important;
+ max-width: 100% !important;
+ overflow-x: hidden !important;
+ padding: 0.5rem 0 !important;
+ box-sizing: border-box !important;
+}
+
+.board-table {
+ width: 100% !important;
+ border-collapse: collapse !important;
+}
+
+.board-table th,
+.board-table td {
+ text-align: left !important;
+ padding: 0.65rem 0.85rem !important;
+}
+
+/* Toolbar Header Controls */
+.board-toolbar {
+ display: flex !important;
+ flex-direction: row !important;
+ align-items: center !important;
+ justify-content: space-between !important;
+ gap: 1rem !important;
+ width: 100% !important;
+ padding: 0.5rem 0.85rem !important;
+ background-color: #ffffff !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 8px !important;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) !important;
+ box-sizing: border-box !important;
+}
+
+.board-toolbar__left {
+ display: flex !important;
+ flex-direction: row !important;
+ align-items: center !important;
+ gap: 0.75rem !important;
+ flex: 1 !important;
+ min-width: 0 !important;
+}
+
+.board-toolbar__right {
+ display: flex !important;
+ flex-direction: row !important;
+ align-items: center !important;
+ gap: 0.65rem !important;
+ flex-shrink: 0 !important;
+}
+
+.board-toolbar__count-badge {
+ display: inline-flex !important;
+ align-items: center !important;
+ gap: 0.4rem !important;
+ padding: 0.3rem 0.65rem !important;
+ background-color: #f1f5f9 !important;
+ color: #475569 !important;
+ font-size: 0.825rem !important;
+ font-weight: 600 !important;
+ border-radius: 16px !important;
+ border: 1px solid #e2e8f0 !important;
+ white-space: nowrap !important;
+}
+
+.board-toolbar__count-badge i {
+ color: #007bff !important;
+}
+
+.board-toolbar__search {
+ position: relative !important;
+ display: flex !important;
+ align-items: center !important;
+ flex: 1 !important;
+ max-width: 380px !important;
+ min-width: 160px !important;
+}
+
+.board-toolbar__search-icon {
+ position: absolute !important;
+ left: 0.75rem !important;
+ color: #94a3b8 !important;
+ font-size: 0.85rem !important;
+ pointer-events: none !important;
+}
+
+.board-toolbar__search-input {
+ width: 100% !important;
+ padding: 0.35rem 0.65rem 0.35rem 2.1rem !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 6px !important;
+ font-size: 0.85rem !important;
+ background-color: #ffffff !important;
+ color: #1e293b !important;
+}
+
+.board-toolbar__search-input:focus {
+ outline: none !important;
+ border-color: #007bff !important;
+ box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.15) !important;
+}
+
+.board-toolbar__view-toggle {
+ display: inline-flex !important;
+ flex-direction: row !important;
+ align-items: center !important;
+ background-color: #f1f5f9 !important;
+ padding: 2px !important;
+ border-radius: 6px !important;
+ border: 1px solid #cbd5e1 !important;
+}
+
+.board-toolbar__toggle-btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ gap: 0.35rem !important;
+ padding: 0.3rem 0.65rem !important;
+ border: none !important;
+ background: transparent !important;
+ color: #64748b !important;
+ font-size: 0.825rem !important;
+ font-weight: 500 !important;
+ border-radius: 4px !important;
+ cursor: pointer !important;
+ white-space: nowrap !important;
+ transition: all 0.2s ease !important;
+}
+
+.board-toolbar__toggle-btn i {
+ font-size: 0.85rem !important;
+}
+
+.board-toolbar__toggle-btn:hover {
+ color: #1e293b !important;
+ background-color: rgba(255, 255, 255, 0.6) !important;
+}
+
+.board-toolbar__toggle-btn--active {
+ background-color: #007bff !important;
+ color: #ffffff !important;
+ font-weight: 600 !important;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important;
+}
+
+.board-toolbar__toggle-btn--active i {
+ color: #ffffff !important;
+}
+
+@media (max-width: 768px) {
+ .board-toolbar__toggle-btn span {
+ display: none !important;
+ }
+ .board-toolbar__toggle-btn {
+ padding: 0.35rem 0.55rem !important;
+ }
+}
+
+/* YouTube-style discussion thread on a board post. */
+.board-comments {
+ margin-top: 1.5rem;
+ max-width: 900px;
+ color: #0f172a;
+}
+
+.board-comments__heading {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ margin-bottom: 1.25rem;
+}
+
+.board-comments__heading h3 { margin: 0; font-size: 1.15rem; }
+.board-comments__heading span { color: #64748b; font-size: .8rem; font-weight: 600; }
+.board-comments__heading i { margin-right: .35rem; }
+.board-comments__voter { display: inline-flex; align-items: center; gap: .4rem; margin-left: auto; color: #64748b; font-size: .75rem; font-weight: 600; white-space: nowrap; }
+.board-comments__voter select { max-width: 180px; padding: .25rem .4rem; font-size: .78rem; }
+
+.board-comment-composer,
+.board-comment {
+ display: flex;
+ gap: .8rem;
+}
+
+.board-comment-avatar {
+ display: flex;
+ flex: 0 0 38px;
+ width: 38px;
+ height: 38px;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ background: linear-gradient(135deg, #2563eb, #7c3aed);
+ color: #fff;
+ font-size: .78rem;
+ font-weight: 700;
+}
+
+.board-comment-composer__body,
+.board-comment__content { min-width: 0; flex: 1; }
+.board-comment-composer__identity { max-width: 240px; margin-bottom: .45rem; font-size: .8rem; }
+
+.board-comment-composer__input {
+ width: 100%;
+ min-height: 36px;
+ padding: .45rem 0;
+ resize: vertical;
+ border: 0;
+ border-bottom: 1px solid #94a3b8;
+ border-radius: 0;
+ background: transparent;
+ color: #0f172a;
+ font: inherit;
+ line-height: 1.4;
+ box-sizing: border-box;
+}
+
+.board-comment-composer__input:focus { outline: 0; border-bottom: 2px solid #2563eb; }
+.board-comment-composer__input:disabled { cursor: not-allowed; opacity: .6; }
+
+.board-comment-composer__actions,
+.board-comment__actions {
+ display: flex;
+ align-items: center;
+ gap: .45rem;
+ margin-top: .55rem;
+}
+
+.board-comment-composer__actions { justify-content: flex-end; }
+.board-comment-composer__actions button,
+.board-comment__actions button,
+.board-comment__like,
+.board-comment-composer__replying button {
+ border: 0;
+ background: transparent;
+ color: #475569;
+ cursor: pointer;
+ font-size: .78rem;
+ font-weight: 700;
+}
+
+.board-comment-composer__submit {
+ padding: .45rem .85rem !important;
+ border-radius: 999px !important;
+ background: #2563eb !important;
+ color: #fff !important;
+}
+.board-comment-composer__submit:disabled { background: #dbe3ef !important; color: #94a3b8 !important; cursor: not-allowed; }
+.board-comment-composer__cancel:hover,
+.board-comment__actions button:hover { color: #2563eb; }
+
+.board-comment-composer__replying { display: flex; align-items: center; gap: .25rem; margin-bottom: .35rem; color: #64748b; font-size: .8rem; }
+.board-comment-composer__replying button { margin-left: .3rem; }
+.board-comment-composer__hint,
+.board-comment-composer__error { margin: .4rem 0 0; font-size: .78rem; }
+.board-comment-composer__hint { color: #64748b; }
+.board-comment-composer__error { color: #dc2626; }
+
+.board-comments__list { margin-top: 1.8rem; }
+.board-comment { margin-top: 1.35rem; }
+.board-comment__header { display: flex; align-items: center; justify-content: space-between; min-height: 18px; }
+.board-comment__meta { display: flex; align-items: baseline; gap: .55rem; font-size: .8rem; }
+.board-comment__meta b { color: #1e293b; }
+.board-comment__meta span { color: #64748b; font-size: .75rem; }
+.board-comment__menu { width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: #0f172a; cursor: pointer; opacity: 0; }
+.board-comment:hover .board-comment__menu, .board-comment__menu:focus { opacity: 1; }
+.board-comment__menu:hover { background: #f1f5f9; }
+.board-comment__text { margin: .2rem 0 0; white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.45; }
+.board-comment__actions { gap: .65rem; margin-top: .35rem; }
+.board-comment__actions button { padding: .25rem .2rem; color: #0f172a; }
+.board-comment__like { padding: .25rem .35rem; color: #94a3b8; }
+.board-comment__actions i { margin-right: .2rem; }
+.board-comment__replies-toggle {
+ position: relative;
+ margin-top: .3rem;
+ padding: .25rem .35rem;
+ border: 0;
+ background: transparent;
+ color: #2563eb;
+ cursor: pointer;
+ font-size: .78rem;
+ font-weight: 700;
+}
+.board-comment__replies-toggle:hover { background: #eff6ff; border-radius: 4px; }
+.board-comment__replies-toggle i { margin-left: .15rem; }
+.board-comment__replies-toggle::before { content: ''; position: absolute; left: -3.15rem; bottom: .8rem; width: 1.5rem; height: 2.2rem; border-left: 1px solid #e2e8f0; border-bottom: 1px solid #e2e8f0; border-radius: 0 0 0 .75rem; pointer-events: none; }
+.board-comment__replies { margin-top: .2rem; padding-left: 1rem; border-left: 2px solid #e2e8f0; }
+.board-comments__status,
+.board-comments__empty { margin: 2rem 0; color: #64748b; text-align: center; }
+.board-comments__empty i { font-size: 1.5rem; }
+
+@media (max-width: 560px) {
+ .board-comments__heading { flex-wrap: wrap; justify-content: space-between; gap: .5rem; }
+ .board-comments__voter { width: 100%; margin-left: 0; }
+ .board-comments__voter select { flex: 1; max-width: none; }
+ .board-comment-composer, .board-comment { gap: .6rem; }
+ .board-comment-avatar { flex-basis: 32px; width: 32px; height: 32px; font-size: .68rem; }
+ .board-comment__replies { padding-left: .6rem; }
+ .board-comment__replies-toggle::before { left: -2.65rem; width: 1.2rem; }
+ .board-card__notes-btn span { display: none; }
+ .board-card__notes-btn { width: 30px; height: 30px; justify-content: center; padding: 0 !important; }
+ .board-card__notes-btn i { margin: 0 !important; }
+}
+
+/* Pagination Controls (< 1 - 25 >) on exact same level right next to toggle */
+.board-pagination {
+ display: inline-flex !important;
+ flex-direction: row !important;
+ align-items: center !important;
+ gap: 0.25rem !important;
+ background-color: #ffffff !important;
+ padding: 2px 4px !important;
+ border-radius: 6px !important;
+ border: 1px solid #cbd5e1 !important;
+}
+
+.board-pagination__btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ width: 26px !important;
+ height: 26px !important;
+ min-width: 26px !important;
+ min-height: 26px !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 4px !important;
+ background: #ffffff !important;
+ color: #007bff !important;
+ font-size: 0.825rem !important;
+ cursor: pointer !important;
+ transition: all 0.15s ease !important;
+}
+
+.board-pagination__btn i {
+ font-size: 0.825rem !important;
+ color: #007bff !important;
+}
+
+.board-pagination__btn:hover:not(:disabled) {
+ background-color: #007bff !important;
+ color: #ffffff !important;
+ border-color: #007bff !important;
+}
+
+.board-pagination__btn:hover:not(:disabled) i {
+ color: #ffffff !important;
+}
+
+.board-pagination__btn:disabled {
+ opacity: 0.4 !important;
+ cursor: not-allowed !important;
+ color: #94a3b8 !important;
+ border-color: #e2e8f0 !important;
+ background-color: #f1f5f9 !important;
+}
+
+.board-pagination__btn:disabled i {
+ color: #94a3b8 !important;
+}
+
+.board-pagination__label {
+ font-size: 0.825rem !important;
+ font-weight: 700 !important;
+ color: #334155 !important;
+ padding: 0 0.35rem !important;
+ white-space: nowrap !important;
+ user-select: none !important;
+}
+
+/* Bottom Pagination Container */
+.board-view-footer {
+ display: flex !important;
+ justify-content: center !important;
+ align-items: center !important;
+ padding: 1rem 0 0.5rem 0 !important;
+ width: 100% !important;
+}
+
+/* Board Grid Layout Modes */
+.board-grid {
+ display: flex !important;
+ flex-direction: column !important;
+ width: 100% !important;
+ box-sizing: border-box !important;
+}
+
+.board-grid--compact {
+ display: flex !important;
+ flex-direction: column !important;
+ gap: 0.5rem !important;
+ width: 100% !important;
+}
+
+.board-grid--card {
+ display: grid !important;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) !important;
+ gap: 1.25rem !important;
+ width: 100% !important;
+}
+
+.board-grid__empty {
+ display: flex !important;
+ flex-direction: column !important;
+ align-items: center !important;
+ justify-content: center !important;
+ padding: 4rem 2rem !important;
+ text-align: center !important;
+ background: #ffffff !important;
+ border: 2px dashed #cbd5e1 !important;
+ border-radius: 12px !important;
+ width: 100% !important;
+ box-sizing: border-box !important;
+}
+
+.board-grid__empty-icon {
+ font-size: 3rem !important;
+ color: #cbd5e1 !important;
+ margin-bottom: 1rem !important;
+}
+
+.board-grid__empty-title {
+ font-size: 1.15rem !important;
+ font-weight: 600 !important;
+ color: #475569 !important;
+ margin: 0 0 0.5rem 0 !important;
+}
+
+.board-grid__empty-desc {
+ font-size: 0.9rem !important;
+ color: #94a3b8 !important;
+ margin: 0 !important;
+}
+
+/* ===================================================
+ COMPACT VIEW MODE: FULL-WIDTH HORIZONTAL ROW BANNER
+ (Identical to Retroshare C++ Qt GUI Posted design)
+ =================================================== */
+.board-card {
+ box-sizing: border-box !important;
+}
+
+.board-card--compact {
+ display: flex !important;
+ flex-direction: row !important;
+ align-items: center !important;
+ width: 100% !important;
+ min-height: 70px !important;
+ padding: 0.45rem 0.75rem !important;
+ background-color: #eef2f5 !important;
+ border: 1px solid #d1d5db !important;
+ border-radius: 4px !important;
+ gap: 0.75rem !important;
+ box-sizing: border-box !important;
+ margin-bottom: 0.35rem !important;
+}
+
+.board-card--compact:hover {
+ background-color: #e2e8f0 !important;
+ border-color: #9ca3af !important;
+}
+
+/* Vote Pill (Matching Comments Button style with normal-sized icons) */
+.board-card__vote-pill {
+ display: inline-flex !important;
+ align-items: center !important;
+ gap: 0.4rem !important;
+ padding: 0.2rem 0.55rem !important;
+ background-color: #f1f5f9 !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 20px !important;
+ box-sizing: border-box !important;
+}
+
+button.board-card__vote-btn,
+.board-card__vote-pill .board-card__vote-btn {
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+ padding: 0.1rem 0.2rem !important;
+ margin: 0 !important;
+ cursor: pointer !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ line-height: 1 !important;
+ border-radius: 4px !important;
+ transition: background-color 0.15s ease !important;
+ outline: none !important;
+}
+
+.board-card__vote-pill .board-card__vote-btn:hover {
+ background-color: #e2e8f0 !important;
+ box-shadow: none !important;
+}
+
+.board-card__vote-pill .board-card__vote-btn--up i {
+ color: #16a34a !important;
+ font-size: 1.15rem !important;
+}
+
+.board-card__vote-pill .board-card__vote-btn--down i {
+ color: #dc2626 !important;
+ font-size: 1.15rem !important;
+}
+
+.board-card__vote-pill .board-card__vote-score {
+ font-size: 0.9rem !important;
+ font-weight: 700 !important;
+ color: #1e293b !important;
+ padding: 0 0.15rem !important;
+ line-height: 1 !important;
+ min-width: 1rem !important;
+ text-align: center !important;
+}
+
+/* Thumbnail Image Container */
+.board-card--compact .board-card__image-container {
+ width: 110px !important;
+ height: 62px !important;
+ flex-shrink: 0 !important;
+ border-radius: 4px !important;
+ overflow: hidden !important;
+ background-color: #cbd5e1 !important;
+}
+
+.board-card--compact .board-card__image {
+ width: 100% !important;
+ height: 100% !important;
+ object-fit: cover !important;
+ display: block !important;
+}
+
+.board-card--compact .board-card__placeholder-wrapper {
+ width: 100% !important;
+ height: 100% !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ background: linear-gradient(135deg, #e2e8f0 0%, #cbd5e1 100%) !important;
+}
+
+.board-card__placeholder-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: .3rem;
+ color: #64748b;
+ font-size: .72rem;
+ font-weight: 600;
+}
+.board-card__placeholder-content i { font-size: 1.35rem; }
+
+.board-card--compact .board-card__placeholder-img {
+ width: 24px !important;
+ height: 24px !important;
+ color: #64748b !important;
+}
+
+/* Main Details Section */
+.board-card--compact .board-card__content {
+ display: flex !important;
+ flex-direction: column !important;
+ justify-content: center !important;
+ flex: 1 !important;
+ min-width: 0 !important;
+ padding: 0 !important;
+}
+
+/* Title: Blue bold underlined italicized link (Matches Qt GUI) */
+.board-card--compact .board-card__title {
+ font-size: 1.05rem !important;
+ font-weight: 700 !important;
+ color: #2255aa !important;
+ text-decoration: underline !important;
+ font-style: italic !important;
+ white-space: nowrap !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ margin: 0 0 0.15rem 0 !important;
+ cursor: pointer !important;
+}
+
+.board-card--compact .board-card__title:hover {
+ color: #1d4ed8 !important;
+}
+
+/* Meta line: Posted by */
+.board-card--compact .board-card__meta {
+ font-size: 0.8rem !important;
+ color: #475569 !important;
+ margin-bottom: 0.2rem !important;
+}
+
+.board-card--compact .board-card__meta b {
+ color: #1e293b !important;
+}
+
+/* Footer: Comment button matching Qt GUI */
+.board-card--compact .board-card__footer {
+ display: flex !important;
+ align-items: center !important;
+ gap: 0.5rem !important;
+ padding: 0 !important;
+ border: none !important;
+ margin: 0 !important;
+}
+
+button.board-card__comments-btn,
+.board-card__comments-btn,
+.board-card--compact .board-card__comments-btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ gap: 0.35rem !important;
+ padding: 0.2rem 0.5rem !important;
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+ color: #64748b !important;
+ font-size: 0.85rem !important;
+ font-weight: 500 !important;
+ cursor: pointer !important;
+ outline: none !important;
+}
+
+button.board-card__comments-btn:hover,
+.board-card__comments-btn:hover,
+.board-card--compact .board-card__comments-btn:hover {
+ color: #007bff !important;
+ text-decoration: underline !important;
+ box-shadow: none !important;
+}
+
+button.board-card__notes-btn,
+.board-card__notes-btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ gap: 0.35rem !important;
+ padding: 0.2rem 0.5rem !important;
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+ color: #64748b !important;
+ font-size: 0.85rem !important;
+ font-weight: 500 !important;
+ cursor: pointer !important;
+}
+
+.board-card__notes-btn:hover { color: #007bff !important; text-decoration: underline !important; }
+
+/* ===================================================
+ CARD VIEW MODE: ELEVATED GRID CARD
+ =================================================== */
+.board-card--card {
+ display: flex !important;
+ flex-direction: column !important;
+ background-color: #ffffff !important;
+ border: 1px solid #e2e8f0 !important;
+ border-radius: 10px !important;
+ overflow: hidden !important;
+ transition: transform 0.2s ease, box-shadow 0.2s ease !important;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04) !important;
+}
+
+.board-card--card:hover {
+ transform: translateY(-3px) !important;
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.08) !important;
+ border-color: #cbd5e1 !important;
+}
+
+.board-card--card .board-card__vote-col {
+ display: none !important;
+}
+
+.board-card--card .board-card__image-container {
+ width: 100% !important;
+ height: 170px !important;
+ overflow: hidden !important;
+ background-color: #f1f5f9 !important;
+}
+
+.board-card--card .board-card__image {
+ width: 100% !important;
+ height: 100% !important;
+ object-fit: cover !important;
+ display: block !important;
+}
+
+.board-card--card .board-card__placeholder-wrapper {
+ width: 100% !important;
+ height: 100% !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%) !important;
+}
+
+.board-card--card .board-card__placeholder-img {
+ width: 36px !important;
+ height: 36px !important;
+ color: #94a3b8 !important;
+}
+
+.board-card--card .board-card__content {
+ display: flex !important;
+ flex-direction: column !important;
+ flex: 1 !important;
+ padding: 1rem !important;
+}
+
+.board-card--card .board-card__title {
+ font-size: 1.05rem !important;
+ font-weight: 700 !important;
+ color: #0f172a !important;
+ margin: 0 0 0.4rem 0 !important;
+ white-space: nowrap !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ cursor: pointer !important;
+}
+
+.board-card--card .board-card__title:hover {
+ color: #007bff !important;
+}
+
+.board-card--card .board-card__meta {
+ font-size: 0.8rem !important;
+ color: #64748b !important;
+ margin-bottom: 0.5rem !important;
+}
+
+.board-card--card .board-card__notes-wrapper {
+ display: flex !important;
+ flex-direction: column !important;
+ gap: 0.35rem !important;
+ margin-bottom: 0.75rem !important;
+}
+
+.board-card--card .board-card__notes {
+ font-size: 0.85rem !important;
+ line-height: 1.45 !important;
+ color: #475569 !important;
+ background-color: #f8fafc !important;
+ border-left: 3px solid #cbd5e1 !important;
+ padding: 0.4rem 0.6rem !important;
+ word-break: break-word !important;
+}
+
+.board-card--card .board-card__notes--clamped {
+ display: -webkit-box !important;
+ -webkit-line-clamp: 3 !important;
+ -webkit-box-orient: vertical !important;
+ overflow: hidden !important;
+ white-space: pre-line !important;
+}
+
+.board-card--card .board-card__notes--expanded {
+ display: block !important;
+ white-space: pre-line !important;
+}
+
+.board-card--card .board-card__notes-toggle {
+ align-self: flex-start !important;
+ background: none !important;
+ border: none !important;
+ padding: 0.1rem 0.3rem !important;
+ color: #007bff !important;
+ font-size: 0.775rem !important;
+ font-weight: 600 !important;
+ cursor: pointer !important;
+}
+
+.board-card--card .board-card__notes-toggle:hover {
+ text-decoration: underline !important;
+}
+
+.board-card--card .board-card__footer {
+ display: flex !important;
+ align-items: center !important;
+ justify-content: flex-end !important;
+ margin-top: auto !important;
+ padding-top: 0.65rem !important;
+ border-top: 1px solid #f1f5f9 !important;
+}
+
+.board-card--card .board-card__comments-btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ gap: 0.4rem !important;
+ padding: 0.3rem 0.6rem !important;
+ background-color: #f1f5f9 !important;
+ color: #475569 !important;
+ border: 1px solid #e2e8f0 !important;
+ border-radius: 6px !important;
+ font-size: 0.8rem !important;
+ font-weight: 500 !important;
+ cursor: pointer !important;
+}
+
+.board-card--card .board-card__comments-btn:hover {
+ background-color: #007bff !important;
+ color: #ffffff !important;
+ border-color: #007bff !important;
+}
+
+.board-card--card .board-card__comments-btn:hover i {
+ color: #ffffff !important;
+}
+
+.board-card--card .board-card__notes-btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ gap: 0.4rem !important;
+ padding: 0.3rem 0.6rem !important;
+ background-color: #f8fafc !important;
+ color: #475569 !important;
+ border: 1px solid #e2e8f0 !important;
+ border-radius: 6px !important;
+ font-size: 0.8rem !important;
+ font-weight: 500 !important;
+}
+
+.board-card--card .board-card__notes-btn:hover { background-color: #e0f2fe !important; color: #0369a1 !important; border-color: #7dd3fc !important; text-decoration: none !important; }
+
+.board-notes-dialog { min-width: min(560px, 75vw); max-width: 75vw; }
+.board-notes-dialog h3 { margin: 0 2rem .8rem 0; color: #0f172a; }
+.board-notes-dialog__label { margin: 0 0 .35rem; color: #64748b; font-size: .78rem; font-weight: 700; text-transform: uppercase; }
+.board-notes-dialog__content { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; color: #1e293b; line-height: 1.55; }
+
+/* =========================================================
+ PhotoView Lightbox Modal Styles (Matching Qt GUI PhotoView)
+ ========================================================= */
+
+/* Fullscreen overlay element appended to body by openPhotoModal() */
+#photo-view-overlay {
+ display: none;
+ position: fixed;
+ inset: 0;
+ z-index: 999999;
+ background-color: rgba(0, 0, 0, 0.85);
+ align-items: center;
+ justify-content: center;
+}
+
+.photo-view-dialog {
+ background-color: #f8fafc !important;
+ border-radius: 8px !important;
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5) !important;
+ display: flex !important;
+ flex-direction: column !important;
+ max-width: 90vw !important;
+ max-height: 90vh !important;
+ width: 820px !important;
+ overflow: hidden !important;
+ position: relative !important;
+ z-index: 1 !important;
+}
+
+.photo-view-header {
+ display: flex !important;
+ align-items: center !important;
+ justify-content: space-between !important;
+ padding: 0.75rem 1rem !important;
+ background-color: #ffffff !important;
+ border-bottom: 1px solid #e2e8f0 !important;
+}
+
+.photo-view-title {
+ font-size: 1.05rem !important;
+ font-style: italic !important;
+ font-weight: 700 !important;
+ color: #1e293b !important;
+ margin: 0 !important;
+ flex: 1 !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ white-space: nowrap !important;
+}
+
+.photo-view-close-btn {
+ background: none !important;
+ border: none !important;
+ font-size: 1.6rem !important;
+ line-height: 1 !important;
+ color: #64748b !important;
+ cursor: pointer !important;
+ padding: 0 0.4rem !important;
+}
+
+.photo-view-close-btn:hover {
+ color: #ef4444 !important;
+}
+
+.photo-view-body {
+ display: flex !important;
+ flex-direction: row !important;
+ align-items: stretch !important;
+ background-color: #0f172a !important;
+ flex: 1 !important;
+ min-height: 380px !important;
+ max-height: 68vh !important;
+ overflow: hidden !important;
+}
+
+/* Left/right nav columns (fixed 56px wide, vertically center the button) */
+.photo-view-nav-col {
+ width: 56px !important;
+ flex-shrink: 0 !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ background-color: rgba(0, 0, 0, 0.25) !important;
+}
+
+/* Image wrapper fills remaining space */
+.photo-view-img-wrap {
+ flex: 1 !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ min-width: 0 !important;
+ padding: 0.75rem !important;
+}
+
+.photo-view-img {
+ max-width: 100% !important;
+ max-height: 65vh !important;
+ object-fit: contain !important;
+ display: block !important;
+ border-radius: 4px !important;
+}
+
+.photo-view-no-img {
+ color: #94a3b8 !important;
+ font-size: 0.95rem !important;
+}
+
+/* Nav button — static in flex column, no absolute positioning */
+.photo-view-nav-btn {
+ width: 38px !important;
+ height: 38px !important;
+ background-color: #ffffff !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 6px !important;
+ color: #007bff !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ cursor: pointer !important;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3) !important;
+ transition: all 0.15s ease !important;
+ flex-shrink: 0 !important;
+}
+
+.photo-view-nav-btn i {
+ font-size: 1rem !important;
+ color: #007bff !important;
+}
+
+.photo-view-nav-btn:hover {
+ background-color: #007bff !important;
+ color: #ffffff !important;
+ border-color: #007bff !important;
+}
+
+.photo-view-nav-btn:hover i {
+ color: #ffffff !important;
+}
+
+.photo-view-footer {
+ display: flex !important;
+ align-items: center !important;
+ justify-content: space-between !important;
+ padding: 0.75rem 1rem !important;
+ background-color: #ffffff !important;
+ border-top: 1px solid #e2e8f0 !important;
+}
+
+.photo-view-meta {
+ font-size: 0.875rem !important;
+ color: #475569 !important;
+}
+
+.photo-view-meta b {
+ color: #0f172a !important;
+}
+
+/* Responsive: Hide board header description on mobile screens */
+@media (max-width: 768px) {
+ .media-item__desc {
+ display: none !important;
+ }
+ .media-item__details {
+ flex-basis: 100% !important;
+ width: 100% !important;
+ }
+}
+
+
+
+@use '../abstracts' as *;
+
+.file-section {
+ margin-top: 2rem;
+ @include flex(column);
+}
+
+.comments-section {
+ margin-top: 2rem;
+ @include flex($justify: space-between);
+ &__menu {
+ @include flex($gap: 1rem);
+ &-id {
+ @include flex($gap: 0.25rem, $align: center);
+ }
+ }
+}
+
+#toggleunsub {
+ position: relative;
+ background: gray;
+}
+
+/* subject */
+table.channels {
+ & th:nth-child(1) {
+ width: 50%;
+ text-align: start;
+ }
+ /* subject */
+ & td:nth-child(1) {
+ text-align: start;
+ /* Truncate text with '...' */
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ & tr:hover {
+ background-color: $light-color;
+ cursor: pointer;
+ }
+ & tr.hidden {
+ display: none;
+ }
+}
+
+/* subject */
+table {
+ padding: 0.5rem;
+ &.comments {
+ border: 1px solid #eee;
+ & th {
+ height: 40px;
+ &:nth-child(1) {
+ width: 2%;
+ }
+ &:nth-child(2) {
+ width: 40%;
+ }
+ }
+ & td {
+ word-wrap: break-word;
+ &:nth-child(2) {
+ text-align: start;
+ }
+ }
+ }
+ &.files {
+ & th:first-child {
+ text-align: start;
+ width: 60%;
+ }
+ & tr td:first-child {
+ text-align: start;
+ }
+ & td {
+ word-wrap: break-word;
+ }
+ }
+}
+
+.posts-container-card .channel-post__placeholder {
+ flex: 1 1 auto;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: .35rem;
+ color: #64748b;
+ background: linear-gradient(135deg, #f8fafc, #dbe5f1);
+}
+.channel-post__placeholder i { font-size: 1.35rem; color: #64748b; }
+.channel-post__placeholder span { font-size: 2rem; font-weight: 700; color: #2563eb; }
+.channel-post__placeholder small { font-size: .72rem; font-weight: 600; }
+
+/* Compact YouTube-style post description with an opt-in expansion control. */
+.post-description {
+ margin: 1rem 0;
+ padding: .85rem 1rem;
+ border-radius: 10px;
+ background: #f1f5f9;
+ color: #1e293b;
+}
+.post-description__text { overflow-wrap: anywhere; line-height: 1.5; }
+.post-description__text > :first-child { margin-top: 0; }
+.post-description__text > :last-child { margin-bottom: 0; }
+.post-description__text--collapsed {
+ display: -webkit-box;
+ overflow: hidden;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 3;
+}
+.post-description__toggle {
+ margin-top: .35rem;
+ padding: 0 !important;
+ border: 0 !important;
+ box-shadow: none !important;
+ background: transparent !important;
+ color: #0f172a !important;
+ font-size: .85rem !important;
+ font-weight: 700 !important;
+}
+.post-description__toggle:hover { color: #2563eb !important; text-decoration: underline; }
+
+/* Keep image and generated-thumbnail cards the same size instead of stretching
+ * a sparse grid row to the full height of the Posts panel. */
+.posts-container { align-content: start; grid-auto-rows: 240px; }
+.posts-container-card { height: 240px; min-height: 0; overflow: hidden; }
+.posts-container-card > img,
+.posts-container-card > .channel-post__placeholder { min-height: 0; }
+
+@media (max-width: 700px) {
+ .posts-container { grid-auto-rows: 210px; gap: 1rem; }
+ .posts-container-card { height: 210px; }
+}
+
+/* Channel attachment table -> compact cards on phones. */
+@media (max-width: 700px) {
+ .file-section { margin-top: 1.25rem; }
+
+ table.channel-files,
+ table.channel-files tbody,
+ table.channel-files tr,
+ table.channel-files td {
+ display: block;
+ width: 100% !important;
+ box-sizing: border-box;
+ }
+
+ table.channel-files { padding: 0; table-layout: auto; }
+ table.channel-files thead { display: none; }
+
+ table.channel-files tr {
+ margin: 0 0 .7rem;
+ padding: .7rem;
+ border: 1px solid #dbe3ef;
+ border-radius: 8px;
+ background: #fff;
+ }
+
+ table.channel-files td {
+ min-width: 0;
+ padding: .25rem 0;
+ border: 0;
+ text-align: left;
+ }
+
+ table.channel-files td::before {
+ display: block;
+ margin-bottom: .1rem;
+ color: #64748b;
+ content: attr(data-label);
+ font-size: .72rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ }
+
+ table.channel-files .channel-file__name {
+ overflow-wrap: anywhere;
+ color: #0f172a;
+ font-weight: 600;
+ line-height: 1.35;
+ }
+
+ table.channel-files .channel-file__size { color: #475569; }
+ table.channel-files .channel-file__action { padding-top: .5rem; }
+ table.channel-files .channel-file__action > button { min-width: 116px; }
+ table.channel-files .channel-file__action .file-view { margin-top: .6rem; }
+}
+/* #options{
+ width: 100px;
+ text-align: center;
+ font-size: medium;
+ margin-left: 20px;
+ height: 40px;
+} */
+#mtags {
+ width: 160px;
+ text-align: center;
+ font-size: medium;
+ margin-left: 10px;
+ height: 40px;
+}
+
+
+
+@use '../abstracts' as *;
+
+.lobby {
+ margin: 10px;
+ border: 1px solid #aaa;
+ border-radius: 20px;
+}
+
+.lobby .mainname {
+ margin: 20px;
+ font-weight: 100;
+ font-size: 1.2em;
+}
+
+.topic {
+ color: #666;
+}
+
+.lobby>.topic {
+ font-size: 0.95em;
+ margin-left: 25px;
+ margin-bottom: 5px;
+}
+
+.lefttitle {
+ margin-top: 15px;
+ margin-bottom: 0;
+ font-weight: 100;
+ font-size: 1.2em;
+}
+
+.leftname {
+ margin-top: 5px;
+ margin-bottom: 5px;
+ padding: 5px;
+ font-weight: 100;
+ font-size: 1em;
+}
+
+.leftlobby>.topic {
+ font-size: 0.75em;
+ margin-left: 15px;
+ margin-bottom: 5px;
+}
+
+.subscribed,
+.public {
+ cursor: pointer;
+}
+
+.leftlobby {
+ border: 1px solid #aaa;
+ border-radius: 10px;
+ margin-top: 5px;
+ background-color: white;
+}
+
+.leftlobby.selected-lobby,
+.selectedidentity {
+ color: white;
+ background-color: #3ba4d7;
+}
+
+.rightbar {
+ position: absolute;
+ width: 185px;
+ background-color: white;
+ overflow: auto;
+ top: 130px;
+ bottom: 15px;
+ right: 15px;
+}
+
+.user {
+ padding: 5px;
+}
+
+.lobbyName {
+ padding: 15px;
+ margin-top: 2rem;
+}
+
+.lobbies {
+ position: absolute;
+ width: 185px;
+ left: 165px;
+ bottom: 15px;
+ top: 130px;
+ overflow: auto;
+}
+
+.messages,
+.setup {
+ position: absolute;
+ background-color: white;
+ top: 130px;
+ left: 360px;
+ right: 215px;
+ overflow: auto;
+}
+
+.messages {
+ bottom: 115px;
+}
+
+.messagetext {
+ white-space: break-spaces;
+ margin-right: 5px;
+}
+
+.message>* {
+ margin-left: 5px;
+}
+
+.username {
+ color: darkgreen;
+ font-weight: bolder;
+}
+
+.chatMessage {
+ position: absolute;
+ background-color: white;
+ height: 85px;
+ bottom: 15px;
+ right: 215px;
+ left: 360px;
+}
+
+textarea.chatMsg {
+ height: 100%;
+ width: 100%;
+}
+
+.chatatchar {
+ margin-left: 0.2em;
+ margin-right: 0.2em;
+ color: silver;
+}
+
+.setupicon {
+ margin-left: 1em;
+ cursor: pointer;
+}
+
+.leaveicon {
+ margin-left: 1em;
+ cursor: pointer;
+ color: #d40000;
+}
+
+.selectidentity {
+ margin: 15px;
+ font-size: 1.2em;
+}
+
+.setup>.identity {
+ cursor: pointer;
+}
+
+.setup {
+ bottom: 15px;
+}
+
+.createDistantChat {
+ margin-top: 1em;
+}
+
+.no-lobbies {
+
+ .messages,
+ .chatMessage,
+ .setup {
+ left: 165px;
+ }
+}
+
+/* CHAT ROOM (Single Chat) - Desktop Grid Layout */
+@media (min-width: 900px) {
+ .node-panel.chat-room {
+ display: grid !important;
+ grid-template-columns: 250px 1fr 200px !important;
+ /* Lobbies, Chat, Users */
+ grid-template-rows: auto 1fr auto !important;
+ /* Header, Messages, Input */
+ grid-template-areas:
+ "lobbies header rightbar"
+ "lobbies messages rightbar"
+ "lobbies input rightbar" !important;
+ padding: 0 !important;
+ height: 100% !important;
+ }
+
+ .node-panel.chat-room .lobbyName {
+ grid-area: header;
+ padding: 10px;
+ border-bottom: 1px solid #eee;
+ margin: 0;
+ z-index: 10;
+ background: white;
+ }
+
+ .node-panel.chat-room .lobbies {
+ grid-area: lobbies;
+ position: static !important;
+ width: auto !important;
+ height: auto !important;
+ border-right: 1px solid #ccc;
+ overflow-y: auto;
+ display: block !important;
+ top: auto !important;
+ bottom: auto !important;
+ left: auto !important;
+ }
+
+ .node-panel.chat-room .messages {
+ grid-area: messages;
+ position: static !important;
+ width: auto !important;
+ height: auto !important;
+ overflow-y: auto;
+ padding: 10px;
+ left: auto !important;
+ right: auto !important;
+ top: auto !important;
+ bottom: auto !important;
+ margin: 0 !important;
+ }
+
+ .node-panel.chat-room .rightbar {
+ grid-area: rightbar;
+ position: static !important;
+ width: auto !important;
+ border-left: 1px solid #ccc;
+ overflow-y: auto;
+ display: block !important;
+ }
+
+ .node-panel.chat-room .chatMessage {
+ grid-area: input;
+ position: static !important;
+ width: auto !important;
+ height: auto !important;
+ border-top: 1px solid #eee;
+ left: auto !important;
+ right: auto !important;
+ bottom: auto !important;
+ flex: 0 0 auto;
+ padding: 10px !important;
+ background: white;
+ z-index: 10;
+ }
+}
+
+/* Mobile Overrides - Ensure Flex Column */
+@media (max-width: 899px) {
+ .node-panel.chat-room {
+ display: flex !important;
+ flex-direction: column !important;
+ height: 100% !important;
+ position: relative !important;
+ }
+
+ .node-panel.chat-room .lobbyName {
+ flex: 0 0 auto;
+ }
+
+ .node-panel.chat-room .messages {
+ flex: 1 !important;
+ overflow-y: auto !important;
+ position: relative !important;
+ top: 0 !important;
+ bottom: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ width: 100% !important;
+ height: auto !important;
+ margin: 0 !important;
+ }
+
+ .node-panel.chat-room .chatMessage {
+ flex: 0 0 auto !important;
+ position: relative !important;
+ bottom: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ width: 100% !important;
+ height: auto !important;
+ z-index: 100;
+ }
+
+ .node-panel.chat-room .rightbar,
+ .node-panel.chat-room .lobbies {
+ display: none !important;
+ position: fixed !important;
+ top: 60px !important;
+ bottom: 0 !important;
+ width: 80% !important;
+ background: white !important;
+ z-index: 200 !important;
+ box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2) !important;
+ }
+
+ .node-panel.chat-room.show-lobbies .lobbies {
+ display: block !important;
+ left: 0 !important;
+ }
+
+ .node-panel.chat-room.show-users .rightbar {
+ display: block !important;
+ right: 0 !important;
+ }
+
+ .chat-overlay {
+ display: none;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.4);
+ z-index: 150;
+ }
+
+ .show-lobbies .chat-overlay,
+ .show-users .chat-overlay {
+ display: block;
+ }
+
+ /* Mobile Icons in Header */
+ .mobile-menu-icons {
+ display: flex;
+ gap: 15px;
+ font-size: 1.2rem;
+ }
+
+ .mobile-menu-icons i {
+ cursor: pointer;
+ padding: 5px;
+ }
+}
+
+@media (min-width: 900px) {
+ .mobile-menu-icons {
+ display: none;
+ }
+}
+
+/* =====================================================
+ CHAT HUB - Two-Pane Layout (matching Network page)
+ ===================================================== */
+
+.chat-hub-container {
+ display: flex;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ background-color: #f1f5f9;
+}
+
+.chat-hub-left-pane {
+ width: 320px;
+ min-width: 300px;
+ max-width: 350px;
+ border-right: 1px solid #cbd5e1;
+ display: flex;
+ flex-direction: column;
+ background: #ffffff;
+ box-shadow: 2px 0 5px rgba(0, 0, 0, 0.05);
+}
+
+.chat-own-profile-card {
+ padding: 0.85rem 1.25rem !important;
+ border-bottom: 1px solid #e2e8f0 !important;
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%) !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: space-between !important;
+ gap: 0.75rem !important;
+
+ .profile-header {
+ display: flex !important;
+ align-items: center !important;
+ gap: 0.75rem !important;
+ flex: 1 !important;
+ min-width: 0 !important;
+ }
+
+ .chat-create-lobby-btn {
+ display: flex !important;
+ align-items: center !important;
+ gap: 0.35rem !important;
+ padding: 0.4rem 0.85rem !important;
+ font-size: 0.85rem !important;
+ font-weight: 600 !important;
+ border-radius: 0.375rem !important;
+ cursor: pointer !important;
+ flex-shrink: 0 !important;
+ white-space: nowrap !important;
+ }
+
+ .profile-info {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ overflow: hidden;
+
+ .profile-name {
+ font-weight: 700;
+ color: #1e293b;
+ font-size: 1.1rem;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .profile-status {
+ font-size: 0.85rem;
+ color: #10b981;
+ font-weight: 500;
+ display: flex;
+ align-items: center;
+ gap: 0.35rem;
+
+ &::before {
+ content: '';
+ display: inline-block;
+ width: 8px;
+ height: 8px;
+ background-color: #10b981;
+ border-radius: 50%;
+ }
+ }
+ }
+}
+
+.chat-rooms-list-container {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ .searchbar-container {
+ padding: 0.75rem 1rem;
+ border-bottom: 1px solid #e2e8f0;
+
+ input.searchbar {
+ width: 100%;
+ padding: 0.5rem 0.75rem;
+ font-size: 0.9rem;
+ border: 1px solid #cbd5e1;
+ border-radius: 0.375rem;
+ background-color: #f8fafc;
+ outline: none;
+ transition: all 0.2s;
+
+ &:focus {
+ background-color: #ffffff;
+ border-color: #3ba4d7;
+ box-shadow: 0 0 0 3px rgba(59, 164, 215, 0.15);
+ }
+ }
+ }
+
+ .rooms-scroll {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0.5rem 0;
+ }
+}
+
+.rooms-section-title {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.75rem 1rem 0.375rem;
+ font-size: 0.75rem;
+ font-weight: 700;
+ color: #64748b;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+
+ i {
+ font-size: 0.7rem;
+ color: #94a3b8;
+ }
+}
+
+.chat-room-list-item {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 0.75rem 1rem;
+ margin: 0.125rem 0.5rem;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ transition: all 0.2s;
+
+ &:hover {
+ background-color: #f1f5f9;
+ }
+
+ &.selected {
+ background-color: #e0f2fe;
+
+ .room-name {
+ color: #0369a1;
+ font-weight: 600;
+ }
+ }
+
+ .room-icon {
+ flex-shrink: 0;
+ width: 36px;
+ height: 36px;
+ border-radius: 0.5rem;
+ background: linear-gradient(135deg, #3ba4d7, #0ea5e9);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #ffffff;
+ font-size: 1.35rem;
+ }
+
+ &.public-room .room-icon {
+ background: linear-gradient(135deg, #10b981, #059669);
+ }
+
+ .room-meta {
+ flex: 1;
+ min-width: 0;
+
+ .room-name {
+ font-size: 0.95rem;
+ color: #334155;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ transition: color 0.2s;
+ }
+
+ .room-topic {
+ font-size: 0.8rem;
+ color: #94a3b8;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+
+ .room-badge {
+ flex-shrink: 0;
+ min-width: 24px;
+ height: 24px;
+ border-radius: 12px;
+ background-color: #e2e8f0;
+ color: #475569;
+ font-size: 0.75rem;
+ font-weight: 700;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 0.375rem;
+ }
+}
+
+.chat-hub-right-pane {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ background-color: #f8fafc;
+}
+
+.chat-pane-placeholder {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ color: #94a3b8;
+ gap: 1rem;
+ padding: 2rem;
+ text-align: center;
+
+ i {
+ font-size: 4rem;
+ color: #cbd5e1;
+ }
+
+ p {
+ font-size: 1.1rem;
+ max-width: 400px;
+ }
+}
+
+.chat-hub-tab-content {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1.5rem;
+}
+
+.chat-room-detail-view {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+
+ .detail-header {
+ display: flex;
+ align-items: flex-start;
+ gap: 1.5rem;
+ padding-bottom: 1.5rem;
+ border-bottom: 1px solid #e2e8f0;
+ flex-wrap: wrap;
+
+ .detail-title {
+ flex: 1;
+ min-width: 200px;
+
+ h2 {
+ font-size: 1.75rem;
+ font-weight: 800;
+ color: #1e293b;
+ margin-bottom: 0.25rem;
+ }
+
+ .detail-subtitle {
+ font-size: 0.9rem;
+ color: #64748b;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ }
+ }
+
+ .detail-actions {
+ display: flex;
+ gap: 0.75rem;
+ flex-wrap: wrap;
+
+ button {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.5rem 1rem;
+ font-size: 0.9rem;
+ }
+ }
+ }
+
+ .detail-section {
+ background-color: #ffffff;
+ border-radius: 0.5rem;
+ border: 1px solid #e2e8f0;
+ padding: 1.25rem;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
+
+ h3 {
+ font-size: 1.1rem;
+ font-weight: 700;
+ color: #334155;
+ margin-bottom: 1rem;
+ padding-bottom: 0.5rem;
+ border-bottom: 1px solid #f1f5f9;
+ }
+
+ .info-grid {
+ display: grid;
+ grid-template-columns: 130px 1fr;
+ row-gap: 0.75rem;
+ font-size: 0.9rem;
+
+ .info-label {
+ font-weight: 600;
+ color: #64748b;
+ }
+
+ .info-value {
+ color: #1e293b;
+ word-break: break-all;
+ }
+ }
+ }
+}
+
+.participants-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
+ gap: 0.5rem;
+}
+
+.participant-card {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.5rem 0.75rem;
+ background-color: #f8fafc;
+ border: 1px solid #e2e8f0;
+ border-radius: 0.375rem;
+
+ .participant-name {
+ font-size: 0.875rem;
+ color: #334155;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+}
+
+.no-participants {
+ color: #94a3b8;
+ font-size: 0.9rem;
+ font-style: italic;
+}
+
+.detail-actions-footer {
+ display: flex;
+ gap: 0.75rem;
+
+ button {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.5rem 1rem;
+ font-size: 0.9rem;
+ }
+}
+
+.join-description {
+ color: #64748b;
+ font-size: 0.9rem;
+ margin-bottom: 1rem;
+}
+
+.identities-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+ gap: 0.75rem;
+}
+
+.identity-card {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.75rem 1rem;
+ background-color: #f8fafc;
+ border: 1px solid #e2e8f0;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ transition: all 0.2s;
+
+ &:hover {
+ background-color: #e0f2fe;
+ border-color: #3ba4d7;
+ }
+
+ .identity-name {
+ font-size: 0.95rem;
+ font-weight: 600;
+ color: #334155;
+ }
+
+ i {
+ color: #3ba4d7;
+ font-size: 0.9rem;
+ }
+}
+
+.no-rooms {
+ padding: 1rem;
+ color: #94a3b8;
+ text-align: center;
+ font-style: italic;
+}
+
+/* Chat Hub Responsive - Mobile */
+@media (max-width: 899px) {
+ .chat-hub-container {
+ flex-direction: column;
+ }
+
+ .chat-hub-left-pane {
+ width: 100%;
+ min-width: 0;
+ max-width: none;
+ max-height: 45%;
+ border-right: none;
+ border-bottom: 1px solid #cbd5e1;
+ }
+
+ .chat-hub-right-pane {
+ flex: 1;
+ min-height: 0;
+ }
+}
+
+/* =====================================================
+ CHAT HUB - Right Pane Conversation & Tabs Styling
+ ===================================================== */
+
+.chat-hub-header-bar {
+ padding: 0.75rem 1.5rem;
+ background-color: #ffffff;
+ border-bottom: 1px solid #e2e8f0;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 65px;
+ flex-shrink: 0;
+}
+
+.chat-hub-header-bar .chat-header-info {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.chat-hub-header-bar .chat-header-info .chat-header-name {
+ font-size: 1.15rem;
+ font-weight: 800;
+ color: #1e293b;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.chat-hub-header-bar .chat-header-info .chat-header-topic {
+ font-size: 0.85rem;
+ color: #64748b;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-top: 0.125rem;
+}
+
+.chat-hub-header-bar .chat-header-actions {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.chat-hub-header-bar .chat-header-actions button {
+ display: flex;
+ align-items: center;
+ gap: 0.35rem;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.85rem;
+}
+
+.chat-hub-tabs-container {
+ background-color: #ffffff;
+ border-bottom: 1px solid #cbd5e1;
+ padding: 0.5rem 1.5rem 0;
+}
+
+.chat-hub-tabs {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.chat-hub-tabs .tab-btn {
+ padding: 0.625rem 1.25rem;
+ font-size: 0.95rem;
+ font-weight: 600;
+ color: #64748b;
+ background: transparent;
+ border: none;
+ border-radius: 0.375rem 0.375rem 0 0;
+ border-bottom: 3px solid transparent;
+ cursor: pointer;
+ box-shadow: none;
+ transition: all 0.2s;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.chat-hub-tabs .tab-btn:hover {
+ color: #334155;
+ background-color: #f1f5f9;
+}
+
+.chat-hub-tabs .tab-btn.active {
+ color: #3ba4d7;
+ border-bottom-color: #3ba4d7;
+ background-color: transparent;
+}
+
+.chat-hub-tab-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ background-color: #f8fafc;
+}
+
+.chat-hub-conversation-layout {
+ display: flex;
+ flex-direction: row;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+}
+
+.chat-hub-conversation-main {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ height: 100%;
+ overflow: hidden;
+}
+
+.chat-hub-rightbar {
+ width: 200px;
+ border-left: 1px solid #cbd5e1;
+ background-color: #ffffff;
+ display: flex;
+ flex-direction: column;
+ flex-shrink: 0;
+}
+
+.chat-hub-rightbar .rightbar-title {
+ padding: 0.75rem 1rem;
+ font-size: 0.85rem;
+ font-weight: 700;
+ color: #64748b;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ border-bottom: 1px solid #e2e8f0;
+}
+
+.chat-hub-rightbar .rightbar-users-list {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0.5rem;
+}
+
+.chat-hub-rightbar .user {
+ padding: 0.5rem 0.75rem;
+ font-size: 0.9rem;
+ color: #334155;
+ border-radius: 0.375rem;
+ transition: all 0.2s;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.chat-hub-rightbar .user:hover {
+ background-color: #f1f5f9;
+ color: #0f172a;
+}
+
+.chat-hub-rightbar .user .defaultAvatar {
+ width: 2rem;
+ height: 2rem;
+ font-size: 0.9rem;
+ flex-shrink: 0;
+}
+
+.chat-hub-rightbar .user img.avatar {
+ width: 2rem;
+ height: 2rem;
+ flex-shrink: 0;
+}
+
+@media (max-width: 899px) {
+ .chat-hub-rightbar {
+ display: none;
+ }
+}
+
+.chat-hub-messages {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1.25rem 1.5rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+/* Chat bubble overrides for two-pane layout */
+.chat-hub-messages .message {
+ display: flex;
+ flex-direction: column;
+ max-width: 70%;
+ padding: 0.625rem 0.875rem;
+ border-radius: 0.75rem;
+ font-size: 0.925rem;
+ line-height: 1.4;
+ word-break: break-word;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.chat-hub-messages .message.incoming {
+ align-self: flex-start;
+ align-items: flex-start;
+ background-color: #ffffff;
+ color: #1e293b;
+ border: 1px solid #e2e8f0;
+ border-bottom-left-radius: 0.125rem;
+}
+
+.chat-hub-messages .message.outgoing {
+ align-self: flex-end;
+ align-items: flex-end;
+ background-color: #3ba4d7;
+ color: #ffffff;
+ border-bottom-right-radius: 0.125rem;
+}
+
+.chat-hub-messages .message .username {
+ font-size: 0.75rem;
+ margin-bottom: 0.25rem;
+ padding: 0 0.125rem;
+ font-weight: 700;
+}
+
+.chat-hub-messages .message.incoming .username {
+ color: #0369a1;
+}
+
+.chat-hub-messages .message.outgoing .username {
+ color: #e0f2fe;
+}
+
+.chat-hub-messages .message .messagetext {
+ white-space: break-spaces;
+ margin: 0;
+}
+
+.chat-hub-messages .message .datetime {
+ font-size: 0.7rem;
+ margin-top: 0.25rem;
+ padding: 0 0.125rem;
+ opacity: 0.8;
+}
+
+.chat-hub-messages .message.incoming .datetime {
+ color: #64748b;
+}
+
+.chat-hub-messages .message.outgoing .datetime {
+ color: #f1f5f9;
+}
+
+.chat-hub-input-area {
+ padding: 0.75rem 1.5rem;
+ background-color: #ffffff;
+ border-top: 1px solid #cbd5e1;
+ display: flex;
+ gap: 0.75rem;
+ align-items: flex-end;
+ flex-shrink: 0;
+}
+
+.chat-hub-input-area textarea.chat-hub-textarea {
+ flex: 1;
+ resize: vertical;
+ min-height: 40px;
+ max-height: 250px;
+ height: 40px;
+ padding: 0.5rem 0.75rem;
+ border: 1px solid #cbd5e1;
+ border-radius: 0.375rem;
+ font-size: 0.9rem;
+ outline: none;
+ transition: border-color 0.2s, box-shadow 0.2s;
+ background-color: #f8fafc;
+}
+
+.chat-hub-input-area textarea.chat-hub-textarea:focus {
+ background-color: #ffffff;
+ border-color: #3ba4d7;
+ box-shadow: 0 0 0 3px rgba(59, 164, 215, 0.15);
+}
+
+.chat-hub-input-area button.chat-hub-send-btn {
+ padding: 0.5rem 1.25rem;
+ font-size: 0.9rem;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ border-radius: 0.375rem;
+}
+
+button.chat-hub-action-btn,
+label.chat-hub-action-btn,
+.chat-hub-action-btn {
+ display: inline-flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ width: 36px !important;
+ height: 36px !important;
+ min-width: 36px !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ background: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+ color: #64748b !important;
+ font-size: 1.15rem !important;
+ border-radius: 0.375rem !important;
+ cursor: pointer !important;
+ transition: all 0.15s ease !important;
+ outline: none !important;
+}
+
+button.chat-hub-action-btn:hover,
+label.chat-hub-action-btn:hover,
+.chat-hub-action-btn:hover {
+ background-color: #e2e8f0 !important;
+ color: #3b82f6 !important;
+ box-shadow: none !important;
+}
+
+button.chat-hub-action-btn i,
+label.chat-hub-action-btn i,
+.chat-hub-action-btn i {
+ font-size: 1.15rem !important;
+ color: inherit !important;
+}
+
+/* Compact Room Chat Style (No bubbles, unique nickname colors, IRC-style) */
+.chat-hub-messages.compact-container,
+.messages.compact-container {
+ gap: 0 !important;
+ padding: 0.75rem 1rem !important;
+ background-color: #ffffff !important;
+ display: flex !important;
+ flex-direction: column !important;
+}
+
+.chat-hub-messages.compact-container .message.compact,
+.messages.compact-container .message.compact {
+ display: block !important;
+ max-width: 100% !important;
+ padding: 0.1rem 0 !important;
+ border-radius: 0 !important;
+ background-color: transparent !important;
+ border: none !important;
+ box-shadow: none !important;
+ align-self: flex-start !important;
+ font-size: 0.875rem !important;
+ line-height: 1.45 !important;
+ margin: 0 !important;
+ white-space: nowrap !important;
+}
+
+.chat-hub-messages.compact-container .message.compact:hover,
+.messages.compact-container .message.compact:hover {
+ background-color: #f8fafc !important;
+ overflow: visible !important;
+ white-space: normal !important;
+}
+
+.chat-hub-messages.compact-container .message.compact .datetime,
+.messages.compact-container .message.compact .datetime {
+ color: #a0a0a0 !important;
+ margin-right: 0.4rem !important;
+ font-size: 0.78rem !important;
+ font-family: monospace !important;
+ opacity: 1 !important;
+ display: inline !important;
+}
+
+.chat-hub-messages.compact-container .message.compact .username,
+.messages.compact-container .message.compact .username {
+ font-weight: bold !important;
+ margin-right: 0.2rem !important;
+ font-size: 0.875rem !important;
+ display: inline !important;
+}
+
+.chat-hub-messages.compact-container .message.compact .messagetext,
+.messages.compact-container .message.compact .messagetext {
+ color: #1e293b !important;
+ white-space: normal !important;
+ word-break: break-word !important;
+ display: inline !important;
+ margin: 0 !important;
+}
+
+/* User Tooltip Styling (Standalone Fixed Floating Tooltip) */
+.user-tooltip {
+ position: fixed !important;
+ width: 280px !important;
+ background-color: #ffffe1 !important;
+ border: 1px solid #7f7f7f !important;
+ box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.25) !important;
+ padding: 0.5rem !important;
+ border-radius: 0.25rem !important;
+ z-index: 10000 !important;
+ white-space: normal !important;
+ display: flex !important;
+ gap: 0.5rem !important;
+ align-items: flex-start !important;
+ color: #000000 !important;
+ font-size: 0.8rem !important;
+ text-align: left !important;
+ pointer-events: none !important;
+}
+
+.user-tooltip .tooltip-avatar {
+ flex-shrink: 0 !important;
+}
+
+.user-tooltip .tooltip-avatar .jdenticon-avatar,
+.user-tooltip .tooltip-avatar .defaultAvatar,
+.user-tooltip .tooltip-avatar img.avatar {
+ width: 56px !important;
+ height: 56px !important;
+ min-width: 56px !important;
+ min-height: 56px !important;
+ border-radius: 2px !important;
+ border: 1px solid #999999 !important;
+ box-shadow: none !important;
+ object-fit: cover !important;
+}
+
+.user-tooltip .tooltip-details {
+ display: flex !important;
+ flex-direction: column !important;
+ gap: 0.2rem !important;
+ min-width: 0 !important;
+ flex: 1 !important;
+}
+
+.user-tooltip .tooltip-details .tooltip-row {
+ line-height: 1.2 !important;
+ display: flex !important;
+ flex-direction: row !important;
+ align-items: baseline !important;
+ gap: 0.35rem !important;
+ white-space: normal !important;
+ word-break: break-all !important;
+}
+
+.user-tooltip .tooltip-details .tooltip-row .tooltip-label {
+ font-weight: bold !important;
+ color: #000000 !important;
+ font-size: 0.8rem !important;
+ flex-shrink: 0 !important;
+}
+
+.user-tooltip .tooltip-details .tooltip-row .tooltip-value {
+ font-weight: normal !important;
+ color: #000000 !important;
+ font-size: 0.8rem !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+}
+
+.user-tooltip .tooltip-details .tooltip-row .tooltip-value.tooltip-id {
+ font-family: monospace !important;
+ font-size: 0.75rem !important;
+ color: #0000bb !important;
+}
+
+/* Chat Modal Dialogs (Create Room, Attach File, Invite Friends) */
+.attach-modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ background-color: rgba(15, 23, 42, 0.5);
+ backdrop-filter: blur(4px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+}
+
+.attach-modal {
+ background: #ffffff;
+ border-radius: 0.5rem;
+ width: 480px;
+ max-width: 92vw;
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ color: #1e293b;
+ box-sizing: border-box;
+}
+
+.attach-modal h4 {
+ margin: 0 0 1rem 0;
+ font-size: 1.15rem;
+ font-weight: 700;
+ color: #0f172a;
+}
+
+.attach-modal .attach-modal-header {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ margin-bottom: 1rem;
+}
+
+.attach-modal .attach-modal-header h4 {
+ margin: 0;
+}
+
+.attach-modal .attach-modal-header .attach-modal-icon {
+ font-size: 1.25rem;
+ color: #3b82f6;
+}
+
+/* Emoji Picker Dropdown & Grid Styling */
+.emoji-picker-wrapper {
+ position: relative;
+ display: inline-flex;
+}
+
+.emoji-picker {
+ position: absolute;
+ bottom: 48px;
+ left: 0;
+ z-index: 9999;
+ width: 320px;
+ background: #ffffff;
+ border: 1px solid #cbd5e1;
+ border-radius: 12px;
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
+ padding: 0.75rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ font-family: inherit;
+
+ .emoji-search-row {
+ position: relative;
+ display: flex;
+ align-items: center;
+
+ .emoji-search-icon {
+ position: absolute;
+ left: 0.6rem;
+ color: #94a3b8;
+ font-size: 0.85rem;
+ pointer-events: none;
+ }
+
+ input.emoji-search-input {
+ width: 100%;
+ padding: 0.4rem 1.8rem 0.4rem 1.8rem;
+ font-size: 0.85rem;
+ border: 1px solid #cbd5e1;
+ border-radius: 6px;
+ outline: none;
+ background-color: #f8fafc;
+ transition: border-color 0.15s ease;
+
+ &:focus {
+ border-color: #3b82f6;
+ background-color: #ffffff;
+ }
+ }
+
+ .emoji-search-clear {
+ position: absolute;
+ right: 0.5rem;
+ background: transparent;
+ border: none;
+ color: #94a3b8;
+ cursor: pointer;
+ padding: 0.2rem;
+ font-size: 0.85rem;
+
+ &:hover {
+ color: #ef4444;
+ }
+ }
+ }
+
+ .emoji-categories {
+ display: flex;
+ justify-content: space-between;
+ padding-bottom: 0.4rem;
+ border-bottom: 1px solid #f1f5f9;
+ margin-bottom: 0.25rem;
+
+ .emoji-cat-btn {
+ background: transparent !important;
+ border: none !important;
+ font-size: 1.1rem !important;
+ padding: 0.25rem 0.35rem !important;
+ border-radius: 6px !important;
+ cursor: pointer !important;
+ transition: background-color 0.15s ease, transform 0.1s ease !important;
+ line-height: 1 !important;
+ width: auto !important;
+ height: auto !important;
+ min-width: unset !important;
+
+ &:hover {
+ background-color: #f1f5f9 !important;
+ transform: scale(1.15);
+ }
+
+ &.active {
+ background-color: #e0f2fe !important;
+ border-radius: 6px !important;
+ }
+ }
+ }
+
+ .emoji-grid {
+ display: grid !important;
+ grid-template-columns: repeat(8, 1fr) !important;
+ gap: 2px !important;
+ max-height: 220px !important;
+ overflow-y: auto !important;
+ padding-right: 2px !important;
+
+ &::-webkit-scrollbar {
+ width: 5px;
+ }
+ &::-webkit-scrollbar-thumb {
+ background: #cbd5e1;
+ border-radius: 3px;
+ }
+
+ .emoji-btn {
+ background: transparent !important;
+ border: none !important;
+ font-size: 1.25rem !important;
+ padding: 0.35rem 0 !important;
+ cursor: pointer !important;
+ border-radius: 6px !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ width: auto !important;
+ height: auto !important;
+ min-width: unset !important;
+ transition: background-color 0.1s ease, transform 0.1s ease !important;
+
+ &:hover {
+ background-color: #e2e8f0 !important;
+ transform: scale(1.2);
+ }
+ }
+ }
+}
+
+/* Rightbar / Chat Participants Right-Click Context Menu */
+.rightbar-context-menu,
+.chat-msg-context-menu {
+ position: absolute !important;
+ z-index: 9999 !important;
+ right: 10px !important;
+ background-color: #ffffff !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 8px !important;
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1) !important;
+ padding: 0.35rem 0 !important;
+ min-width: 220px !important;
+ font-family: inherit !important;
+ overflow: hidden !important;
+
+ .menu-item,
+ .context-menu-item {
+ display: flex !important;
+ align-items: center !important;
+ padding: 0.55rem 0.85rem !important;
+ font-size: 0.875rem !important;
+ font-weight: 500 !important;
+ color: #1e293b !important;
+ cursor: pointer !important;
+ transition: background-color 0.15s ease, color 0.15s ease !important;
+ user-select: none !important;
+
+ &:hover {
+ background-color: #f1f5f9 !important;
+ color: #0284c7 !important;
+ }
+
+ i {
+ font-size: 0.95rem !important;
+ width: 1.25rem !important;
+ text-align: center !important;
+ }
+ }
+}
+
+/* User Avatar Hover Tooltip */
+.user-tooltip {
+ position: fixed !important;
+ z-index: 10000 !important;
+ background-color: #ffffff !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 12px !important;
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1) !important;
+ padding: 0.85rem 1rem !important;
+ display: flex !important;
+ gap: 0.85rem !important;
+ align-items: center !important;
+ min-width: 280px !important;
+ max-width: 380px !important;
+ pointer-events: none !important;
+ font-family: inherit !important;
+
+ .tooltip-avatar {
+ flex-shrink: 0 !important;
+ }
+
+ .tooltip-details {
+ display: flex !important;
+ flex-direction: column !important;
+ gap: 0.3rem !important;
+ flex: 1 !important;
+ min-width: 0 !important;
+
+ .tooltip-row {
+ display: flex !important;
+ align-items: center !important;
+ font-size: 0.85rem !important;
+ line-height: 1.3 !important;
+
+ .tooltip-label {
+ font-weight: 600 !important;
+ color: #64748b !important;
+ margin-right: 0.35rem !important;
+ flex-shrink: 0 !important;
+ }
+
+ .tooltip-value {
+ color: #1e293b !important;
+ font-weight: 500 !important;
+ word-break: break-all !important;
+
+ &.tooltip-id {
+ font-family: monospace !important;
+ font-size: 0.78rem !important;
+ color: #475569 !important;
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+@use '../abstracts' as *;
+
+.mail {
+ .permission-flag {
+ margin-bottom: 1rem;
+ @include flex($gap: 1rem);
+ }
+ &-tags {
+ padding: 0.5rem;
+ border: 1px solid transparentize($dark-color, 0.8);
+ border-radius: 6px;
+ &__container {
+ @include flex(column);
+ & .tag-item {
+ @include flex($align: center, $gap: 4px);
+ border-bottom: 1px solid transparentize($dark-color, 0.9);
+ padding: 2px 0;
+
+ &:last-child {
+ border: none;
+ }
+ &__color {
+ width: 1.25rem;
+ height: 1.25rem;
+ aspect-ratio: 1;
+ }
+ &__name {
+ font-size: 1.125rem;
+ }
+ &__modify {
+ margin-left: auto;
+ font-size: 0.75rem;
+ @include flex($gap: 4px);
+ }
+ &:hover {
+ background-color: $light-color;
+ }
+ & button,
+ & button.red {
+ padding: 0.25rem 0.6rem;
+ }
+ }
+ }
+ }
+}
+
+.mail-tags-form .input-field {
+ margin-bottom: 0.5rem;
+ label {
+ margin-right: 0.5rem;
+ }
+}
+
+.external-address {
+ margin: 0;
+ padding-left: 1rem;
+ height: 100px;
+ overflow: hidden auto;
+ &::-webkit-scrollbar {
+ display: none;
+ }
+}
+
+.proxy-server {
+ @include flex(column, $gap: 4px);
+ &__tor,
+ &__i2p {
+ & > h4 {
+ margin-bottom: 0.25rem;
+ }
+ & > input {
+ margin-right: 0.5rem;
+ }
+ .proxy-outgoing {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+ &__status {
+ width: 1rem;
+ height: 1rem;
+ aspect-ratio: 1;
+ border: 1px solid black;
+ border-radius: 50%;
+ }
+ }
+ }
+}
+
+.config-files {
+ @include flex(column, $gap: 1rem);
+}
+
+/* Hidden Service Configuration layout overrides */
+.proxy-server-container {
+ width: 100%;
+ @include flex(column, $gap: 1rem);
+}
+
+.proxy-description {
+ color: #334155;
+ font-size: 0.95rem;
+ margin-bottom: 0.5rem;
+}
+
+.proxy-rows-container {
+ @include flex(column, $gap: 0.75rem);
+ width: 100%;
+}
+
+.proxy-row {
+ display: grid;
+ grid-template-columns: 160px 220px 220px auto;
+ gap: 0.75rem;
+ align-items: center;
+ width: 100%;
+}
+
+.proxy-label {
+ font-size: 0.95rem;
+ font-weight: 500;
+ color: #1e293b;
+}
+
+.proxy-addr-input,
+.proxy-port-input {
+ width: 100% !important;
+ max-width: none !important;
+}
+
+.proxy-status-container {
+ @include flex($align: center, $gap: 0.5rem);
+}
+
+.proxy-status-bullet {
+ width: 14px;
+ height: 14px;
+ border-radius: 50%;
+ display: inline-block;
+ border: 1px solid #475569;
+}
+
+.proxy-status-text {
+ font-size: 0.95rem;
+ color: #1e293b;
+}
+
+
+
+
+@use '../abstracts/' as *;
+
+.file-view {
+ width: 100%;
+ padding: 1rem;
+ margin-top: 1.5rem;
+ border-radius: 8px;
+ border: 1px solid #ccc;
+ animation: fadein 0.5s;
+ &__heading {
+ @include flex($justify: space-between);
+ margin-bottom: 0.5rem;
+ &-chunk {
+ @include flex($gap: 1rem);
+ }
+ }
+ &__body {
+ @include flex(column, $gap: 1rem);
+ &-details {
+ @include flex($align: center);
+ &-stat {
+ width: 100%;
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ & span > i {
+ margin-right: 0.5rem;
+ }
+ }
+ &-action {
+ @include flex($gap: 1rem);
+ height: 100%;
+ & button,
+ & button.red {
+ padding: 0.25rem 0.75rem;
+ }
+ }
+ }
+ }
+}
+
+table.myfiles td {
+ word-wrap: break-word;
+}
+table.myfiles th:nth-child(1) {
+ width: 2%;
+}
+table.myfiles th:nth-child(2) {
+ width: 50%;
+}
+table.myfiles td:nth-child(2) {
+ text-align: start;
+}
+table.friendsfiles td {
+ word-wrap: break-word;
+}
+table.friendsfiles th:nth-child(1) {
+ width: 2%;
+}
+table.friendsfiles th:nth-child(2) {
+ width: 50%;
+}
+table.friendsfiles th:nth-child(4) {
+ width: 40%;
+}
+table.friendsfiles td:nth-child(2) {
+ text-align: start;
+}
+
+// File Search
+.file-search-container {
+ margin-top: 1rem;
+ padding: 8px;
+ @include flex($gap: 8px);
+ border: 1px solid transparentize($dark-color, 0.8);
+ border-radius: 6px;
+ height: 100%;
+ overflow: auto;
+
+ &__keywords {
+ flex-basis: 15%;
+ padding-right: 0.25rem;
+ border-right: 1px solid transparentize($dark-color, 0.9);
+
+ & .keywords-container {
+ @include flex(column);
+ border-top: 2.5px solid transparentize($dark-color, 0.92);
+ margin-top: 0.125rem;
+ padding-top: 0.25rem;
+
+ & a {
+ font-size: 1.2rem;
+ text-decoration: none;
+ color: $dark-color;
+
+ &.selected {
+ color: $primary-color;
+ }
+ }
+ }
+ }
+
+ &__results {
+ flex-basis: 85%;
+ height: 100%;
+ overflow: auto;
+
+ & .results-container {
+ & .results-header {
+ & tr {
+ display: flex;
+ & th {
+ font-size: 1.25rem;
+ font-weight: bold;
+ text-align: left;
+
+ &:nth-child(1) {
+ flex-basis: 40%;
+ }
+ &:nth-child(2) {
+ flex-basis: 10%;
+ text-align: center;
+ }
+ &:nth-child(3) {
+ flex-basis: 40%;
+ }
+ &:nth-child(4) {
+ flex-basis: 10%;
+ }
+ }
+ }
+ }
+ & .results {
+ height: 100%;
+ overflow: auto;
+ & tr {
+ display: flex;
+ & .results {
+ &__hash,
+ &__name {
+ text-align: left;
+ flex-basis: 40%;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ span {
+ margin-left: 8px;
+ }
+ }
+ &__size {
+ flex-basis: 10%;
+ }
+ &__download {
+ flex-basis: 10%;
+ @include flex($justify: start, $align: center);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+.search-form {
+ display: flex;
+ width: 40%;
+ input {
+ width: 100%;
+ }
+ button {
+ margin-left: 0.5rem;
+ }
+}
+
+.shareManagerPopupOverlay {
+ @include popupOverlay;
+ .shareManagerPopup {
+ position: absolute;
+ inset: 0;
+ margin: auto;
+ width: 80%;
+ height: 90%;
+ & > .widget {
+ padding: 1.5rem;
+ }
+ & .close-btn {
+ position: absolute;
+ top: 1.5rem;
+ right: 1.5rem;
+ }
+ }
+}
+
+.share-manager {
+ @include flex(column, $justify: space-between);
+ &__table {
+ margin: 1rem 0 auto;
+ thead {
+ font-weight: bold;
+ text-align: left;
+ td:nth-child(1),
+ td:nth-child(2) {
+ padding-left: 0.5rem;
+ }
+ td:nth-child(3),
+ td:nth-child(4) {
+ & .tooltip {
+ font-weight: normal;
+ font-size: 1rem;
+ }
+ }
+ }
+ tbody {
+ text-align: left;
+ td:nth-child(4) {
+ font-size: 1rem;
+ }
+ }
+ td {
+ input {
+ border: 0 !important;
+ &[type='text'] {
+ width: 100%;
+ }
+ }
+ &:nth-child(1) {
+ width: 45%;
+ }
+ &:nth-child(2) {
+ width: 20%;
+ }
+ &:nth-child(3) {
+ width: 10%;
+ }
+ &:nth-child(4) {
+ width: 25%;
+ }
+ }
+ }
+ &__actions {
+ @include flex($justify: space-between);
+ }
+ &__form {
+ @include flex(column, $gap: 0.5rem);
+ &_input {
+ @include flex(column, $gap: 0.5rem);
+ input {
+ flex-grow: 1;
+ }
+ }
+ }
+
+ .share-flags {
+ /* hide checkbox */
+ input.share-flags-check {
+ display: none;
+ /* use label with 'for' to manipulate checkbox */
+ & + label.share-flags-label {
+ color: grey;
+ margin-right: 0.25rem;
+ padding: 0.25rem 0.25rem 0.125rem;
+ border: 1px solid #6d6d6d;
+ border-radius: 0.5rem;
+ }
+ &:checked + label.share-flags-label {
+ color: $primary-retro-color;
+ }
+ }
+ }
+ label span {
+ display: inline-block;
+ width: 1.125rem;
+ }
+}
+.manage-visibility {
+ label {
+ width: 100%;
+ cursor: pointer;
+ }
+ @include flex($justify: space-between);
+}
+
+/* FILES MODULE RESPONSIVENESS */
+@media (max-width: 700px) {
+
+ /* General Files Layout */
+ .file-view__body-details {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ }
+
+ /* File Detail Grid (Downloads/Uploads) */
+ .file-view__body-details-stat {
+ grid-template-columns: 1fr;
+ gap: 0.5rem;
+ }
+
+ .file-view__body-details-stat span {
+ display: flex;
+ align-items: center;
+ }
+
+ /* Share Manager Table -> Cards */
+ .share-manager__table,
+ .share-manager__table thead,
+ .share-manager__table tbody,
+ .share-manager__table tr,
+ .share-manager__table td {
+ display: block;
+ width: 100% !important;
+ }
+
+ .share-manager__table thead {
+ display: none;
+ /* Hide header on mobile */
+ }
+
+ .share-manager__table tr {
+ border: 1px solid #ccc;
+ border-radius: 8px;
+ margin-bottom: 1rem;
+ padding: 0.5rem;
+ background: white;
+ }
+
+ .share-manager__table td {
+ margin-bottom: 0.5rem;
+ border: none !important;
+ padding-left: 0 !important;
+ }
+
+ /* My Files / Friends Files Tables -> Cards */
+ table.myfiles,
+ table.myfiles tr,
+ table.myfiles td,
+ table.friendsfiles,
+ table.friendsfiles tr,
+ table.friendsfiles td {
+ display: block;
+ width: 100% !important;
+ }
+
+ table.myfiles th,
+ table.friendsfiles th {
+ display: none;
+ }
+
+ table.myfiles tr,
+ table.friendsfiles tr {
+ border: 1px solid #ccc;
+ border-radius: 8px;
+ margin-bottom: 1rem;
+ padding: 0.5rem;
+ background: white;
+ }
+
+ /* Search Container Layout */
+ .file-search-container {
+ flex-direction: column;
+ }
+
+ .file-search-container__keywords {
+ flex-basis: auto;
+ width: 100%;
+ border-right: none;
+ border-bottom: 1px solid rgba(20, 20, 27, 0.1);
+ padding-bottom: 1rem;
+ margin-bottom: 1rem;
+ }
+
+ /* Search results table -> cards */
+ .results-container,
+ .results-container thead,
+ .results-container tbody,
+ .results-container tr,
+ .results-container td {
+ display: block;
+ width: 100% !important;
+ }
+
+ .results-container thead {
+ display: none;
+ }
+
+ .results-container tr {
+ border-bottom: 1px solid #eee;
+ padding: 1rem 0;
+ }
+
+ .results-container td {
+ margin-bottom: 0.5rem;
+ word-break: break-all;
+ }
+}
+
+
+
+.forums-node-panel {
+ position: relative;
+ bottom: 200px;
+ margin-left: 200px;
+ animation: fadein 0.5s;
+}
+
+/* subject */
+table.forums th:nth-child(1) {
+ width: 50%;
+ text-align: start;
+}
+/* subject */
+table.forums td:nth-child(1) {
+ text-align: start;
+ /* Truncate text with '...' */
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+table.forums tr:hover {
+ background-color: #eef3f6;
+ cursor: pointer;
+}
+
+table.forums tr.hidden {
+ display: none;
+}
+
+#searchforum {
+ position: relative;
+ margin-left: 250px;
+ /* top: 50px; */
+}
+
+#forumdetails {
+ position: relative;
+ padding: 10px;
+}
+.p {
+ margin: 0;
+}
+#toggleunsub {
+ position: relative;
+ background: gray;
+}
+
+table.threads tr:hover {
+ background-color: #eef3f6;
+ cursor: pointer;
+}
+table.threads td {
+ word-wrap: break-word;
+}
+table.threadreply th:nth-child(2) {
+ width: 50%;
+}
+table.threadreply th:nth-child(1) {
+ width: 2%;
+}
+table.threadreply td:nth-child(2) {
+ width: 50%;
+ text-align: start;
+}
+table.threadreply td {
+ word-wrap: break-word;
+}
+table.threadreply tr:hover {
+ background-color: #eef3f6;
+ cursor: pointer;
+}
+
+
+
+@use 'sass:color';
+@use '../abstracts' as *;
+
+.homepage {
+ margin: 2rem auto 0;
+ @include flex(column, $gap: 4rem);
+
+ .logo {
+ @include flex($justify: center, $align: center);
+
+ & img {
+ width: 90px;
+ }
+
+ .retroshareText {
+ @include flex(column, $align: center);
+
+ & .retrotext {
+ font-size: 36px;
+ font-weight: 600;
+ line-height: 1.125;
+
+ &>span {
+ color: $primary-retro-color;
+ }
+ }
+
+ &>b {
+ font-size: 14px;
+ line-height: 1;
+ }
+ }
+ }
+
+ .certificate {
+ @include flex(column, $gap: 4rem);
+
+ &__heading {
+ text-align: center;
+
+ &>h1 {
+ margin-bottom: 1rem;
+ }
+ }
+
+ &__content {
+ @include flex(column, $gap: 2rem);
+ padding: 2rem;
+ text-align: center;
+ border: 1.5px solid color.adjust($primary-retro-color, $alpha: -0.8);
+ border-radius: 6px;
+ box-shadow: 0px 0px 8px 2px color.adjust($dark-color, $alpha: -0.95);
+
+ .rsId>p {
+ margin-bottom: 0.5rem;
+ color: $primary-retro-color;
+ }
+
+ .retroshareID {
+ padding: 0.25rem;
+ @include flex($align: center);
+ justify-self: start;
+ font-size: 1.25rem;
+ border-radius: 4px;
+ background: color.adjust($dark-color, $alpha: -0.95);
+
+ & .textArea {
+ padding: 0;
+ width: 100%;
+ height: auto;
+ font-size: 1rem;
+ font-family: monospace;
+ background: transparent;
+ border: none;
+ resize: none;
+ overflow: hidden;
+ field-sizing: content;
+ }
+
+ & i {
+ color: $primary-retro-color;
+ }
+
+ &>i {
+ margin: 0 0.5rem;
+ cursor: pointer;
+ }
+ }
+
+ .webhelp {
+ padding: 0.5rem;
+ background: whitesmoke;
+ @include flex($justify: center, $align: center, $gap: 0.5rem);
+ border-radius: 4px;
+ border: 1px solid color.adjust($dark-color, $alpha: -0.5);
+ width: fit-content;
+ cursor: pointer;
+
+ &-container {
+ display: grid;
+ place-items: center;
+ }
+
+ &:hover {
+ background: $light-color;
+ border: 1px solid $dark-color;
+ }
+
+ &>i {
+ font-size: 1.2rem;
+ color: green;
+ }
+ }
+
+ .add-friend>h6,
+ .webhelp-container>h6 {
+ font-weight: normal;
+ margin-bottom: 0.5rem;
+ }
+ }
+ }
+}
+
+/* Responsive Mobile Home Page Styles */
+@media (max-width: 768px) {
+ .homepage {
+ margin: 1rem auto !important;
+ padding: 0 1rem !important;
+ gap: 2rem !important;
+ max-width: 100% !important;
+ box-sizing: border-box !important;
+
+ .logo {
+ flex-direction: column !important;
+ gap: 0.5rem !important;
+ text-align: center !important;
+
+ & img {
+ width: 60px !important;
+ }
+
+ .retroshareText {
+ .retrotext {
+ font-size: 1.6rem !important;
+ }
+ & > b {
+ font-size: 0.75rem !important;
+ }
+ }
+ }
+
+ .certificate {
+ gap: 2rem !important;
+
+ &__heading {
+ & > h1 {
+ font-size: 1.35rem !important;
+ margin-bottom: 0.5rem !important;
+ }
+ font-size: 0.85rem !important;
+ }
+
+ &__content {
+ padding: 1rem 0.75rem !important;
+ gap: 1.25rem !important;
+
+ .retroshareID {
+ padding: 0.5rem !important;
+ font-size: 0.85rem !important;
+ max-width: 100% !important;
+
+ .textArea {
+ font-size: 0.8rem !important;
+ word-break: break-all !important;
+ overflow-wrap: anywhere !important;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+@forward "login";
+@forward "home";
+@forward "network";
+@forward "people";
+@forward "chat";
+@forward "mail";
+@forward "files";
+@forward "channel";
+@forward "forums";
+@forward "board";
+@forward "config";
+
+
+
+@use 'sass:color';
+@use '../abstracts' as *;
+
+.login-page {
+ background-image: linear-gradient(-45deg,
+ color.adjust($primary-color, $alpha: -0.25),
+ color.adjust($primary-retro-color, $alpha: -0.25));
+ height: 100%;
+ animation: fadein 0.5s;
+
+ .login-container {
+ background-color: white;
+ box-shadow: 3px 3px 5px color.adjust($dark-color, $alpha: -0.6);
+ margin: auto;
+ position: relative;
+ top: 100px;
+ max-width: 400px;
+ max-height: 500px;
+ border-radius: 5px;
+ @include flex(column, $align: center);
+
+ & input {
+ padding: 0.375rem 0.75rem;
+ border-radius: 0.275rem;
+ }
+
+ & * {
+ margin-bottom: 1rem;
+ }
+
+ &>img {
+ margin: 1rem 0 2rem;
+ }
+
+ & extra {
+ margin: 0;
+ }
+
+ &>a {
+ text-decoration: underline;
+ cursor: pointer;
+ }
+ }
+
+ .extra>label,
+ .extra>br,
+ .extra>input {
+ margin-bottom: 0;
+ }
+}
+
+
+@use '../abstracts/' as *;
+
+.side-bar {
+ @include flex(column);
+ background: white;
+ .mail-compose-btn {
+ width: 96%;
+ margin: 0.25rem;
+ padding: 0.75rem 0;
+ }
+
+ .sidebar a,
+ .sidebarquickview a {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ }
+
+ .sidebar-badge {
+ margin-left: auto;
+ background-color: #3b82f6;
+ color: #ffffff;
+ font-size: 0.725rem;
+ font-weight: 700;
+ padding: 0.15rem 0.45rem;
+ border-radius: 999px;
+ line-height: 1;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 1.2rem;
+ }
+}
+
+.compose-mail {
+ &__from {
+ @include flex($justify: flex-start, $align: center, $gap: 0.5rem);
+ padding-bottom: 0.5rem;
+ border-bottom: 2px solid $light-color;
+ }
+ &__recipients {
+ padding: 0.5rem 0;
+ @include flex(column, $gap: 0.5rem);
+ border-bottom: 2px solid $light-color;
+ &__container {
+ @include flex($gap: 0.5rem);
+ & > label {
+ text-transform: capitalize;
+ }
+ .recipients {
+ width: 100%;
+ @include flex($gap: 0.5rem);
+ flex-wrap: wrap;
+ &__selected {
+ padding: 0.125rem 0.5rem;
+ @include flex($align: center, $gap: 0.5rem);
+ border: 1px solid $light-color;
+ border-radius: 3px;
+ cursor: default;
+ & i {
+ cursor: pointer;
+ padding: 0.25rem;
+ }
+ }
+ &__input {
+ display: flex;
+ position: relative;
+ flex-grow: 1;
+ &-field {
+ flex-grow: 1;
+ min-width: 200px;
+ padding: 0;
+ border: none;
+ box-shadow: none;
+ &:focus + .recipients__input-list {
+ display: flex;
+ }
+ }
+ &-list {
+ z-index: 1;
+ position: absolute;
+ top: 1rem;
+ padding: 0;
+ width: 100%;
+ max-height: 15rem;
+ flex-direction: column;
+ overflow: auto;
+ display: none;
+ background: white;
+ border-top: 1px solid $light-color;
+ border-bottom: 1px solid $light-color;
+ &:hover {
+ display: flex;
+ }
+ & li {
+ list-style: none;
+ padding: 0.25rem 0.5rem;
+ cursor: pointer;
+ background: white;
+ border: 1px solid $light-color;
+ border-top: 0px;
+ &:hover {
+ background: $light-color;
+ }
+ &:last-child {
+ border-bottom: 0px;
+ }
+ }
+ }
+ }
+ }
+ }
+ .remove-recipient {
+ padding: 0.125rem 0.5rem;
+ }
+ }
+ input[type='text'].compose-mail__subject {
+ padding: 0.5rem 0;
+ border: none;
+ box-shadow: none;
+ border-bottom: 2px solid $light-color;
+ border-radius: 0;
+ }
+ &__message {
+ margin: 0.5rem 0;
+ height: 100%;
+ @include flex(column);
+ overflow: auto;
+ &-body {
+ height: 100%;
+ outline: transparent;
+ }
+ }
+ &__send-btn {
+ @include flex($align: center, $gap: 0.5rem);
+ & i {
+ transform: translateY(-1px);
+ }
+ }
+}
+
+.msg-view {
+ height: 100%;
+ @include flex(column, $gap: 1rem);
+ overflow: auto;
+ &-nav {
+ @include flex($justify: space-between, $align: column);
+ &__action {
+ @include flex($gap: 0.5rem);
+ }
+ }
+ &__header {
+ @include flex(column, $gap: 1rem);
+ & > h3 {
+ line-height: 1;
+ }
+ & .msg-details {
+ @include flex($gap: 1rem);
+ &__avatar {
+ height: max-content;
+ }
+ &__info {
+ @include flex(column);
+ &-item {
+ @include flex($gap: 0.5rem);
+ }
+ }
+ }
+ }
+ &__body {
+ height: 100%;
+ overflow: auto;
+ font-size: 14px !important;
+ }
+ &__attachment {
+ height: 50%;
+ overflow: auto;
+ @include flex(column);
+ &-items {
+ height: 100%;
+ overflow: auto;
+ }
+ }
+}
+
+.mail-tag {
+ width: 8rem;
+ padding: 0.5rem;
+}
+.msgHeader {
+ display: flex;
+}
+.msgHeaderDetails {
+ @include flex(column);
+}
+
+table.mails {
+ & th {
+ /* star */
+ &:nth-child(1) {
+ width: 5%;
+ color: $golden-yellow-color;
+ }
+ /* attachments */
+ &:nth-child(2) {
+ width: 5%;
+ color: darken($light-color, 50%);
+ }
+ /* subject */
+ &:nth-child(3) {
+ width: 50%;
+ text-align: start;
+ }
+ /* From */
+ &:nth-child(4),
+ /* date */
+ &:nth-child(5) {
+ width: 20%;
+ text-align: start;
+ }
+ }
+
+ & td {
+ /* subject */
+ &:nth-child(3) {
+ text-align: start;
+ /* Truncate text with '...' */
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ /* From */
+ &:nth-child(4),
+ /* date */
+ &:nth-child(5) {
+ text-align: start;
+ }
+ }
+
+ & tr {
+ &:hover {
+ background-color: $light-color;
+ cursor: pointer;
+ }
+ &.unread {
+ color: black;
+ background-color: $light-color;
+ }
+ }
+
+ //Remove hover effects from the table head
+ & > tr:hover {
+ cursor: auto;
+ background-color: white;
+ }
+
+ & th.sortable-th {
+ cursor: pointer;
+ user-select: none;
+ transition: background-color 0.2s, color 0.2s;
+
+ &:hover {
+ background-color: $light-color;
+ color: darken($light-color, 80%);
+ }
+ }
+}
+
+/* hide checkbox */
+input.star-check {
+ display: none;
+ /* use label with 'for' to manipulate checkbox */
+ & + label.star-check {
+ color: grey;
+ }
+ &:checked + label.star-check {
+ color: $golden-yellow-color;
+ }
+}
+
+/* mail_util.js styles */
+#truncate {
+ height: 6rem;
+ overflow: auto;
+ &.truncated-view {
+ height: 1.75rem;
+ overflow: hidden;
+ }
+}
+.toggle-truncate {
+ font-size: 0.75rem;
+ padding: 0 0.25rem;
+ background: #999;
+ color: $dark-color;
+ box-shadow: none;
+ border-radius: 2px;
+}
+
+// Normal mail attachment view
+table.attachment-container {
+ padding: 0;
+
+ & > tr {
+ border: 0;
+ }
+
+ .attachment-header {
+ width: 100%;
+ @include flex($justify: space-between);
+
+ th {
+ text-align: start;
+
+ &:nth-child(1) {
+ flex-basis: 45%;
+ }
+ &:nth-child(2) {
+ flex-basis: 15%;
+ }
+ &:nth-child(3) {
+ flex-basis: 10%;
+ }
+ &:nth-child(4) {
+ flex-basis: 20%;
+ }
+ &:nth-child(5) {
+ text-align: center;
+ flex-basis: 10%;
+ }
+ }
+ }
+
+ .attachment {
+ width: 100%;
+ @include flex($justify: space-between);
+ text-align: start;
+
+ &__name {
+ flex-basis: 45%;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ span {
+ margin-left: 8px;
+ }
+ }
+
+ &__from {
+ flex-basis: 15%;
+ }
+ &__size {
+ flex-basis: 10%;
+ }
+ &__date {
+ flex-basis: 20%;
+ }
+ & td:nth-child(5) {
+ @include flex($justify: center, $align: center);
+ flex-basis: 10%;
+
+ & button {
+ font-size: 0.875rem;
+ }
+ }
+ }
+}
+
+// Attachment Section attachment view
+.view-toggle {
+ height: max-content;
+ border: 1px solid $primary-color;
+ border-radius: 4px;
+ display: flex;
+
+ & * {
+ padding: 4px 12px;
+ border-radius: 4px;
+ }
+}
+
+.composePopupOverlay {
+ @include popupOverlay;
+ .composePopup {
+ position: absolute;
+ inset: 0;
+ margin: auto;
+ width: 80%;
+ height: 90%;
+ & > .widget {
+ padding: 2rem;
+ }
+ & .close-btn {
+ position: absolute;
+ top: 1.5rem;
+ right: 1.5rem;
+ }
+ }
+}
+
+/* Modern Attachment Card Styling */
+.attachments-wrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ margin-top: 0.5rem;
+}
+
+.attachment-card {
+ background: #ffffff;
+ border: 1px solid #e2e8f0;
+ border-radius: 0.5rem;
+ padding: 0.75rem 1rem;
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
+
+ .attachment-icon {
+ width: 40px;
+ height: 40px;
+ border-radius: 0.5rem;
+ background: #eff6ff;
+ color: #3b82f6;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.2rem;
+ flex-shrink: 0;
+ }
+
+ .attachment-info {
+ flex: 1;
+ min-width: 0;
+
+ .attachment-name {
+ font-weight: 600;
+ font-size: 0.9rem;
+ color: #1e293b;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .attachment-size {
+ font-size: 0.75rem;
+ color: #64748b;
+ }
+ }
+
+ .btn-attachment-download {
+ padding: 0.4rem 0.75rem;
+ font-size: 0.8rem;
+ height: 34px;
+ }
+}
+
+.mobile-fab-compose {
+ display: none;
+}
+
+/* Mobile Responsiveness for Mail UI */
+@media (max-width: 768px) {
+ .side-bar {
+ width: 100% !important;
+ flex-direction: row !important;
+ overflow-x: auto !important;
+ overflow-y: hidden !important;
+ white-space: nowrap !important;
+ border-bottom: 1px solid #cbd5e1 !important;
+ padding: 0.5rem !important;
+ flex-shrink: 0 !important;
+ background: #ffffff !important;
+ }
+
+ .side-bar .mail-compose-btn {
+ display: none !important;
+ }
+
+ .side-bar .sidebar {
+ width: auto !important;
+ flex-direction: row !important;
+ gap: 0.25rem !important;
+ }
+
+ .side-bar .sidebar a {
+ padding: 0.5rem 0.75rem !important;
+ font-size: 0.85rem !important;
+ border-radius: 0.375rem !important;
+ border-left: none !important;
+ border-bottom: none !important;
+ display: inline-flex !important;
+ align-items: center !important;
+ gap: 0.35rem !important;
+ }
+
+ .side-bar .sidebar a .sidebar-link-text {
+ display: none !important;
+ }
+
+ .side-bar .sidebar a i {
+ margin-right: 0 !important;
+ font-size: 1.1rem !important;
+ }
+
+ .side-bar .sidebar a .sidebar-badge {
+ margin-left: 0 !important;
+ background: #3b82f6 !important;
+ color: #ffffff !important;
+ font-size: 0.7rem !important;
+ font-weight: 700 !important;
+ padding: 0.15rem 0.4rem !important;
+ border-radius: 999px !important;
+ line-height: 1 !important;
+ }
+
+ .side-bar .sidebar a.selected-sidebar-link {
+ background-color: #e0f2fe !important;
+ color: #0369a1 !important;
+ border-left: none !important;
+ font-weight: 600 !important;
+ }
+
+ .side-bar .sidebarquickview {
+ display: none !important; /* Hide quickview tags on mobile bar; filter via colored dropdown */
+ }
+
+ select.mail-tag {
+ padding: 0.45rem 0.75rem !important;
+ border-radius: 0.5rem !important;
+ border: 1px solid #cbd5e1 !important;
+ font-size: 0.85rem !important;
+ font-weight: 600 !important;
+ background-color: #ffffff !important;
+ color: #1e293b !important;
+ outline: none !important;
+ cursor: pointer !important;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
+ }
+
+ .node-panel {
+ width: 100% !important;
+ flex: 1 !important;
+ padding: 0.5rem !important;
+ overflow: auto !important;
+ }
+
+ /* Mail List Table -> Mobile Card List View */
+ .table-pagination-container table.mails {
+ display: block !important;
+ width: 100% !important;
+ }
+
+ .table-pagination-container table.mails tr:first-child {
+ display: none !important;
+ }
+
+ .table-pagination-container table.mails tbody {
+ display: flex !important;
+ flex-direction: column !important;
+ gap: 0.5rem !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody {
+ display: flex !important;
+ flex-direction: column !important;
+ padding: 0.85rem !important;
+ background: #ffffff !important;
+ border: 1px solid #e2e8f0 !important;
+ border-radius: 0.65rem !important;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03) !important;
+ position: relative !important;
+ margin-bottom: 0.25rem !important;
+ transition: all 0.2s ease !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody.unread {
+ background: #f0f9ff !important;
+ border-color: #bae6fd !important;
+ border-left: 4px solid #0284c7 !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody td {
+ display: block !important;
+ padding: 0 !important;
+ border: none !important;
+ }
+
+ /* Top Row: Sender Info & Date */
+ .table-pagination-container table.mails tr.msgbody td.cell-from {
+ order: 1 !important;
+ margin-bottom: 0.35rem !important;
+ padding-right: 5rem !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody td.cell-from div {
+ display: flex !important;
+ align-items: center !important;
+ gap: 0.5rem !important;
+ width: 100% !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody td.cell-from div .jdenticon-avatar,
+ .table-pagination-container table.mails tr.msgbody td.cell-from div .defaultAvatar,
+ .table-pagination-container table.mails tr.msgbody td.cell-from div img.avatar {
+ flex-shrink: 0 !important;
+ width: 28px !important;
+ height: 28px !important;
+ min-width: 28px !important;
+ min-height: 28px !important;
+ aspect-ratio: 1 / 1 !important;
+ object-fit: cover !important;
+ border-radius: 50% !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody td.cell-from div span {
+ font-weight: 700 !important;
+ font-size: 0.95rem !important;
+ color: #1e293b !important;
+ white-space: nowrap !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody td.cell-date {
+ order: 2 !important;
+ position: absolute !important;
+ top: 0.85rem !important;
+ right: 0.85rem !important;
+ font-size: 0.75rem !important;
+ font-weight: 600 !important;
+ color: #64748b !important;
+ white-space: nowrap !important;
+ }
+
+ /* Subject Row */
+ .table-pagination-container table.mails tr.msgbody td.cell-subject {
+ order: 3 !important;
+ margin-bottom: 0.25rem !important;
+ font-size: 0.9rem !important;
+ color: #334155 !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody td.cell-subject span {
+ font-weight: 600 !important;
+ }
+
+ /* Star & Attachments */
+ .table-pagination-container table.mails tr.msgbody td.cell-star {
+ order: 4 !important;
+ position: absolute !important;
+ bottom: 0.75rem !important;
+ right: 0.85rem !important;
+ }
+
+ .table-pagination-container table.mails tr.msgbody td.cell-attachment {
+ order: 5 !important;
+ position: absolute !important;
+ bottom: 0.75rem !important;
+ right: 2.5rem !important;
+ color: #64748b !important;
+ }
+
+ /* Mail Reader (MessageView) Mobile Layout */
+ .msg-view {
+ padding: 0.5rem !important;
+ gap: 0.75rem !important;
+ }
+
+ .msg-view .msg-view-nav {
+ background: #ffffff !important;
+ padding: 0.5rem 0.75rem !important;
+ border-radius: 0.5rem !important;
+ border: 1px solid #e2e8f0 !important;
+ }
+
+ .msg-view .msg-view-nav__action button {
+ padding: 0.45rem 0.65rem !important;
+ min-width: 38px !important;
+ height: 38px !important;
+ justify-content: center !important;
+ }
+
+ .msg-view .msg-view-nav__action button .btn-text {
+ display: none !important;
+ }
+
+ .msg-view .msg-view-nav__action button i {
+ margin: 0 !important;
+ font-size: 1rem !important;
+ }
+
+ .msg-view__header {
+ background: #ffffff !important;
+ padding: 1rem !important;
+ border-radius: 0.5rem !important;
+ border: 1px solid #e2e8f0 !important;
+ }
+
+ .msg-view__header h3 {
+ font-size: 1.25rem !important;
+ font-weight: 800 !important;
+ color: #0f172a !important;
+ line-height: 1.3 !important;
+ }
+
+ .msg-view__body {
+ background: #ffffff !important;
+ padding: 1rem !important;
+ border-radius: 0.5rem !important;
+ border: 1px solid #e2e8f0 !important;
+ font-size: 0.95rem !important;
+ line-height: 1.6 !important;
+ color: #1e293b !important;
+ }
+
+ .msg-view__attachment {
+ height: auto !important;
+ }
+
+ /* Floating Action Button (Compose Mail) */
+ .mobile-fab-compose {
+ position: fixed !important;
+ bottom: 1.75rem !important;
+ right: 1.5rem !important;
+ width: 54px !important;
+ height: 54px !important;
+ border-radius: 50% !important;
+ background: linear-gradient(135deg, #3b82f6, #2563eb) !important;
+ color: #ffffff !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ font-size: 1.35rem !important;
+ box-shadow: 0 4px 14px rgba(37, 99, 235, 0.45) !important;
+ border: none !important;
+ z-index: 1000 !important;
+ cursor: pointer !important;
+ transition: transform 0.2s ease !important;
+ }
+
+ .mobile-fab-compose:active {
+ transform: scale(0.92) !important;
+ }
+
+ .composePopupOverlay .composePopup {
+ width: 95% !important;
+ height: 95% !important;
+ }
+}
+
+.mail-mobile-nav-toggle { display: none; }
+.mail-nav-drawer { display: contents; }
+.mail-mobile-box-title { display: none; }
+
+/* Mail folders become a left drawer on phones. */
+@media (max-width: 768px) {
+ .side-bar {
+ height: 44px !important;
+ padding: .25rem !important;
+ overflow: visible !important;
+ }
+
+ .mail-mobile-nav-toggle {
+ display: inline-flex !important;
+ width: 40px;
+ height: 40px;
+ align-items: center;
+ justify-content: center;
+ border: 0;
+ border-radius: 6px;
+ background: #ffffff;
+ color: #0f172a;
+ cursor: pointer;
+ font-size: 1.15rem;
+ }
+
+ .mail-nav-drawer {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1100;
+ display: flex !important;
+ flex-direction: column;
+ width: min(82vw, 300px);
+ height: 100dvh;
+ padding: 1rem 0;
+ overflow-y: auto;
+ background: #ffffff;
+ border-right: 1px solid #e2e8f0;
+ box-shadow: 8px 0 24px rgba(15, 23, 42, .16);
+ transform: translateX(-105%);
+ transition: transform 180ms ease;
+ }
+
+ .mail-nav-drawer--open { transform: translateX(0); }
+ .mail-mobile-box-title {
+ display: flex !important;
+ align-items: center;
+ gap: .55rem;
+ margin: .35rem 0 .55rem;
+ color: #0f172a;
+ font-size: 1.45rem;
+ font-weight: 600;
+ }
+ .mail-mobile-box-title i { color: #3b82f6; font-size: 1.35rem; }
+ .mail-box-content > .widget__heading { display: none; }
+ .mail-nav-drawer .mail-compose-btn { display: flex !important; margin: 0 .85rem .75rem !important; }
+ .mail-nav-drawer .sidebar,
+ .mail-nav-drawer .sidebarquickview { display: flex !important; flex-direction: column !important; width: 100% !important; }
+ .mail-nav-drawer .sidebarquickview { margin-top: .5rem; border-top: 1px solid #e2e8f0; padding-top: .5rem; }
+ .mail-nav-drawer .sidebarquickview h6 { display: block !important; margin: 0 .9rem .35rem; color: #64748b; }
+ .mail-nav-drawer .sidebar a,
+ .mail-nav-drawer .sidebarquickview a { display: flex !important; width: auto; padding: .7rem 1rem !important; border-radius: 0 !important; }
+ .mail-nav-drawer .sidebar a .sidebar-link-text { display: inline !important; }
+ .mail-nav-drawer .sidebar a i { margin-right: .75rem !important; font-size: 1.1rem !important; }
+}
+
+
+
+@use '../abstracts' as *;
+
+.network-container {
+ display: flex;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ background-color: #f1f5f9;
+}
+
+.network-left-pane {
+ width: 320px;
+ min-width: 300px;
+ max-width: 350px;
+ border-right: 1px solid #cbd5e1;
+ display: flex;
+ flex-direction: column;
+ background: #ffffff;
+ box-shadow: 2px 0 5px rgba(0, 0, 0, 0.05);
+}
+
+.own-profile-card {
+ padding: 1.25rem;
+ border-bottom: 1px solid #e2e8f0;
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+
+ .profile-header {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ }
+
+ .profile-info {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ overflow: hidden;
+
+ .profile-name {
+ font-weight: 700;
+ color: #1e293b;
+ font-size: 1.1rem;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .profile-status {
+ font-size: 0.85rem;
+ color: #10b981;
+ font-weight: 500;
+ display: flex;
+ align-items: center;
+ gap: 0.35rem;
+
+ &::before {
+ content: '';
+ display: inline-block;
+ width: 8px;
+ height: 8px;
+ background-color: #10b981;
+ border-radius: 50%;
+ }
+ }
+ }
+
+ .own-identity-select-container {
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+
+ label {
+ font-size: 0.75rem;
+ color: #64748b;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ }
+
+ select.own-identity-select {
+ width: 100%;
+ padding: 0.375rem 0.5rem;
+ font-size: 0.85rem;
+ border: 1px solid #cbd5e1;
+ border-radius: 0.375rem;
+ background-color: #ffffff;
+ color: #334155;
+ outline: none;
+ cursor: pointer;
+ transition: border-color 0.2s;
+
+ &:focus {
+ border-color: #3ba4d7;
+ }
+ }
+ }
+}
+
+.friends-list-container {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ .searchbar-container {
+ padding: 0.75rem 1rem;
+ border-bottom: 1px solid #e2e8f0;
+
+ input.searchbar {
+ width: 100%;
+ padding: 0.5rem 0.75rem;
+ font-size: 0.9rem;
+ border: 1px solid #cbd5e1;
+ border-radius: 0.375rem;
+ background-color: #f8fafc;
+ outline: none;
+ transition: all 0.2s;
+
+ &:focus {
+ background-color: #ffffff;
+ border-color: #3ba4d7;
+ box-shadow: 0 0 0 3px rgba(59, 164, 215, 0.15);
+ }
+ }
+ }
+
+ .friends-scroll {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0.5rem 0;
+ }
+}
+
+.friend-list-item {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ padding: 0.75rem 1rem;
+ margin: 0.125rem 0.5rem;
+ border-radius: 0.5rem;
+ cursor: pointer;
+ transition: all 0.2s;
+
+ &:hover {
+ background-color: #f1f5f9;
+ }
+
+ &.selected {
+ background-color: #e0f2fe;
+
+ .friend-name {
+ color: #0369a1;
+ font-weight: 600;
+ }
+ }
+
+ .friend-avatar {
+ flex-shrink: 0;
+ }
+
+ .friend-meta {
+ flex: 1;
+ min-width: 0;
+
+ .friend-name {
+ font-size: 0.95rem;
+ color: #334155;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ transition: color 0.2s;
+ }
+
+ .friend-status {
+ font-size: 0.8rem;
+ color: #94a3b8;
+
+ &.online {
+ color: #10b981;
+ font-weight: 500;
+ }
+ }
+ }
+}
+
+.network-right-pane {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ background-color: #f8fafc;
+}
+
+.network-pane-placeholder {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ color: #94a3b8;
+ gap: 1rem;
+ padding: 2rem;
+ text-align: center;
+
+ i {
+ font-size: 4rem;
+ color: #cbd5e1;
+ }
+
+ p {
+ font-size: 1.1rem;
+ max-width: 400px;
+ }
+}
+
+.network-tabs {
+ display: flex;
+ background-color: #ffffff;
+ border-bottom: 1px solid #cbd5e1;
+ padding: 0.5rem 1rem 0;
+ gap: 0.5rem;
+
+ .tab-btn {
+ padding: 0.625rem 1.25rem;
+ font-size: 0.95rem;
+ font-weight: 600;
+ color: #64748b;
+ background: transparent;
+ border: none;
+ border-radius: 0.375rem 0.375rem 0 0;
+ border-bottom: 3px solid transparent;
+ cursor: pointer;
+ box-shadow: none;
+ transition: all 0.2s;
+
+ &:hover {
+ color: #334155;
+ background-color: #f1f5f9;
+ }
+
+ &.active {
+ color: #3ba4d7;
+ border-bottom-color: #3ba4d7;
+ background-color: transparent;
+ }
+ }
+}
+
+.network-tab-content {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1.5rem;
+}
+
+.network-detail-view {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+
+ .detail-header {
+ display: flex;
+ align-items: center;
+ gap: 1.5rem;
+ padding-bottom: 1.5rem;
+ border-bottom: 1px solid #e2e8f0;
+
+ .detail-title {
+ flex: 1;
+
+ h2 {
+ font-size: 1.75rem;
+ font-weight: 800;
+ color: #1e293b;
+ margin-bottom: 0.25rem;
+ }
+
+ .detail-subtitle {
+ font-size: 0.9rem;
+ color: #64748b;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ }
+ }
+
+ .detail-actions {
+ display: flex;
+ gap: 0.75rem;
+
+ button {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.5rem 1rem;
+ font-size: 0.9rem;
+ }
+ }
+ }
+
+ .detail-section {
+ background-color: #ffffff;
+ border-radius: 0.5rem;
+ border: 1px solid #e2e8f0;
+ padding: 1.25rem;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
+
+ h3 {
+ font-size: 1.1rem;
+ font-weight: 700;
+ color: #334155;
+ margin-bottom: 1rem;
+ padding-bottom: 0.5rem;
+ border-bottom: 1px solid #f1f5f9;
+ }
+
+ .info-grid {
+ display: grid;
+ grid-template-columns: 120px 1fr;
+ row-gap: 0.75rem;
+ font-size: 0.9rem;
+
+ .info-label {
+ font-weight: 600;
+ color: #64748b;
+ }
+
+ .info-value {
+ color: #1e293b;
+ word-break: break-all;
+ }
+ }
+ }
+
+ .locations-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ gap: 1rem;
+ }
+
+ .location-card {
+ background-color: #ffffff;
+ border: 1px solid #e2e8f0;
+ border-radius: 0.5rem;
+ padding: 1rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
+
+ .loc-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid #f1f5f9;
+ padding-bottom: 0.5rem;
+ margin-bottom: 0.25rem;
+
+ .loc-name {
+ font-weight: 700;
+ color: #334155;
+ font-size: 0.95rem;
+ }
+
+ .loc-status {
+ font-size: 0.75rem;
+ font-weight: 600;
+ padding: 0.125rem 0.5rem;
+ border-radius: 0.25rem;
+
+ &.online {
+ background-color: #d1fae5;
+ color: #065f46;
+ }
+
+ &.offline {
+ background-color: #f1f5f9;
+ color: #475569;
+ }
+ }
+ }
+
+ .loc-body {
+ font-size: 0.85rem;
+ display: grid;
+ grid-template-columns: 80px 1fr;
+ row-gap: 0.25rem;
+
+ .loc-label {
+ color: #64748b;
+ }
+
+ .loc-val {
+ color: #334155;
+ word-break: break-all;
+ }
+ }
+
+ .loc-footer {
+ margin-top: 0.5rem;
+ display: flex;
+ justify-content: flex-end;
+
+ button {
+ font-size: 0.8rem;
+ padding: 0.25rem 0.75rem;
+ }
+ }
+ }
+}
+
+.network-chat-view {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ overflow: hidden;
+ background-color: #f8fafc;
+
+ .chat-messages {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1.25rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ }
+
+ .chat-bubble-container {
+ display: flex;
+ flex-direction: column;
+ max-width: 70%;
+
+ &.outgoing {
+ align-self: flex-end;
+ align-items: flex-end;
+
+ .chat-bubble {
+ background-color: #3ba4d7;
+ color: #ffffff;
+ border-bottom-right-radius: 0.125rem;
+ }
+ }
+
+ &.incoming {
+ align-self: flex-start;
+ align-items: flex-start;
+
+ .chat-bubble {
+ background-color: #ffffff;
+ color: #1e293b;
+ border: 1px solid #e2e8f0;
+ border-bottom-left-radius: 0.125rem;
+ }
+ }
+
+ .chat-sender {
+ font-size: 0.75rem;
+ color: #64748b;
+ margin-bottom: 0.25rem;
+ padding: 0 0.25rem;
+ }
+
+ .chat-bubble {
+ padding: 0.625rem 0.875rem;
+ border-radius: 0.75rem;
+ font-size: 0.925rem;
+ line-height: 1.4;
+ white-space: break-spaces;
+ word-break: break-word;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+ }
+
+ .chat-time {
+ font-size: 0.7rem;
+ color: #94a3b8;
+ margin-top: 0.25rem;
+ padding: 0 0.25rem;
+ }
+ }
+
+ .chat-input-area {
+ padding: 1rem;
+ background-color: #ffffff;
+ border-top: 1px solid #cbd5e1;
+ display: flex;
+ gap: 0.75rem;
+ align-items: center;
+
+ textarea.chat-textarea {
+ flex: 1;
+ resize: none;
+ height: 40px;
+ padding: 0.5rem 0.75rem;
+ border: 1px solid #cbd5e1;
+ border-radius: 0.375rem;
+ font-size: 0.9rem;
+ outline: none;
+ transition: all 0.2s;
+
+ &:focus {
+ border-color: #3ba4d7;
+ box-shadow: 0 0 0 3px rgba(59, 164, 215, 0.15);
+ }
+ }
+
+ button.send-btn {
+ padding: 0.5rem 1.25rem;
+ font-size: 0.9rem;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ }
+ }
+
+ .chat-warning {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ color: #64748b;
+ text-align: center;
+ padding: 2rem;
+ gap: 1rem;
+
+ i {
+ font-size: 3rem;
+ color: #cbd5e1;
+ }
+
+ h4 {
+ font-weight: 700;
+ color: #334155;
+ }
+
+ p {
+ max-width: 350px;
+ font-size: 0.9rem;
+ }
+ }
+}
+
+/* Responsive Layout for Mobile/Small Screens */
+@media (max-width: 768px) {
+ .network-container {
+ flex-direction: column !important;
+ }
+
+ .network-left-pane {
+ width: 100% !important;
+ max-width: none !important;
+ height: 45% !important;
+ border-right: none !important;
+ border-bottom: 1px solid #cbd5e1 !important;
+ }
+
+ .network-right-pane {
+ height: 55% !important;
+ flex: 1 !important;
+ }
+
+ /* Hide text labels on mobile screens so profile action buttons show icons only */
+ .detail-actions button .btn-text,
+ .detail-header .detail-actions button .btn-text {
+ display: none !important;
+ }
+
+ .detail-actions button,
+ .detail-header .detail-actions button {
+ padding: 0.45rem 0.65rem !important;
+ min-width: 38px !important;
+ height: 38px !important;
+ justify-content: center !important;
+ align-items: center !important;
+ }
+
+ .detail-actions button i,
+ .detail-header .detail-actions button i {
+ margin: 0 !important;
+ font-size: 1.05rem !important;
+ }
+
+ .network-detail-view .detail-header {
+ flex-direction: column !important;
+ align-items: flex-start !important;
+ gap: 1rem !important;
+
+ .friend-avatar {
+ margin-bottom: 0.25rem !important;
+ }
+ }
+
+ .locations-grid {
+ grid-template-columns: 1fr !important;
+ }
+}
+
+
+
+.identity {
+ color: #444;
+ font-size: 1.1em;
+ margin: 20px;
+ padding: 10px;
+ border: 1px solid #aaa;
+ border-radius: 20px;
+ & > h4 {
+ margin: 5px;
+ font-size: 1.3em;
+ }
+ & button {
+ font-size: 0.9em;
+ }
+ & .details {
+ display: grid;
+ grid-template-columns: 140px auto;
+ grid-row-gap: 5px;
+ justify-content: left;
+ }
+}
+
+.defaultAvatar {
+ width: 3rem;
+ height: 3rem;
+ aspect-ratio: 1;
+ background: lightsteelblue;
+ border-radius: 50%;
+ display: grid;
+ place-items: center;
+ & p {
+ font-weight: 900;
+ color: #666f7f;
+ transform: translateY(1px);
+ }
+}
+img.avatar {
+ display: block;
+ width: 3rem;
+ height: max-content;
+ aspect-ratio: 1;
+ margin-right: 0.3em;
+ border-radius: 50%;
+}
+
+.counter {
+ margin-left: 0.5em;
+ &:before {
+ content: '(';
+ }
+ &:after {
+ content: ')';
+ }
+}
+
+.chatInit {
+ margin-left: 0.5em;
+ color: green;
+ cursor: pointer;
+}
+
+.people-sidebar-header {
+ display: flex;
+ flex-direction: column;
+ padding: 0.75rem 1rem 0.5rem 1rem;
+ gap: 0.75rem;
+ border-bottom: 1px solid #e2e8f0;
+ background-color: #ffffff;
+
+ .searchbar-wrapper {
+ position: relative;
+ display: flex;
+ align-items: center;
+
+ i.fa-search {
+ position: absolute;
+ left: 0.85rem;
+ color: #94a3b8;
+ font-size: 0.9rem;
+ }
+
+ input.searchbar-input {
+ width: 100%;
+ padding: 0.5rem 0.75rem 0.5rem 2.25rem;
+ border: 1px solid #e2e8f0;
+ border-radius: 0.5rem;
+ font-size: 0.9rem;
+ background-color: #f8fafc;
+ color: #1e293b;
+ outline: none;
+ transition: all 0.2s ease;
+
+ &:focus {
+ border-color: #3b82f6;
+ background-color: #ffffff;
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
+ }
+ }
+ }
+
+ .segmented-control {
+ display: flex;
+ background-color: #f1f5f9;
+ padding: 3px;
+ border-radius: 0.5rem;
+ gap: 4px;
+
+ button.segment-tab {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+ padding: 0.5rem 0.75rem;
+ font-size: 0.9rem;
+ font-weight: 600;
+ color: #64748b;
+ background: transparent;
+ border: none;
+ border-radius: 0.375rem;
+ cursor: pointer;
+ box-shadow: none;
+ transition: all 0.2s ease;
+
+ &:hover {
+ color: #1e293b;
+ }
+
+ &.active {
+ background-color: #ffffff;
+ color: #0f172a;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
+
+ .segment-badge {
+ background-color: #019dff;
+ color: #ffffff;
+ }
+ }
+
+ .segment-badge {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #cbd5e1;
+ color: #334155;
+ font-size: 0.75rem;
+ font-weight: 700;
+ min-width: 1.25rem;
+ height: 1.25rem;
+ padding: 0 0.35rem;
+ border-radius: 9999px;
+ line-height: 1;
+ transition: all 0.2s ease;
+ }
+ }
+ }
+
+ .sub-filter-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem;
+ min-height: 32px;
+
+ select.filter-select {
+ padding: 0.35rem 0.6rem;
+ border: 1px solid #cbd5e1;
+ border-radius: 0.375rem;
+ font-size: 0.85rem;
+ font-weight: 600;
+ color: #475569;
+ background-color: #ffffff;
+ cursor: pointer;
+ outline: none;
+ }
+
+ .btn-add-id {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border-radius: 0.375rem;
+ background-color: #3b82f6;
+ color: #ffffff;
+ border: none;
+ cursor: pointer;
+ font-size: 0.9rem;
+ transition: background-color 0.2s;
+
+ &:hover {
+ background-color: #2563eb;
+ }
+ }
+ }
+}
+
+/* Main People Page Flex Layout Container */
+.people-container {
+ display: flex !important;
+ flex-direction: row !important;
+ height: 100% !important;
+ width: 100% !important;
+ overflow: hidden !important;
+ background-color: #f1f5f9 !important;
+}
+
+/* Left Sidebar Pane (320px fixed width on Desktop) */
+.people-left-pane {
+ width: 320px !important;
+ min-width: 300px !important;
+ max-width: 350px !important;
+ height: 100% !important;
+ border-right: 1px solid #cbd5e1 !important;
+ display: flex !important;
+ flex-direction: column !important;
+ background: #ffffff !important;
+ box-shadow: 2px 0 5px rgba(0, 0, 0, 0.05) !important;
+ flex-shrink: 0 !important;
+ overflow: hidden !important;
+}
+
+/* Right Content Details Pane */
+.people-right-pane {
+ flex: 1 !important;
+ min-width: 0 !important;
+ height: 100% !important;
+ display: flex !important;
+ flex-direction: column !important;
+ overflow: hidden !important;
+ background-color: #f8fafc !important;
+}
+
+/* Scrollable list section inside left sidebar */
+.people-list-container {
+ flex: 1 !important;
+ overflow-y: auto !important;
+ padding: 0.5rem 0 !important;
+}
+
+/* Active Chats list item */
+.chat-item {
+ display: flex !important;
+ align-items: center !important;
+ gap: 0.75rem !important;
+ padding: 0.65rem 0.85rem !important;
+ margin: 0.2rem 0.5rem !important;
+ border-radius: 0.5rem !important;
+ cursor: pointer !important;
+ transition: all 0.2s ease !important;
+ position: relative !important;
+
+ &:hover {
+ background-color: #f1f5f9 !important;
+ }
+
+ &.selected {
+ background-color: #e0f2fe !important;
+
+ .chat-name {
+ color: #0369a1 !important;
+ font-weight: 700 !important;
+ }
+ }
+
+ .chat-avatar-wrapper {
+ position: relative !important;
+ flex-shrink: 0 !important;
+
+ .status-dot {
+ position: absolute !important;
+ bottom: 0 !important;
+ right: 0 !important;
+ width: 10px !important;
+ height: 10px !important;
+ border-radius: 50% !important;
+ border: 2px solid #ffffff !important;
+ }
+ }
+
+ .chat-info {
+ flex: 1 !important;
+ min-width: 0 !important;
+ display: flex !important;
+ flex-direction: column !important;
+
+ .chat-name {
+ font-size: 0.95rem !important;
+ font-weight: 600 !important;
+ color: #1e293b !important;
+ white-space: nowrap !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ }
+
+ .chat-last-msg {
+ font-size: 0.825rem !important;
+ color: #64748b !important;
+ white-space: nowrap !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ margin-top: 0.1rem !important;
+ }
+ }
+
+ .chat-meta {
+ display: flex !important;
+ flex-direction: column !important;
+ align-items: flex-end !important;
+ flex-shrink: 0 !important;
+
+ .chat-time {
+ font-size: 0.75rem !important;
+ color: #94a3b8 !important;
+ font-weight: 500 !important;
+ }
+ }
+}
+
+/* Responsive Layout for Mobile/Small Screens */
+@media (max-width: 768px) {
+ .people-container {
+ flex-direction: column !important;
+ }
+ .people-left-pane {
+ width: 100% !important;
+ max-width: none !important;
+ height: 45% !important;
+ border-right: none !important;
+ border-bottom: 1px solid #cbd5e1 !important;
+ }
+ .people-right-pane {
+ height: 55% !important;
+ }
+
+ /* Hide text labels on mobile screens so profile action buttons show icons only */
+ .detail-actions button .btn-text,
+ .detail-header .detail-actions button .btn-text {
+ display: none !important;
+ }
+
+ /* Hide Distant Chat Tunnel and Chatting as text on mobile screens to save header space */
+ .chat-tunnel-status .tunnel-label,
+ .select-own-profile .chatting-as-label {
+ display: none !important;
+ }
+
+ .detail-actions button,
+ .detail-header .detail-actions button {
+ padding: 0.45rem 0.65rem !important;
+ min-width: 38px !important;
+ height: 38px !important;
+ justify-content: center !important;
+ align-items: center !important;
+ }
+
+
+/* People Sidebar Right-Click Context Menu */
+.people-context-menu {
+ position: absolute !important;
+ z-index: 9999 !important;
+ background-color: #ffffff !important;
+ border: 1px solid #cbd5e1 !important;
+ border-radius: 8px !important;
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.1) !important;
+ padding: 0.35rem 0 !important;
+ min-width: 180px !important;
+ font-family: inherit !important;
+ overflow: hidden !important;
+
+ .menu-item {
+ display: flex !important;
+ align-items: center !important;
+ padding: 0.6rem 0.9rem !important;
+ font-size: 0.875rem !important;
+ font-weight: 500 !important;
+ color: #1e293b !important;
+ cursor: pointer !important;
+ transition: background-color 0.15s ease, color 0.15s ease !important;
+ user-select: none !important;
+
+ &:hover {
+ background-color: #f1f5f9 !important;
+ color: #0284c7 !important;
+ }
+
+ i {
+ font-size: 1rem !important;
+ width: 1.25rem !important;
+ text-align: center !important;
+ }
+ }
+}
+
+
+
+
+// -----------------------------------------------------------------------------
+// This file contains all application-wide button styles.
+// -----------------------------------------------------------------------------
+@use "../abstracts" as *;
+
+button {
+ @include button($primary-color);
+ white-space: nowrap !important;
+ flex-shrink: 0 !important;
+}
+button.red {
+ @include button($red-color);
+ white-space: nowrap !important;
+ flex-shrink: 0 !important;
+}
+
+
+
+
+@forward 'buttons';
+@forward 'media';
+@forward 'navbar';
+@forward 'posts';
+@forward 'progress-bar';
+@forward 'statusbar';
+
+
+
+
+@use 'sass:color';
+@use '../abstracts' as *;
+
+.media-item {
+ display: flex;
+ margin-top: 0.5rem;
+ padding: 1rem;
+ border: 1px solid color.adjust($dark-color, $alpha: -0.9);
+ border-radius: 4px;
+
+ &__details {
+ flex-basis: 40%;
+ @include flex($align: start, $gap: 0.5rem);
+
+ & img {
+ width: 6rem;
+ object-fit: contain;
+ }
+ }
+
+ &__desc {
+ flex-basis: 60%;
+ }
+
+ @media (max-width: 768px) {
+ &__desc {
+ display: none !important;
+ }
+
+ &__details {
+ flex-basis: 100% !important;
+ width: 100% !important;
+ }
+ }
+}
+
+
+@use 'sass:color';
+@use '../abstracts' as *;
+
+.active-link {
+ background: rgba(255, 255, 255, 0.1) !important;
+}
+
+/* Navbar */
+.nav-menu {
+ background-color: $dark-color;
+ box-shadow: 0 5px 5px #222;
+ @include flex(column, $align: center);
+ height: 100%;
+ padding: 0.25rem;
+ margin-right: 0rem;
+
+ &__logo {
+ padding: 1.2rem 0;
+ @include flex($align: center, $gap: 0.3rem);
+
+ img {
+ width: 1.6rem;
+ }
+
+ h5 {
+ line-height: 1;
+ color: white;
+ }
+ }
+
+ &__box {
+ padding: 2rem 0.125rem;
+ @include flex(column, $gap: 0.5rem);
+ position: relative;
+
+ .item {
+ margin: 0;
+ padding: 0.675rem 0.5rem;
+ width: 10rem;
+ @include flex($align: center);
+ line-height: 1;
+ border-radius: 0.5rem;
+ text-decoration: none;
+ color: #ccc;
+ text-transform: capitalize;
+ transition: 0ms;
+
+ &:hover {
+ background-color: color.adjust($light-color, $alpha: -0.85);
+ }
+
+ i.sidenav-icon {
+ width: 2.5rem;
+ height: 1.4rem;
+ display: grid;
+ place-items: center;
+ }
+ }
+
+ .item.item-selected {
+ color: $primary-light-color;
+ background-color: color.adjust($primary-light-color, $alpha: -0.85);
+ font-weight: medium;
+ }
+
+ button.toggle-nav {
+ display: none;
+ position: absolute;
+ padding: 0;
+ top: 0;
+ right: -1rem;
+ background: color.adjust($primary-color, $lightness: 15%);
+ width: 1.5rem;
+ height: 1.5rem;
+ aspect-ratio: 1;
+ justify-content: center;
+ align-items: center;
+ border-radius: 50%;
+ box-shadow: none;
+ }
+ }
+
+ &.collapsed {
+ .nav-menu__logo {
+ .logo-container {
+ @include flex(column, $align: center, $gap: 0.5rem);
+
+ &>*:not(img) {
+ display: block;
+ }
+ }
+
+ & .nav-menu__logo-text {
+ display: none !important;
+ }
+ }
+
+ .nav-menu__box {
+ .item {
+ padding: 0.675rem 0;
+ width: 2.5rem;
+ justify-content: center;
+ transition: 300ms;
+
+ & span,
+ & p {
+ display: none !important;
+ }
+ }
+ }
+
+ button i {
+ rotate: 180deg;
+ }
+ }
+
+ // only show toggle button when sidebar is hovered
+ &:hover button.toggle-nav {
+ display: flex;
+ }
+}
+
+.sidebar {
+ width: 13rem;
+ background-color: white;
+ @include flex(column);
+
+ & a {
+ text-decoration: none;
+ text-transform: capitalize;
+ padding: 1rem;
+ cursor: pointer;
+ color: #999;
+
+ &:hover {
+ color: #222;
+ }
+ }
+
+ & .selected-sidebar-link {
+ font-weight: bold;
+ color: #222;
+ border-left: 5px solid #3ba4d7;
+ animation: expand-left-border 0.1s;
+ }
+}
+
+.sidebar-mobile-toggle,
+.sidebar-drawer__title,
+.sidebar-drawer__backdrop { display: none !important; }
+
+.sidebarquickview {
+ &>h6 {
+ padding: 0.5rem;
+ }
+
+ & a {
+ text-decoration: none;
+ text-transform: capitalize;
+ padding: 0.5rem 1rem;
+ display: block;
+ color: #999;
+
+ & a:hover {
+ color: #222;
+ }
+ }
+
+ & .selected-sidebarquickview-link {
+ font-weight: bold;
+ color: #222;
+ border-left: 5px solid #3ba4d7;
+ animation: expand-left-border 0.1s;
+ }
+}
+
+/* Content adjacent to sidebar */
+.node-panel {
+ width: 100%;
+ padding: 0.5rem;
+ animation: fadein 0.5s;
+}
+
+@keyframes expand-left-border {
+ from {
+ border-left: 0;
+ }
+
+ to {
+ border-left: 5px solid #3ba4d7;
+ }
+}
+
+/* GLOBAL SIDEBAR TO TABS */
+@media (max-width: 700px) {
+ .tab-content {
+ flex-direction: column;
+ }
+
+ .sidebar {
+ width: 100% !important;
+ flex-direction: row !important;
+ overflow-x: auto !important;
+ overflow-y: hidden !important;
+ white-space: nowrap !important;
+ border-bottom: 1px solid rgba(20, 20, 27, 0.1) !important;
+ background: white !important;
+ z-index: 50 !important;
+ flex-shrink: 0 !important;
+ height: auto !important;
+ padding: 0 !important;
+ }
+
+ .sidebar a {
+ display: inline-block !important;
+ padding: 0.8rem 1.2rem !important;
+ border-bottom: 3px solid transparent !important;
+ border-left: none !important;
+ }
+
+ .sidebar .selected-sidebar-link {
+ border-left: none !important;
+ border-bottom: 3px solid #3ba4d7 !important;
+ animation: none !important;
+ }
+
+ /* Hide quickview headings on mobile to save space if needed */
+ .sidebarquickview>h4,
+ .sidebarquickview>h6 {
+ display: none !important;
+ }
+
+ /* Boards, Channels and Forums use a drawer instead of the horizontal tabs. */
+ .sidebar-drawer {
+ display: block;
+ position: relative;
+ width: 100%;
+ height: 44px;
+ z-index: 1000;
+ }
+
+ .sidebar-mobile-toggle {
+ display: inline-flex !important;
+ width: 40px;
+ height: 40px;
+ align-items: center;
+ justify-content: center;
+ border: 0;
+ border-radius: 6px;
+ background: #ffffff;
+ color: #0f172a;
+ cursor: pointer;
+ font-size: 1.15rem;
+ }
+
+ .sidebar-mobile-toggle:hover { background: #f1f5f9; }
+
+ .sidebar-drawer .sidebar {
+ position: fixed !important;
+ top: 0;
+ left: 0;
+ display: flex !important;
+ flex-direction: column !important;
+ width: min(82vw, 300px) !important;
+ height: 100dvh !important;
+ padding: 1rem 0 !important;
+ overflow-y: auto !important;
+ overflow-x: hidden !important;
+ transform: translateX(-105%);
+ transition: transform 180ms ease;
+ border: 0 !important;
+ border-right: 1px solid #e2e8f0 !important;
+ background: #ffffff !important;
+ opacity: 1 !important;
+ pointer-events: auto !important;
+ box-shadow: 8px 0 24px rgba(15, 23, 42, 0.16);
+ white-space: normal !important;
+ z-index: 1002;
+ }
+
+ .sidebar-drawer .sidebar.sidebar--mobile-open { transform: translateX(0); }
+ .sidebar-drawer .sidebar a {
+ display: block !important;
+ padding: .8rem 1.25rem !important;
+ border: 0 !important;
+ border-left: 4px solid transparent !important;
+ color: #334155 !important;
+ font-size: .95rem;
+ }
+
+ .sidebar-drawer .sidebar .selected-sidebar-link {
+ border-left-color: #3ba4d7 !important;
+ border-bottom: 0 !important;
+ background: #f0f9ff;
+ color: #0f172a !important;
+ }
+
+ .sidebar-drawer__title {
+ display: block !important;
+ margin: 0 1.25rem .65rem;
+ padding-bottom: .75rem;
+ border-bottom: 1px solid #e2e8f0;
+ color: #64748b;
+ font-size: .75rem;
+ font-weight: 700;
+ letter-spacing: .06em;
+ text-transform: uppercase;
+ }
+
+ .sidebar-drawer__backdrop {
+ display: none !important;
+ position: fixed;
+ inset: 0;
+ background: rgba(15, 23, 42, .35);
+ /* The drawer itself owns navigation input; this layer is visual only. */
+ pointer-events: none;
+ z-index: 1001;
+ }
+}
+
+@media (min-width: 701px) {
+ .sidebar-drawer { display: contents; }
+ .sidebar-mobile-toggle,
+ .sidebar-drawer__title,
+ .sidebar-drawer__backdrop { display: none !important; }
+}
+
+
+
+@use 'sass:color';
+@use '../abstracts' as *;
+
+.posts {
+ height: 100%;
+ margin-top: 1rem;
+ flex-direction: column;
+ overflow: auto;
+
+ &__heading {
+ @include flex(column, $justify: space-between);
+ }
+
+ &-container {
+ height: 100%;
+ padding: 1rem;
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
+ gap: 2rem;
+ border: 1px solid color.adjust($dark-color, $alpha: -0.9);
+ border-radius: 4px;
+ overflow: auto;
+
+ &-card {
+ min-height: 240px;
+ flex-direction: column;
+ border: 1px solid color.adjust($dark-color, $alpha: -0.5);
+ border-radius: 4px;
+ cursor: pointer;
+ text-align: center;
+
+ & img {
+ flex-basis: 90%;
+ object-fit: cover;
+ }
+
+ & p {
+ padding: 0 0.125rem;
+ flex-basis: 10%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+ }
+}
+
+
+@use 'sass:color';
+@use '../abstracts/colors' as *;
+
+.progress-bar {
+ width: 100%;
+ height: 2rem;
+ position: relative;
+ text-align: center;
+ background-color: $light-color;
+ border-radius: 20px;
+ overflow: hidden;
+
+ &__status {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ color: $dark-color;
+ background-color: $primary-color;
+ }
+
+ &__percent {
+ position: absolute;
+ inset: 0;
+ margin: auto;
+ width: fit-content;
+ height: fit-content;
+ }
+
+ &-chunks {
+ position: relative;
+ margin-top: 0.5rem;
+ width: 100%;
+ height: 2rem;
+ display: flex;
+ border-radius: 0.25rem;
+ overflow: hidden;
+ background-color: $light-color;
+
+ & .chunk {
+ width: 100%;
+
+ &[data-chunkVal='0'] {
+ background-color: color.adjust($primary-light-color, $alpha: -0.8);
+ }
+
+ &[data-chunkVal='1'] {
+ background-color: $red-color;
+ }
+
+ &[data-chunkVal='2'] {
+ background-color: $primary-color;
+ }
+
+ &[data-chunkVal='3'] {
+ background-color: $golden-yellow-color;
+ }
+ }
+
+ &__percent {
+ position: absolute;
+ inset: 0;
+ margin: auto;
+ width: fit-content;
+ height: fit-content;
+ }
+ }
+}
+
+
+@use '../abstracts' as *;
+
+/* Status Bar Styles */
+.statusbar {
+ @include flex($justify: space-between, $align: center);
+ height: 28px;
+ background-color: $dark-color;
+ border-top: 1px solid #2e2e38;
+ padding: 0 1rem;
+ font-size: 0.8rem;
+ color: #94a3b8;
+ z-index: 100;
+ box-sizing: border-box;
+ user-select: none;
+ flex-shrink: 0;
+
+ &-left {
+ @include flex($align: center, $gap: 0.75rem);
+ }
+
+ &-right {
+ @include flex($align: center, $gap: 0.75rem);
+ }
+
+ &-item {
+ @include flex($align: center);
+ }
+
+ &-divider {
+ width: 1px;
+ height: 14px;
+ background-color: #2e2e38;
+ }
+}
+
+.status-bullet {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ display: inline-block;
+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
+}
+
+@media (max-width: 768px) {
+ .statusbar {
+ height: 22px !important;
+ padding: 0 0.4rem !important;
+ font-size: 0.72rem !important;
+
+ .statusbar-left,
+ .statusbar-right {
+ gap: 0.35rem !important;
+ }
+
+ .statusbar-label,
+ .statusbar-total-bytes,
+ .statusbar-extra-info {
+ display: none !important;
+ }
+
+ .statusbar-divider {
+ height: 10px !important;
+ margin: 0 0.1rem !important;
+ }
+ }
+}
+
+
+