diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt index 1575fc4..6f4e467 100644 --- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt +++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteCard.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextDecoration @@ -45,23 +46,18 @@ fun NoteCard( modifier = Modifier .fillMaxWidth() - // Elevation instead of an edge line. The card used to be framed by a - // 1px tint border, which measured a higher contrast against its own - // fill (1.56-2.09) than the fill managed against the board - // (1.03-1.05) — so the loudest thing on every card was the same line - // in the same place, and a board of them read as a grid of outlines - // however different the colours inside. See NoteTint.cardBackground. - // - // It matters most in LIGHT mode, where an untagged card is a 1.04 - // contrast against the board and nothing but a shadow can lift it - // off. In dark the shadow is black on near-black and invisible, which - // is why the subdued fills were moved onto the card surface instead. + // Depth, not the boundary — the edge below is that. 1dp: enough to + // separate a white card from a #fafafa board, and the web's own + // `shadow-sm` is the value it is matching. .shadow(CARD_ELEVATION, RoundedCornerShape(CARD_RADIUS)) // Clipped BEFORE clickable, so the ripple is bounded by the card's // rounded corners instead of a rectangle overhanging them. .clip(RoundedCornerShape(CARD_RADIUS)) .clickable(onClickLabel = stringResource(R.string.board_open_note), onClick = onOpen) .background(tint.cardBackground(dark, strong)) + // ONE grey edge on every card, regardless of its colour — the tint is + // deliberately not consulted here. See CARD_EDGE_DARK. + .border(1.dp, if (dark) CARD_EDGE_DARK else CARD_EDGE_LIGHT, RoundedCornerShape(CARD_RADIUS)) .padding(12.dp), ) { // Body then checklist, in order — a note can carry both (M13 step 2), and @@ -248,10 +244,31 @@ private const val MAX_PREVIEW_LINES = 8 private const val MAX_WRAPPED_LINES = 2 private const val MAX_LABEL_CHIPS = 3 private val CARD_RADIUS = 12.dp +private val CARD_ELEVATION = 1.dp -// Enough to lift a white card off a #fafafa board and no more. Material's own -// resting card elevation is 1dp; this is a shade above it because the board is a -// masonry field of cards rather than one card on a page, and at 1dp the whole field -// reads flat again — which is what the removed border was compensating for. -private val CARD_ELEVATION = 2.dp +// THE CARD'S EDGE — one grey, every card, both weights, all ten colour keys. It is a +// constant here rather than a column in NoteTint precisely so the palette CANNOT vary +// it; uniformity is the feature. +// +// The version of this that came from the palette was a `{hue}-900` border, and it +// failed twice over: the line measured 1.56-2.09 against its own fill while the fill +// managed only 1.03-1.05 against the board, so it was the loudest thing on the card — +// and it carried the same information the fill did. A field of cards read as a grid of +// outlines however different the colours inside were. A neutral line carries no +// information at all, which is exactly what lets it be structure instead of content. +// +// The two values are MATCHED rather than chosen by eye: each measures ~1.6-1.7 against +// the card it edges (light 1.57-1.98 across all twenty fills, dark 1.58-1.73), so the +// edge reads with the same authority in either theme. Dark is `neutral-700`, which is +// what the `default` card's border always was — one entry's value promoted to the rule +// for all of them. Light sits between `neutral-300` and `neutral-400`, neither of which +// lands in range: 300 fades to 1.18 on a gray-tagged card, 400 jumps to 2.52 and reads +// as a wireframe. +// +// NOT a translucent black/white edge, which is the tidier way to write this and was +// measured and rejected: a border composites over the card's own fill, so `White` at +// 20% comes out #56396D on a purple card and #A3C9C1 on a teal one. Hue-coded edges are +// the thing being removed. +private val CARD_EDGE_LIGHT = Color(0xFFB8B8B8) +private val CARD_EDGE_DARK = Color(0xFF404040) private val CHIP_RADIUS = 6.dp diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteTint.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteTint.kt index 3c30e6a..eb2b0a5 100644 --- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteTint.kt +++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteTint.kt @@ -72,18 +72,14 @@ data class NoteTint( * not a wall of white. Drawing those at the same weight is what prompted the * operator's "the tints look the same as the chosen colors". * - * THE CARD NO LONGER HAS A BORDER. It used to carry a 1px `{hue}-900` edge, and - * measured against its own fill that line was a 1.56–2.09 contrast where the fill - * managed 1.03–1.05 against the board. The loudest thing on every card was an - * identical line in an identical place, so a board of them read as a grid of - * outlined rectangles whatever colour was inside — the operator's "too samey even - * with the color differences". [border] survives for panels, banners and pickers, - * which are single elements rather than a field of them; a note card gets none. - * - * What replaces it differs by theme, because elevation does. Dark leans on - * [darkCardSubdued] sitting above the near-black board. Light leans on a real - * shadow (`NoteCard.kt`), since white-on-#fafafa is a 1.04 contrast and no fill - * is going to rescue it. + * THE CARD'S EDGE IS NO LONGER A TINT. It used to carry a 1px `{hue}-900` border, + * and measured against its own fill that line was a 1.56–2.09 contrast where the + * fill managed 1.03–1.05 against the board — so the loudest thing on every card + * was a line saying exactly what the fill already said, and a field of them read + * as a grid of outlines whatever colour was inside. The card still has an edge; + * it is one grey for all ten keys and it lives in `NoteCard.kt` as a constant, so + * the palette cannot vary it. [border] is untouched and still serves panels, + * banners, the update card and the pickers — single elements, not a field. * * WHAT SEPARATES THE TWO WEIGHTS IS CHROMA, NOT LIGHTNESS. In dark they now sit * within a hair of each other (red: 1.11 against the board versus 1.12) and diff --git a/frontend/src/components/NoteCard.vue b/frontend/src/components/NoteCard.vue index d392d41..23aa0a5 100644 --- a/frontend/src/components/NoteCard.vue +++ b/frontend/src/components/NoteCard.vue @@ -222,7 +222,7 @@ onBeforeUnmount(() => document.removeEventListener("mousedown", onDocMousedown))