-
+
diff --git a/styles.css b/styles.css
index 8c449e2..eaeec2d 100644
--- a/styles.css
+++ b/styles.css
@@ -34,6 +34,26 @@
}
}
+ /* ---------- wrap-aware separators (JS-toggled, see main.js) ----------
+ Shared hook used by the announcement banner and hero tagline row: a
+ "·" between two pieces of text that can independently wrap onto
+ separate lines. No CSS selector exists for "am I on the same line as
+ my sibling," so main.js measures and toggles this class instead of a
+ fixed breakpoint. Visible by default so a no-JS visitor always sees
+ the dot (today's behavior), never hidden by default.
+
+ display, not visibility: a hidden separator must take no space, or
+ it still gets counted when justify-content: center balances its flex
+ line — a lone badge sharing its line with a space-reserving invisible
+ dot renders off-center. Safe from the "text merges together" bug that
+ originally motivated reserving space: both wrap-sep contexts space
+ their siblings with a real flex `gap` (see .announcement-inner,
+ .tagline-row) rather than the separator's own margin, so removing it
+ from flow still leaves normal spacing behind, never a collision. */
+ .wrap-sep-hidden {
+ display: none;
+ }
+
body {
margin: 0;
background: var(--ground);
@@ -478,17 +498,28 @@
display: flex;
justify-content: center;
flex-wrap: wrap;
- gap: 0.6rem 0;
+ /* column-gap carries the spacing now (was 0 — the dot's own margin
+ used to be the only thing separating the phrases). Needs to be a
+ real flex gap, not a margin on the dot, so removing a hidden dot
+ from flow (see .wrap-sep-hidden) still leaves normal spacing
+ between the two phrases instead of running them together. */
+ gap: 0.6rem 0.7rem;
font-family: var(--font-mono);
font-size: 0.82rem;
letter-spacing: 0.04em;
color: var(--ink-muted);
}
- .tagline-row span:not(:last-child)::after {
- content: "·";
+ /* Real element instead of a ::after pseudo-element — needs to be a
+ measurable, independently-toggleable DOM node for the wrap-aware
+ script in main.js to hide it when its neighbors wrap apart. No margin
+ of its own: the column-gap above already provides 0.7rem on each
+ side of it (matching the old margin-inline's total spacing exactly),
+ and still applies directly between the two phrases whenever the dot
+ itself is removed from flow. */
+ .tag-sep {
color: var(--gold-dim);
- margin-inline: 0.7rem;
+ user-select: none;
}
.hero-ctas {
@@ -502,6 +533,11 @@
.btn {
display: inline-flex;
align-items: center;
+ /* Centers label text horizontally too — matters once a button is
+ stretched wider than its content (e.g. action-stack children filling
+ a fixed-width column) or wraps to multiple lines; a no-op otherwise,
+ so every button gets this instead of one-off overrides per case. */
+ justify-content: center;
gap: 0.5rem;
padding: 0.8rem 1.5rem;
font-family: var(--font-mono);
@@ -1330,6 +1366,14 @@
width: 7.25rem;
}
+ /* "○ Disabled" is the longer of the two user labels. Not scoped to
+ button.status-badge like the two above — your own row's badge is a
+ plain non-interactive span (see users.php), and it still needs to line
+ up in the same column. */
+ .user-row .status-badge {
+ width: 7rem;
+ }
+
/* Admin row actions: the button-group styling shared by every admin
list (menu items/categories, announcements, users). The actual
row/column layout for each list is its own CSS Grid, defined where
@@ -1576,7 +1620,7 @@
}
.user-grid-wrap {
- grid-template-columns: minmax(0, 1fr) auto auto auto;
+ grid-template-columns: auto minmax(0, 1fr) auto auto auto;
}
.item-grid-wrap,
@@ -1640,12 +1684,13 @@
}
.user-grid-head, .user-row {
- grid-template-areas: "username role created actions";
+ grid-template-areas: "status username role created actions";
}
.col-status,
.item-row [data-label="Status"],
- .ann-row [data-label="Status"] {
+ .ann-row [data-label="Status"],
+ .user-row [data-label="Status"] {
grid-area: status;
}
@@ -1726,10 +1771,37 @@
columns: subgrid` from the desktop rule, so this one change is all
it takes to reflow the whole list (see grid-template-areas per row
further down for how each field then stacks within that column). */
+ /* Every list's cards get a second column on mobile so Actions can sit
+ in the top-right corner alongside that list's leading field, instead
+ of stacking at the very bottom of the card — overrides the shared
+ single-column rule that would otherwise apply here too.
+ minmax(0, auto), not plain auto, so this column can still shrink
+ below its content's natural width under pressure instead of forcing
+ the whole row to overflow the card. */
.item-grid-wrap,
.ann-grid-wrap,
.user-grid-wrap {
- grid-template-columns: 1fr;
+ grid-template-columns: 1fr minmax(0, auto);
+ }
+
+ /* Users' actions column gets a fixed cap instead of auto: "Change
+ Password" is long enough that its max-content size (what auto would
+ size the column to) is wider than this corner has room for, which
+ pushed the button past the card edge. A firm cap plus the
+ wrap/stretch rules below keep it predictable instead. */
+ .user-grid-wrap {
+ grid-template-columns: minmax(0, 1fr) 6rem;
+ }
+
+ /* Every row's Actions cell holds one or two .action-stacks (move
+ up/down, edit/delete, etc. — each stacked vertically, see
+ .action-stack itself further up) side by side. Keeps those stacks
+ from wrapping onto their own lines in this narrow corner, which is
+ what the shared .row-actions wrap rule below would otherwise do. */
+ .item-row .row-actions,
+ .ann-row .row-actions,
+ .user-row .row-actions {
+ flex-wrap: nowrap;
}
.item-grid-head,
@@ -1770,28 +1842,50 @@
.item-row {
grid-template-areas:
- "status"
- "item"
- "price"
- "actions";
+ "status actions"
+ "item item"
+ "price price";
+ /* Overrides the shared align-items: center above — on desktop that
+ vertically centers Status against the taller Item cell in one wide
+ row, which is fine, but here it also centers Status against the
+ taller Actions block above, pushing its badge down instead of
+ keeping both flush with the card's top edge. */
+ align-items: start;
}
.ann-row {
grid-template-areas:
- "status"
- "headline"
- "type"
- "schedule"
- "placements"
- "actions";
+ "status actions"
+ "headline headline"
+ "type type"
+ "schedule schedule"
+ "placements placements";
+ align-items: start;
}
.user-row {
grid-template-areas:
- "username"
- "role"
- "created"
- "actions";
+ "status actions"
+ "username username"
+ "role role"
+ "created created";
+ align-items: start;
+ }
+
+ /* Stretches Actions' whole flex chain out to the fixed 6rem column
+ above (each is shrink-wrapped by default), then lets "Change
+ Password" — long enough on its own to blow out this corner next to a
+ username — wrap onto two lines within that width instead of forcing
+ the column wider. Every other action-stack button here (Edit,
+ Delete, ↑/↓) is short enough to stay on one line regardless. */
+ .user-row .row-actions,
+ .user-row .action-stack,
+ .user-row .row-actions .btn {
+ width: 100%;
+ }
+
+ .user-row .btn-change-password {
+ white-space: normal;
}
.category-panel .panel-head {