prototype(#54): variants and the settled ledger row
Adds the three category-list variants the set was judged against (roomy, tabular, tabular+gold) and the fixes that came out of looking at them in a browser: - square everywhere, with enough specificity to beat the theme's own `border-radius: 8px !important`; only the status dot stays round - a drop shadow under every bounded surface, so a square edge reads as an edge and not a cut - Cinzel always uppercase - the Well component: the three right-hand readings sit in recesses on a shared grid, inset on all four sides - the clamped teaser clamps by line count, not by NodeBB's hard max-height, which was cutting the glyphs
@@ -55,7 +55,7 @@
|
|||||||
.wg-panel {
|
.wg-panel {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: var(--wg-panel);
|
background: var(--wg-panel);
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
padding: var(--wg-pad, 1rem);
|
padding: var(--wg-pad, 1rem);
|
||||||
}
|
}
|
||||||
.wg-panel::before {
|
.wg-panel::before {
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
====================================================================== */
|
====================================================================== */
|
||||||
.wg-ledger {
|
.wg-ledger {
|
||||||
background: var(--wg-panel-2);
|
background: var(--wg-panel-2);
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.wg-ledger__row {
|
.wg-ledger__row {
|
||||||
|
|||||||
@@ -4,24 +4,73 @@
|
|||||||
Every rule below is one of the named components doing its job on real
|
Every rule below is one of the named components doing its job on real
|
||||||
NodeBB markup. Nothing new is invented here. */
|
NodeBB markup. Nothing new is invented here. */
|
||||||
|
|
||||||
/* ---- PANEL: edges fade. No hairline runs corner to corner. ---- */
|
/* ---- SQUARE. One shape, every surface. A cut or rounded corner is a second
|
||||||
|
shape language and the shell only gets one. ---- */
|
||||||
|
/* specificity has to beat the theme's own `border-radius: 8px !important` */
|
||||||
|
html body [class],
|
||||||
|
html body [class]::before,
|
||||||
|
html body [class]::after,
|
||||||
|
html body [class] [class],
|
||||||
|
html body [class] [class][class],
|
||||||
|
html body blockquote,
|
||||||
|
html body pre,
|
||||||
|
html body code,
|
||||||
|
html body img,
|
||||||
|
html body input,
|
||||||
|
html body textarea,
|
||||||
|
html body button {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
/* Signets stay square like everything else — the theme's own signet plate is
|
||||||
|
the settled treatment and it is square. Only the status dot is round,
|
||||||
|
because it is a dot. */
|
||||||
|
html body [class] [class].status,
|
||||||
|
html body .status {
|
||||||
|
border-radius: 50% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- PANEL: edges fade. No hairline runs corner to corner, but the edge is
|
||||||
|
present enough to hold the panel off the page. ---- */
|
||||||
li[component="categories/category"],
|
li[component="categories/category"],
|
||||||
li[component="category/topic"],
|
li[component="category/topic"],
|
||||||
.westgate-surface,
|
.westgate-surface,
|
||||||
.card {
|
.card,
|
||||||
|
ul.categories-list,
|
||||||
|
ul.westgate-categories-list,
|
||||||
|
[component="post/content"],
|
||||||
|
.post-container {
|
||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
li[component="categories/category"]::after,
|
ul.categories-list::after,
|
||||||
.westgate-surface::after {
|
ul.westgate-categories-list::after,
|
||||||
|
.westgate-surface::after,
|
||||||
|
.post-container::after,
|
||||||
|
body.template-category .category-header::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
border-radius: inherit;
|
border: 1px solid rgba(var(--wg-pewter-rgb), 0.34);
|
||||||
border: 1px solid var(--wg-border);
|
-webkit-mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, 0.16));
|
||||||
-webkit-mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, 0.12));
|
mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, 0.16));
|
||||||
mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, 0.12));
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- A square edge with no falloff reads as a cut, not an edge. Every
|
||||||
|
bounded surface sits on a wide, offset-down black shadow: no lift, no
|
||||||
|
stacking claim, just the corner catching the room (Candlelight). ---- */
|
||||||
|
html body ul.categories-list,
|
||||||
|
html body ul.westgate-categories-list,
|
||||||
|
html body .westgate-surface,
|
||||||
|
html body .post-container,
|
||||||
|
html body .topic-list-header,
|
||||||
|
html body [data-widget-area] .card,
|
||||||
|
html body.template-category .category-header {
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.02),
|
||||||
|
0 10px 26px rgba(0, 0, 0, 0.34),
|
||||||
|
0 2px 4px rgba(0, 0, 0, 0.28) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- LEDGER: rows are ruled, not boxed. The category list is a ledger:
|
/* ---- LEDGER: rows are ruled, not boxed. The category list is a ledger:
|
||||||
@@ -30,8 +79,6 @@ ul.categories-list,
|
|||||||
ul.westgate-categories-list {
|
ul.westgate-categories-list {
|
||||||
gap: 0 !important;
|
gap: 0 !important;
|
||||||
background: var(--wg-panel-2);
|
background: var(--wg-panel-2);
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
ul.categories-list li[component="categories/category"],
|
ul.categories-list li[component="categories/category"],
|
||||||
ul.westgate-categories-list li[component="categories/category"] {
|
ul.westgate-categories-list li[component="categories/category"] {
|
||||||
@@ -71,6 +118,17 @@ li[component="categories/category"] h2.title::after,
|
|||||||
background: linear-gradient(90deg, rgba(var(--wg-gold-rgb), 0.34), transparent);
|
background: linear-gradient(90deg, rgba(var(--wg-gold-rgb), 0.34), transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- CASE: Cinzel is always uppercase. One rule, no exceptions, because
|
||||||
|
its lowercase is a small-caps design and reads as a weaker version of the
|
||||||
|
same thing rather than a second voice. ---- */
|
||||||
|
html body [class] h1,
|
||||||
|
html body [class] h2,
|
||||||
|
html body [class] h3,
|
||||||
|
html body .topic-title,
|
||||||
|
html body .breadcrumb {
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- PLAQUE: the page title becomes a name plate, not a band. ---- */
|
/* ---- PLAQUE: the page title becomes a name plate, not a band. ---- */
|
||||||
body.template-category .category-header .category-title,
|
body.template-category .category-header .category-title,
|
||||||
body.template-topic .topic-title h1 {
|
body.template-topic .topic-title h1 {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const ornament = read('real-surface.css');
|
|||||||
const VARIANTS = { before: paletteB, after: paletteB + ornament };
|
const VARIANTS = { before: paletteB, after: paletteB + ornament };
|
||||||
const PAGES = [
|
const PAGES = [
|
||||||
['categories', '/categories'],
|
['categories', '/categories'],
|
||||||
|
['category', '/category/8'],
|
||||||
['topic', '/topic/2'],
|
['topic', '/topic/2'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 555 KiB After Width: | Height: | Size: 559 KiB |
|
Before Width: | Height: | Size: 633 KiB After Width: | Height: | Size: 635 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 421 KiB |
|
After Width: | Height: | Size: 231 KiB |
|
After Width: | Height: | Size: 418 KiB |
|
After Width: | Height: | Size: 226 KiB |
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 966 KiB After Width: | Height: | Size: 962 KiB |
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 961 KiB After Width: | Height: | Size: 969 KiB |
@@ -0,0 +1,30 @@
|
|||||||
|
/* Variant: gilt structures, pewter only speaks.
|
||||||
|
Two Metals inverted from #53's assignment — the metals keep separate jobs,
|
||||||
|
but the visible edge work goes back to gold and pewter is demoted to
|
||||||
|
metadata text only. Answers "there is too much silver now". */
|
||||||
|
:root {
|
||||||
|
--wg-border: rgba(var(--wg-gold-rgb), 0.2);
|
||||||
|
--wg-border-soft: rgba(var(--wg-gold-rgb), 0.11);
|
||||||
|
--wg-ledger-ruling: rgba(var(--wg-gold-rgb), 0.08);
|
||||||
|
--wg-ledger-rule-strong: rgba(var(--wg-gold-rgb), 0.2);
|
||||||
|
--wg-ledger-border: rgba(var(--wg-gold-rgb), 0.24);
|
||||||
|
}
|
||||||
|
/* panel edges, ledger edge, icon ring: gilt */
|
||||||
|
html body ul.categories-list::after,
|
||||||
|
html body ul.westgate-categories-list::after,
|
||||||
|
html body .westgate-surface::after,
|
||||||
|
html body .post-container::after,
|
||||||
|
html body.template-category .category-header::after {
|
||||||
|
border-color: rgba(var(--wg-gold-rgb), 0.28) !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .icon {
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.12),
|
||||||
|
inset 0 -3px 7px rgba(0, 0, 0, 0.52),
|
||||||
|
0 0 0 1px rgba(var(--wg-gold-rgb), 0.28) !important;
|
||||||
|
}
|
||||||
|
/* category names keep the ledger ink, one step brighter than body */
|
||||||
|
html body li[component="categories/category"] h2.title,
|
||||||
|
html body li[component="categories/category"] h2.title a {
|
||||||
|
color: var(--wg-ledger-ink) !important;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/* Variant: rows breathe. The category list goes back to separate panels with
|
||||||
|
air between them, instead of one ruled ledger. Same components, same square
|
||||||
|
shape, same fading edge — only the ledger reading is dropped. */
|
||||||
|
html body ul.categories-list,
|
||||||
|
html body ul.westgate-categories-list {
|
||||||
|
gap: var(--wg-space-sm, 0.75rem) !important;
|
||||||
|
background: none !important;
|
||||||
|
}
|
||||||
|
html body ul.categories-list::after,
|
||||||
|
html body ul.westgate-categories-list::after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
html body ul.categories-list li[component="categories/category"],
|
||||||
|
html body ul.westgate-categories-list li[component="categories/category"] {
|
||||||
|
background: var(--wg-panel-2) !important;
|
||||||
|
background-image: none !important;
|
||||||
|
padding: var(--wg-space-md, 1rem) !important;
|
||||||
|
}
|
||||||
|
/* each row gets its own fading edge, since it is a panel again */
|
||||||
|
html body ul.categories-list li[component="categories/category"]::after,
|
||||||
|
html body ul.westgate-categories-list li[component="categories/category"]::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border: 1px solid rgba(var(--wg-pewter-rgb), 0.34);
|
||||||
|
-webkit-mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, 0.16));
|
||||||
|
mask-image: linear-gradient(180deg, #000, rgba(0, 0, 0, 0.16));
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
/* Variant: the ledger row as a line in a record, not three blocks in a row.
|
||||||
|
The data columns move into WELLS; the left side stays prose. */
|
||||||
|
|
||||||
|
/* ---- WELL — a recess, the inverse of Panel. Panel is laid on the surface
|
||||||
|
and casts down; a well is cut into it and shadows inward. Three of them,
|
||||||
|
one per reading, bleeding to the row's right edge. The gap between two
|
||||||
|
wells is their divider: a well never carries a rule inside it. ---- */
|
||||||
|
html body li[component="categories/category"] > div.col-lg-5 {
|
||||||
|
background: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
align-items: stretch !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
gap: 0.4rem !important;
|
||||||
|
/* the wells sit inside the row's margin on every side — a well cut flush to
|
||||||
|
the right edge reads as the row running off the page */
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the stat pair: two equal columns of well, not two little cards */
|
||||||
|
html body li[component="categories/category"] .meta.stats,
|
||||||
|
html body li[component="categories/category"] .stats {
|
||||||
|
display: grid !important;
|
||||||
|
/* the counts need only their own width; the room goes to the teaser */
|
||||||
|
grid-template-columns: 6rem 6rem !important;
|
||||||
|
justify-content: end !important;
|
||||||
|
gap: 0.4rem !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
background: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the well itself */
|
||||||
|
html body li[component="categories/category"] .stats .card,
|
||||||
|
html body li[component="categories/category"] .stats .card-header,
|
||||||
|
html body li[component="categories/category"] .teaser {
|
||||||
|
/* the basin sits below the row it is cut into, but not as dead as the
|
||||||
|
page floor: between panel-2 and bg-deep */
|
||||||
|
background: color-mix(in srgb, var(--wg-panel-2) 45%, var(--wg-bg-deep)) !important;
|
||||||
|
background-image: none !important;
|
||||||
|
border: 0 !important;
|
||||||
|
box-shadow:
|
||||||
|
inset 0 1px 3px rgba(0, 0, 0, 0.55),
|
||||||
|
inset 0 0 0 1px rgba(var(--wg-gold-rgb), 0.1) !important;
|
||||||
|
padding: 0.5rem 0.85rem !important;
|
||||||
|
}
|
||||||
|
/* the teaser is prose, so it gets the room and a proper margin of its own */
|
||||||
|
html body li[component="categories/category"] .teaser {
|
||||||
|
flex: 1 1 auto !important;
|
||||||
|
/* the basin's inset is even on all four sides — a wider left/right inset
|
||||||
|
reads as the text not filling the well */
|
||||||
|
padding: 0.55rem !important;
|
||||||
|
}
|
||||||
|
/* the teaser's inner blocks are flex items once the well is a flex box, so
|
||||||
|
they shrink to their text and stop filling. Make them fill it. */
|
||||||
|
html body li[component="categories/category"] .lastpost,
|
||||||
|
html body li[component="categories/category"] .westgate-lastpost {
|
||||||
|
flex: 1 1 auto !important;
|
||||||
|
width: 100% !important;
|
||||||
|
min-width: 0 !important;
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] [component="category/posts"] {
|
||||||
|
padding-left: 0 !important;
|
||||||
|
width: 100% !important;
|
||||||
|
min-width: 0 !important;
|
||||||
|
/* the byline and its line of prose are one block, not two rows */
|
||||||
|
gap: 0.1rem !important;
|
||||||
|
height: auto !important;
|
||||||
|
line-height: 1.35 !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .teaser .text-nowrap {
|
||||||
|
line-height: 1.2 !important;
|
||||||
|
/* the signet's ring is drawn outside its 18px box, and this row is
|
||||||
|
`text-truncate` (overflow: hidden), so at x=0 the left of the ring is cut.
|
||||||
|
Give it the ring's width back. */
|
||||||
|
padding-left: 2px !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .stats .card {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column !important;
|
||||||
|
align-items: center !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the number carries; the label is engraved and small */
|
||||||
|
html body li[component="categories/category"] .stats .card > span:first-child {
|
||||||
|
font-family: var(--wg-font-display) !important;
|
||||||
|
color: var(--wg-text) !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .stats .card > span + span,
|
||||||
|
html body li[component="categories/category"] .stats small {
|
||||||
|
font-family: var(--wg-font-display) !important;
|
||||||
|
font-size: 0.78rem !important;
|
||||||
|
letter-spacing: 0.12em !important;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
color: var(--wg-text-muted) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the teaser well reads as text, so it is set left and loses NodeBB's
|
||||||
|
inline pure-white rule — a ledger has one ruling weight, not two */
|
||||||
|
html body li[component="categories/category"] .teaser {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .teaser *,
|
||||||
|
html body li[component="categories/category"] .lastpost,
|
||||||
|
html body li[component="categories/category"] .westgate-lastpost {
|
||||||
|
text-align: left !important;
|
||||||
|
border-left: 0 !important;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
}
|
||||||
|
/* the byline row must stretch, or it shrinks to its own text and the
|
||||||
|
`text-truncate` on it starts clipping the signet */
|
||||||
|
html body li[component="categories/category"] [component="category/posts"],
|
||||||
|
html body li[component="categories/category"] .lastpost,
|
||||||
|
html body li[component="categories/category"] .westgate-lastpost {
|
||||||
|
align-items: stretch !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .teaser .text-nowrap,
|
||||||
|
html body li[component="categories/category"] .teaser .post-content {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .teaser p,
|
||||||
|
html body li[component="categories/category"] [component="category/posts"] p {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0 !important;
|
||||||
|
color: var(--wg-text-muted) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the left side is prose and stops at its own measure; the wells take the
|
||||||
|
room that was standing empty between the two */
|
||||||
|
html body li[component="categories/category"] > div.col-lg-7 {
|
||||||
|
flex: 0 0 46% !important;
|
||||||
|
max-width: 46% !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] > div.col-lg-5 {
|
||||||
|
flex: 1 1 auto !important;
|
||||||
|
max-width: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* one baseline for the whole row, so rows scan as lines rather than pages.
|
||||||
|
The columns stretch: a centred well cannot grow, so a two-line teaser
|
||||||
|
overflows it top and bottom and gets clipped. */
|
||||||
|
html body li[component="categories/category"] {
|
||||||
|
align-items: stretch !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] .teaser,
|
||||||
|
html body li[component="categories/category"] .lastpost,
|
||||||
|
html body li[component="categories/category"] .westgate-lastpost,
|
||||||
|
html body li[component="categories/category"] [component="category/posts"] {
|
||||||
|
height: auto !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
/* the clamp keeps its own overflow — it is what puts the ellipsis on. But its
|
||||||
|
line box has to be taller than the glyphs, or `overflow: hidden` shaves the
|
||||||
|
ascenders off the first line and the descenders off the last. */
|
||||||
|
html body li[component="categories/category"] .post-content {
|
||||||
|
height: auto !important;
|
||||||
|
min-height: 0 !important;
|
||||||
|
line-height: 1.5 !important;
|
||||||
|
/* NodeBB's `line-clamp-sm-2` clamps by a hard `max-height` sized to its own
|
||||||
|
line-height. Ours is taller, so that max-height cuts the glyphs. Drop it
|
||||||
|
and clamp by line count instead. */
|
||||||
|
max-height: none !important;
|
||||||
|
display: -webkit-box !important;
|
||||||
|
-webkit-line-clamp: 2 !important;
|
||||||
|
-webkit-box-orient: vertical !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
html body li[component="categories/category"] h2.title {
|
||||||
|
margin-bottom: 0.15rem !important;
|
||||||
|
}
|
||||||