v1.5 - history and timeline as well as many datastructure updates added, polished, fixes
This commit is contained in:
parent
1f0aa3078f
commit
1d84400aef
63 changed files with 7927 additions and 208 deletions
663
src/pages/sections/history/timeline.css
Normal file
663
src/pages/sections/history/timeline.css
Normal file
|
|
@ -0,0 +1,663 @@
|
|||
/**
|
||||
* History timeline — scoped under .ngu-tl.
|
||||
*
|
||||
* Everything themeable is a custom property with a fallback, so rewiring to the
|
||||
* site tokens is a one-block edit at the top. Typefaces are deliberately not
|
||||
* set: the timeline inherits the page's type and only controls scale, weight
|
||||
* and tracking.
|
||||
*/
|
||||
|
||||
.ngu-tl {
|
||||
/* Defaults match the site palette; History.tsx overrides accent and
|
||||
surface per section so the rail sits on the right background. */
|
||||
--tl-ink: #16343a;
|
||||
--tl-muted: #4a6b72;
|
||||
--tl-faint: #8aa7ad;
|
||||
--tl-rail: #cfe4e8;
|
||||
--tl-surface: #ffffff;
|
||||
--tl-accent: #138ba0;
|
||||
--tl-accent-soft: color-mix(in srgb, var(--tl-accent) 12%, transparent);
|
||||
|
||||
--tl-gutter: 5rem;
|
||||
--tl-rail-x: 1.75rem;
|
||||
--tl-rail-w: 2px;
|
||||
|
||||
color: var(--tl-ink);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.ngu-tl {
|
||||
--tl-gutter: 3rem;
|
||||
--tl-rail-x: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* ——— Decade block ——————————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__decade {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* The rail. One per decade block so the pre-program run can change style
|
||||
without breaking the line's continuity. */
|
||||
.ngu-tl__decade::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: var(--tl-rail-x);
|
||||
width: var(--tl-rail-w);
|
||||
background: var(--tl-rail);
|
||||
}
|
||||
|
||||
.ngu-tl__decade--pre::before {
|
||||
background: none;
|
||||
border-left: var(--tl-rail-w) dashed var(--tl-rail);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Last decade fades out rather than stopping dead. */
|
||||
.ngu-tl__decade:last-child::before {
|
||||
bottom: 2rem;
|
||||
mask-image: linear-gradient(to bottom, #000 60%, transparent);
|
||||
}
|
||||
|
||||
.ngu-tl__decade--pre {
|
||||
color: var(--tl-muted);
|
||||
}
|
||||
|
||||
/* ——— Decade header ——————————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__decadeHead {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: var(--tl-gutter) minmax(0, 1fr);
|
||||
align-items: start;
|
||||
padding-block: 3.5rem 1.75rem;
|
||||
}
|
||||
|
||||
.ngu-tl__decade:first-child .ngu-tl__decadeHead {
|
||||
padding-block-start: 0.5rem;
|
||||
}
|
||||
|
||||
/* Numeral breaks the rail. */
|
||||
.ngu-tl__decadeNum {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-left: calc(var(--tl-rail-x) * -1 + 0.125rem);
|
||||
padding-block: 0.35rem;
|
||||
background: var(--tl-surface);
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 650;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: 0.01em;
|
||||
line-height: 1.1;
|
||||
writing-mode: vertical-rl;
|
||||
text-orientation: sideways;
|
||||
color: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__decade--pre .ngu-tl__decadeNum {
|
||||
color: var(--tl-faint);
|
||||
}
|
||||
|
||||
.ngu-tl__decadeTitle {
|
||||
font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.125rem);
|
||||
font-weight: 600;
|
||||
line-height: 1.12;
|
||||
letter-spacing: -0.018em;
|
||||
margin: 0;
|
||||
max-width: 22ch;
|
||||
}
|
||||
|
||||
.ngu-tl__decadeTagline {
|
||||
margin: 0.5rem 0 0;
|
||||
font-size: 1.0625rem;
|
||||
line-height: 1.5;
|
||||
color: var(--tl-muted);
|
||||
max-width: 54ch;
|
||||
}
|
||||
|
||||
.ngu-tl__decadeBlurb {
|
||||
margin: 0.875rem 0 0;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.65;
|
||||
color: var(--tl-muted);
|
||||
max-width: 62ch;
|
||||
}
|
||||
|
||||
.ngu-tl__gapNote {
|
||||
margin: 1rem 0 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
border: 1px dashed var(--tl-rail);
|
||||
border-radius: 999px;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--tl-faint);
|
||||
}
|
||||
|
||||
/* ——— Year node ———————————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__year {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ngu-tl__yearBtn {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
grid-template-columns: var(--tl-gutter) minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding-block: 0.6875rem;
|
||||
background: none;
|
||||
border: 0;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.ngu-tl__yearBtn:hover .ngu-tl__yearLabel {
|
||||
color: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__yearBtn:focus-visible {
|
||||
outline: 2px solid var(--tl-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* Dot sits on the rail; --tl-dot is set inline from the year's item count, so
|
||||
scrolling the page gives you the organization's density at a glance. */
|
||||
.ngu-tl__dot {
|
||||
position: relative;
|
||||
justify-self: start;
|
||||
margin-left: calc(var(--tl-rail-x) - (var(--tl-dot, 8px) / 2) + (var(--tl-rail-w) / 2));
|
||||
width: var(--tl-dot, 8px);
|
||||
height: var(--tl-dot, 8px);
|
||||
border-radius: 50%;
|
||||
background: var(--tl-rail);
|
||||
box-shadow: 0 0 0 4px var(--tl-surface);
|
||||
transition: background-color 140ms ease, transform 140ms ease;
|
||||
}
|
||||
|
||||
.ngu-tl__yearBtn:hover .ngu-tl__dot {
|
||||
background: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__year--featured .ngu-tl__dot {
|
||||
background: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__year--featured .ngu-tl__dot::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: -5px;
|
||||
border: 1.5px solid var(--tl-accent);
|
||||
border-radius: 50%;
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.ngu-tl__year--open .ngu-tl__dot {
|
||||
background: var(--tl-accent);
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
.ngu-tl__decade--pre .ngu-tl__dot {
|
||||
background: var(--tl-surface);
|
||||
border: 1.5px solid var(--tl-rail);
|
||||
}
|
||||
|
||||
.ngu-tl__yearLabel {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 550;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: -0.01em;
|
||||
transition: color 140ms ease;
|
||||
}
|
||||
|
||||
.ngu-tl__yearCount {
|
||||
font-size: 0.8125rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: var(--tl-faint);
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
.ngu-tl__year--empty .ngu-tl__yearLabel {
|
||||
color: var(--tl-faint);
|
||||
font-weight: 450;
|
||||
}
|
||||
|
||||
/* ——— Expanded panel ——————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__panel {
|
||||
padding: 0.25rem 0 1.5rem var(--tl-gutter);
|
||||
animation: ngu-tl-reveal 220ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
|
||||
}
|
||||
|
||||
@keyframes ngu-tl-reveal {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
}
|
||||
|
||||
.ngu-tl__month {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.ngu-tl__month:first-child {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.ngu-tl__monthLabel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin: 0 0 0.625rem;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 550;
|
||||
color: var(--tl-muted);
|
||||
}
|
||||
|
||||
.ngu-tl__monthLabel::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--tl-rail);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.ngu-tl__undated .ngu-tl__monthLabel {
|
||||
font-style: italic;
|
||||
font-weight: 450;
|
||||
color: var(--tl-faint);
|
||||
}
|
||||
|
||||
.ngu-tl__list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.125rem;
|
||||
}
|
||||
|
||||
/* ——— Entry ————————————————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__entry {
|
||||
display: grid;
|
||||
grid-template-columns: 2.75rem minmax(0, 1fr);
|
||||
gap: 0.75rem;
|
||||
padding: 0.5rem 0.75rem 0.5rem 0;
|
||||
border-radius: 0.5rem;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a.ngu-tl__entry:hover {
|
||||
background: var(--tl-accent-soft);
|
||||
}
|
||||
|
||||
a.ngu-tl__entry:focus-visible {
|
||||
outline: 2px solid var(--tl-accent);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.ngu-tl__entryDay {
|
||||
font-size: 0.8125rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
color: var(--tl-faint);
|
||||
padding-top: 0.1875rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ngu-tl__entryTitle {
|
||||
display: block;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
a.ngu-tl__entry:hover .ngu-tl__entryTitle {
|
||||
color: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__entryMeta {
|
||||
display: block;
|
||||
margin-top: 0.125rem;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--tl-muted);
|
||||
}
|
||||
|
||||
.ngu-tl__entryBlurb {
|
||||
margin: 0.375rem 0 0;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.6;
|
||||
color: var(--tl-muted);
|
||||
max-width: 64ch;
|
||||
}
|
||||
|
||||
/* Kind marker: a shape, not a colored pill, so a screenful of entries stays
|
||||
calm and the type still carries the hierarchy. */
|
||||
.ngu-tl__kind {
|
||||
display: inline-block;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
vertical-align: 0.0625rem;
|
||||
background: var(--tl-faint);
|
||||
}
|
||||
|
||||
.ngu-tl__kind--milestone {
|
||||
border-radius: 50%;
|
||||
background: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__kind--event {
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
.ngu-tl__kind--award {
|
||||
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
|
||||
}
|
||||
|
||||
.ngu-tl__kind--person {
|
||||
border-radius: 50%;
|
||||
background: none;
|
||||
box-shadow: inset 0 0 0 1.5px var(--tl-faint);
|
||||
}
|
||||
|
||||
/* ——— Featured entries ————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__featured {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.ngu-tl__entry--featured {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
padding: 1rem 1.125rem;
|
||||
border-left: 2px solid var(--tl-accent);
|
||||
background: var(--tl-accent-soft);
|
||||
border-radius: 0 0.5rem 0.5rem 0;
|
||||
}
|
||||
|
||||
.ngu-tl__entry--featured .ngu-tl__entryTitle {
|
||||
font-size: 1.0625rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.008em;
|
||||
}
|
||||
|
||||
.ngu-tl__entry--featured .ngu-tl__entryDay {
|
||||
text-align: left;
|
||||
padding: 0 0 0.25rem;
|
||||
}
|
||||
|
||||
a.ngu-tl__entry--featured:hover {
|
||||
background: color-mix(in srgb, var(--tl-accent) 18%, transparent);
|
||||
}
|
||||
|
||||
/* ——— Empty state ——————————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__empty {
|
||||
padding: 0.5rem 0 1.25rem var(--tl-gutter);
|
||||
font-size: 0.875rem;
|
||||
color: var(--tl-faint);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ngu-tl *,
|
||||
.ngu-tl *::before,
|
||||
.ngu-tl *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ——— Toolbar + utilities ————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.ngu-tl__toolbarBtn {
|
||||
padding: 0.375rem 0.75rem;
|
||||
border: 1px solid var(--tl-rail);
|
||||
border-radius: 999px;
|
||||
background: none;
|
||||
color: var(--tl-muted);
|
||||
font: inherit;
|
||||
font-size: 0.8125rem;
|
||||
cursor: pointer;
|
||||
transition: color 140ms ease, border-color 140ms ease;
|
||||
}
|
||||
|
||||
.ngu-tl__toolbarBtn:hover {
|
||||
color: var(--tl-accent);
|
||||
border-color: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__toolbarBtn:focus-visible {
|
||||
outline: 2px solid var(--tl-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.ngu-tl__emptyState {
|
||||
padding: 3rem 0;
|
||||
color: var(--tl-muted);
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
|
||||
.ngu-tl__srOnly {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* ——— Upcoming block ——————————————————————————————————————————
|
||||
Opens upward: the toggle is first in the DOM, column-reverse puts the
|
||||
list above it. Faded because none of it has happened yet. */
|
||||
|
||||
.ngu-tl__upcoming {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.ngu-tl__upcoming::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 1.25rem;
|
||||
bottom: 0;
|
||||
left: var(--tl-rail-x);
|
||||
border-left: var(--tl-rail-w) dashed var(--tl-rail);
|
||||
}
|
||||
|
||||
.ngu-tl__upcomingBtn {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
grid-template-columns: var(--tl-gutter) minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding-block: 0.75rem;
|
||||
background: none;
|
||||
border: 0;
|
||||
font: inherit;
|
||||
color: var(--tl-muted);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ngu-tl__upcomingBtn:hover {
|
||||
color: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__upcomingBtn:focus-visible {
|
||||
outline: 2px solid var(--tl-accent);
|
||||
outline-offset: 2px;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.ngu-tl__upcomingDot {
|
||||
justify-self: start;
|
||||
margin-left: calc(var(--tl-rail-x) - 4px + (var(--tl-rail-w) / 2));
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
border: 1.5px dashed var(--tl-accent);
|
||||
box-shadow: 0 0 0 4px var(--tl-surface);
|
||||
}
|
||||
|
||||
.ngu-tl__upcomingLabel {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.ngu-tl__chevron {
|
||||
font-size: 0.75rem;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
/* Everything above the toggle is provisional, and reads that way. */
|
||||
.ngu-tl__upcomingList {
|
||||
opacity: 0.62;
|
||||
animation: ngu-tl-rise 240ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
|
||||
}
|
||||
|
||||
.ngu-tl__upcomingList:hover,
|
||||
.ngu-tl__upcomingList:focus-within {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ngu-tl__upcomingList .ngu-tl__dot {
|
||||
background: var(--tl-surface);
|
||||
border: 1.5px dashed var(--tl-accent);
|
||||
}
|
||||
|
||||
@keyframes ngu-tl-rise {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
}
|
||||
|
||||
/* ——— Event / org / award logo ————————————————————————————————— */
|
||||
|
||||
.ngu-tl__logo {
|
||||
display: inline-block;
|
||||
width: 1.125rem;
|
||||
height: 1.125rem;
|
||||
margin-right: 0.5rem;
|
||||
vertical-align: -0.1875rem;
|
||||
object-fit: contain;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.ngu-tl__entry--featured .ngu-tl__logo {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
vertical-align: -0.3125rem;
|
||||
}
|
||||
|
||||
/* ——— People roster ——————————————————————————————————————————— */
|
||||
|
||||
.ngu-tl__entryWrap {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ngu-tl__roster {
|
||||
padding: 0.125rem 0 0.5rem 3.5rem;
|
||||
}
|
||||
|
||||
.ngu-tl__roster--featured {
|
||||
padding: 0.5rem 1.125rem 1rem;
|
||||
border-left: 2px solid var(--tl-accent);
|
||||
background: var(--tl-accent-soft);
|
||||
margin-top: -0.5rem;
|
||||
border-radius: 0 0 0.5rem 0;
|
||||
}
|
||||
|
||||
.ngu-tl__rosterTeam {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--tl-faint);
|
||||
}
|
||||
|
||||
.ngu-tl__people {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.375rem 1rem;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ngu-tl__person {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.ngu-tl__personPhoto {
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
background: var(--tl-accent-soft);
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.ngu-tl__personPhoto--blank {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.02em;
|
||||
color: var(--tl-accent);
|
||||
}
|
||||
|
||||
.ngu-tl__personName {
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.ngu-tl__personTitle {
|
||||
display: block;
|
||||
font-size: 0.6875rem;
|
||||
color: var(--tl-faint);
|
||||
}
|
||||
|
||||
/* ——— Kind markers, continued ————————————————————————————————— */
|
||||
|
||||
.ngu-tl__kind--organization {
|
||||
border-radius: 2px;
|
||||
background: none;
|
||||
box-shadow: inset 0 0 0 1.5px var(--tl-faint);
|
||||
}
|
||||
|
||||
.ngu-tl__kind--people {
|
||||
border-radius: 50%;
|
||||
background: none;
|
||||
box-shadow: inset 0 0 0 1.5px var(--tl-faint);
|
||||
}
|
||||
|
||||
.ngu-tl__entryBody {
|
||||
display: block;
|
||||
min-width: 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue