astro-theme-popular 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/index.mjs +81 -0
  4. package/package.json +47 -0
  5. package/schemas.ts +137 -0
  6. package/scripts/blog-filter.js +24 -0
  7. package/scripts/checklist.js +42 -0
  8. package/scripts/copy-code.js +25 -0
  9. package/scripts/nav.js +12 -0
  10. package/scripts/toc.js +25 -0
  11. package/src/components/AuthorBox.astro +51 -0
  12. package/src/components/Callout.astro +22 -0
  13. package/src/components/Checklist.astro +29 -0
  14. package/src/components/DemoBar.astro +50 -0
  15. package/src/components/EventRow.astro +59 -0
  16. package/src/components/Footer.astro +42 -0
  17. package/src/components/Header.astro +49 -0
  18. package/src/components/OrganizerCard.astro +21 -0
  19. package/src/components/PageHero.astro +19 -0
  20. package/src/components/Pagination.astro +35 -0
  21. package/src/components/PostCard.astro +36 -0
  22. package/src/layouts/BaseLayout.astro +102 -0
  23. package/src/lib/slugs.ts +10 -0
  24. package/src/pages/[slug].astro +62 -0
  25. package/src/pages/authors/[slug].astro +39 -0
  26. package/src/pages/blog/[...page].astro +52 -0
  27. package/src/pages/blog/[slug].astro +122 -0
  28. package/src/pages/events/[...page].astro +86 -0
  29. package/src/pages/events/[slug].astro +81 -0
  30. package/src/pages/index.astro +178 -0
  31. package/src/pages/organizers/[...page].astro +38 -0
  32. package/src/pages/rss.xml.js +33 -0
  33. package/src/pages/speakers/[slug].astro +39 -0
  34. package/src/pages/tags/[tag]/[...page].astro +47 -0
  35. package/src/pages/venues/[slug].astro +50 -0
  36. package/src/styles/base.css +113 -0
  37. package/src/styles/components.css +310 -0
  38. package/src/styles/tokens/colors.css +82 -0
  39. package/src/styles/tokens/elevation.css +27 -0
  40. package/src/styles/tokens/fonts.css +9 -0
  41. package/src/styles/tokens/spacing.css +39 -0
  42. package/src/styles/tokens/typography.css +43 -0
  43. package/tsconfig.json +6 -0
@@ -0,0 +1,113 @@
1
+ /* ============================================================
2
+ POPULAR: base.css
3
+ Resets, document defaults, and layout utilities.
4
+ Everything references the design tokens (tokens/*.css) so a
5
+ site can re-theme purely by overriding CSS custom properties.
6
+ ============================================================ */
7
+
8
+ *, *::before, *::after { box-sizing: border-box; }
9
+
10
+ html { -webkit-text-size-adjust: 100%; }
11
+ @media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
12
+
13
+ body {
14
+ margin: 0;
15
+ font-family: var(--font-sans);
16
+ font-size: var(--text-base);
17
+ line-height: var(--leading-normal);
18
+ color: var(--text-body);
19
+ background: var(--surface-page);
20
+ -webkit-font-smoothing: antialiased;
21
+ }
22
+
23
+ img, svg, video { max-width: 100%; display: block; }
24
+
25
+ a { color: var(--text-link); text-decoration: none; }
26
+ a:hover { color: var(--text-link-hover); }
27
+
28
+ h1, h2, h3, h4 {
29
+ color: var(--text-strong);
30
+ letter-spacing: var(--tracking-tight);
31
+ line-height: var(--leading-tight);
32
+ margin: 0 0 0.6em;
33
+ }
34
+ h1 { font-size: var(--text-3xl); font-weight: var(--weight-bold); }
35
+ h2 { font-size: var(--text-2xl); font-weight: var(--weight-bold); }
36
+ h3 { font-size: var(--text-xl); font-weight: var(--weight-semibold); }
37
+
38
+ p { margin: 0 0 1rem; }
39
+
40
+ /* Inline code: Python-docs style, mono font on a soft grey chip.
41
+ Code inside pre blocks keeps the highlighter's own background. */
42
+ pre, code, kbd { font-family: var(--font-mono); }
43
+ code {
44
+ font-size: 0.875em;
45
+ background: var(--surface-code);
46
+ padding: 0.1em 0.35em;
47
+ border-radius: var(--radius-sm);
48
+ }
49
+ pre code { font-size: inherit; background: none; padding: 0; border-radius: 0; }
50
+
51
+ :focus-visible { outline: none; box-shadow: var(--shadow-focus); border-radius: var(--radius-sm); }
52
+
53
+ /* --- Layout utilities --- */
54
+ .g-container { max-width: var(--container-max); margin: 0 auto; padding-inline: var(--gutter); }
55
+ .g-narrow { max-width: 52rem; margin: 0 auto; padding-inline: var(--gutter); } /* legacy self-centering column */
56
+ /* Reading-measure column. Use inside .g-container so the text's left edge
57
+ lines up with the page hero and every other page type. */
58
+ .g-article { max-width: 52rem; }
59
+ .g-section { padding-block: var(--section-pad-y); }
60
+ .g-section--sm { padding-block: var(--space-5); }
61
+
62
+ /* Surface bands */
63
+ .g-bg-white { background: var(--surface-page); }
64
+ .g-bg-wash { background: var(--surface-wash); }
65
+ .g-bg-wash-soft { background: var(--surface-wash-soft); }
66
+ .g-bg-tertiary { background: var(--surface-tertiary); }
67
+ .g-bg-ink { background: var(--surface-ink); color: var(--ink-200); }
68
+
69
+ /* Eyebrow (Quantico display accent) */
70
+ .g-eyebrow {
71
+ display: inline-block;
72
+ font-family: var(--font-display);
73
+ font-size: var(--text-sm);
74
+ font-weight: var(--weight-bold);
75
+ letter-spacing: var(--tracking-wider);
76
+ text-transform: uppercase;
77
+ color: var(--color-primary);
78
+ }
79
+
80
+ /* Section heading block */
81
+ .g-section-head { display: flex; flex-direction: column; gap: 0.6rem; max-width: 46rem; }
82
+ .g-section-head--center { align-items: center; text-align: center; margin-inline: auto; }
83
+ .g-section-head h2 { margin: 0; }
84
+ .g-section-head .g-lead { margin: 0; font-size: var(--text-md); color: var(--text-muted); line-height: var(--leading-normal); }
85
+
86
+ .g-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
87
+ .g-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-4); }
88
+ .g-stack { display: flex; flex-direction: column; gap: 1.2rem; }
89
+ .g-row { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }
90
+
91
+ .g-prose { font-size: var(--text-md); line-height: var(--leading-relaxed); color: var(--text-body); }
92
+ /* Underline prose links so color is never the only distinguisher (WCAG 1.4.1);
93
+ matters for adopters whose brand link color is close to the body text.
94
+ Only bare markdown links: components inside prose (buttons, tags) carry a
95
+ class and are already visually distinct. */
96
+ .g-prose a:not([class]) { text-decoration: underline; text-underline-offset: 2px; }
97
+ .g-prose > * + * { margin-top: 1.1rem; }
98
+ .g-prose ul, .g-prose ol { padding-left: 1.2rem; display: flex; flex-direction: column; gap: 0.5rem; }
99
+ .g-prose h2 { margin-top: 1.8rem; }
100
+ .g-prose img { border-radius: var(--radius-xl); box-shadow: var(--shadow-sm); }
101
+ /* One background for every fenced block, whatever the highlighter did.
102
+ !important beats the inline background-color that Chroma (Hugo) and
103
+ Shiki (Astro) emit, and unhighlighted languages get the same canvas. */
104
+ .g-prose pre { overflow-x: auto; padding: 1rem 1.2rem; border-radius: var(--radius-lg); background: var(--surface-code-block) !important; color: var(--ink-100); }
105
+
106
+ /* Skip link for a11y */
107
+ .g-skip { position: absolute; left: -999px; top: 0; background: var(--color-primary); color: #fff; padding: 0.6rem 1rem; border-radius: var(--radius-md); z-index: 100; }
108
+ .g-skip:focus { left: 0.5rem; top: 0.5rem; color: #fff; }
109
+
110
+ @media (max-width: 920px) {
111
+ :root { --text-4xl: 2.75rem; --text-3xl: 2.25rem; --text-2xl: 1.9rem; --section-pad-y: 3rem; }
112
+ .g-grid-3, .g-grid-2 { grid-template-columns: 1fr; }
113
+ }
@@ -0,0 +1,310 @@
1
+ /* ============================================================
2
+ POPULAR: components.css
3
+ Class-based ports of the theme's components. Pair with a
4
+ FontAwesome 6 stylesheet for icons (loaded in head).
5
+ ============================================================ */
6
+
7
+ /* ---------- Buttons ---------- */
8
+ .g-btn {
9
+ display: inline-flex; align-items: center; justify-content: center; gap: 0.55em;
10
+ min-height: var(--control-height-md);
11
+ padding: 0.6rem 1.4rem;
12
+ font-family: var(--font-sans); font-size: var(--text-base); font-weight: var(--weight-semibold);
13
+ line-height: 1.1; letter-spacing: 0.01em;
14
+ border: var(--border-width-thick) solid transparent;
15
+ border-radius: var(--radius-pill);
16
+ cursor: pointer; white-space: nowrap; text-decoration: none;
17
+ transition: background var(--duration-base) var(--ease-out), color var(--duration-base) var(--ease-out),
18
+ transform var(--duration-fast) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
19
+ }
20
+ .g-btn:hover { transform: translateY(-1px); }
21
+ .g-btn--sm { min-height: var(--control-height-sm); padding: 0.4rem 0.95rem; font-size: var(--text-sm); }
22
+ .g-btn--lg { min-height: var(--control-height-lg); padding: 0.85rem 1.9rem; font-size: var(--text-md); }
23
+ .g-btn--block { display: flex; width: 100%; }
24
+
25
+ .g-btn--primary { background: var(--color-primary); color: var(--text-on-brand); }
26
+ .g-btn--primary:hover { background: var(--color-primary-hover); color: var(--text-on-brand); box-shadow: var(--shadow-brand); }
27
+ .g-btn--secondary { background: var(--color-secondary); color: var(--text-on-brand); }
28
+ .g-btn--secondary:hover { background: color-mix(in srgb, var(--color-secondary) 80%, #000); color: var(--text-on-brand); box-shadow: var(--shadow-sm); }
29
+ .g-btn--outline { background: transparent; color: var(--color-primary); border-color: var(--color-primary); }
30
+ .g-btn--outline:hover { background: var(--color-primary); color: var(--text-on-brand); box-shadow: var(--shadow-sm); }
31
+ .g-btn--ghost { background: transparent; color: var(--text-link); }
32
+ .g-btn--ghost:hover { background: var(--color-primary-subtle); color: var(--text-link); }
33
+ .g-btn--accent { background: var(--color-accent); color: var(--text-on-brand); }
34
+ .g-btn--accent:hover { background: var(--color-accent-hover); color: var(--text-on-brand); box-shadow: var(--shadow-sm); }
35
+ .g-btn--dark { background: var(--ink-800); color: var(--text-on-brand); }
36
+ .g-btn--dark:hover { background: var(--ink-900); color: var(--text-on-brand); box-shadow: var(--shadow-sm); }
37
+
38
+ /* ---------- Badges & tags ---------- */
39
+ .g-badge {
40
+ display: inline-flex; align-items: center; gap: 0.4em;
41
+ padding: 0.28em 0.7em; font-size: var(--text-xs); font-weight: var(--weight-semibold);
42
+ line-height: 1.2; letter-spacing: 0.01em; border-radius: var(--radius-pill); white-space: nowrap;
43
+ background: var(--color-primary); color: #fff;
44
+ }
45
+ .g-badge--soft { background: var(--gold-50); color: var(--gold-700); }
46
+ .g-badge--secondary { background: var(--color-secondary); }
47
+ .g-badge--secondary.g-badge--soft { background: var(--gold-50); color: var(--gold-700); }
48
+ .g-badge--success { background: var(--green-500); }
49
+ .g-badge--success.g-badge--soft { background: #e6f3ec; color: #0f6e44; }
50
+ .g-badge--warning { background: var(--amber-500); color: #142a36; }
51
+ .g-badge--warning.g-badge--soft { background: #fff7e0; color: #946a00; }
52
+ .g-badge--ink { background: var(--ink-800); }
53
+
54
+ .g-tag {
55
+ display: inline-flex; align-items: center;
56
+ padding: 0.2em 0.65em; font-size: var(--text-xs); font-weight: var(--weight-medium);
57
+ border-radius: var(--radius-pill); border: var(--border-width) solid var(--border-subtle);
58
+ color: var(--text-muted); background: var(--surface-card);
59
+ transition: background var(--duration-base) var(--ease-out), border-color var(--duration-base) var(--ease-out), color var(--duration-base) var(--ease-out);
60
+ }
61
+ .g-tag::before { content: "#"; opacity: 0.55; margin-right: 0.05em; }
62
+ a.g-tag:hover { background: var(--gold-50); border-color: var(--color-primary); color: var(--gold-700); }
63
+
64
+ /* Blog filter buttons */
65
+ .g-filter { font-family: var(--font-sans); padding: 0.3rem 0.8rem; border-radius: var(--radius-pill); font-size: var(--text-sm); font-weight: var(--weight-medium); border: var(--border-width) solid var(--border-subtle); background: var(--surface-card); color: var(--text-body); cursor: pointer; }
66
+ .g-filter:hover { border-color: var(--color-primary); color: var(--gold-700); }
67
+ .g-filter.is-active { background: var(--gold-50); border-color: var(--color-primary); color: var(--gold-700); }
68
+
69
+ /* Pager (list pagination) */
70
+ .g-pager { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.4rem; margin-top: var(--space-5); }
71
+ .g-pager__num, .g-pager__nav {
72
+ display: inline-flex; align-items: center; justify-content: center; gap: 0.45em;
73
+ min-width: 2.2rem; min-height: 2.2rem; padding: 0.3rem 0.8rem;
74
+ border-radius: var(--radius-pill); font-size: var(--text-sm); font-weight: var(--weight-medium);
75
+ border: var(--border-width) solid var(--border-subtle); background: var(--surface-card); color: var(--text-body);
76
+ }
77
+ a.g-pager__num:hover, .g-pager__nav:hover { border-color: var(--color-primary); color: var(--gold-700); }
78
+ .g-pager__num.is-active { background: var(--gold-50); border-color: var(--color-primary); color: var(--gold-700); }
79
+
80
+ /* ---------- Testimonials ---------- */
81
+ .g-quote {
82
+ display: flex; flex-direction: column; gap: 1rem; height: 100%; margin: 0;
83
+ background: var(--surface-card); border: var(--border-width) solid var(--border-subtle);
84
+ border-radius: var(--radius-xl); padding: 1.5rem; box-shadow: var(--shadow-sm);
85
+ }
86
+ .g-quote blockquote { margin: 0; line-height: var(--leading-relaxed); color: var(--text-body); }
87
+ .g-quote blockquote::before {
88
+ content: "\201C";
89
+ display: block; font-family: var(--font-display); font-size: 2.5rem; line-height: 1;
90
+ color: var(--color-primary);
91
+ }
92
+ .g-quote figcaption { display: flex; align-items: center; gap: 0.75rem; margin-top: auto; }
93
+ .g-quote figcaption img { width: 2.75rem; height: 2.75rem; border-radius: 50%; object-fit: cover; }
94
+ .g-quote__name { display: block; font-weight: var(--weight-semibold); color: var(--text-strong); }
95
+ .g-quote__role { display: block; font-size: var(--text-sm); color: var(--text-muted); }
96
+
97
+ /* Year heading for date-grouped lists (events) */
98
+ .g-year { margin: var(--space-3) 0 0; font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wide); color: var(--text-muted); }
99
+ .g-year:first-child { margin-top: 0; }
100
+
101
+ /* ---------- Cards ---------- */
102
+ .g-card {
103
+ display: flex; flex-direction: column; height: 100%;
104
+ background: var(--surface-card); border: var(--border-width) solid var(--border-subtle);
105
+ border-radius: var(--radius-xl); overflow: hidden; box-shadow: var(--shadow-sm);
106
+ transition: transform var(--duration-slow) var(--ease-out), box-shadow var(--duration-slow) var(--ease-out);
107
+ }
108
+ .g-card:hover { transform: var(--hover-lift); box-shadow: var(--shadow-lg); }
109
+ .g-card__media { aspect-ratio: 16 / 9; overflow: hidden; background: var(--gold-100); }
110
+ .g-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--duration-slow) var(--ease-out); }
111
+ .g-card:hover .g-card__media img { transform: scale(1.04); }
112
+ .g-card__body { display: flex; flex-direction: column; gap: 0.6rem; padding: var(--space-4); flex: 1; }
113
+ .g-card__eyebrow { font-family: var(--font-display); font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wider); text-transform: uppercase; color: var(--color-primary); }
114
+ .g-card__title { margin: 0; font-size: var(--text-lg); font-weight: var(--weight-semibold); line-height: var(--leading-snug); color: var(--text-strong); }
115
+ .g-card__title a { color: inherit; }
116
+ .g-card__title a:hover { color: var(--color-primary); }
117
+ .g-card__text { font-size: var(--text-base); line-height: var(--leading-normal); color: var(--text-muted); }
118
+ .g-card__footer { margin-top: auto; padding-top: 0.6rem; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
119
+
120
+ /* Icon medallion used in feature cards */
121
+ .g-medallion {
122
+ display: inline-flex; width: 52px; height: 52px; align-items: center; justify-content: center;
123
+ border-radius: var(--radius-circle); background: var(--gold-50); color: var(--color-primary); font-size: 1.3rem;
124
+ }
125
+ .g-medallion--lg { width: 68px; height: 68px; font-size: 1.7rem; background: var(--surface-wash); }
126
+
127
+ /* ---------- Persona (organizer / speaker bio) ---------- */
128
+ .g-persona {
129
+ display: flex; gap: var(--space-4); align-items: flex-start;
130
+ background: var(--surface-card); border: var(--border-width) solid var(--border-subtle);
131
+ border-left: 4px solid var(--color-secondary); border-radius: var(--radius-lg);
132
+ padding: var(--space-4); box-shadow: var(--shadow-sm);
133
+ }
134
+ .g-persona--primary { border-left-color: var(--color-primary); }
135
+ .g-persona__img { flex: 0 0 auto; width: 76px; height: 76px; border-radius: var(--radius-circle); object-fit: cover; border: 3px solid var(--color-secondary); }
136
+ .g-persona--primary .g-persona__img { border-color: var(--color-primary); }
137
+ .g-persona__name { font-size: var(--text-lg); font-weight: var(--weight-semibold); color: var(--text-strong); line-height: 1.2; }
138
+ .g-persona__role { font-size: var(--text-sm); color: var(--color-secondary); font-weight: var(--weight-medium); }
139
+ .g-persona__bio { margin: 0.35rem 0 0; font-size: var(--text-sm); line-height: var(--leading-normal); color: var(--text-muted); }
140
+ .g-persona__socials { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
141
+ .g-persona__socials a { color: var(--ink-400); font-size: 1rem; }
142
+ .g-persona__socials a:hover { color: var(--color-primary); }
143
+
144
+ /* Organizer grid card (photo on top) */
145
+ .g-org { text-align: left; }
146
+ .g-org__img { width: 100%; aspect-ratio: 1/1; object-fit: cover; border-radius: var(--radius-xl); box-shadow: var(--shadow-sm); }
147
+ .g-org__name { margin: 0.9rem 0 0.1rem; font-size: var(--text-lg); font-weight: var(--weight-semibold); color: var(--text-strong); }
148
+ .g-org__role { font-size: var(--text-sm); color: var(--color-primary); font-weight: var(--weight-medium); }
149
+ .g-org__bio { margin: 0.5rem 0 0; font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-normal); }
150
+
151
+ /* ---------- Post navigation (older/newer neighbors on blog singles) ---------- */
152
+ .g-postnav { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); margin-top: var(--space-5); }
153
+ .g-postnav__card { display: flex; flex-direction: column; gap: 0.35rem; padding: var(--space-3); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-lg); background: var(--surface-card); }
154
+ .g-postnav__card:hover { border-color: var(--color-primary); box-shadow: var(--shadow-sm); }
155
+ .g-postnav__card--next { text-align: right; align-items: flex-end; grid-column: 2; }
156
+ .g-postnav__label { font-size: var(--text-xs); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--text-muted); }
157
+ .g-postnav__title { font-weight: var(--weight-semibold); color: var(--text-strong); }
158
+ @media (max-width: 640px) { .g-postnav { grid-template-columns: 1fr; } .g-postnav__card--next { grid-column: 1; text-align: left; align-items: flex-start; } }
159
+
160
+ /* ---------- Header / nav ---------- */
161
+ .g-header { position: sticky; top: 0; z-index: 50; background: color-mix(in srgb, var(--surface-page) 88%, transparent); backdrop-filter: saturate(140%) blur(10px); border-bottom: var(--border-width) solid var(--border-subtle); }
162
+ .g-nav { display: flex; align-items: center; gap: var(--space-4); padding-block: 0.75rem; }
163
+ .g-brand { display: flex; align-items: center; gap: 0.6rem; }
164
+ .g-brand img { height: 44px; width: 44px; border-radius: var(--radius-md); }
165
+ .g-brand__text { display: flex; flex-direction: column; line-height: 1; }
166
+ .g-brand__name { font-weight: var(--weight-bold); color: var(--color-primary); font-size: var(--text-md); }
167
+ .g-brand__sub { font-family: var(--font-display); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; font-size: 0.7rem; color: var(--ink-800); }
168
+ .g-navlinks { display: flex; gap: 0.4rem; list-style: none; margin: 0 0 0 auto; padding: 0; align-items: center; }
169
+ .g-navlinks a { display: inline-block; padding: 0.5rem 0.9rem; border-radius: var(--radius-pill); font-size: var(--text-base); font-weight: var(--weight-medium); color: var(--text-body); }
170
+ .g-navlinks a:hover { color: var(--color-primary); }
171
+ .g-navlinks a.is-active { color: var(--color-primary); background: var(--gold-50); }
172
+ .g-navlinks li { position: relative; }
173
+ .g-navlinks__caret { font-size: 0.6em; margin-left: 0.35rem; }
174
+ .g-navlinks__sub { display: none; position: absolute; top: 100%; left: 0; z-index: 30; min-width: 11rem; flex-direction: column; gap: 0.15rem; margin: 0; padding: 0.4rem; list-style: none; background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); }
175
+ .g-navlinks li.has-sub:hover > .g-navlinks__sub, .g-navlinks li.has-sub:focus-within > .g-navlinks__sub { display: flex; }
176
+ .g-navlinks__sub a { display: block; border-radius: var(--radius-md); }
177
+ .g-nav__cta { margin-left: 0.4rem; }
178
+ .g-nav__toggle { display: none; margin-left: auto; background: none; border: none; font-size: 1.4rem; color: var(--ink-800); cursor: pointer; padding: 0.4rem; }
179
+
180
+ /* ---------- Code copy button ---------- */
181
+ pre { position: relative; }
182
+ .g-copy { position: absolute; top: 0.45rem; right: 0.45rem; padding: 0.35rem 0.55rem; border: none; border-radius: var(--radius-md); background: rgba(255, 255, 255, 0.12); color: #f8f8f2; font-size: var(--text-sm); cursor: pointer; opacity: 0; transition: opacity 0.15s ease; }
183
+ pre:hover .g-copy, .g-copy:focus-visible { opacity: 1; }
184
+ .g-copy:hover { background: rgba(255, 255, 255, 0.24); }
185
+ .g-copy.is-copied { color: #6ee7b7; }
186
+
187
+ /* ---------- Hero ---------- */
188
+ .g-hero { background: var(--surface-wash); }
189
+ .g-hero__grid { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: var(--space-5); align-items: center; padding-block: var(--space-6); }
190
+ .g-hero__content { display: flex; flex-direction: column; gap: 1.4rem; }
191
+ .g-hero h1 { margin: 0; font-size: var(--text-4xl); font-weight: var(--weight-bold); color: var(--ink-800); }
192
+ .g-hero__lead { margin: 0; font-size: var(--text-md); line-height: var(--leading-normal); color: var(--ink-700); max-width: 34rem; }
193
+ .g-hero__media { border-radius: var(--radius-xl); overflow: hidden; box-shadow: var(--shadow-lg); border: 4px solid var(--surface-card); }
194
+ .g-hero__media img { width: 100%; aspect-ratio: 16/12; object-fit: cover; }
195
+
196
+ /* Interior page hero band */
197
+ .g-pagehero { background: var(--surface-wash); }
198
+ .g-pagehero .g-container { padding-block: var(--space-6) var(--space-5); }
199
+ .g-pagehero h1 { margin: 0.6rem 0 0; color: var(--ink-800); max-width: 50rem; }
200
+ .g-pagehero__lead { margin: 1rem 0 0; font-size: var(--text-md); color: var(--ink-700); max-width: 46rem; line-height: var(--leading-normal); }
201
+
202
+ /* ---------- Stats strip ---------- */
203
+ .g-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); padding-block: var(--space-5); }
204
+ .g-stat { text-align: center; }
205
+ .g-stat__n { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--text-2xl); color: var(--gold-300); }
206
+ .g-stat__l { font-size: var(--text-sm); color: var(--ink-300); margin-top: 0.2rem; }
207
+
208
+ /* ---------- Feature (image + text) ---------- */
209
+ .g-feature { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: var(--space-5); align-items: center; padding-block: var(--section-pad-y); }
210
+ .g-feature__media { border-radius: var(--radius-xl); overflow: hidden; box-shadow: var(--shadow-md); border: 4px solid var(--surface-card); }
211
+ .g-feature__media img { width: 100%; aspect-ratio: 4/3; object-fit: cover; }
212
+ .g-feature__body { display: flex; flex-direction: column; gap: 1rem; }
213
+ .g-meta-line { display: flex; flex-direction: column; gap: 0.4rem; font-size: var(--text-base); color: var(--text-body); }
214
+ .g-meta-line i { color: var(--color-primary); width: 22px; }
215
+
216
+ /* ---------- Event row ---------- */
217
+ .g-event { display: grid; grid-template-columns: 160px 1fr auto; gap: var(--space-4); align-items: stretch; background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-xl); padding: var(--space-4); box-shadow: var(--shadow-sm); }
218
+ .g-event__date { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; background: var(--surface-wash); border-radius: var(--radius-lg); padding: var(--space-3); }
219
+ .g-event__dow { font-family: var(--font-display); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; font-size: var(--text-xs); color: var(--color-primary); }
220
+ .g-event__day { font-size: var(--text-xl); font-weight: var(--weight-bold); color: var(--ink-800); line-height: 1.1; margin-top: 0.2rem; }
221
+ .g-event__time { font-size: var(--text-xs); color: var(--text-muted); margin-top: 0.2rem; }
222
+ .g-event__body { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
223
+ .g-event__body h3 { margin: 0; font-size: var(--text-lg); font-weight: var(--weight-semibold); }
224
+ .g-event__body p { margin: 0; font-size: var(--text-base); color: var(--text-muted); line-height: var(--leading-normal); }
225
+ .g-event__meta { font-size: var(--text-sm); color: var(--text-body); }
226
+ .g-event__meta i { color: var(--color-primary); width: 20px; }
227
+ .g-event__aside { display: flex; flex-direction: column; justify-content: center; align-items: flex-end; gap: 0.5rem; }
228
+
229
+ /* ---------- Get-involved block ---------- */
230
+ .g-involve { display: grid; grid-template-columns: auto 1fr auto; gap: var(--space-5); align-items: center; padding-block: var(--section-pad-y); border-bottom: var(--border-width) solid var(--border-subtle); }
231
+ .g-involve__body { display: flex; flex-direction: column; gap: 0.6rem; max-width: 42rem; }
232
+ .g-involve__cta { display: flex; flex-direction: column; gap: 0.6rem; min-width: 190px; }
233
+
234
+ /* ---------- Docs (handbook / runbooks) ---------- */
235
+ .g-doc { display: grid; grid-template-columns: 260px 1fr; gap: var(--space-5); align-items: start; padding-block: var(--space-5) var(--space-6); }
236
+ .g-doc-toc { position: sticky; top: 92px; display: flex; flex-direction: column; gap: 0.15rem; }
237
+ .g-doc-toc__label { font-family: var(--font-display); font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wider); text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.6rem; }
238
+ .g-doc-toc a { display: block; padding: 0.4rem 0.7rem; border-radius: var(--radius-md); font-size: var(--text-sm); line-height: 1.3; color: var(--text-body); border-left: 3px solid transparent; }
239
+ .g-doc-toc a:hover { color: var(--color-primary); }
240
+ .g-doc-toc a.is-active { color: var(--gold-700); background: var(--gold-50); border-left-color: var(--color-primary); font-weight: var(--weight-semibold); }
241
+ .g-doc__content { min-width: 0; }
242
+ .g-doc__content h2 { margin-top: 2.5rem; }
243
+ .g-doc__content h2, .g-doc__content h3, .g-doc__content h4 { scroll-margin-top: 108px; }
244
+ .g-doc__content h2:first-child { margin-top: 0; }
245
+
246
+ /* ---------- Callout ---------- */
247
+ .g-callout { display: flex; gap: 0.9rem; padding: var(--space-4); border-radius: var(--radius-lg); border: var(--border-width) solid var(--gold-300); background: var(--surface-wash-soft); margin: 1.2rem 0; }
248
+ .g-callout > i { font-size: 1.1rem; margin-top: 0.15rem; color: var(--gold-700); }
249
+ .g-callout__title { font-weight: var(--weight-semibold); color: var(--text-strong); font-size: var(--text-base); margin-bottom: 0.3rem; }
250
+ .g-callout__body { font-size: var(--text-base); line-height: var(--leading-normal); color: var(--text-body); }
251
+ .g-callout__body p:last-child { margin-bottom: 0; }
252
+ .g-callout--tip { background: #e6f3ec; border-color: #a7d7bd; } .g-callout--tip > i { color: #0f6e44; }
253
+ .g-callout--warn { background: #fff7e0; border-color: #f2d488; } .g-callout--warn > i { color: #946a00; }
254
+ /* Tip/warn tints are fixed light colors, so their text stays fixed dark
255
+ even under dark brand palettes (title/body tokens go light there). */
256
+ .g-callout--tip .g-callout__title, .g-callout--warn .g-callout__title { color: #142a36; }
257
+ .g-callout--tip .g-callout__body, .g-callout--warn .g-callout__body { color: #243a47; }
258
+
259
+ /* ---------- Checklist ---------- */
260
+ .g-checklist { background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-sm); margin: 1.2rem 0; }
261
+ .g-checklist__head { display: flex; justify-content: space-between; align-items: center; padding: 0.7rem var(--space-4); background: var(--surface-tertiary); border-bottom: var(--border-width) solid var(--border-subtle); }
262
+ .g-checklist__head span:first-child { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-strong); }
263
+ .g-checklist__count { font-size: var(--text-sm); color: var(--text-muted); font-weight: var(--weight-medium); }
264
+ .g-checklist__count.is-complete { color: #0f6e44; }
265
+ .g-checklist ul { list-style: none; margin: 0; padding: 0; }
266
+ .g-checklist li { border-bottom: var(--border-width) solid var(--border-subtle); }
267
+ .g-checklist li:last-child { border-bottom: none; }
268
+ .g-check { width: 100%; display: flex; gap: 0.8rem; align-items: flex-start; text-align: left; background: none; border: none; padding: 0.8rem var(--space-4); cursor: pointer; font-family: var(--font-sans); }
269
+ .g-check__box { flex: 0 0 auto; width: 22px; height: 22px; margin-top: 0.1rem; border-radius: 6px; border: 2px solid var(--border-default); background: var(--surface-card); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 0.7rem; transition: all var(--duration-fast) var(--ease-out); }
270
+ .g-check__label { font-size: var(--text-base); line-height: var(--leading-normal); color: var(--text-body); }
271
+ .g-check.is-done .g-check__box { border-color: var(--color-primary); background: var(--color-primary); }
272
+ .g-check.is-done .g-check__label { color: var(--text-muted); text-decoration: line-through; }
273
+
274
+ /* ---------- Footer ---------- */
275
+ .g-footer { background: var(--surface-ink); color: var(--ink-200); }
276
+ .g-footer__top { display: flex; flex-wrap: wrap; gap: var(--space-5); padding-block: var(--space-5) var(--space-4); }
277
+ .g-footer__brand { display: flex; flex-direction: column; gap: 1rem; flex: 1 1 240px; max-width: 26rem; }
278
+ .g-footer__brand img { height: 56px; width: 56px; border-radius: var(--radius-md); }
279
+ .g-footer__ack { margin: 0; font-size: var(--text-sm); line-height: var(--leading-normal); color: var(--ink-300); }
280
+ .g-footer__col { flex: 1 0 140px; }
281
+ .g-footer__col-title { font-family: var(--font-display); font-size: var(--text-xs); font-weight: var(--weight-bold); letter-spacing: var(--tracking-wider); text-transform: uppercase; color: var(--white); }
282
+ .g-footer__col ul { list-style: none; margin: 0.7rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
283
+ .g-footer__col a { color: var(--ink-300); font-size: var(--text-sm); }
284
+ .g-footer__col a:hover { color: var(--white); }
285
+ .g-footer__bottom { border-top: var(--border-width) solid rgba(255,255,255,0.1); }
286
+ .g-footer__bottom .g-container { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 0.5rem; padding-block: 1.1rem; font-size: var(--text-xs); color: var(--ink-400); }
287
+ .g-social { display: inline-flex; width: 38px; height: 38px; align-items: center; justify-content: center; border-radius: var(--radius-circle); background: rgba(255,255,255,0.08); color: var(--ink-200); font-size: 1rem; }
288
+ .g-social:hover { background: var(--white); color: #142a36; }
289
+
290
+ /* ---------- Responsive ---------- */
291
+ @media (max-width: 920px) {
292
+ .g-hero__grid, .g-feature, .g-doc, .g-event, .g-involve { grid-template-columns: 1fr; }
293
+ .g-stats { grid-template-columns: repeat(2, 1fr); }
294
+ /* Narrow screens: the sidebar becomes a pill row of sibling doc pages.
295
+ The column labels and per-heading anchors only make sense in a sticky
296
+ sidebar; the headings they point to sit directly below anyway. */
297
+ .g-doc-toc { position: static; flex-direction: row; flex-wrap: wrap; gap: 0.4rem; border-bottom: var(--border-width) solid var(--border-subtle); padding-bottom: 0.8rem; margin-bottom: 1rem; }
298
+ .g-doc-toc__label { display: none; }
299
+ .g-doc-toc a[href^="#"] { display: none; }
300
+ .g-doc-toc a { border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-pill); padding: 0.3rem 0.8rem; }
301
+ .g-doc-toc a.is-active { border-color: var(--color-primary); }
302
+ .g-involve__cta { min-width: 0; }
303
+ .g-event__aside { align-items: flex-start; }
304
+ .g-navlinks { display: none; position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; align-items: stretch; margin: 0; padding: 0.5rem var(--gutter) 1rem; background: var(--surface-page); border-bottom: var(--border-width) solid var(--border-subtle); box-shadow: var(--shadow-md); }
305
+ .g-navlinks.is-open { display: flex; }
306
+ .g-navlinks li.has-sub > .g-navlinks__sub, .g-navlinks li.has-sub:hover > .g-navlinks__sub { display: flex; position: static; min-width: 0; padding: 0 0 0 1rem; background: none; border: none; box-shadow: none; }
307
+ .g-navlinks__caret { display: none; }
308
+ .g-nav__toggle { display: block; }
309
+ .g-nav__cta { display: none; }
310
+ }
@@ -0,0 +1,82 @@
1
+ /* ============================================================
2
+ COLORS: Popular theme
3
+ The default identity is Popular's own: marquee gold, sunglass
4
+ black, and periwinkle (the Pop!ular music-video palette).
5
+ Base palette ramps first, then semantic aliases.
6
+ ============================================================ */
7
+ :root {
8
+ /* --- Marquee gold (primary) --- */
9
+ --gold-50: #fdf7e7; /* champagne, soft tint */
10
+ --gold-100: #f9edc9; /* champagne, hero wash */
11
+ --gold-200: #f3dfa4;
12
+ --gold-300: #d9ba7b;
13
+ --gold-400: #c3963d;
14
+ --gold-500: #a16207; /* theme primary, marquee gold */
15
+ --gold-600: #8a5303;
16
+ --gold-700: #713f12; /* deep gold, links & active states */
17
+ --gold-800: #5c3610;
18
+ --gold-900: #3d2408;
19
+
20
+ /* --- Ink neutrals (theme dark = sunglass black #141417) --- */
21
+ --ink-900: #0a0a0d;
22
+ --ink-800: #141417; /* theme dark, primary text on light */
23
+ --ink-700: #243a47;
24
+ --ink-600: #41535e;
25
+ --ink-500: #61727c;
26
+ --ink-400: #8a98a1;
27
+ --ink-300: #b8c2c9;
28
+ --ink-200: #dce2e6;
29
+ --ink-100: #eef1f3;
30
+ --ink-50: #f8f9fa; /* theme light */
31
+ --white: #ffffff;
32
+
33
+ /* --- Periwinkle accent (a certain music-video blazer) --- */
34
+ --indigo-500: #7d8ff2;
35
+ --indigo-400: #93a2f5;
36
+ --indigo-300: #b3bdf8;
37
+
38
+ /* --- Bootstrap semantic hues carried by the theme --- */
39
+ --green-500: #198754; /* success */
40
+ --cyan-500: #0dcaf0; /* info */
41
+ --amber-500: #ffc107; /* warning */
42
+ --red-500: #dc3545; /* danger */
43
+
44
+ /* ----------------------------------------------------------
45
+ SEMANTIC ALIASES: reference these in components
46
+ ---------------------------------------------------------- */
47
+ --color-primary: var(--gold-500);
48
+ --color-primary-hover: var(--gold-600);
49
+ --color-primary-active: var(--gold-700);
50
+ --color-secondary: var(--ink-800); /* sunglass black */
51
+ --color-accent: var(--indigo-500);
52
+ --color-accent-hover: color-mix(in srgb, var(--indigo-500) 85%, #000);
53
+
54
+ --color-primary-subtle: var(--gold-50); /* tinted fills, 10% vibe */
55
+ --color-accent-subtle: #eef0fd;
56
+
57
+ /* Text */
58
+ --text-strong: var(--ink-800);
59
+ --text-body: var(--ink-700);
60
+ --text-muted: var(--ink-500);
61
+ --text-on-brand: var(--white);
62
+ --text-link: var(--gold-700);
63
+ --text-link-hover: var(--gold-500);
64
+
65
+ /* Surfaces */
66
+ --surface-page: var(--white);
67
+ --surface-wash: var(--gold-100); /* hero / section wash */
68
+ --surface-wash-soft: var(--gold-50);
69
+ --surface-card: var(--white);
70
+ --surface-tertiary: var(--ink-50); /* "body-tertiary" bands */
71
+ --surface-code: var(--ink-100); /* inline code chip */
72
+ --surface-code-block: var(--ink-900); /* fenced code blocks */
73
+ --surface-ink: var(--ink-800); /* footer / dark sections */
74
+
75
+ /* Borders */
76
+ --border-subtle: var(--ink-200);
77
+ --border-default: var(--ink-300);
78
+ --border-strong: var(--ink-800);
79
+
80
+ /* Focus ring */
81
+ --focus-ring: color-mix(in srgb, var(--gold-500) 45%, transparent);
82
+ }
@@ -0,0 +1,27 @@
1
+ /* ============================================================
2
+ ELEVATION & MOTION: Popular theme
3
+ Soft Bootstrap-style shadows. Cards lift on hover ("card-zoom"
4
+ in the theme). Motion is gentle: short ease-out fades + lifts,
5
+ no bounces.
6
+ ============================================================ */
7
+ :root {
8
+ /* Shadows */
9
+ --shadow-xs: 0 1px 2px rgba(20, 42, 54, 0.06);
10
+ --shadow-sm: 0 2px 8px rgba(20, 42, 54, 0.08);
11
+ --shadow-md: 0 6px 20px rgba(20, 42, 54, 0.10);
12
+ --shadow-lg: 0 16px 40px rgba(20, 42, 54, 0.14);
13
+ --shadow-brand: 0 10px 28px rgba(161, 98, 7, 0.25); /* marquee-gold glow */
14
+
15
+ /* Focus ring shadow */
16
+ --shadow-focus: 0 0 0 0.25rem var(--focus-ring);
17
+
18
+ /* Motion */
19
+ --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1); /* @kind other */
20
+ --ease-in-out: cubic-bezier(0.45, 0, 0.55, 1); /* @kind other */
21
+ --duration-fast: 120ms; /* @kind other */
22
+ --duration-base: 200ms; /* @kind other */
23
+ --duration-slow: 320ms; /* @kind other */
24
+
25
+ /* Card hover lift */
26
+ --hover-lift: translateY(-4px); /* @kind other */
27
+ }
@@ -0,0 +1,9 @@
1
+ /* ============================================================
2
+ FONTS: Popular theme
3
+ The live site uses Inter as its single workhorse typeface
4
+ (Hinode/Bootstrap theme). Quantico is an OPTIONAL geometric
5
+ display accent that echoes the squared "VANCOUVER" lettering
6
+ in the logo wordmark: use sparingly for hero/section accents.
7
+ Swap or extend these via the brand config or your own fonts.css.
8
+ ============================================================ */
9
+ @import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,200..800;1,14..32,400..600&family=Quantico:ital,wght@0,400;0,700;1,400;1,700&display=swap");
@@ -0,0 +1,39 @@
1
+ /* ============================================================
2
+ SPACING & RADIUS: Popular theme
3
+ Bootstrap-rooted 0.25rem spacer scale (the theme is Bootstrap 5),
4
+ plus radii echoing the theme's rounded cards & pill buttons.
5
+ ============================================================ */
6
+ :root {
7
+ /* Spacing: Bootstrap spacer scale (4px base) */
8
+ --space-0: 0;
9
+ --space-1: 0.25rem; /* 4 */
10
+ --space-2: 0.5rem; /* 8 */
11
+ --space-3: 1rem; /* 16 */
12
+ --space-4: 1.5rem; /* 24 */
13
+ --space-5: 3rem; /* 48 */
14
+ --space-6: 4.5rem; /* 72 */
15
+ --space-7: 6rem; /* 96 */
16
+
17
+ /* Section rhythm */
18
+ --section-pad-y: 4.5rem;
19
+ --container-max: 1140px; /* Bootstrap xl container */
20
+ --gutter: 1.5rem;
21
+
22
+ /* Radius: theme uses Bootstrap defaults + pills */
23
+ --radius-sm: 0.25rem;
24
+ --radius-md: 0.375rem; /* Bootstrap default */
25
+ --radius-lg: 0.5rem;
26
+ --radius-xl: 1rem; /* image / hero corners */
27
+ --radius-pill: 50rem; /* buttons, badges */
28
+ --radius-circle: 50%;
29
+
30
+ /* Control sizing */
31
+ --control-height-sm: 2rem;
32
+ --control-height-md: 2.625rem;
33
+ --control-height-lg: 3.25rem;
34
+ --tap-target-min: 44px;
35
+
36
+ /* Border widths */
37
+ --border-width: 1px;
38
+ --border-width-thick: 2px;
39
+ }
@@ -0,0 +1,43 @@
1
+ /* ============================================================
2
+ TYPOGRAPHY: Popular theme
3
+ Inter is the workhorse for everything (matches live theme).
4
+ Quantico is an optional squared display accent echoing the
5
+ "VANCOUVER" wordmark: uppercase, tracked-out, used sparingly.
6
+ ============================================================ */
7
+ :root {
8
+ /* Families */
9
+ --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
10
+ --font-display: "Quantico", "Inter", system-ui, sans-serif; /* squared accent */
11
+ --font-mono: ui-monospace, "SFMono-Regular", "Consolas", "Liberation Mono", monospace;
12
+
13
+ /* Weights */
14
+ --weight-extralight: 200;
15
+ --weight-light: 300;
16
+ --weight-regular: 400;
17
+ --weight-medium: 500;
18
+ --weight-semibold: 600;
19
+ --weight-bold: 700;
20
+
21
+ /* Type scale (1.250 major-third-ish, tuned for web) */
22
+ --text-xs: 0.75rem; /* 12px: captions, eyebrow */
23
+ --text-sm: 0.875rem; /* 14px: meta, labels */
24
+ --text-base: 1rem; /* 16px: body */
25
+ --text-md: 1.125rem; /* 18px: lead body */
26
+ --text-lg: 1.375rem; /* 22px: card titles */
27
+ --text-xl: 1.75rem; /* 28px: h3 */
28
+ --text-2xl: 2.25rem; /* 36px: h2 */
29
+ --text-3xl: 3rem; /* 48px: h1 */
30
+ --text-4xl: 4rem; /* 64px: hero display */
31
+
32
+ /* Line heights */
33
+ --leading-tight: 1.15;
34
+ --leading-snug: 1.3;
35
+ --leading-normal: 1.6;
36
+ --leading-relaxed: 1.75;
37
+
38
+ /* Letter spacing */
39
+ --tracking-tight: -0.02em;
40
+ --tracking-normal: 0;
41
+ --tracking-wide: 0.04em;
42
+ --tracking-wider: 0.12em; /* Quantico eyebrows / VANCOUVER vibe */
43
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "jsx": "preserve"
5
+ }
6
+ }