feat: refonte mobile de la section Configurations #114
This commit is contained in:
+28
-19
@@ -1551,6 +1551,17 @@
|
||||
<nav class="help-nav" id="config-nav">
|
||||
<div class="help-nav-header">
|
||||
<div class="help-nav-title" data-i18n="config.title">Configuration</div>
|
||||
<button
|
||||
class="help-toc-close"
|
||||
id="config-toc-close"
|
||||
data-i18n-attr="aria-label:config.toc_close"
|
||||
aria-label="Fermer le sommaire"
|
||||
>
|
||||
<i
|
||||
data-lucide="x"
|
||||
style="width: 16px; height: 16px"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="help-nav-search-wrap">
|
||||
<input
|
||||
@@ -2146,7 +2157,6 @@
|
||||
>Nombre max de tokens élargis par préfixe (10-200)</span
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
<div class="config-actions-row">
|
||||
<button class="config-btn-save"
|
||||
id="cfg-save-backend" data-i18n="help.shortcut_save">
|
||||
@@ -2509,7 +2519,7 @@
|
||||
|
||||
<!-- Partages publics -->
|
||||
<section class="config-section help-section" id="cfg-partages-publics">
|
||||
<h2 id="cfg-partages-publics">📤 Partages publics</h2>
|
||||
<h2>📤 Partages publics</h2>
|
||||
<p class="config-description">
|
||||
Liens de partage publics pour des documents
|
||||
(lecture seule, sans authentification).
|
||||
@@ -2517,23 +2527,22 @@
|
||||
<div id="shares-list"></div>
|
||||
</section>
|
||||
|
||||
<!-- Plugins -->
|
||||
<section
|
||||
class="config-section help-section"
|
||||
id="cfg-plugins"
|
||||
>
|
||||
<h2 data-i18n="config.section_plugins">🧩 Plugins</h2>
|
||||
<p class="config-description" data-i18n="plugins.description">
|
||||
Extend ObsiGate with custom renderers, search filters, and editor actions.
|
||||
</p>
|
||||
<div id="plugins-settings-container"></div>
|
||||
</section>
|
||||
<!-- Plugins -->
|
||||
<section
|
||||
class="config-section help-section"
|
||||
id="cfg-plugins"
|
||||
>
|
||||
<h2 data-i18n="config.section_plugins">🧩 Plugins</h2>
|
||||
<p class="config-description" data-i18n="plugins.description">
|
||||
Extend ObsiGate with custom renderers, search filters, and editor actions.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- À propos -->
|
||||
<section
|
||||
class="config-section help-section"
|
||||
id="cfg-about"
|
||||
>
|
||||
<!-- À propos -->
|
||||
<section
|
||||
class="config-section help-section"
|
||||
id="cfg-about"
|
||||
>
|
||||
<h2 data-i18n="auto.a3319169">📦 À propos</h2>
|
||||
<div
|
||||
id="config-about"
|
||||
@@ -5614,7 +5623,7 @@ curl -X POST https://votre-serveur.com/webhook \
|
||||
data-lucide="folder-open"
|
||||
style="width: 20px; height: 20px"
|
||||
></i>
|
||||
<span class="mt-label">settings.search</span>
|
||||
<span class="mt-label" data-i18n="settings.explorer">Explorateur</span>
|
||||
</button>
|
||||
<button
|
||||
class="mt-btn"
|
||||
|
||||
+38
-6
@@ -767,10 +767,15 @@ function initConfigModal() {
|
||||
openBtn.addEventListener("click", async () => {
|
||||
modal.classList.add("active");
|
||||
closeHeaderMenu();
|
||||
// BUG-071: reset the TOC to the CSS default (mobile: hidden, desktop:
|
||||
// visible) like the help modal does on open.
|
||||
// BUG-071/#114: reset the TOC to the CSS default (mobile: hidden drawer,
|
||||
// desktop: visible sidebar) like the help modal does on open. Clear the
|
||||
// stale inline display and the drawer-open class so a previous mobile
|
||||
// session cannot leave the nav stuck open.
|
||||
var configNavOnOpen = document.getElementById("config-nav");
|
||||
if (configNavOnOpen) configNavOnOpen.style.display = '';
|
||||
modal.classList.remove("config-toc-open");
|
||||
var configHamburgerOnOpen = document.getElementById("config-hamburger");
|
||||
if (configHamburgerOnOpen) configHamburgerOnOpen.classList.remove("active");
|
||||
renderConfigFilters();
|
||||
loadConfigFields();
|
||||
loadDiagnostics();
|
||||
@@ -786,6 +791,12 @@ function initConfigModal() {
|
||||
closeBtn.addEventListener("click", closeConfigModal);
|
||||
modal.addEventListener("click", (e) => {
|
||||
if (e.target === modal) {
|
||||
// #114: a tap on the backdrop (or outside the drawer) first closes the
|
||||
// TOC drawer; only a second tap closes the whole modal.
|
||||
if (modal.classList.contains("config-toc-open")) {
|
||||
_setConfigNav(false);
|
||||
return;
|
||||
}
|
||||
closeConfigModal();
|
||||
}
|
||||
});
|
||||
@@ -890,17 +901,19 @@ function initConfigModal() {
|
||||
});
|
||||
}
|
||||
|
||||
// BUG-071: mobile table of contents. #config-nav shares the .help-nav
|
||||
// BUG-071/#114: mobile table of contents. #config-nav shares the .help-nav
|
||||
// rule that hides it below 768px, but — unlike the help modal — the config
|
||||
// modal had no toggle to reveal it, leaving mobile users with no way to
|
||||
// reach a section. The header hamburger opens it as a top block; picking
|
||||
// a section smooth-scrolls inside the modal and collapses it on mobile.
|
||||
// reach a section. The header hamburger opens it as a left slide-over
|
||||
// drawer (backdrop via .config-toc-open on the modal); picking a section
|
||||
// smooth-scrolls inside the modal and collapses it on mobile.
|
||||
var configNav = document.getElementById("config-nav");
|
||||
var configHamburger = document.getElementById("config-hamburger");
|
||||
function _isConfigMobile() { return window.innerWidth <= 768; }
|
||||
function _setConfigNav(open) {
|
||||
if (!configNav) return;
|
||||
configNav.style.display = open ? "flex" : "none";
|
||||
modal.classList.toggle("config-toc-open", !!open && _isConfigMobile());
|
||||
if (configHamburger) configHamburger.classList.toggle("active", !!open);
|
||||
}
|
||||
if (configHamburger) {
|
||||
@@ -910,6 +923,14 @@ function initConfigModal() {
|
||||
_setConfigNav(hidden);
|
||||
});
|
||||
}
|
||||
// #114: close button inside the drawer header.
|
||||
var configTocClose = document.getElementById("config-toc-close");
|
||||
if (configTocClose) {
|
||||
configTocClose.addEventListener("click", function(e) {
|
||||
e.stopPropagation();
|
||||
_setConfigNav(false);
|
||||
});
|
||||
}
|
||||
if (configNav) {
|
||||
configNav.querySelectorAll(".help-nav-link").forEach(function(a) {
|
||||
a.addEventListener("click", function(e) {
|
||||
@@ -930,6 +951,11 @@ function initConfigModal() {
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape" && modal.classList.contains("active")) {
|
||||
// #114: Escape closes the TOC drawer first, then the modal.
|
||||
if (modal.classList.contains("config-toc-open")) {
|
||||
_setConfigNav(false);
|
||||
return;
|
||||
}
|
||||
closeConfigModal();
|
||||
}
|
||||
});
|
||||
@@ -949,7 +975,13 @@ function initConfigModal() {
|
||||
|
||||
function closeConfigModal() {
|
||||
const modal = document.getElementById("config-modal");
|
||||
if (modal) modal.classList.remove("active");
|
||||
if (modal) {
|
||||
modal.classList.remove("active");
|
||||
// #114: never leave the drawer-open class (backdrop) behind.
|
||||
modal.classList.remove("config-toc-open");
|
||||
const nav = document.getElementById("config-nav");
|
||||
if (nav) nav.style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
// --- Config field helpers ---
|
||||
|
||||
@@ -578,6 +578,7 @@
|
||||
"config.test": "Test",
|
||||
"config.timeout_label": "Search timeout (ms)",
|
||||
"config.title": "Settings",
|
||||
"config.toc_close": "Close contents",
|
||||
"config.toc_toggle": "Show contents",
|
||||
"config.title_boost": "Title boost",
|
||||
"config.title_boost_hint": "Relevance multiplier for title matches",
|
||||
@@ -1631,25 +1632,21 @@
|
||||
"search.whole_word": "Whole word",
|
||||
"settings.about": "📦 About",
|
||||
"settings.ai": "🤖 AI",
|
||||
"settings.backend": "⚙️ Backend",
|
||||
"settings.backend_hint": "These settings are saved on the server. Some require a restart or reindexing.",
|
||||
"settings.backend_section": "Backend Settings",
|
||||
"settings.client_label": "These settings apply immediately on the client side.",
|
||||
"settings.diagnostics": "🩺 Diagnostics",
|
||||
"settings.explorer": "Files",
|
||||
"settings.history_count_desc": "Between 5 and 100 files (saved on server)",
|
||||
"settings.history_count_label": "Files in history",
|
||||
"settings.history_section": "Recent History",
|
||||
"settings.no_restart_badge": "No restart needed",
|
||||
"settings.profile": "👤 Profile",
|
||||
"settings.reindex": "Force reindex",
|
||||
"settings.restart_badge": "Restart required",
|
||||
"settings.save": "Save",
|
||||
"settings.search": "Search",
|
||||
"settings.tabs": "Tabs",
|
||||
"settings.search_placeholder": "Search...",
|
||||
"settings.sync": "🔄 Sync",
|
||||
"settings.tabs": "Tabs",
|
||||
"settings.themes": "🎨 Themes",
|
||||
"settings.plugins": "🧩 Plugins",
|
||||
"share.copied": "Link copied!",
|
||||
"share.copy_link": "Copy link",
|
||||
"share.create": "Create share link",
|
||||
|
||||
@@ -578,6 +578,7 @@
|
||||
"config.test": "Tester",
|
||||
"config.timeout_label": "Timeout recherche (ms)",
|
||||
"config.title": "Configuration",
|
||||
"config.toc_close": "Fermer le sommaire",
|
||||
"config.toc_toggle": "Afficher le sommaire",
|
||||
"config.title_boost": "Boost titre",
|
||||
"config.title_boost_hint": "Multiplicateur de pertinence pour les correspondances dans le titre",
|
||||
@@ -1631,25 +1632,21 @@
|
||||
"search.whole_word": "Mot entier",
|
||||
"settings.about": "📦 À propos",
|
||||
"settings.ai": "🤖 IA",
|
||||
"settings.backend": "⚙️ Backend",
|
||||
"settings.backend_hint": "Ces paramètres sont sauvegardés sur le serveur. Certains nécessitent un redémarrage ou une réindexation.",
|
||||
"settings.backend_section": "Paramètres backend",
|
||||
"settings.client_label": "Ces paramètres s'appliquent immédiatement côté client.",
|
||||
"settings.diagnostics": "🩺 Diagnostics",
|
||||
"settings.explorer": "Explorateur",
|
||||
"settings.history_count_desc": "Entre 5 et 100 fichiers (sauvegarde sur le serveur)",
|
||||
"settings.history_count_label": "Nombre de fichiers dans l'historique",
|
||||
"settings.history_section": "Historique récent",
|
||||
"settings.no_restart_badge": "Redémarrage non requis",
|
||||
"settings.profile": "👤 Profil",
|
||||
"settings.reindex": "Forcer réindexation",
|
||||
"settings.restart_badge": "Redémarrage requis",
|
||||
"settings.save": "Sauvegarder",
|
||||
"settings.search": "Recherche",
|
||||
"settings.tabs": "Tabs",
|
||||
"settings.search_placeholder": "Rechercher...",
|
||||
"settings.sync": "🔄 Synchronisation",
|
||||
"settings.tabs": "Onglets",
|
||||
"settings.themes": "🎨 Thèmes",
|
||||
"settings.plugins": "🧩 Plugins",
|
||||
"share.copied": "Lien copié !",
|
||||
"share.copy_link": "Copier le lien",
|
||||
"share.create": "Créer un lien de partage",
|
||||
|
||||
+272
-38
@@ -3164,6 +3164,23 @@ select {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.help-hamburger:hover { color: var(--accent); border-color: var(--accent); }
|
||||
/* #114: close button for the mobile TOC drawer (hidden on desktop where the
|
||||
nav is always visible). Scoped to #config-modal so the help modal — which
|
||||
has no such button — is unaffected. */
|
||||
.help-toc-close {
|
||||
display: none;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
padding: 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.help-nav {
|
||||
width: 260px;
|
||||
min-width: 260px;
|
||||
@@ -4777,22 +4794,204 @@ body.resizing-v {
|
||||
}
|
||||
}
|
||||
|
||||
/* BUG-071: Configurations modal — mobile usability (viewport ≤ 768px).
|
||||
#config-nav shares the .help-nav rule that hides it, but the config modal
|
||||
had no toggle (unlike the help modal): the header hamburger
|
||||
(#config-hamburger, same .help-hamburger treatment) reveals it as a
|
||||
collapsible top block. Two-column grids and fixed-width add-rows are
|
||||
stacked/wrapped so nothing overflows a 360px viewport. */
|
||||
/* --- #114: Configurations modal — mobile UX refonte (viewport ≤ 768px).
|
||||
Builds on BUG-071 (which stacked grids/wrapped rows): the TOC becomes a
|
||||
left slide-over drawer with a backdrop, the modal goes full-screen with
|
||||
100dvh, every interactive control gets a ≥44px touch target, inputs are
|
||||
≥16px to stop iOS auto-zoom, and the backend Save row sticks to the
|
||||
bottom of its scroll container. The drawer is opened by JS toggling
|
||||
.config-toc-open on #config-modal (backdrop + nav visibility) plus an
|
||||
inline display on #config-nav (kept for the display-reset contract). */
|
||||
@media (max-width: 768px) {
|
||||
/* TOC as a collapsible top block (JS toggles inline display flex/none,
|
||||
which wins over the hiding rule); the list scrolls within a capped nav. */
|
||||
#config-modal #config-nav {
|
||||
/* Full-screen modal with dynamic viewport height (mobile browser chrome). */
|
||||
#config-modal {
|
||||
padding: 0;
|
||||
align-items: stretch;
|
||||
}
|
||||
#config-modal .editor-container {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
max-height: 100vh;
|
||||
max-height: 100dvh;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* Hamburger: 44px touch target (shared .help-hamburger rule in the help
|
||||
modal media query also sets 44px; this scopes it to the config modal
|
||||
in case rule order changes). */
|
||||
#config-modal .help-hamburger {
|
||||
display: inline-flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
min-width: 44px;
|
||||
}
|
||||
/* Close button in the TOC drawer header. */
|
||||
#config-modal .help-toc-close {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
#config-modal .help-nav-header {
|
||||
padding: 12px 12px 8px;
|
||||
gap: 8px;
|
||||
}
|
||||
/* Close (X) in the modal header. */
|
||||
#config-modal .editor-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
min-width: 44px;
|
||||
}
|
||||
/* Anti-zoom: ≥16px font on text fields inside the config modal. Never
|
||||
target input[type=text] globally — it would clobber .mfa-code-input. */
|
||||
#config-modal .config-input,
|
||||
#config-modal .config-select,
|
||||
#config-modal .help-nav-search,
|
||||
#config-modal .profile-field .config-input,
|
||||
#config-modal .profile-field .config-select {
|
||||
min-height: 44px;
|
||||
font-size: 16px;
|
||||
}
|
||||
#config-modal .config-input--num {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
#config-modal .help-nav-search-wrap {
|
||||
padding: 0 12px 10px;
|
||||
}
|
||||
#config-modal .help-search-clear {
|
||||
min-width: 44px;
|
||||
min-height: 44px;
|
||||
}
|
||||
#config-modal .help-nav-link {
|
||||
min-height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* Sticky Save row inside #cfg-backend-settings (its scroll container is
|
||||
#config-scroll.help-content, which is the overflow ancestor). */
|
||||
#config-modal .config-actions-row {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 0;
|
||||
padding: 10px 0 calc(10px + env(safe-area-inset-bottom, 0));
|
||||
background: var(--bg-primary);
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
#config-modal .config-actions-row .config-btn-save,
|
||||
#config-modal .config-actions-row .config-btn-secondary,
|
||||
#config-modal .config-actions-row .config-btn-primary,
|
||||
#config-modal .config-actions-row .config-btn-danger {
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
min-height: 44px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#config-modal .config-btn-save,
|
||||
#config-modal .config-btn-secondary,
|
||||
#config-modal .config-btn-primary,
|
||||
#config-modal .config-btn-danger,
|
||||
#config-modal .config-btn-add,
|
||||
#config-modal .config-btn-sm,
|
||||
#config-modal .mfa-link-btn,
|
||||
#config-modal .theme-action-btn,
|
||||
#config-modal .profile-avatar-actions .config-btn-secondary,
|
||||
#config-modal .editor-btn {
|
||||
min-height: 44px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#config-modal .config-btn-sm,
|
||||
#config-modal .mfa-link-btn,
|
||||
#config-modal .theme-action-btn {
|
||||
min-width: 44px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
/* Profile avatar row: wrap instead of overflowing a 360px viewport. */
|
||||
#config-modal .profile-avatar-row {
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
#config-modal .profile-form {
|
||||
max-width: 100%;
|
||||
}
|
||||
/* MFA: one-column recovery list, wrapping action rows, full-width code
|
||||
input with a readable letter-spacing (12px overflows 360px). */
|
||||
#config-modal .mfa-recovery-list {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 6px;
|
||||
}
|
||||
#config-modal .mfa-verify-section,
|
||||
#config-modal .mfa-recovery-actions,
|
||||
#config-modal .mfa-disable-actions {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#config-modal .mfa-verify-section .config-input,
|
||||
#config-modal .mfa-verify-section .config-btn-primary {
|
||||
flex: 1 1 100%;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid var(--border);
|
||||
max-height: 46vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#config-modal .mfa-recovery-actions .config-btn-secondary,
|
||||
#config-modal .mfa-disable-actions .config-btn-danger {
|
||||
flex: 1 1 auto;
|
||||
min-height: 44px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#config-modal .mfa-code-input {
|
||||
width: 100%;
|
||||
max-width: 320px;
|
||||
min-height: 52px;
|
||||
font-size: 24px;
|
||||
letter-spacing: 6px;
|
||||
}
|
||||
#config-modal .mfa-secret-code {
|
||||
display: block;
|
||||
word-break: break-all;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
#config-modal .mfa-code-input-group {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
/* WebAuthn key rows: wrap instead of clipping the remove button. */
|
||||
#config-modal .webauthn-key-item {
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
#config-modal .webauthn-key-label {
|
||||
flex: 1 1 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
#config-modal .webauthn-key-item .config-btn-sm {
|
||||
min-height: 44px;
|
||||
min-width: 44px;
|
||||
}
|
||||
#config-modal .hidden-files-add-row {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#config-modal .hidden-files-add-row .config-input {
|
||||
flex: 1 1 100%;
|
||||
max-width: none;
|
||||
min-width: 0;
|
||||
}
|
||||
#config-modal .config-diag-row {
|
||||
flex-wrap: wrap;
|
||||
gap: 4px 8px;
|
||||
}
|
||||
/* AI keys sticky footer: clear the mobile toolbar + home indicator. */
|
||||
#config-modal .ai-keys-footer {
|
||||
padding-bottom: calc(12px + env(safe-area-inset-bottom, 0));
|
||||
bottom: 0;
|
||||
}
|
||||
/* Two-column grids → single column. */
|
||||
#config-modal .ai-default-grid,
|
||||
@@ -4851,6 +5050,61 @@ body.resizing-v {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
/* Drawer: left slide-over above a dimming backdrop. Higher specificity
|
||||
than the generic .help-nav rules (body .help-nav / .help-nav) that hide
|
||||
the nav on mobile. JS toggles .config-toc-open on #config-modal. */
|
||||
#config-modal #config-nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: min(320px, 88vw);
|
||||
min-width: 0;
|
||||
max-width: 88vw;
|
||||
max-height: 100dvh;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
z-index: 40;
|
||||
background: var(--bg-secondary);
|
||||
border-right: 1px solid var(--border);
|
||||
border-bottom: none;
|
||||
box-shadow: none;
|
||||
backdrop-filter: none;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
animation: config-toc-slide-in 200ms ease-out;
|
||||
}
|
||||
#config-modal.config-toc-open #config-nav {
|
||||
display: flex;
|
||||
max-height: 100dvh;
|
||||
}
|
||||
#config-modal .help-nav-list {
|
||||
padding-bottom: calc(20px + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
/* Backdrop: covers the full modal, sits above the content (z-index auto)
|
||||
and below the drawer (z-index 40). Clicks on the pseudo-element are
|
||||
attributed to #config-modal, so the existing e.target === modal handler
|
||||
closes the drawer first; it also blocks taps reaching the content. */
|
||||
#config-modal.config-toc-open::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 35;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
@keyframes config-toc-slide-in {
|
||||
from {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
/* Content area gets a bottom pad so the sticky Save row never covers the
|
||||
last controls while the virtual keyboard is open. */
|
||||
#config-modal #config-scroll .config-content {
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Toast notifications --- */
|
||||
@@ -5819,28 +6073,6 @@ body.resizing-v {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.config-btn-add {
|
||||
padding: 6px 12px;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all 150ms ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.config-btn-add:hover {
|
||||
background: color-mix(in srgb, var(--accent) 85%, black);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.config-btn-add:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Utility — hidden class
|
||||
--------------------------------------------------------------------------- */
|
||||
@@ -7907,7 +8139,6 @@ body.popup-mode .content-area {
|
||||
.webhook-events { color: var(--text-muted); font-size: 0.7rem; }
|
||||
.webhook-delete { background: none; border: none; color: var(--text-error); cursor: pointer; font-size: 1rem; padding: 2px 6px; }
|
||||
.config-add-row { display: flex; gap: 8px; margin-top: 8px; }
|
||||
.config-btn-add { padding: 6px 14px; background: var(--accent); color: #fff; border: none; border-radius: 6px; cursor: pointer; font-size: 0.8rem; }
|
||||
|
||||
/* ── API/MCP tokens UI (#107) ── */
|
||||
.token-item {
|
||||
@@ -8506,9 +8737,13 @@ body.desktop-mode .editor-container {
|
||||
|
||||
.help-hamburger {
|
||||
display: inline-flex;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
min-width: 44px;
|
||||
}
|
||||
|
||||
/* TOC: collapsible block at top (not slide-over) */
|
||||
/* TOC drawer: collapsible block for the help modal; the config modal
|
||||
(#114) overrides this with a fixed left drawer + backdrop. */
|
||||
.help-nav {
|
||||
position: static;
|
||||
width: 100%;
|
||||
@@ -10763,7 +10998,6 @@ body.desktop-mode .editor-container {
|
||||
}
|
||||
.mfa-link-btn:hover { opacity: 0.8; }
|
||||
.mfa-error { color: #e74c3c; font-size: 13px; margin-top: 8px; }
|
||||
.mfa-recovery-input { width: 200px; font-size: 20px; letter-spacing: 4px; }
|
||||
|
||||
/* MFA Settings (Security tab) */
|
||||
.mfa-status-section { padding: 16px 0; }
|
||||
|
||||
Reference in New Issue
Block a user