Give destruction its own colour, take ember back
The stylesheet asserted twice that --ember only ever means "new chapter" while spending it on eight things, including "Nothing new." — the heat signal firing on its own negation. Add a --danger token (a duller oxblood, tuned per theme) and move remove hover, the open remove cell, the confirm wash and the login error onto it. Text-input focus follows the .searchbar idiom and turns --paper, so a valid number field no longer paints itself red. Drop .empty.hot. Ember now survives on the is-new group, the Updated tab and the brand, which the law comment now says out loud. Contrast, both themes: --danger on --ink 4.82 dark / 6.65 light, --danger-ink on the solid button 4.94 / 7.30, --danger-soft on the wash 9.00 / 7.98. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+28
-14
@@ -74,6 +74,12 @@
|
|||||||
--ember-wash: #1a1211; /* ember-tinted surface */
|
--ember-wash: #1a1211; /* ember-tinted surface */
|
||||||
--ember-ink: #150907; /* text on solid ember */
|
--ember-ink: #150907; /* text on solid ember */
|
||||||
--ember-soft: #eda798; /* text on ember wash */
|
--ember-soft: #eda798; /* text on ember wash */
|
||||||
|
/* Destruction is hot but not ember: a duller oxblood, so a remove confirm is
|
||||||
|
never mistaken across the room for an unread chapter. */
|
||||||
|
--danger: #cf5c4d;
|
||||||
|
--danger-wash: #211311;
|
||||||
|
--danger-ink: #150808;
|
||||||
|
--danger-soft: #e2aaa1;
|
||||||
--brass: #b8912f; /* favourite — a second, cooler metal */
|
--brass: #b8912f; /* favourite — a second, cooler metal */
|
||||||
--trash: #977671; /* remove, resting — icons need 3:1, not 4.5:1 */
|
--trash: #977671; /* remove, resting — icons need 3:1, not 4.5:1 */
|
||||||
|
|
||||||
@@ -120,6 +126,10 @@
|
|||||||
--ember-wash: #fbeee9;
|
--ember-wash: #fbeee9;
|
||||||
--ember-ink: #fff;
|
--ember-ink: #fff;
|
||||||
--ember-soft: #8d2c17;
|
--ember-soft: #8d2c17;
|
||||||
|
--danger: #97362a;
|
||||||
|
--danger-wash: #fbe9e5;
|
||||||
|
--danger-ink: #fff;
|
||||||
|
--danger-soft: #7c2c22;
|
||||||
--brass: #8a681c;
|
--brass: #8a681c;
|
||||||
--trash: #8c6558;
|
--trash: #8c6558;
|
||||||
|
|
||||||
@@ -155,8 +165,11 @@ button { cursor: pointer; }
|
|||||||
|
|
||||||
@keyframes barSlide { from { transform: translateX(-100%) } to { transform: translateX(320%) } }
|
@keyframes barSlide { from { transform: translateX(-100%) } to { transform: translateX(320%) } }
|
||||||
@keyframes sheetIn { from { opacity: 0; transform: translateY(-4px) } to { opacity: 1; transform: none } }
|
@keyframes sheetIn { from { opacity: 0; transform: translateY(-4px) } to { opacity: 1; transform: none } }
|
||||||
/* Transient system states pulse in grey: ember stays reserved for "new
|
/* The law: ember means "new chapter", and nothing else on a list screen —
|
||||||
chapter" so a tired glance never misreads a busy bar as unread heat. */
|
busy, error and destruction all stay off it, so a tired glance never
|
||||||
|
misreads a system state as unread heat. The one exception is the brand
|
||||||
|
itself (the wordmark, and the login screen, which shows no series at all).
|
||||||
|
Destruction has its own token, --danger. */
|
||||||
@keyframes mutePulse { 0%, 100% { opacity: .35 } 50% { opacity: 1 } }
|
@keyframes mutePulse { 0%, 100% { opacity: .35 } 50% { opacity: 1 } }
|
||||||
|
|
||||||
/* One measured column, edges drawn rather than boxed. */
|
/* One measured column, edges drawn rather than boxed. */
|
||||||
@@ -447,12 +460,12 @@ button { cursor: pointer; }
|
|||||||
.actions .on { color: var(--brass); }
|
.actions .on { color: var(--brass); }
|
||||||
.actions .restore { color: var(--paper); }
|
.actions .restore { color: var(--paper); }
|
||||||
.actions .remove { color: var(--trash); }
|
.actions .remove { color: var(--trash); }
|
||||||
.actions .remove:hover { color: var(--ember); }
|
.actions .remove:hover { color: var(--danger); }
|
||||||
.actions .open { background: var(--hover); color: var(--paper); }
|
.actions .open { background: var(--hover); color: var(--paper); }
|
||||||
/* Lifecycle cells already sit on --ash, which is what --hover resolves to, so
|
/* Lifecycle cells already sit on --ash, which is what --hover resolves to, so
|
||||||
an open one needs the next step up to stay legible as the panel's owner. */
|
an open one needs the next step up to stay legible as the panel's owner. */
|
||||||
.actions .lifecycle.open { background: var(--rule); }
|
.actions .lifecycle.open { background: var(--rule); }
|
||||||
.actions .remove.open { background: var(--ember-wash); color: var(--ember); }
|
.actions .remove.open { background: var(--danger-wash); color: var(--danger); }
|
||||||
.is-dim .actions > * { color: var(--mute-2); }
|
.is-dim .actions > * { color: var(--mute-2); }
|
||||||
|
|
||||||
/* Three clusters by consequence: navigate (play) | organize (favourite,
|
/* Three clusters by consequence: navigate (play) | organize (favourite,
|
||||||
@@ -493,7 +506,9 @@ button { cursor: pointer; }
|
|||||||
font: 500 17px var(--font-mono);
|
font: 500 17px var(--font-mono);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.chapter-form input:focus { border-color: var(--ember); }
|
/* Focus follows the .searchbar idiom — paper, not heat: a red border on a
|
||||||
|
valid number field reads as "invalid". */
|
||||||
|
.chapter-form input:focus { border-color: var(--paper); }
|
||||||
.chapter-form input::-webkit-outer-spin-button,
|
.chapter-form input::-webkit-outer-spin-button,
|
||||||
.chapter-form input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
.chapter-form input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
||||||
.chapter-form button {
|
.chapter-form button {
|
||||||
@@ -511,9 +526,9 @@ button { cursor: pointer; }
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
background: var(--ember-wash);
|
background: var(--danger-wash);
|
||||||
}
|
}
|
||||||
.confirm-row span { font: 400 17px var(--font-display); color: var(--ember-soft); }
|
.confirm-row span { font: 400 17px var(--font-display); color: var(--danger-soft); }
|
||||||
.confirm-row div { display: flex; gap: 8px; }
|
.confirm-row div { display: flex; gap: 8px; }
|
||||||
.confirm-row button {
|
.confirm-row button {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
@@ -526,12 +541,12 @@ button { cursor: pointer; }
|
|||||||
.confirm-row button:hover { color: var(--paper); }
|
.confirm-row button:hover { color: var(--paper); }
|
||||||
.confirm-row .danger-solid {
|
.confirm-row .danger-solid {
|
||||||
border: none;
|
border: none;
|
||||||
background: var(--ember);
|
background: var(--danger);
|
||||||
color: var(--ember-ink);
|
color: var(--danger-ink);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
/* Archive and finish are reversible, so their confirm asks in grey — only the
|
/* Archive and finish are reversible, so their confirm asks in grey — only the
|
||||||
irreversible remove gets the ember wash. */
|
irreversible remove gets the danger wash. */
|
||||||
.confirm-row.calm { background: var(--ash); }
|
.confirm-row.calm { background: var(--ash); }
|
||||||
.confirm-row.calm span { color: var(--paper-dim); }
|
.confirm-row.calm span { color: var(--paper-dim); }
|
||||||
.confirm-row .go {
|
.confirm-row .go {
|
||||||
@@ -568,7 +583,7 @@ button { cursor: pointer; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Busy: a grey hairline slides across the top of the sheet — deliberately not
|
/* Busy: a grey hairline slides across the top of the sheet — deliberately not
|
||||||
ember, which only ever means "new chapter". */
|
ember, which on a list screen only ever means "new chapter". */
|
||||||
.card.htmx-request { overflow: hidden; }
|
.card.htmx-request { overflow: hidden; }
|
||||||
.card.htmx-request .actions { pointer-events: none; opacity: .5; }
|
.card.htmx-request .actions { pointer-events: none; opacity: .5; }
|
||||||
.card.htmx-request::before {
|
.card.htmx-request::before {
|
||||||
@@ -590,7 +605,6 @@ button { cursor: pointer; }
|
|||||||
padding: 40px 20px 48px;
|
padding: 40px 20px 48px;
|
||||||
}
|
}
|
||||||
.empty strong { font: 400 20px var(--font-display); color: var(--paper); }
|
.empty strong { font: 400 20px var(--font-display); color: var(--paper); }
|
||||||
.empty.hot strong { color: var(--ember); }
|
|
||||||
.empty .clear-search {
|
.empty .clear-search {
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
@@ -653,12 +667,12 @@ button { cursor: pointer; }
|
|||||||
letter-spacing: .16em;
|
letter-spacing: .16em;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
.login-card input:focus { border-bottom-color: var(--ember); }
|
.login-card input:focus { border-bottom-color: var(--paper); }
|
||||||
.login-card .error {
|
.login-card .error {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
font: 400 13px/1.4 var(--font-body);
|
font: 400 13px/1.4 var(--font-body);
|
||||||
color: var(--ember);
|
color: var(--danger);
|
||||||
}
|
}
|
||||||
.login-card button {
|
.login-card button {
|
||||||
height: 54px;
|
height: 54px;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{{else if eq .Tab "fav"}}
|
{{else if eq .Tab "fav"}}
|
||||||
<div class="empty"><strong>No favourites yet.</strong><p>Star a series to pin it here.</p></div>
|
<div class="empty"><strong>No favourites yet.</strong><p>Star a series to pin it here.</p></div>
|
||||||
{{else if eq .Tab "new"}}
|
{{else if eq .Tab "new"}}
|
||||||
<div class="empty hot"><strong>Nothing new.</strong><p>Every series is caught up to its latest chapter.</p></div>
|
<div class="empty"><strong>Nothing new.</strong><p>Every series is caught up to its latest chapter.</p></div>
|
||||||
{{else if eq .Tab "archived"}}
|
{{else if eq .Tab "archived"}}
|
||||||
<div class="empty"><strong>Nothing archived.</strong><p>Shelve a series to park it here — it keeps getting checked for new chapters.</p></div>
|
<div class="empty"><strong>Nothing archived.</strong><p>Shelve a series to park it here — it keeps getting checked for new chapters.</p></div>
|
||||||
{{else if eq .Tab "finished"}}
|
{{else if eq .Tab "finished"}}
|
||||||
|
|||||||
Reference in New Issue
Block a user