release: v0.15.0 (#585)

Eighteen changes since v0.14.0. See CHANGELOG.md for the full list and the upgrade notes (bump IMAGE_CACHE_VERSION).
This commit is contained in:
Ralksta
2026-09-19 22:24:10 +02:00
committed by GitHub
parent e99d3f2f1b
commit c3f92ca4ec
74 changed files with 4791 additions and 2146 deletions

View File

@@ -57,8 +57,9 @@
font-size: 0.85rem;
}
.picker-search input:focus {
outline: none;
.picker-search input:focus-visible {
outline: var(--admin-focus-ring);
outline-offset: 1px;
border-color: var(--admin-border-focus);
}

View File

@@ -155,8 +155,9 @@
font-family: monospace;
}
.asset-picker-uuid-input:focus {
outline: none;
.asset-picker-uuid-input:focus-visible {
outline: var(--admin-focus-ring);
outline-offset: 1px;
border-color: var(--admin-border-focus);
}

View File

@@ -117,10 +117,11 @@
transition: border-color 0.15s;
}
.admin-field input:focus,
.admin-field select:focus,
.admin-field textarea:focus {
outline: none;
.admin-field input:focus-visible,
.admin-field select:focus-visible,
.admin-field textarea:focus-visible {
outline: var(--admin-focus-ring);
outline-offset: 1px;
border-color: var(--admin-border-focus);
}
@@ -159,7 +160,8 @@
}
.admin-listbox-trigger:focus-visible {
outline: none;
outline: var(--admin-focus-ring);
outline-offset: 1px;
border-color: var(--admin-border-focus);
}

View File

@@ -0,0 +1,339 @@
/* The diagnostics page (/admin/diagnostics). */
/* Each check is one line with a severity dot: the point is scanning a list for
the ones that are not green, not reading prose. Green ones recede. */
.diag-page {
max-width: 880px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.diag-head {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: flex-end;
gap: 1rem;
}
.diag-head h2 {
margin: 0;
font-size: 1.35rem;
font-weight: 700;
text-wrap: balance;
}
.diag-sub {
margin: 0.3rem 0 0;
font-size: 0.8rem;
color: var(--admin-text-muted);
}
.diag-actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
/* ── Overview tiles ── */
.diag-vitals {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.75rem;
}
@media (max-width: 720px) {
.diag-vitals {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
.diag-vital {
display: flex;
flex-direction: column;
gap: 0.25rem;
padding: 0.75rem 0.9rem;
background: var(--admin-bg-raised);
border: 1px solid var(--admin-border);
border-radius: 10px;
}
.diag-vital-label {
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--admin-text-muted);
}
.diag-vital-val {
display: flex;
align-items: center;
gap: 0.45rem;
font-size: 1rem;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.diag-vital-meta {
min-height: 1em;
font-size: 0.75rem;
color: var(--admin-text-muted);
}
.diag-vital-meta a {
color: var(--admin-warning);
}
/* ── Check groups ── */
.diag-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.diag-group-title {
margin: 0;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--admin-text-muted);
}
.diag-checks {
margin: 0;
padding: 0;
list-style: none;
background: var(--admin-bg-raised);
border: 1px solid var(--admin-border);
border-radius: 10px;
}
.diag-check {
border-bottom: 1px solid var(--admin-border);
}
.diag-check:last-child {
border-bottom: none;
}
.diag-check-row {
display: grid;
grid-template-columns: 8px minmax(0, 1fr) auto;
align-items: start;
gap: 0.75rem;
padding: 0.8rem 1rem;
}
@media (max-width: 560px) {
.diag-check-row {
grid-template-columns: 8px minmax(0, 1fr);
}
.diag-check-side {
grid-column: 2;
justify-content: flex-start;
}
}
.diag-dot {
width: 8px;
height: 8px;
margin-top: 0.4rem;
border-radius: 50%;
flex-shrink: 0;
background: var(--admin-text-muted);
}
.diag-vital-val .diag-dot {
margin-top: 0;
}
.diag-check--ok .diag-dot,
.diag-dot--ok {
background: var(--admin-success);
}
.diag-check--warn .diag-dot {
background: var(--admin-warning);
}
.diag-check--error .diag-dot,
.diag-dot--error {
background: var(--admin-error);
}
.diag-check-body {
display: flex;
flex-direction: column;
gap: 0.2rem;
min-width: 0;
}
.diag-check-title {
font-size: 0.86rem;
font-weight: 600;
color: var(--admin-text);
}
.diag-check--ok .diag-check-title,
.diag-check--unknown .diag-check-title {
font-weight: 500;
color: var(--admin-text-secondary);
}
.diag-check-detail {
max-width: 70ch;
font-size: 0.78rem;
line-height: 1.45;
color: var(--admin-text-muted);
}
.diag-check-side {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
gap: 0.4rem;
}
/* ── Alt-text list ── */
.diag-alt {
padding: 0 1rem 1rem calc(1rem + 8px + 0.75rem);
}
.diag-coverage {
display: flex;
align-items: center;
gap: 0.6rem;
margin-bottom: 0.4rem;
font-size: 0.75rem;
color: var(--admin-text-secondary);
font-variant-numeric: tabular-nums;
}
.diag-coverage-bar {
flex: 1;
max-width: 320px;
height: 6px;
border-radius: 999px;
background: var(--admin-border);
overflow: hidden;
}
.diag-coverage-bar span {
display: block;
height: 100%;
background: var(--admin-success);
}
.diag-album {
padding: 0.75rem 0;
border-top: 1px dashed var(--admin-border);
}
.diag-album-head {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.diag-album-name {
font-size: 0.82rem;
font-weight: 600;
}
.diag-album-path {
margin-left: 0.4rem;
font-size: 0.72rem;
font-weight: 400;
color: var(--admin-text-muted);
}
.diag-album-count {
font-size: 0.72rem;
color: var(--admin-warning);
white-space: nowrap;
font-variant-numeric: tabular-nums;
}
.diag-thumbs {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
gap: 0.5rem;
}
.diag-thumb {
display: flex;
flex-direction: column;
gap: 0.25rem;
min-width: 0;
color: inherit;
text-decoration: none;
}
.diag-thumb img {
width: 100%;
aspect-ratio: 3 / 2;
object-fit: cover;
border: 1px solid var(--admin-border);
border-radius: 6px;
background: var(--admin-bg-elevated);
transition: border-color 0.15s;
}
.diag-thumb:hover img {
border-color: var(--admin-border-hover);
}
.diag-thumb-name {
overflow: hidden;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.68rem;
color: var(--admin-text-muted);
white-space: nowrap;
text-overflow: ellipsis;
}
.diag-thumb-more {
aspect-ratio: 3 / 2;
border: 1px dashed var(--admin-border);
border-radius: 6px;
background: none;
font-family: inherit;
font-size: 0.75rem;
color: var(--admin-text-muted);
cursor: pointer;
}
.diag-thumb-more:hover {
border-color: var(--admin-border-hover);
color: var(--admin-text);
}
.diag-note {
margin: 0.5rem 0 0;
max-width: 70ch;
font-size: 0.75rem;
line-height: 1.45;
color: var(--admin-text-muted);
}
.diag-note code {
padding: 0.05rem 0.3rem;
border-radius: 4px;
background: var(--admin-bg-elevated);
font-size: 0.72rem;
}
@media (prefers-reduced-motion: reduce) {
.diag-thumb img {
transition: none;
}
}

View File

@@ -3,87 +3,32 @@
later sheets override earlier ones, so the order there is the cascade. */
/* ── Drawer Live Preview ────────────────────────────────────── */
.drawer-live-preview-panel {
/* Only the frame is admin styling. Everything inside the canvas is the public
page's own markup, styled by globals.css and the preset — so nothing here
may target the subpage-* classes. */
.subpage-preview {
display: flex;
flex-direction: column;
gap: 1.5rem;
gap: 0.75rem;
padding: 0.5rem 0;
}
.preview-hero-banner {
text-align: center;
padding: 1.75rem 1rem;
background: var(--admin-bg-elevated);
border-radius: 12px;
border: 1px dashed var(--admin-border);
}
.preview-hero-title {
font-size: 1.3rem;
font-weight: 700;
.subpage-preview__note {
margin: 0;
color: var(--admin-text);
}
.preview-hero-sub {
font-size: 0.82rem;
color: var(--admin-text-muted);
margin: 0.35rem 0 0;
}
.preview-section-group {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.preview-section-title {
font-size: 0.95rem;
font-weight: 600;
margin: 0;
border-bottom: 1px solid var(--admin-border);
padding-bottom: 0.35rem;
}
.preview-section-desc {
font-size: 0.78rem;
color: var(--admin-text-muted);
margin: 0;
}
.preview-albums-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
gap: 0.75rem;
}
.preview-album-tile {
background: var(--admin-bg-raised);
border: 1px solid var(--admin-border);
border-radius: 8px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.preview-album-cover {
width: 100%;
aspect-ratio: 4/3;
background: var(--admin-bg-elevated);
overflow: hidden;
}
.preview-album-cover img {
width: 100%;
height: 100%;
object-fit: cover;
}
.preview-album-title {
font-size: 0.75rem;
font-weight: 500;
padding: 0.4rem 0.5rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--admin-text-muted);
}
.subpage-preview__frame {
border: 1px solid var(--admin-border);
border-radius: 10px;
overflow: hidden;
}
/* The site's own page surface, as <body> paints it. */
.subpage-preview__canvas {
background: var(--bg-primary);
color: var(--text-primary);
font-family: var(--font-sans);
line-height: 1.6;
}

View File

@@ -557,6 +557,7 @@ h3 .svg-icon {
/* Modal Tabs */
.backup-modal-tabs {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
border-bottom: 1px solid var(--admin-border);
@@ -706,6 +707,17 @@ h3 .svg-icon {
border: 1px solid rgba(245, 158, 11, 0.3);
}
.backup-badge.deleted {
background: rgba(239, 68, 68, 0.1);
color: var(--admin-error, #ef4444);
border: 1px solid rgba(239, 68, 68, 0.3);
}
.backup-slug {
font-size: 0.88rem;
color: var(--admin-text);
}
.backup-item-meta code {
font-family: monospace;
font-size: 0.72rem;

View File

@@ -108,13 +108,18 @@
color: var(--admin-text, #f0f0f0) !important;
font-size: 0.85rem !important;
padding: 0.55rem 0.75rem !important;
outline: none !important;
transition: border-color 0.15s !important;
}
.essay-block-editor input[type='text']:focus,
.essay-block-editor textarea:focus,
.essay-block-editor select:focus {
/* The base rule used to carry `outline: none !important`, which removed the
focus ring from these fields for good, not just on hover. It is gone; the
ring is added on focus instead, with the same !important so it wins against
the other !important declarations in this file. */
.essay-block-editor input[type='text']:focus-visible,
.essay-block-editor textarea:focus-visible,
.essay-block-editor select:focus-visible {
outline: var(--admin-focus-ring) !important;
outline-offset: 1px !important;
border-color: var(--admin-border-focus, #888888) !important;
}

View File

@@ -105,10 +105,13 @@
transition: all 0.15s;
}
.builder-search-input:focus {
outline: none;
/* The only field that already got this right (accent border plus shadow).
It moves to the same ring as every other field, so focus looks the same
throughout the admin panel. */
.builder-search-input:focus-visible {
outline: var(--admin-focus-ring);
outline-offset: 1px;
border-color: var(--admin-accent);
box-shadow: 0 0 0 1px var(--admin-accent);
background: var(--admin-bg);
}

View File

@@ -268,8 +268,10 @@
word-break: break-all;
}
/* Subpage Overview Grid */
.subpage-grid {
/* Subpage Overview Grid.
Not `.subpage-grid`: that is the public page's cover grid, which globals.css
styles everywhere — and which the drawer's Live Preview renders for real. */
.subpage-tiles {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 0.75rem;
@@ -410,8 +412,9 @@
border-color: var(--admin-border);
}
.subpage-name-input:focus {
outline: none;
.subpage-name-input:focus-visible {
outline: var(--admin-focus-ring);
outline-offset: 1px;
border-color: var(--admin-border-focus);
background: var(--admin-bg-input);
}
@@ -474,8 +477,9 @@
border-radius: 4px;
}
.section-title-input:focus {
outline: none;
.section-title-input:focus-visible {
outline: var(--admin-focus-ring);
outline-offset: 1px;
border-color: var(--admin-border-hover);
background: var(--admin-bg);
}
@@ -484,3 +488,9 @@
font-size: 0.8rem !important;
padding: 0.4rem 0.5rem !important;
}
/* The tile a diagnostics link pointed at (`/admin/pages?album=<id>`). */
.album-tile--linked {
outline: 2px solid var(--admin-warning);
outline-offset: 3px;
}

View File

@@ -1,4 +1,4 @@
/* Sidebar nav, preset preview mockups, the status badge and its dropdown, grouped feature settings, the doctor report. */
/* Sidebar nav, preset preview mockups, the status badge and its dropdown, grouped feature settings. */
/* Split out of admin.css (#533). Loaded from admin.css in a fixed order —
later sheets override earlier ones, so the order there is the cascade. */
@@ -427,68 +427,6 @@
color: var(--admin-text-muted);
}
/* ── Config doctor report (#491) ──────────────────────────────
Each finding is one line with a severity dot: the point is scanning a list
for the ones that are not green, not reading prose. */
.doctor-list {
margin: 0;
padding: 0;
list-style: none;
}
.doctor-item {
display: flex;
align-items: flex-start;
gap: 0.7rem;
padding: 0.8rem 0;
border-bottom: 1px solid var(--admin-border);
}
.doctor-item:last-child {
border-bottom: none;
}
.doctor-dot {
width: 8px;
height: 8px;
margin-top: 0.42rem;
border-radius: 50%;
flex-shrink: 0;
background: var(--admin-success);
}
.doctor-item--warn .doctor-dot {
background: var(--admin-accent);
}
.doctor-item--error .doctor-dot {
background: var(--admin-error);
}
.doctor-item-body {
display: flex;
flex-direction: column;
gap: 0.2rem;
}
.doctor-item-title {
font-size: 0.84rem;
font-weight: 600;
color: var(--admin-text);
}
/* A finding that needs nothing recedes; the eye should land on the others. */
.doctor-item--ok .doctor-item-title {
font-weight: 500;
color: var(--admin-text-secondary);
}
.doctor-item-detail {
font-size: 0.75rem;
line-height: 1.45;
color: var(--admin-text-muted);
}
/* The metadata group as one card with an expander: four permanently visible
sub-switches read as four decisions, when they are details of one. */
.metadata-card {
@@ -691,7 +629,7 @@
}
.status-val.update {
color: var(--admin-warning, #f59e0b);
color: var(--admin-warning);
}
.status-val.unknown {

View File

@@ -15,14 +15,24 @@
--admin-bg-input: #161616;
--admin-border: #2e2e2e;
--admin-border-hover: #444444;
--admin-border-focus: #666666;
--admin-border-focus: #777777;
--admin-text: #f0f0f0;
--admin-text-secondary: #a0a0a0;
--admin-text-muted: #707070;
--admin-accent: #f59e0b;
/* Focus used to show only as a border colour change from #2e2e2e to
#666666, a contrast of 2.37:1 where WCAG 1.4.11 asks for 3:1 against
adjacent colours, so keyboard users could barely see where they were.
The border value now clears 3:1, and a real ring comes on top: the
accent sits at 8.8:1 on the dark background. */
--admin-focus-ring: 2px solid var(--admin-accent);
/* One height for every control in the header row. */
--admin-control-height: 36px;
--admin-success: #4ade80;
/* Warnings get their own token rather than the accent: a preset may recolour
the accent (studio-modern makes it red), and a warning must not read as an
error because of the theme. */
--admin-warning: #f59e0b;
--admin-error: #f87171;
--admin-error-bg: #2d1111;
--admin-error-border: #5c2020;
@@ -40,12 +50,13 @@
--admin-bg-input: #ffffff;
--admin-border: #e0e0e0;
--admin-border-hover: #c0c0c0;
--admin-border-focus: #999999;
--admin-border-focus: #7f7f7f;
--admin-text: #1a1a1a;
--admin-text-secondary: #555555;
--admin-text-muted: #888888;
--admin-accent: #d97706;
--admin-success: #16a34a;
--admin-warning: #b45309;
--admin-error: #dc2626;
--admin-error-bg: #fef2f2;
--admin-error-border: #fecaca;