feat: sidebar récursive par arbre + liste des récents
Port de la logique buildTree/renderTree de MarkdownRender-nodejs vers Pena-tauri pour une navigation dossier à profondeur illimitée avec <details> collapsibles, gestion du Home.md par dossier et ouverture automatique des ancêtres du fichier courant. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
# Règles — Captures d'écran
|
||||||
|
|
||||||
|
## Emplacement
|
||||||
|
Les captures d'écran sont disponibles à l'emplacement suivant :
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/Gato/Images/Captures d'écran/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quand les consulter
|
||||||
|
- Lorsque l'utilisateur mentionne une capture d'écran sans fournir de chemin explicite.
|
||||||
|
- Lorsqu'un bug visuel ou un comportement d'interface est décrit — consulter la capture la plus récente pour avoir le contexte visuel.
|
||||||
|
- Lorsqu'une tâche porte sur l'UI et qu'une illustration de l'état actuel est utile.
|
||||||
|
- Après avoir relancé l'application pour vérifier un changement visuel.
|
||||||
|
|
||||||
|
## Comportement attendu
|
||||||
|
- Lire le fichier le plus récent du dossier (tri par date de modification).
|
||||||
|
- Ne pas demander à l'utilisateur de fournir le chemin si la capture se trouve dans ce dossier.
|
||||||
|
- Ne pas demander à l'utilisateur de prendre une capture d'écran.
|
||||||
|
- **Ne jamais prendre de capture d'écran de façon autonome** (`scrot`, `grim`, `gnome-screenshot`, `import`, etc.).
|
||||||
|
|
||||||
|
## Note technique
|
||||||
|
Le nom du dossier contient un `é` dont l'encodage n'est pas résolu correctement par `ls` ni `find`. Utiliser **Python `os.scandir`** pour lister les fichiers :
|
||||||
|
|
||||||
|
```python
|
||||||
|
import os, shutil
|
||||||
|
base = "/home/Gato/Images"
|
||||||
|
for entry in os.scandir(base):
|
||||||
|
if "Captures" in entry.name:
|
||||||
|
files = sorted(os.scandir(entry.path), key=lambda e: e.stat().st_mtime, reverse=True)
|
||||||
|
shutil.copy(files[0].path, '/tmp/screenshot.png')
|
||||||
|
```
|
||||||
|
|
||||||
|
Puis lire `/tmp/screenshot.png` avec le tool `Read`.
|
||||||
@@ -17,6 +17,10 @@
|
|||||||
<button id="btn-open-file">Ouvrir un fichier Markdown</button>
|
<button id="btn-open-file">Ouvrir un fichier Markdown</button>
|
||||||
<button id="btn-open-dir">Ouvrir un dossier wiki</button>
|
<button id="btn-open-dir">Ouvrir un dossier wiki</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="home-recents" class="home-recents hidden">
|
||||||
|
<p class="home-recents__label">Récents</p>
|
||||||
|
<ul id="home-recents-list" class="home-recents__list"></ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="view-reader" class="hidden">
|
<div id="view-reader" class="hidden">
|
||||||
|
|||||||
+122
-51
@@ -6,6 +6,50 @@ const viewReader = document.getElementById('view-reader');
|
|||||||
const sidebar = document.querySelector('#sidebar');
|
const sidebar = document.querySelector('#sidebar');
|
||||||
const content = document.querySelector('#content');
|
const content = document.querySelector('#content');
|
||||||
|
|
||||||
|
const RECENTS_KEY = 'pena_recents';
|
||||||
|
const RECENTS_MAX = 8;
|
||||||
|
|
||||||
|
function loadRecents() {
|
||||||
|
try { return JSON.parse(localStorage.getItem(RECENTS_KEY) ?? '[]'); }
|
||||||
|
catch { return []; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveRecent(path, mode) {
|
||||||
|
const name = path.replace(/\\/g, '/').split('/').pop().replace(/\.md$/i, '');
|
||||||
|
const parent = path.replace(/\\/g, '/').split('/').slice(0, -1).join('/');
|
||||||
|
const recents = loadRecents().filter(r => r.path !== path);
|
||||||
|
recents.unshift({ path, mode, name, parent });
|
||||||
|
localStorage.setItem(RECENTS_KEY, JSON.stringify(recents.slice(0, RECENTS_MAX)));
|
||||||
|
renderRecents();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderRecents() {
|
||||||
|
const recents = loadRecents();
|
||||||
|
const container = document.getElementById('home-recents');
|
||||||
|
const list = document.getElementById('home-recents-list');
|
||||||
|
if (recents.length === 0) {
|
||||||
|
container.classList.add('hidden');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
container.classList.remove('hidden');
|
||||||
|
list.innerHTML = recents.map(r => {
|
||||||
|
const icon = r.mode === 'dir' ? '📁' : '📄';
|
||||||
|
const escaped = escapeHtml(r.path);
|
||||||
|
return `<li>
|
||||||
|
<button class="home-recents__item" data-path="${escaped}" data-mode="${r.mode}">
|
||||||
|
<span class="home-recents__item__icon">${icon}</span>
|
||||||
|
<span class="home-recents__item__info">
|
||||||
|
<span class="home-recents__item__name">${escapeHtml(r.name)}</span>
|
||||||
|
<span class="home-recents__item__path">${escapeHtml(r.parent)}</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</li>`;
|
||||||
|
}).join('');
|
||||||
|
list.querySelectorAll('.home-recents__item').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => openPath(btn.dataset.path, btn.dataset.mode));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function showHome() {
|
function showHome() {
|
||||||
viewReader.classList.add('hidden');
|
viewReader.classList.add('hidden');
|
||||||
viewHome.classList.remove('hidden');
|
viewHome.classList.remove('hidden');
|
||||||
@@ -24,67 +68,83 @@ function escapeHtml(str) {
|
|||||||
.replace(/"/g, '"');
|
.replace(/"/g, '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildTree(relPaths, sep) {
|
||||||
|
const tree = { _files: [], _dirs: {} };
|
||||||
|
relPaths.forEach((rel) => {
|
||||||
|
const parts = rel.split(sep);
|
||||||
|
let node = tree;
|
||||||
|
for (let i = 0; i < parts.length - 1; i++) {
|
||||||
|
const dir = parts[i];
|
||||||
|
if (!node._dirs[dir]) node._dirs[dir] = { _files: [], _dirs: {} };
|
||||||
|
node = node._dirs[dir];
|
||||||
|
}
|
||||||
|
node._files.push(rel);
|
||||||
|
});
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTree(node, prefix, sep, currentRel, depth) {
|
||||||
|
let html = '';
|
||||||
|
const depthClass = depth > 0 ? ` class="nav-depth-${Math.min(depth, 3)}"` : '';
|
||||||
|
|
||||||
|
node._files.slice().sort().forEach((rel) => {
|
||||||
|
const label = rel.split(sep).pop().replace(/\.md$/i, '').replace(/-/g, ' ');
|
||||||
|
const abs = prefix + rel;
|
||||||
|
const cls = rel === currentRel ? ' active' : '';
|
||||||
|
if (depth === 0) {
|
||||||
|
html += `\n<li><a href="#" class="nav-root-link${cls}" data-path="${escapeHtml(abs)}">${escapeHtml(label)}</a></li>`;
|
||||||
|
} else {
|
||||||
|
html += `\n<li${depthClass}><a href="#" class="nav-file-link${cls}" data-path="${escapeHtml(abs)}">${escapeHtml(label)}</a></li>`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(node._dirs).sort().forEach((dirName) => {
|
||||||
|
const child = node._dirs[dirName];
|
||||||
|
const isOpen = currentRel && currentRel.split(sep).includes(dirName);
|
||||||
|
const openAttr = isOpen ? ' open' : '';
|
||||||
|
|
||||||
|
const homeFile = child._files.find((f) => /^home\.md$/i.test(f.split(sep).pop()));
|
||||||
|
let folderLabel;
|
||||||
|
if (homeFile) {
|
||||||
|
const abs = prefix + homeFile;
|
||||||
|
const cls = homeFile === currentRel ? ' active' : '';
|
||||||
|
folderLabel = `<a href="#" class="nav-folder-link${cls}" data-path="${escapeHtml(abs)}" onclick="event.stopPropagation()">${escapeHtml(dirName)}</a>`;
|
||||||
|
} else {
|
||||||
|
folderLabel = `<span class="nav-folder-name">${escapeHtml(dirName)}</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const arrow = `<span class="nav-arrow" onclick="event.preventDefault();event.stopPropagation();var d=this.closest('details');d.open=!d.open">▶</span>`;
|
||||||
|
|
||||||
|
const childNode = {
|
||||||
|
_files: homeFile ? child._files.filter((f) => f !== homeFile) : child._files,
|
||||||
|
_dirs: child._dirs,
|
||||||
|
};
|
||||||
|
|
||||||
|
html += `\n<li${depthClass}><details class="nav-folder"${openAttr}>`;
|
||||||
|
html += `\n <summary>${arrow}${folderLabel}</summary>`;
|
||||||
|
html += `\n <ul class="nav-tree">`;
|
||||||
|
html += renderTree(childNode, prefix, sep, currentRel, depth + 1);
|
||||||
|
html += `\n </ul>\n</details></li>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
function buildSidebar(baseDir, files, currentFile) {
|
function buildSidebar(baseDir, files, currentFile) {
|
||||||
const sep = baseDir.includes('\\') ? '\\' : '/';
|
const sep = baseDir.includes('\\') ? '\\' : '/';
|
||||||
const dirName = baseDir.split(sep).pop();
|
const dirName = baseDir.split(sep).pop();
|
||||||
const prefix = baseDir.endsWith(sep) ? baseDir : baseDir + sep;
|
const prefix = baseDir.endsWith(sep) ? baseDir : baseDir + sep;
|
||||||
const toRel = abs => abs.startsWith(prefix) ? abs.slice(prefix.length) : abs;
|
const toRel = abs => abs.startsWith(prefix) ? abs.slice(prefix.length) : abs;
|
||||||
const baseName = rel => rel.split(sep).pop();
|
|
||||||
const currentRel = currentFile ? toRel(currentFile) : null;
|
const currentRel = currentFile ? toRel(currentFile) : null;
|
||||||
|
const relPaths = files.map(toRel);
|
||||||
const groups = new Map();
|
const tree = buildTree(relPaths, sep);
|
||||||
for (const f of files) {
|
|
||||||
const rel = toRel(f);
|
|
||||||
const parts = rel.split(sep);
|
|
||||||
const group = parts.length > 1 ? parts[0] : '';
|
|
||||||
if (!groups.has(group)) groups.set(group, []);
|
|
||||||
groups.get(group).push({ rel, abs: f });
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortedGroups = [...groups.keys()].sort((a, b) => {
|
|
||||||
if (a === '') return -1;
|
|
||||||
if (b === '') return 1;
|
|
||||||
return a.localeCompare(b);
|
|
||||||
});
|
|
||||||
|
|
||||||
let html = `<div class="sidebar__title-block">
|
let html = `<div class="sidebar__title-block">
|
||||||
<h1 class="sidebar__title-block__title">${escapeHtml(dirName)}</h1>
|
<h1 class="sidebar__title-block__title">${escapeHtml(dirName)}</h1>
|
||||||
</div>
|
</div>
|
||||||
<ul class="sidebar__menu">`;
|
<ul class="sidebar__menu nav-tree">`;
|
||||||
|
html += renderTree(tree, prefix, sep, currentRel, 0);
|
||||||
for (const group of sortedGroups) {
|
html += `\n </ul>`;
|
||||||
const pages = groups.get(group).slice().sort((a, b) => a.rel.localeCompare(b.rel));
|
|
||||||
|
|
||||||
if (group !== '') {
|
|
||||||
html += `
|
|
||||||
<li class="sidebar__menu__first-level-title">
|
|
||||||
<span class="sidebar__menu__group-label">${escapeHtml(group)}</span>
|
|
||||||
<ul class="sidebar__menu__second-level">`;
|
|
||||||
for (const { rel, abs } of pages) {
|
|
||||||
const label = baseName(rel).replace(/\.md$/i, '').replace(/-/g, ' ');
|
|
||||||
const cls = rel === currentRel ? ' active' : '';
|
|
||||||
html += `
|
|
||||||
<li class="sidebar__menu__second-level-title">
|
|
||||||
<a href="#" class="sidebar__menu__second-level-title__link${cls}" data-path="${escapeHtml(abs)}">${escapeHtml(label)}</a>
|
|
||||||
</li>`;
|
|
||||||
}
|
|
||||||
html += `
|
|
||||||
</ul>
|
|
||||||
</li>`;
|
|
||||||
} else {
|
|
||||||
for (const { rel, abs } of pages) {
|
|
||||||
const label = baseName(rel).replace(/\.md$/i, '').replace(/-/g, ' ');
|
|
||||||
const cls = rel === currentRel ? ' active' : '';
|
|
||||||
html += `
|
|
||||||
<li class="sidebar__menu__first-level-title">
|
|
||||||
<a href="#" class="sidebar__menu__first-level-title__link${cls}" data-path="${escapeHtml(abs)}">${escapeHtml(label)}</a>
|
|
||||||
</li>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html += `
|
|
||||||
</ul>`;
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +171,14 @@ async function loadPage(filePath) {
|
|||||||
sidebar.querySelectorAll('a').forEach(a => {
|
sidebar.querySelectorAll('a').forEach(a => {
|
||||||
a.classList.toggle('active', a.dataset.path === filePath);
|
a.classList.toggle('active', a.dataset.path === filePath);
|
||||||
});
|
});
|
||||||
|
const active = sidebar.querySelector('a[data-path].active');
|
||||||
|
if (active) {
|
||||||
|
let el = active.parentElement;
|
||||||
|
while (el && el !== sidebar) {
|
||||||
|
if (el.tagName === 'DETAILS') el.open = true;
|
||||||
|
el = el.parentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
content.innerHTML = `<p class="error">Impossible de charger le fichier : ${err}</p>`;
|
content.innerHTML = `<p class="error">Impossible de charger le fichier : ${err}</p>`;
|
||||||
@@ -120,6 +188,7 @@ async function loadPage(filePath) {
|
|||||||
async function openPath(path, mode) {
|
async function openPath(path, mode) {
|
||||||
currentPath = path;
|
currentPath = path;
|
||||||
currentMode = mode;
|
currentMode = mode;
|
||||||
|
saveRecent(path, mode);
|
||||||
|
|
||||||
if (mode === 'file') {
|
if (mode === 'file') {
|
||||||
sidebar.innerHTML = '';
|
sidebar.innerHTML = '';
|
||||||
@@ -153,6 +222,8 @@ async function openPath(path, mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderRecents();
|
||||||
|
|
||||||
document.getElementById('btn-open-file').addEventListener('click', async () => {
|
document.getElementById('btn-open-file').addEventListener('click', async () => {
|
||||||
const selected = await window.__TAURI__.dialog.open({
|
const selected = await window.__TAURI__.dialog.open({
|
||||||
multiple: false,
|
multiple: false,
|
||||||
|
|||||||
+165
@@ -61,6 +61,79 @@ body {
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Home recents ── */
|
||||||
|
.home-recents {
|
||||||
|
margin-top: 40px;
|
||||||
|
width: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__label {
|
||||||
|
color: rgba(255,255,255,0.3);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 9px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.15s;
|
||||||
|
text-align: left;
|
||||||
|
background: rgba(255,255,255,0.04);
|
||||||
|
border: none;
|
||||||
|
width: 100%;
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__item:hover {
|
||||||
|
background: rgba(255,255,255,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__item__icon {
|
||||||
|
font-size: 15px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__item__info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__item__name {
|
||||||
|
color: rgba(255,255,255,0.85);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-recents__item__path {
|
||||||
|
color: rgba(255,255,255,0.3);
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 400;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Sidebar ── */
|
/* ── Sidebar ── */
|
||||||
.sidebar {
|
.sidebar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -152,6 +225,98 @@ body {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Tree nav ── */
|
||||||
|
.nav-tree { list-style: none; margin: 0; padding: 0; }
|
||||||
|
.nav-tree li { margin: 0; }
|
||||||
|
|
||||||
|
.nav-root-link {
|
||||||
|
display: block;
|
||||||
|
padding: 7px 24px;
|
||||||
|
color: rgba(255,255,255,0.85);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
.nav-root-link:hover { color: #ff5577; }
|
||||||
|
.nav-root-link.active { color: #ff5577; font-weight: 500; }
|
||||||
|
|
||||||
|
.nav-folder { margin: 0; }
|
||||||
|
.nav-folder > summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
list-style: none;
|
||||||
|
cursor: default;
|
||||||
|
user-select: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.nav-folder > summary::-webkit-details-marker { display: none; }
|
||||||
|
|
||||||
|
.nav-arrow {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
font-size: 9px;
|
||||||
|
opacity: 0.4;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.18s, opacity 0.2s;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: rgba(255,255,255,0.7);
|
||||||
|
}
|
||||||
|
.nav-arrow:hover { opacity: 1; background: rgba(255,255,255,0.08); }
|
||||||
|
.nav-folder[open] > summary .nav-arrow { transform: rotate(90deg); opacity: 0.8; }
|
||||||
|
|
||||||
|
.nav-folder-link, .nav-folder-name {
|
||||||
|
flex: 1;
|
||||||
|
display: block;
|
||||||
|
padding: 6px 24px 6px 0;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
color: rgba(255,255,255,0.35);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.nav-folder-link:hover { color: rgba(255,255,255,0.85); }
|
||||||
|
.nav-folder-link.active { color: #ff5577; }
|
||||||
|
|
||||||
|
.nav-folder .nav-folder > summary .nav-folder-link,
|
||||||
|
.nav-folder .nav-folder > summary .nav-folder-name {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: 0;
|
||||||
|
color: rgba(255,255,255,0.45);
|
||||||
|
}
|
||||||
|
.nav-folder .nav-folder > summary .nav-folder-link:hover { color: rgba(255,255,255,0.9); }
|
||||||
|
|
||||||
|
.nav-file-link {
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: rgba(255,255,255,0.55);
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
.nav-file-link:hover { color: #ff5577; }
|
||||||
|
.nav-file-link.active { color: #ff5577; font-weight: 500; }
|
||||||
|
|
||||||
|
.nav-depth-1 > .nav-file-link { padding: 5px 24px 5px 52px; }
|
||||||
|
.nav-depth-1 > .nav-folder > summary { padding-left: 24px; }
|
||||||
|
.nav-depth-2 > .nav-file-link { padding: 4px 24px 4px 68px; }
|
||||||
|
.nav-depth-2 > .nav-folder > summary { padding-left: 40px; }
|
||||||
|
.nav-depth-3 > .nav-file-link { padding: 4px 24px 4px 84px; }
|
||||||
|
.nav-depth-3 > .nav-folder > summary { padding-left: 56px; }
|
||||||
|
|
||||||
/* ── Content ── */
|
/* ── Content ── */
|
||||||
.content {
|
.content {
|
||||||
margin-left: 264px;
|
margin-left: 264px;
|
||||||
|
|||||||
Reference in New Issue
Block a user