feat(字幕样式): 增加字幕容器和文本元素的背景样式设置功能
添加字幕容器和各类文本元素(提示文字、消息文字、热词标题、热词问题)的背景颜色、透明度、圆角和内边距设置功能 新增范围滑块样式和实时值显示 实现从现有字幕容器加载样式配置的功能 扩展样式应用逻辑以处理新增的背景相关属性
This commit is contained in:
@@ -77,7 +77,33 @@
|
||||
<h2>📝 字幕样式设置</h2>
|
||||
<button class="panel-close" data-panel="captionPanel">×</button>
|
||||
</div>
|
||||
<div class="panel-content" style="max-height: 500px; overflow-y: auto;">
|
||||
<div class="panel-content" style="max-height: 600px; overflow-y: auto;">
|
||||
<!-- 字幕容器样式 -->
|
||||
<div class="caption-style-section">
|
||||
<h3>字幕容器 (container)</h3>
|
||||
<div class="form-group">
|
||||
<label for="containerBgColor">背景颜色</label>
|
||||
<input type="color" id="containerBgColor" value="#1a1a2e">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="containerBgOpacity">背景透明度</label>
|
||||
<input type="range" id="containerBgOpacity" value="85" min="0" max="100">
|
||||
<span class="range-value">85%</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="containerBorderColor">边框颜色</label>
|
||||
<input type="color" id="containerBorderColor" value="#333333">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="containerBorderRadius">圆角 (px)</label>
|
||||
<input type="number" id="containerBorderRadius" value="8" min="0" max="20">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="containerPadding">内边距 (px)</label>
|
||||
<input type="number" id="containerPadding" value="10" min="0" max="30">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 提示文字样式 -->
|
||||
<div class="caption-style-section">
|
||||
<h3>提示文字 (tip)</h3>
|
||||
@@ -100,6 +126,23 @@
|
||||
<label for="tipLineHeight">行高</label>
|
||||
<input type="number" id="tipLineHeight" value="1.5" min="1" max="3" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="tipBgColor">背景颜色</label>
|
||||
<input type="color" id="tipBgColor" value="#2a2a3e">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="tipBgOpacity">背景透明度</label>
|
||||
<input type="range" id="tipBgOpacity" value="60" min="0" max="100">
|
||||
<span class="range-value">60%</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="tipBorderRadius">圆角 (px)</label>
|
||||
<input type="number" id="tipBorderRadius" value="4" min="0" max="15">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="tipPadding">内边距 (px)</label>
|
||||
<input type="number" id="tipPadding" value="6" min="0" max="20">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 消息文字样式 -->
|
||||
@@ -124,6 +167,23 @@
|
||||
<label for="messageLineHeight">行高</label>
|
||||
<input type="number" id="messageLineHeight" value="1.5" min="1" max="3" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="messageBgColor">背景颜色</label>
|
||||
<input type="color" id="messageBgColor" value="#2a2a3e">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="messageBgOpacity">背景透明度</label>
|
||||
<input type="range" id="messageBgOpacity" value="60" min="0" max="100">
|
||||
<span class="range-value">60%</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="messageBorderRadius">圆角 (px)</label>
|
||||
<input type="number" id="messageBorderRadius" value="4" min="0" max="15">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="messagePadding">内边距 (px)</label>
|
||||
<input type="number" id="messagePadding" value="8" min="0" max="20">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 热词标题样式 -->
|
||||
@@ -148,6 +208,23 @@
|
||||
<label for="hotTitleLineHeight">行高</label>
|
||||
<input type="number" id="hotTitleLineHeight" value="1.5" min="1" max="3" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotTitleBgColor">背景颜色</label>
|
||||
<input type="color" id="hotTitleBgColor" value="#3a3a4e">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotTitleBgOpacity">背景透明度</label>
|
||||
<input type="range" id="hotTitleBgOpacity" value="60" min="0" max="100">
|
||||
<span class="range-value">60%</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotTitleBorderRadius">圆角 (px)</label>
|
||||
<input type="number" id="hotTitleBorderRadius" value="4" min="0" max="15">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotTitlePadding">内边距 (px)</label>
|
||||
<input type="number" id="hotTitlePadding" value="6" min="0" max="20">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 热词问题样式 -->
|
||||
@@ -172,6 +249,23 @@
|
||||
<label for="hotIssuesLineHeight">行高</label>
|
||||
<input type="number" id="hotIssuesLineHeight" value="1.5" min="1" max="3" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotIssuesBgColor">背景颜色</label>
|
||||
<input type="color" id="hotIssuesBgColor" value="#2a2a3e">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotIssuesBgOpacity">背景透明度</label>
|
||||
<input type="range" id="hotIssuesBgOpacity" value="60" min="0" max="100">
|
||||
<span class="range-value">60%</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotIssuesBorderRadius">圆角 (px)</label>
|
||||
<input type="number" id="hotIssuesBorderRadius" value="4" min="0" max="15">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hotIssuesPadding">内边距 (px)</label>
|
||||
<input type="number" id="hotIssuesPadding" value="6" min="0" max="20">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="applyCaptionStyleBtn" class="btn btn-primary" style="width: 100%; margin-top: 16px;">应用样式</button>
|
||||
|
||||
@@ -60,25 +60,47 @@ const elements = {
|
||||
toggleLogBtn: document.getElementById('toggleLogBtn'),
|
||||
applyCaptionStyleBtn: document.getElementById('applyCaptionStyleBtn'),
|
||||
|
||||
containerBgColor: document.getElementById('containerBgColor'),
|
||||
containerBgOpacity: document.getElementById('containerBgOpacity'),
|
||||
containerBorderColor: document.getElementById('containerBorderColor'),
|
||||
containerBorderRadius: document.getElementById('containerBorderRadius'),
|
||||
containerPadding: document.getElementById('containerPadding'),
|
||||
|
||||
tipFontSize: document.getElementById('tipFontSize'),
|
||||
tipFontWeight: document.getElementById('tipFontWeight'),
|
||||
tipColor: document.getElementById('tipColor'),
|
||||
tipLineHeight: document.getElementById('tipLineHeight'),
|
||||
tipBgColor: document.getElementById('tipBgColor'),
|
||||
tipBgOpacity: document.getElementById('tipBgOpacity'),
|
||||
tipBorderRadius: document.getElementById('tipBorderRadius'),
|
||||
tipPadding: document.getElementById('tipPadding'),
|
||||
|
||||
messageFontSize: document.getElementById('messageFontSize'),
|
||||
messageFontWeight: document.getElementById('messageFontWeight'),
|
||||
messageColor: document.getElementById('messageColor'),
|
||||
messageLineHeight: document.getElementById('messageLineHeight'),
|
||||
messageBgColor: document.getElementById('messageBgColor'),
|
||||
messageBgOpacity: document.getElementById('messageBgOpacity'),
|
||||
messageBorderRadius: document.getElementById('messageBorderRadius'),
|
||||
messagePadding: document.getElementById('messagePadding'),
|
||||
|
||||
hotTitleFontSize: document.getElementById('hotTitleFontSize'),
|
||||
hotTitleFontWeight: document.getElementById('hotTitleFontWeight'),
|
||||
hotTitleColor: document.getElementById('hotTitleColor'),
|
||||
hotTitleLineHeight: document.getElementById('hotTitleLineHeight'),
|
||||
hotTitleBgColor: document.getElementById('hotTitleBgColor'),
|
||||
hotTitleBgOpacity: document.getElementById('hotTitleBgOpacity'),
|
||||
hotTitleBorderRadius: document.getElementById('hotTitleBorderRadius'),
|
||||
hotTitlePadding: document.getElementById('hotTitlePadding'),
|
||||
|
||||
hotIssuesFontSize: document.getElementById('hotIssuesFontSize'),
|
||||
hotIssuesFontWeight: document.getElementById('hotIssuesFontWeight'),
|
||||
hotIssuesColor: document.getElementById('hotIssuesColor'),
|
||||
hotIssuesLineHeight: document.getElementById('hotIssuesLineHeight'),
|
||||
hotIssuesBgColor: document.getElementById('hotIssuesBgColor'),
|
||||
hotIssuesBgOpacity: document.getElementById('hotIssuesBgOpacity'),
|
||||
hotIssuesBorderRadius: document.getElementById('hotIssuesBorderRadius'),
|
||||
hotIssuesPadding: document.getElementById('hotIssuesPadding'),
|
||||
|
||||
logLevel: document.getElementById('logLevel'),
|
||||
|
||||
@@ -369,42 +391,165 @@ function applyCaptionStyle() {
|
||||
return;
|
||||
}
|
||||
|
||||
const tipEl = captionContainer.querySelector('.layout-hub-tip');
|
||||
const messageEl = captionContainer.querySelector('.layout-hub-message');
|
||||
const hotTitleEl = captionContainer.querySelector('.layout-hub-hot-title');
|
||||
const hotIssuesEl = captionContainer.querySelector('.layout-hub-hot-issues');
|
||||
captionContainer.style.backgroundColor = hexToRgba(
|
||||
elements.containerBgColor.value,
|
||||
elements.containerBgOpacity.value / 100
|
||||
);
|
||||
captionContainer.style.borderColor = elements.containerBorderColor.value;
|
||||
captionContainer.style.borderRadius = `${elements.containerBorderRadius.value}px`;
|
||||
captionContainer.style.padding = `${elements.containerPadding.value}px`;
|
||||
|
||||
const tipEl = captionContainer.querySelector('.layout-hub-tip');
|
||||
if (tipEl) {
|
||||
tipEl.style.fontSize = `${elements.tipFontSize.value}px`;
|
||||
tipEl.style.fontWeight = elements.tipFontWeight.value;
|
||||
tipEl.style.color = elements.tipColor.value;
|
||||
tipEl.style.lineHeight = elements.tipLineHeight.value;
|
||||
tipEl.style.backgroundColor = hexToRgba(
|
||||
elements.tipBgColor.value,
|
||||
elements.tipBgOpacity.value / 100
|
||||
);
|
||||
tipEl.style.borderRadius = `${elements.tipBorderRadius.value}px`;
|
||||
tipEl.style.padding = `${elements.tipPadding.value}px`;
|
||||
}
|
||||
|
||||
const messageEl = captionContainer.querySelector('.layout-hub-message');
|
||||
if (messageEl) {
|
||||
messageEl.style.fontSize = `${elements.messageFontSize.value}px`;
|
||||
messageEl.style.fontWeight = elements.messageFontWeight.value;
|
||||
messageEl.style.color = elements.messageColor.value;
|
||||
messageEl.style.lineHeight = elements.messageLineHeight.value;
|
||||
messageEl.style.backgroundColor = hexToRgba(
|
||||
elements.messageBgColor.value,
|
||||
elements.messageBgOpacity.value / 100
|
||||
);
|
||||
messageEl.style.borderRadius = `${elements.messageBorderRadius.value}px`;
|
||||
messageEl.style.padding = `${elements.messagePadding.value}px`;
|
||||
}
|
||||
|
||||
const hotTitleEl = captionContainer.querySelector('.layout-hub-hot-title');
|
||||
if (hotTitleEl) {
|
||||
hotTitleEl.style.fontSize = `${elements.hotTitleFontSize.value}px`;
|
||||
hotTitleEl.style.fontWeight = elements.hotTitleFontWeight.value;
|
||||
hotTitleEl.style.color = elements.hotTitleColor.value;
|
||||
hotTitleEl.style.lineHeight = elements.hotTitleLineHeight.value;
|
||||
hotTitleEl.style.backgroundColor = hexToRgba(
|
||||
elements.hotTitleBgColor.value,
|
||||
elements.hotTitleBgOpacity.value / 100
|
||||
);
|
||||
hotTitleEl.style.borderRadius = `${elements.hotTitleBorderRadius.value}px`;
|
||||
hotTitleEl.style.padding = `${elements.hotTitlePadding.value}px`;
|
||||
}
|
||||
|
||||
const hotIssuesEl = captionContainer.querySelector('.layout-hub-hot-issues');
|
||||
if (hotIssuesEl) {
|
||||
hotIssuesEl.style.fontSize = `${elements.hotIssuesFontSize.value}px`;
|
||||
hotIssuesEl.style.fontWeight = elements.hotIssuesFontWeight.value;
|
||||
hotIssuesEl.style.color = elements.hotIssuesColor.value;
|
||||
hotIssuesEl.style.lineHeight = elements.hotIssuesLineHeight.value;
|
||||
hotIssuesEl.style.backgroundColor = hexToRgba(
|
||||
elements.hotIssuesBgColor.value,
|
||||
elements.hotIssuesBgOpacity.value / 100
|
||||
);
|
||||
hotIssuesEl.style.borderRadius = `${elements.hotIssuesBorderRadius.value}px`;
|
||||
hotIssuesEl.style.padding = `${elements.hotIssuesPadding.value}px`;
|
||||
}
|
||||
|
||||
logger.info('字幕样式已应用');
|
||||
}
|
||||
|
||||
function hexToRgba(hex, alpha) {
|
||||
const r = parseInt(hex.slice(1, 3), 16);
|
||||
const g = parseInt(hex.slice(3, 5), 16);
|
||||
const b = parseInt(hex.slice(5, 7), 16);
|
||||
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
||||
}
|
||||
|
||||
function loadCaptionStyleFromContainer() {
|
||||
const captionContainer = document.querySelector('.caption-container-hub');
|
||||
if (!captionContainer) return;
|
||||
|
||||
const containerStyles = window.getComputedStyle(captionContainer);
|
||||
const containerBg = containerStyles.backgroundColor;
|
||||
const containerBorder = containerStyles.borderColor;
|
||||
const containerRadius = containerStyles.borderRadius;
|
||||
const containerPad = containerStyles.padding;
|
||||
|
||||
if (containerBg && containerBg !== 'transparent') {
|
||||
const rgbaMatch = containerBg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
|
||||
if (rgbaMatch) {
|
||||
elements.containerBgColor.value = rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3]));
|
||||
elements.containerBgOpacity.value = rgbaMatch[4] ? Math.round(parseFloat(rgbaMatch[4]) * 100) : 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (containerBorder && containerBorder !== 'transparent' && containerBorder !== 'rgba(0, 0, 0, 0)') {
|
||||
const rgbaMatch = containerBorder.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
|
||||
if (rgbaMatch) {
|
||||
elements.containerBorderColor.value = rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3]));
|
||||
}
|
||||
}
|
||||
|
||||
elements.containerBorderRadius.value = parseInt(containerRadius) || 8;
|
||||
elements.containerPadding.value = parseInt(containerPad) || 10;
|
||||
|
||||
updateRangeValue(elements.containerBgOpacity);
|
||||
|
||||
const sections = [
|
||||
{ selector: '.layout-hub-tip', elements: { fontSize: elements.tipFontSize, fontWeight: elements.tipFontWeight, color: elements.tipColor, lineHeight: elements.tipLineHeight, bgColor: elements.tipBgColor, bgOpacity: elements.tipBgOpacity, borderRadius: elements.tipBorderRadius, padding: elements.tipPadding } },
|
||||
{ selector: '.layout-hub-message', elements: { fontSize: elements.messageFontSize, fontWeight: elements.messageFontWeight, color: elements.messageColor, lineHeight: elements.messageLineHeight, bgColor: elements.messageBgColor, bgOpacity: elements.messageBgOpacity, borderRadius: elements.messageBorderRadius, padding: elements.messagePadding } },
|
||||
{ selector: '.layout-hub-hot-title', elements: { fontSize: elements.hotTitleFontSize, fontWeight: elements.hotTitleFontWeight, color: elements.hotTitleColor, lineHeight: elements.hotTitleLineHeight, bgColor: elements.hotTitleBgColor, bgOpacity: elements.hotTitleBgOpacity, borderRadius: elements.hotTitleBorderRadius, padding: elements.hotTitlePadding } },
|
||||
{ selector: '.layout-hub-hot-issues', elements: { fontSize: elements.hotIssuesFontSize, fontWeight: elements.hotIssuesFontWeight, color: elements.hotIssuesColor, lineHeight: elements.hotIssuesLineHeight, bgColor: elements.hotIssuesBgColor, bgOpacity: elements.hotIssuesBgOpacity, borderRadius: elements.hotIssuesBorderRadius, padding: elements.hotIssuesPadding } }
|
||||
];
|
||||
|
||||
sections.forEach(section => {
|
||||
const el = captionContainer.querySelector(section.selector);
|
||||
if (!el) return;
|
||||
|
||||
const styles = window.getComputedStyle(el);
|
||||
section.elements.fontSize.value = parseInt(styles.fontSize) || 14;
|
||||
section.elements.fontWeight.value = styles.fontWeight === 'bold' ? 'bold' : 'normal';
|
||||
section.elements.color.value = parseColor(styles.color);
|
||||
section.elements.lineHeight.value = parseFloat(styles.lineHeight) || 1.5;
|
||||
|
||||
if (styles.backgroundColor && styles.backgroundColor !== 'transparent') {
|
||||
const rgbaMatch = styles.backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
|
||||
if (rgbaMatch) {
|
||||
section.elements.bgColor.value = rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3]));
|
||||
section.elements.bgOpacity.value = rgbaMatch[4] ? Math.round(parseFloat(rgbaMatch[4]) * 100) : 100;
|
||||
}
|
||||
}
|
||||
|
||||
section.elements.borderRadius.value = parseInt(styles.borderRadius) || 4;
|
||||
section.elements.padding.value = parseInt(styles.padding) || 6;
|
||||
|
||||
updateRangeValue(section.elements.bgOpacity);
|
||||
});
|
||||
|
||||
logger.info('已从字幕容器加载样式');
|
||||
}
|
||||
|
||||
function parseColor(colorStr) {
|
||||
if (!colorStr) return '#ffffff';
|
||||
if (colorStr.startsWith('#')) return colorStr;
|
||||
const rgbaMatch = colorStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
|
||||
if (rgbaMatch) {
|
||||
return rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3]));
|
||||
}
|
||||
return '#ffffff';
|
||||
}
|
||||
|
||||
function rgbToHex(r, g, b) {
|
||||
return '#' + [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
|
||||
function updateRangeValue(rangeInput) {
|
||||
const valueSpan = rangeInput.nextElementSibling;
|
||||
if (valueSpan && valueSpan.classList.contains('range-value')) {
|
||||
valueSpan.textContent = `${rangeInput.value}%`;
|
||||
}
|
||||
}
|
||||
|
||||
function initCaptionDragAndResize(container) {
|
||||
container.dataset.dragInitialized = 'true';
|
||||
|
||||
@@ -524,6 +669,7 @@ function watchCaptionContainer() {
|
||||
captionContainer.style.userSelect = 'none';
|
||||
captionContainer.style.zIndex = '9999';
|
||||
initCaptionDragAndResize(captionContainer);
|
||||
loadCaptionStyleFromContainer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -534,6 +680,10 @@ function watchCaptionContainer() {
|
||||
subtree: true
|
||||
});
|
||||
|
||||
if (document.querySelector('.caption-container-hub')) {
|
||||
setTimeout(loadCaptionStyleFromContainer, 100);
|
||||
}
|
||||
|
||||
logger.info('已启动字幕容器监听');
|
||||
}
|
||||
|
||||
@@ -593,6 +743,15 @@ function bindEvents() {
|
||||
elements.getOnceCodeBtn.addEventListener('click', handleGetOnceCode);
|
||||
elements.applyCaptionStyleBtn.addEventListener('click', applyCaptionStyle);
|
||||
|
||||
document.querySelectorAll('input[type="range"]').forEach(slider => {
|
||||
slider.addEventListener('input', (e) => {
|
||||
const valueSpan = e.target.nextElementSibling;
|
||||
if (valueSpan && valueSpan.classList.contains('range-value')) {
|
||||
valueSpan.textContent = `${e.target.value}%`;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
elements.clearLogBtn.addEventListener('click', clearLogs);
|
||||
elements.logLevel.addEventListener('change', () => {
|
||||
if (state.isInitialized) {
|
||||
@@ -602,7 +761,10 @@ function bindEvents() {
|
||||
});
|
||||
|
||||
elements.toggleConfigBtn.addEventListener('click', () => togglePanel('configPanel'));
|
||||
elements.toggleCaptionBtn.addEventListener('click', () => togglePanel('captionPanel'));
|
||||
elements.toggleCaptionBtn.addEventListener('click', () => {
|
||||
togglePanel('captionPanel');
|
||||
loadCaptionStyleFromContainer();
|
||||
});
|
||||
elements.toggleLogBtn.addEventListener('click', () => togglePanel('logPanel'));
|
||||
elements.fullscreenBtn.addEventListener('click', toggleFullscreen);
|
||||
|
||||
|
||||
@@ -373,6 +373,32 @@ body {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.caption-style-section input[type="range"] {
|
||||
width: calc(100% - 50px);
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
background: var(--bg-tertiary);
|
||||
outline: none;
|
||||
-webkit-appearance: none;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.caption-style-section input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.caption-style-section .range-value {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-muted);
|
||||
min-width: 35px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* ===== 日志面板 ===== */
|
||||
.log-panel {
|
||||
bottom: calc(var(--spacing-xl) + 60px);
|
||||
|
||||
Reference in New Issue
Block a user