Module:Countdown/styles.css: Difference between revisions
From Shroudforge
More actions
starcitizen>Alistar Bot Name the flat reservation and count the hairline it lies under, so the last pixel of shift goes too (via update-page on MediaWiki MCP Server) |
Bonsaibauer (talk | contribs) m 1 revision imported: Import Star Citizen Modules |
(No difference)
| |
Latest revision as of 22:22, 4 November 2026
/* Module:Countdown
*
* Two states. Before the gadget runs — and forever, without JavaScript — the
* element holds a date range and is styled as a plain readout. Once the gadget
* has built the digit stack it replaces that range with a label and three units
* and adds `t-countdown--live`, and the rules below take over. The range is
* dropped rather than hidden: the stack says everything it said and more, so
* keeping it would only have assistive tech read the same span of time twice.
*
* The gadget also adds one of three tense classes — `--upcoming`, `--running`,
* `--ended` — which is what the colour keys off. Nothing here reaches outside
* the countdown element, which is the point: the card hosting it never has to
* learn what a clock is.
*
* ARRANGEMENT. The clock stands its units in a column by default, for a card
* that gives it a slot down one side, and lies them down into a strip when
* there is no such slot. Two things ask for the strip, and they are different
* questions: below 639px the media query does, because every card is stacked
* there; and at any width `--flat` does, for a card that is stacked throughout
* and therefore has no viewport question to ask. A card must never restyle the
* clock itself — the arrangement is the clock's, the slot is the card's.
*/
.t-countdown {
/* The caption's size, named because three rules need it: the caption draws
* itself with it, and the reservation below is measured in it. */
--countdown-caption: 0.62rem;
/* One unit, as tall as the gadget will build it. The digits carry
* line-height 1, so they are exactly their own size; the caption adds its
* own height plus the 0.25em that separates them, hence the 1.25. */
--countdown-unit: calc(var(--countdown-size, 3rem) + var(--countdown-caption) * 1.25);
/* The reservation for a clock lying down: one unit row, not four. Named
* rather than repeated because all three arrangements that lie the clock
* down need it, and they already have enough to keep in step.
*
* The trailing 1px is the hairline. Lying down it runs across the BLOCK
* axis, and box-sizing is border-box, so it counts against the height —
* standing up the same hairline is on the inline edge and costs nothing,
* which is why the reservation below has no such term. */
--countdown-reserve-flat: calc(var(--countdown-unit) + var(--space-md) * 2 + 1px);
flex: none;
display: flex;
flex-direction: column;
justify-content: center;
/* THE COLUMN THE CLOCK STANDS IN, pinned rather than left to its content,
* and the shift is only the first of two reasons.
*
* The range and the units are different widths — 268px against 87 — so
* going live shrank the clock by 181 and rewrapped the card's prose beside
* it. And left to itself the column's width depends on how long the DATE in
* the settings happens to be, so an event running into September gave the
* body less room to set than one running into May. Neither is something the
* card next to it should be able to feel.
*
* 7rem leaves 80px of content box once the padding is out, which clears
* both sides: the units need 54px, and the range's longest unbreakable word
* is "September" at 76. All three arrangements that lie the clock down
* already set `inline-size: 100%`, so this needs no reset of its own. */
inline-size: 7rem;
padding: var(--space-md);
/* THE ROOM THE CLOCK WILL NEED, reserved before it needs it: a label row and
* three unit rows. The two states hold different things — a date range now,
* a label and three counters once the gadget runs — and left to themselves
* they are different heights, so going live grew the card under the reader
* and pushed every band below it down the page (11px standing up, 30px
* lying down, measured). Reserving the taller of the two in BOTH means the
* swap changes what the clock says and never how much room it takes.
*
* Derived from the same tokens that draw a unit rather than measured off a
* screenshot, so it cannot drift from what it is reserving for. */
min-block-size: calc(var(--line-height-x-small) + var(--countdown-unit) * 3 + var(--space-md) * 2);
font-family: var(--font-family-monospace);
text-align: center;
/* THE TENSE COLOUR, set once here and inherited. The label and the digits
* are halves of one statement — what this is, and how long — so they take
* one colour between them, and each tense below has a single declaration to
* change rather than one per part. Only the unit captions opt back out. */
color: var(--color-subtle);
/* The hairline is the clock's own edge, not the card's: the card takes a
* content slot and has no business deciding that whatever lands in it gets a
* rule. Logical so it follows the flex row's direction rather than assuming
* the clock is always on the right. It runs the full height of the card,
* meeting the border top and bottom. */
border-inline-start: var(--border-subtle);
}
.t-countdown__fallback {
font-size: var(--font-size-small);
line-height: var(--line-height-small);
/* Standing up the range wraps down a narrow column, so a date whose longest
* word outgrows it breaks rather than hangs out of the card. Insurance:
* "September" is the longest word any English date produces and it fits. */
overflow-wrap: break-word;
}
/* Deliberately the same size and tracking as Module:CardLua's kicker: the two
* sit at opposite ends of the card's head and share a top and bottom edge, so
* anything smaller here breaks that line. */
.t-countdown__label {
font-size: var(--font-size-x-small);
line-height: var(--line-height-x-small);
letter-spacing: 0.12em;
text-transform: uppercase;
}
/* Live: the unit rows share whatever height the card has, so the clock fills
* its column instead of clustering. Sizing the digits BY the height would want
* `cqh`, which needs `container-type` — rejected by the TemplateStyles
* sanitizer — so the digits stay on a scale and the rows do the adapting. */
.t-countdown--live {
display: grid;
grid-template-rows: auto;
grid-auto-rows: 1fr;
align-items: center;
justify-items: center;
}
.t-countdown__unit {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
line-height: 1;
}
.t-countdown__value {
/* 3rem is the ceiling before the clock, rather than the card's content,
* starts deciding how tall the row is. */
font-size: var(--countdown-size, 3rem);
font-weight: var(--font-weight-medium);
letter-spacing: -0.04em;
/* Tabular figures so the stacked numbers line up: without it a 1 is
* narrower than a 0 and the column reads ragged. */
font-variant-numeric: tabular-nums;
}
/* The plain number behind each reel — what assistive tech reads instead of a
column of digits. The class is the gadget's to apply but this stylesheet's to
define: the odometer markup is shared with the hero, and only the component it
was built inside knows which stylesheet is guaranteed to be on the page. */
.t-countdown__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset( 50% );
white-space: nowrap;
}
.t-countdown__unit-label {
font-size: var(--countdown-caption);
line-height: 1;
letter-spacing: 0.14em;
text-transform: uppercase;
/* The one part that opts out: the captions name the units and are not part
* of the statement the tense is colouring. */
color: var(--color-subtle);
margin-top: 0.25em;
}
/* ---- Tense --------------------------------------------------------------
* Colour is reinforcement here, never the only carrier: the label already says
* "Coming", "Ends" or "Ended" in words, so nothing is lost on a monochrome
* display or to a screen reader, and no visually-hidden partner is owed.
*
* The stripe is Module:Entity/Ports' overlay retuned for the area. Ports draws
* 2px lines on a 6px period at alpha 0.10 over a 32px pill; the same rule here
* covers roughly twenty times that, and its average lift — duty cycle times
* alpha, 0.033 — visibly washes the colour underneath toward grey. The line
* weight stays at 2px because that is the house signature; the spacing and the
* alpha come down, landing at a lift of 0.012, about a third of Ports.
*/
.t-countdown--running,
.t-countdown--upcoming {
background-image: repeating-linear-gradient(
-45deg,
light-dark(rgba(0, 0, 0, 0.03), rgba(255, 255, 255, 0.06)),
light-dark(rgba(0, 0, 0, 0.03), rgba(255, 255, 255, 0.06)) 2px,
transparent 2px,
transparent 10px
);
}
.t-countdown--running {
color: var(--color-success);
background-color: var(--background-color-success-subtle);
border-inline-start-color: var(--border-color-success);
}
.t-countdown--upcoming {
color: var(--color-warning);
background-color: var(--background-color-warning-subtle);
border-inline-start-color: var(--border-color-warning);
}
/* Ended has no rule, and needs none: claiming no tense means taking no tense
* colour, so it falls back to the subtle the root already sets. That is
* `--color-subtle` rather than `--color-disabled` on purpose — the number still
* carries a fact worth reading, how long ago and so how stale the card is. It
* is past, not inert. */
/* ---- Lying down ----------------------------------------------------------
* The strip. `display` has to be reset explicitly: the live state is a grid,
* and flex-direction is inert on a grid, so flipping the direction alone would
* silently leave the units stacked.
*
* These rules must stay BELOW the tense block. They are single-class like it,
* so which wins is decided on source order, and the strip has to be able to
* move the tense colour from the inline edge to the block edge.
*
* The declarations appear twice, here and in the media query at the foot,
* because one is asked for by a class and the other by a viewport and CSS
* cannot share a block across a media query. Keep them identical.
*/
.t-countdown--flat,
.t-countdown--flat.t-countdown--live {
display: flex;
flex-direction: row;
/* The units end-align as a group; the auto margin below holds the label at
* the start. Both together, so the strip reads left to right as what this
* is and then how long, with the empty space between the two rather than
* spread through them the way space-between would. */
justify-content: flex-end;
align-items: flex-end;
gap: var(--space-md);
inline-size: 100%;
/* Lying down, the rule that divided two columns becomes the one that
* divides two rows. */
border-inline-start: 0;
border-block-start: var(--border-subtle);
/* Three units abreast rather than stacked down a column: at 3rem the strip
* dominates the card it is attached to. */
--countdown-size: 2.5rem;
/* One row now, not four, and the label is shorter than a unit. */
min-block-size: var(--countdown-reserve-flat);
}
.t-countdown--flat .t-countdown__label,
.t-countdown--flat .t-countdown__fallback {
margin-inline-end: auto;
}
.t-countdown--flat.t-countdown--running {
border-block-start-color: var(--border-color-success);
}
.t-countdown--flat.t-countdown--upcoming {
border-block-start-color: var(--border-color-warning);
}
.t-countdown--flat.t-countdown--live .t-countdown__label {
align-self: center;
}
/* Narrow lies every clock down, whether its card asked or not. */
@media (max-width: 639px) {
.t-countdown,
.t-countdown--live {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: flex-end;
gap: var(--space-md);
inline-size: 100%;
border-inline-start: 0;
border-block-start: var(--border-subtle);
--countdown-size: 2.5rem;
min-block-size: var(--countdown-reserve-flat);
}
.t-countdown__label,
.t-countdown__fallback {
margin-inline-end: auto;
}
.t-countdown--running {
border-block-start-color: var(--border-color-success);
}
.t-countdown--upcoming {
border-block-start-color: var(--border-color-warning);
}
.t-countdown--live .t-countdown__label {
align-self: center;
}
}
/* Note what lying down does NOT change: alignment inside a unit. Each unit
* centres its digits over its own caption either way, so the clock reads the
* same on its side as it does standing up. Only the axis changes. */