Files
Haven/public/css/style-theme-picker.css

298 lines
8.3 KiB
CSS

/* Theme picker gallery (public/js/modules/app-theme-picker.js): a search box
and sections of preview cards. Each card is drawn in its own theme's
colours: a built-in card carries data-theme, so the theme's tokens apply
inside it, and a theme file's card gets its palette as --tp-sw-* from the
server. The page's own colours are kept as --tp-page-* on the container,
for the parts that belong to the picker rather than the preview. */
.theme-gallery.theme-selector {
display: block;
padding: 0;
}
/* A little more room than the old row of dots needed. The themes scroll on
their own; the effects and sliders under them stay put (.theme-popup-pinned). */
.theme-popup { max-height: 70vh; flex-direction: column; overflow-y: auto; }
.theme-popup > .theme-popup-header { flex: none; }
/* Positioned so the hidden status line for screen readers (.tp-sr-only,
absolute) sits inside the gallery's own scroll. Placed against the popup
instead, it hung at the foot of the full theme list and gave the popup
twice its height in empty scroll (#5823). */
.theme-popup > .theme-gallery {
position: relative;
flex: 1 1 auto;
min-height: 7rem;
overflow-y: auto;
overscroll-behavior: contain;
}
.theme-popup-pinned {
flex: none;
max-height: 38vh;
overflow-y: auto;
overscroll-behavior: contain;
}
.tp-search-row {
position: sticky;
top: 0;
z-index: 2;
display: flex;
gap: 0.375rem;
margin: 0 0 0.25rem;
padding: 0 0 0.375rem;
background: var(--bg-secondary);
}
.tp-search-row .tp-search { flex: 1 1 auto; min-width: 0; }
.tp-publish-mode {
flex: none;
padding: 0.25rem 0.5rem;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg-input);
color: var(--text-secondary);
font: inherit;
font-size: 0.75rem;
cursor: pointer;
}
.tp-publish-mode[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
/* Out of publish mode, no switches and no "Available to publish" section. */
.theme-gallery:not(.tp-publishing) .tp-publish-row,
.theme-gallery:not(.tp-publishing) .tp-section[data-section="available"] { display: none; }
.tp-search {
display: block;
width: 100%;
box-sizing: border-box;
padding: 0.375rem 0.625rem;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg-input);
color: var(--text-primary);
font: inherit;
font-size: 0.8125rem;
}
.tp-search::placeholder { color: var(--text-muted); }
.tp-search:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 1px;
border-color: var(--accent);
}
.tp-sections {
--tp-page-accent: var(--accent);
--tp-page-glow: var(--accent-glow);
--tp-page-border: var(--border);
--tp-page-hover: var(--text-secondary);
--tp-page-on-accent: var(--accent-text, #fff);
}
.tp-section + .tp-section { margin-top: 0.375rem; }
.tp-section-head { margin: 0; }
.tp-section-toggle {
display: flex;
align-items: center;
gap: 0.375rem;
width: 100%;
padding: 0.25rem 0.125rem;
border: 0;
border-radius: var(--radius-sm);
background: none;
color: var(--text-muted);
font: inherit;
font-size: 0.6875rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
text-align: start;
cursor: pointer;
}
.tp-section-toggle:hover { color: var(--text-secondary); }
.tp-section-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tp-section-name {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tp-count { font-weight: 600; letter-spacing: 0; opacity: 0.8; }
.tp-chevron { transition: transform 0.15s ease; }
.tp-section-toggle[aria-expanded="false"] .tp-chevron { transform: rotate(-90deg); }
.tp-hint {
margin: 0 0.125rem 0.375rem;
color: var(--text-muted);
font-size: 0.6875rem;
line-height: 1.35;
}
.tp-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
gap: 0.375rem;
padding: 0.1875rem 0.125rem 0.25rem;
}
.tp-grid[hidden] { display: none; }
.tp-card-wrap { position: relative; min-width: 0; }
.theme-gallery .tp-card.theme-btn {
position: relative;
display: flex;
flex-direction: column;
align-items: stretch;
width: 100%;
height: auto;
padding: 0;
overflow: hidden;
border: 1px solid var(--tp-page-border);
border-radius: var(--radius-sm);
background: var(--tp-sw-panel, var(--bg-secondary));
color: var(--tp-sw-text, var(--text-primary));
font-family: var(--font-main);
font-size: 0.6875rem;
line-height: 1.25;
text-align: start;
text-shadow: none;
transform: none;
animation: none;
cursor: pointer;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.theme-gallery .tp-card.theme-btn:hover { border-color: var(--tp-page-hover); transform: none; }
.theme-gallery .tp-card.theme-btn:focus-visible {
outline: 2px solid var(--tp-page-accent);
outline-offset: 2px;
}
.theme-gallery .tp-card.theme-btn.tp-on {
border-color: var(--tp-page-accent);
box-shadow: 0 0 0 1px var(--tp-page-accent), 0 0 8px var(--tp-page-glow);
transform: none;
}
.theme-gallery .tp-card.theme-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.theme-gallery .tp-card.tp-overlay { border-style: dashed; }
.tp-preview {
position: relative;
display: flex;
height: 2.25rem;
background: var(--tp-sw-bg, var(--bg-primary));
pointer-events: none;
}
.tp-p-side {
width: 30%;
background: var(--tp-sw-panel, var(--bg-secondary));
}
.tp-p-main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
gap: 0.1875rem;
padding: 0 0.375rem;
}
.tp-p-accent {
width: 55%;
height: 0.25rem;
border-radius: 1rem;
background: var(--tp-sw-accent, var(--accent));
}
.tp-p-line {
width: 85%;
height: 0.1875rem;
border-radius: 1rem;
background: var(--tp-sw-text, var(--text-primary));
opacity: 0.4;
}
.tp-p-line.tp-p-short { width: 50%; }
.tp-preview .theme-icon {
position: absolute;
top: 50%;
inset-inline-start: 15%;
transform: translate(-50%, -50%);
color: var(--tp-sw-accent, var(--accent));
font-family: system-ui, sans-serif;
font-size: 0.75rem;
line-height: 1;
}
[dir="rtl"] .tp-preview .theme-icon { transform: translate(50%, -50%); }
/* Custom and RGB have no fixed palette, so their previews show the idea. */
.tp-card[data-theme="custom"] .tp-preview { background: linear-gradient(135deg, #ff2d6f, #faa61a, #43b581, #7c5cfc); }
.tp-card[data-theme="rgb"] .tp-preview {
background: linear-gradient(90deg, #ff0000, #ff8800, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
background-size: 200% 100%;
animation: rgb-btn-cycle 3s linear infinite;
}
.tp-card[data-theme="custom"] .tp-p-side,
.tp-card[data-theme="rgb"] .tp-p-side { background: rgba(0, 0, 0, 0.25); }
.tp-card[data-theme="custom"] .theme-icon,
.tp-card[data-theme="rgb"] .theme-icon { color: #fff; }
.tp-label {
display: flex;
flex-direction: column;
min-width: 0;
padding: 0.25rem 1.125rem 0.3125rem 0.375rem;
}
[dir="rtl"] .tp-label { padding: 0.25rem 0.375rem 0.3125rem 1.125rem; }
.tp-name,
.tp-author {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tp-name { font-weight: 600; }
.tp-author { font-size: 0.5625rem; opacity: 0.75; }
.tp-check {
display: none;
position: absolute;
bottom: 0.3125rem;
inset-inline-end: 0.25rem;
width: 0.8125rem;
height: 0.8125rem;
border-radius: 50%;
background: var(--tp-page-accent);
color: var(--tp-page-on-accent);
font-family: system-ui, sans-serif;
font-size: 0.5rem;
font-weight: 700;
line-height: 0.8125rem;
text-align: center;
}
.tp-card.tp-on .tp-check { display: block; }
/* The admin's publish switch, under each theme file's card. */
.tp-publish-row {
display: flex;
align-items: center;
gap: 0.375rem;
margin-top: 0.1875rem;
padding: 0.125rem 0.25rem;
border-radius: var(--radius-sm);
color: var(--text-secondary);
font-size: 0.6875rem;
cursor: pointer;
}
.tp-publish-row:hover { background: var(--bg-hover); }
.tp-publish-row .plugin-toggle.tp-publish { margin: 0; }
.tp-publish-text {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tp-empty {
margin: 0.75rem 0;
color: var(--text-muted);
font-size: 0.75rem;
text-align: center;
}
.tp-sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}