@port60/template-kit 0.20.3 → 0.21.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.
- package/package.json +1 -1
- package/src/lib/agentsMd.mjs +17 -0
- package/src/vendor/contract/v1/context.json +2 -2
- package/src/vendor/contract/v1/fonts.json +4 -2
- package/src/vendor/contract/v1/manifest.schema.json +33 -0
- package/src/vendor/contract/v1.lock.json +252 -0
- package/src/vendor/engine/budgets.mjs +1 -1
- package/src/vendor/engine/content-footprint.mjs +9 -9
- package/src/vendor/engine/dialect.mjs +4 -4
- package/src/vendor/validator/behaviors-runtime.js +1 -1
- package/src/vendor/validator/fixture-art.mjs +5 -5
- package/src/vendor/validator/fonts.mjs +13 -3
- package/src/vendor/validator/navigation-highlights.mjs +149 -0
- package/src/vendor/validator/platform-base.css +168 -88
- package/src/vendor/validator/preview.mjs +18 -18
- package/src/vendor/validator/site-context.mjs +18 -6
- package/src/vendor/validator/validate.mjs +125 -44
- package/starter/manifest.json +42 -2
- package/starter/sections/campaigns.liquid +2 -2
- package/starter/sections/cta.liquid +2 -2
- package/starter/sections/hero.liquid +9 -2
- package/starter/sections/homeHero.liquid +9 -9
- package/starter/sections/people.liquid +7 -6
- package/starter/sections/values.liquid +3 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
/* GENERATED by scripts/build-preview-base.mjs from src/styles/global.css
|
|
1
|
+
/* GENERATED by scripts/build-preview-base.mjs from src/styles/global.css, do not edit. */
|
|
2
2
|
/* ---- PLATFORM BASE (the base/skin split, 2026-07-14) ----
|
|
3
3
|
This stylesheet is the platform's base layer: reset, CSS-variable DECLARATIONS (the theming
|
|
4
|
-
contract
|
|
4
|
+
contract, values here are the platform defaults a template overrides via :root:root), chrome
|
|
5
5
|
mechanics (header/nav/burger/footer/auth), and ALL functional-island styling (donation widget,
|
|
6
6
|
donate page, events/tickets, services, articles, members area, consent, address lookup). A
|
|
7
|
-
template's LOOK does not live here
|
|
7
|
+
template's LOOK does not live here, Classic's is src/templates/default/theme.ts, and every
|
|
8
8
|
template ships a themeCss injected at body-end. Fonts load from the layout <head> (preconnect +
|
|
9
|
-
stylesheet link) instead of a CSS @import
|
|
9
|
+
stylesheet link) instead of a CSS @import, an @import chains render-blocking requests. */
|
|
10
10
|
|
|
11
11
|
:root {
|
|
12
12
|
--bg: #fbf6ef;
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
/* Impact map. --marker = the map pin colour (a deliberate brand accent by default; the live-map
|
|
24
24
|
markers are a zoom-scaling MapLibre circle layer that takes this colour). --map-mode = the
|
|
25
25
|
basemap colour mode read by the map island: `auto` derives the map's paper/ink from the theme
|
|
26
|
-
neutrals below, `light`/`dark`/`muted` force a base. Template-owned
|
|
26
|
+
neutrals below, `light`/`dark`/`muted` force a base. Template-owned, set in theme.css or exposed
|
|
27
27
|
as Appearance knobs; the tenant never edits map colour directly. */
|
|
28
28
|
--marker: var(--accent);
|
|
29
29
|
--map-mode: auto;
|
|
30
|
-
/* flat (default) or globe
|
|
30
|
+
/* flat (default) or globe, MapLibre's own globe projection, a rotatable sphere. */
|
|
31
31
|
--map-projection: flat;
|
|
32
32
|
--line: rgba(31, 42, 51, 0.1);
|
|
33
33
|
--line-strong: rgba(18, 135, 122, 0.28);
|
|
34
34
|
--danger: #c0392b;
|
|
35
|
-
/* Donate/primary CTA hover
|
|
35
|
+
/* Donate/primary CTA hover, a clear GREEN "go" cue, shared by every template (a template may
|
|
36
36
|
override the token, but by default hovering a donate button turns green, not just lighter). */
|
|
37
37
|
--cta-hover: #16a34a;
|
|
38
38
|
--cta-hover-strong: #128a3f;
|
|
@@ -51,10 +51,37 @@ html {
|
|
|
51
51
|
scroll-behavior: smooth;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/* Arabic-script text (Arabic, Persian, Urdu…) rendered by
|
|
55
|
-
unicode-range scopes
|
|
56
|
-
downloaded only when an Arabic glyph appears.
|
|
57
|
-
|
|
54
|
+
/* Arabic-script text (Arabic, Persian, Urdu…) rendered by the platform's own webfonts, sized to
|
|
55
|
+
match Latin. unicode-range scopes them to Arabic codepoints only, Latin keeps the template's
|
|
56
|
+
faces, and a file is downloaded only when an Arabic glyph appears.
|
|
57
|
+
The platform Arabic face is KFGQPC HAFS Uthmanic Script (King Fahd Glorious Quran Printing
|
|
58
|
+
Complex, self-hosted under public/fonts/, licence beside it, never modified). It ships one weight,
|
|
59
|
+
so IBM Plex Sans Arabic stays declared behind it for bold and for any glyph HAFS lacks.
|
|
60
|
+
Template font slots name both faces first too (engine/fonts.ts ARABIC_FACES), so a template's own
|
|
61
|
+
body font never drops them; a tenant who picks an Arabic family for a slot keeps their choice.
|
|
62
|
+
To swap the platform face: replace the file and src here, and the name in fonts.ts. */
|
|
63
|
+
@font-face {
|
|
64
|
+
font-family: 'KFGQPC HAFS Uthmanic Script';
|
|
65
|
+
font-style: normal;
|
|
66
|
+
font-weight: 400;
|
|
67
|
+
font-display: swap;
|
|
68
|
+
size-adjust: 130%;
|
|
69
|
+
src: url('/fonts/kfgqpc-hafs-uthmanic-script/UthmanicHafs_V22.woff2') format('woff2');
|
|
70
|
+
unicode-range: U+0600-06FF, U+0750-077F, U+0870-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D;
|
|
71
|
+
}
|
|
72
|
+
/* A platform-hosted CATALOGUE family: not on the default Arabic stack, loaded only when a tenant
|
|
73
|
+
picks it for a font slot. A Quranic Nastaliq face (the Indo-Pak mushaf style): Arabic and Quran
|
|
74
|
+
text render, but Urdu prose letters come out as dotted circles in Chrome, so it is not an Urdu
|
|
75
|
+
body font. size-adjust 130%: 120% sat level with the Latin x-height, the owner reads Arabic more easily a step larger. */
|
|
76
|
+
@font-face {
|
|
77
|
+
font-family: 'KFGQPC Nastaleeq';
|
|
78
|
+
font-style: normal;
|
|
79
|
+
font-weight: 400;
|
|
80
|
+
font-display: swap;
|
|
81
|
+
size-adjust: 130%;
|
|
82
|
+
src: url('/fonts/kfgqpc-nastaleeq/KFGQPCNastaleeq-Regular.woff2') format('woff2');
|
|
83
|
+
unicode-range: U+0600-06FF, U+0750-077F, U+0870-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D;
|
|
84
|
+
}
|
|
58
85
|
@font-face {
|
|
59
86
|
font-family: 'IBM Plex Sans Arabic';
|
|
60
87
|
font-style: normal;
|
|
@@ -77,7 +104,7 @@ html {
|
|
|
77
104
|
body {
|
|
78
105
|
margin: 0;
|
|
79
106
|
min-width: 320px;
|
|
80
|
-
font-family: 'IBM Plex Sans Arabic', 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
107
|
+
font-family: 'KFGQPC HAFS Uthmanic Script', 'IBM Plex Sans Arabic', 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
81
108
|
color: var(--ink);
|
|
82
109
|
background: var(--bg); /* decoration (Classic's radial washes) is the template theme's job */
|
|
83
110
|
}
|
|
@@ -92,8 +119,8 @@ img {
|
|
|
92
119
|
display: block;
|
|
93
120
|
}
|
|
94
121
|
|
|
95
|
-
/* Typography (heading scale/family, paragraph rhythm) is TEMPLATE territory
|
|
96
|
-
templates/default/theme.ts for Classic's. The base deliberately styles no bare h1
|
|
122
|
+
/* Typography (heading scale/family, paragraph rhythm) is TEMPLATE territory, see
|
|
123
|
+
templates/default/theme.ts for Classic's. The base deliberately styles no bare h1-h4/p. */
|
|
97
124
|
|
|
98
125
|
input, button, textarea, select {
|
|
99
126
|
font: inherit;
|
|
@@ -123,7 +150,7 @@ input:focus {
|
|
|
123
150
|
|
|
124
151
|
/* THE CONTENT SEAM. `.container` (contained) and `.full` (edge-to-edge) are the layout intents every
|
|
125
152
|
platform page renders through, and the contract a template fills to place content its way: a template
|
|
126
|
-
STYLES these
|
|
153
|
+
STYLES these, and overrides `--container` for width, to match its own sections. A template must
|
|
127
154
|
NEVER build a parallel content container (a class sized off `--container`); platform pages stay on
|
|
128
155
|
`.container`, so a second container makes them drift from the template's sections. The publish-time
|
|
129
156
|
validator enforces this. A template that leaves the seam alone inherits these platform defaults. */
|
|
@@ -132,7 +159,7 @@ input:focus {
|
|
|
132
159
|
margin: 0 auto;
|
|
133
160
|
}
|
|
134
161
|
|
|
135
|
-
/* Full-bleed intent
|
|
162
|
+
/* Full-bleed intent, edge-to-edge regardless of the container it sits in (a hero image, a colour
|
|
136
163
|
band). Templates restyle it freely; the default breaks out to the viewport width. */
|
|
137
164
|
.full {
|
|
138
165
|
width: 100vw;
|
|
@@ -212,7 +239,7 @@ input:focus {
|
|
|
212
239
|
display: flex;
|
|
213
240
|
align-items: center;
|
|
214
241
|
gap: 0.35rem;
|
|
215
|
-
flex-wrap: nowrap; /* never let items drop to a second line
|
|
242
|
+
flex-wrap: nowrap; /* never let items drop to a second line, compact (below) then burger */
|
|
216
243
|
}
|
|
217
244
|
|
|
218
245
|
.site-nav a {
|
|
@@ -233,7 +260,7 @@ input:focus {
|
|
|
233
260
|
box-shadow: 0 10px 22px rgba(239, 96, 68, 0.26);
|
|
234
261
|
}
|
|
235
262
|
|
|
236
|
-
/* Donate, the Port60 ID sign-in, and the account pill share one exact size
|
|
263
|
+
/* Donate, the Port60 ID sign-in, and the account pill share one exact size, they sit side by
|
|
237
264
|
side, so any height/padding drift between them reads as misalignment. The sign-in/account pair
|
|
238
265
|
is UNSCOPED: they are the member_menu ISLAND's chrome, which must look right inside ANY
|
|
239
266
|
template's nav (artifact layouts don't use .site-nav). */
|
|
@@ -256,7 +283,7 @@ input:focus {
|
|
|
256
283
|
box-shadow: 0 10px 22px rgba(22, 163, 74, 0.3);
|
|
257
284
|
}
|
|
258
285
|
|
|
259
|
-
/* Services dropdown
|
|
286
|
+
/* Services dropdown, populated client-side from the published services. */
|
|
260
287
|
.site-nav .nav-dropdown {
|
|
261
288
|
position: relative;
|
|
262
289
|
display: inline-flex;
|
|
@@ -297,9 +324,9 @@ input:focus {
|
|
|
297
324
|
background: var(--bg-tint);
|
|
298
325
|
}
|
|
299
326
|
|
|
300
|
-
/* The port60 ID sign-in button
|
|
327
|
+
/* The port60 ID sign-in button, the PLATFORM identity brand, deliberately constant across every
|
|
301
328
|
tenant site and template (the "Sign in with Google" pattern): port60 navy + cyan, independent
|
|
302
|
-
of the site palette. The hosted widget it opens offers both sign-in and register. Unscoped
|
|
329
|
+
of the site palette. The hosted widget it opens offers both sign-in and register. Unscoped ,
|
|
303
330
|
island chrome, identical in any template's nav. */
|
|
304
331
|
.nav-p60-signin.nav-p60-signin {
|
|
305
332
|
display: inline-flex;
|
|
@@ -355,9 +382,9 @@ input:focus {
|
|
|
355
382
|
height: 1.25rem;
|
|
356
383
|
}
|
|
357
384
|
|
|
358
|
-
/* Members account pill (signed in)
|
|
385
|
+
/* Members account pill (signed in), a clear "this is your account" affordance, weighted between
|
|
359
386
|
plain nav links and the Donate CTA. The menu anchors right (it's the last nav item).
|
|
360
|
-
`.open` mirrors hover/focus for touch. Unscoped
|
|
387
|
+
`.open` mirrors hover/focus for touch. Unscoped, island chrome, identical in any template's
|
|
361
388
|
nav: the wrapper carries its own positioning anchor and menu-link styling so the dropdown works
|
|
362
389
|
without .site-nav around it. */
|
|
363
390
|
.nav-account {
|
|
@@ -405,7 +432,7 @@ input:focus {
|
|
|
405
432
|
display: flex;
|
|
406
433
|
}
|
|
407
434
|
/* Artifact-template mobile panels (the layout behaviour API: #site-nav gains .open): the account
|
|
408
|
-
menu flows INLINE like any expanded nav group
|
|
435
|
+
menu flows INLINE like any expanded nav group, never a floating card half off the screen.
|
|
409
436
|
Keyed on the .open state the burger sets, so desktop hover/dropdowns are untouched. */
|
|
410
437
|
#site-nav.open .nav-account {
|
|
411
438
|
display: block;
|
|
@@ -463,7 +490,7 @@ input:focus {
|
|
|
463
490
|
background: var(--bg-tint);
|
|
464
491
|
}
|
|
465
492
|
|
|
466
|
-
/* Optional tenant footer mark (branding.footerLogoUrl)
|
|
493
|
+
/* Optional tenant footer mark (branding.footerLogoUrl), height-constrained like the header logo. */
|
|
467
494
|
.footer-logo { display: block; height: 46px; width: auto; max-width: 220px; object-fit: contain; margin-bottom: 0.9rem; }
|
|
468
495
|
|
|
469
496
|
.site-footer {
|
|
@@ -501,7 +528,7 @@ input:focus {
|
|
|
501
528
|
color: rgba(93, 107, 120, 0.8);
|
|
502
529
|
}
|
|
503
530
|
|
|
504
|
-
/* Footer socials
|
|
531
|
+
/* Footer socials, tenant's social links, rendered by the template (ours: here). Variable-driven so
|
|
505
532
|
each theme tints them. */
|
|
506
533
|
.footer-socials {
|
|
507
534
|
display: flex;
|
|
@@ -529,10 +556,10 @@ input:focus {
|
|
|
529
556
|
height: 1.15rem;
|
|
530
557
|
}
|
|
531
558
|
|
|
532
|
-
/* ---------- shared bits (.eyebrow/.card/.section-heading are template-owned
|
|
559
|
+
/* ---------- shared bits (.eyebrow/.card/.section-heading are template-owned, Classic's live in
|
|
533
560
|
templates/default/theme.ts; .button stays here because the islands depend on it) ---------- */
|
|
534
561
|
|
|
535
|
-
/* A kicker may BE a link (the archive's section kicker doubles as the way back)
|
|
562
|
+
/* A kicker may BE a link (the archive's section kicker doubles as the way back), it keeps the
|
|
536
563
|
kicker type treatment whatever the template; hover reveals the affordance. */
|
|
537
564
|
a.eyebrow {
|
|
538
565
|
text-decoration: none;
|
|
@@ -587,15 +614,41 @@ a.eyebrow:hover {
|
|
|
587
614
|
border-color: var(--line);
|
|
588
615
|
}
|
|
589
616
|
|
|
590
|
-
/* ---------- Forms (schema-driven form renderer
|
|
617
|
+
/* ---------- Forms (schema-driven form renderer, components/FormRenderer + DateField) ----------
|
|
591
618
|
Themed entirely from the site tokens so a form looks native on any template. The one thing the base
|
|
592
619
|
input{} rule gets wrong for us is the checkbox (it forces width:100%, stretching the box across the
|
|
593
|
-
row)
|
|
620
|
+
row), pinned below, which is what fixes the check-box alignment. */
|
|
594
621
|
|
|
595
622
|
.p60-form {
|
|
596
623
|
max-width: 640px;
|
|
597
624
|
}
|
|
598
625
|
|
|
626
|
+
.campaign-form {
|
|
627
|
+
margin-block: 2rem;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/* An embedded form belongs to the campaign, not a second page inside it. */
|
|
631
|
+
.p60-form--embedded {
|
|
632
|
+
padding: clamp(1rem, 3vw, 2rem);
|
|
633
|
+
border: 1px solid var(--line);
|
|
634
|
+
border-radius: var(--radius-sm, 12px);
|
|
635
|
+
background: var(--surface);
|
|
636
|
+
color: var(--ink);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
.p60-form--embedded .p60-form-control {
|
|
640
|
+
background: var(--bg);
|
|
641
|
+
border-color: color-mix(in srgb, var(--ink) 35%, var(--surface));
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
.p60-form--embedded .p60-form-control:focus {
|
|
645
|
+
border-color: var(--primary);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.p60-form--embedded > :last-child {
|
|
649
|
+
margin-block-end: 0;
|
|
650
|
+
}
|
|
651
|
+
|
|
599
652
|
.p60-form-intro {
|
|
600
653
|
color: var(--muted);
|
|
601
654
|
margin: 0 0 1.5rem;
|
|
@@ -609,6 +662,18 @@ a.eyebrow:hover {
|
|
|
609
662
|
margin-bottom: 1.15rem;
|
|
610
663
|
}
|
|
611
664
|
|
|
665
|
+
.p60-form-respondent {
|
|
666
|
+
min-inline-size: 0;
|
|
667
|
+
border: 0;
|
|
668
|
+
padding: 0 0 0.5rem;
|
|
669
|
+
margin: 0 0 1.5rem;
|
|
670
|
+
border-block-end: 1px solid var(--line);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.p60-form-respondent > legend {
|
|
674
|
+
margin-block-end: 1rem;
|
|
675
|
+
}
|
|
676
|
+
|
|
612
677
|
.p60-form-label {
|
|
613
678
|
display: block;
|
|
614
679
|
font-weight: 600;
|
|
@@ -676,7 +741,7 @@ textarea.p60-form-control {
|
|
|
676
741
|
font-size: 0.9rem;
|
|
677
742
|
}
|
|
678
743
|
|
|
679
|
-
/* Checkbox rows
|
|
744
|
+
/* Checkbox rows, pin the box small and top-align it with the first line of the label text. */
|
|
680
745
|
.p60-form-check {
|
|
681
746
|
display: flex;
|
|
682
747
|
align-items: flex-start;
|
|
@@ -690,11 +755,18 @@ textarea.p60-form-control {
|
|
|
690
755
|
width: 1.05rem;
|
|
691
756
|
height: 1.05rem;
|
|
692
757
|
flex: 0 0 auto;
|
|
693
|
-
margin: 0.
|
|
694
|
-
|
|
758
|
+
margin: 0.25rem 0 0;
|
|
759
|
+
padding: 0;
|
|
760
|
+
accent-color: var(--accent, var(--primary));
|
|
695
761
|
cursor: pointer;
|
|
696
762
|
}
|
|
697
763
|
|
|
764
|
+
.p60-form-check input:is([type='checkbox'], [type='radio']):focus-visible {
|
|
765
|
+
outline: 2px solid var(--ink);
|
|
766
|
+
outline-offset: 3px;
|
|
767
|
+
box-shadow: none;
|
|
768
|
+
}
|
|
769
|
+
|
|
698
770
|
.p60-form-check.has-error span {
|
|
699
771
|
color: var(--danger);
|
|
700
772
|
}
|
|
@@ -704,7 +776,7 @@ textarea.p60-form-control {
|
|
|
704
776
|
font-style: italic;
|
|
705
777
|
}
|
|
706
778
|
|
|
707
|
-
/* MULTISELECT checkbox list / CHOICE radio list
|
|
779
|
+
/* MULTISELECT checkbox list / CHOICE radio list, vertical lists reusing the aligned check-row. */
|
|
708
780
|
.p60-form-checklist,
|
|
709
781
|
.p60-form-radios {
|
|
710
782
|
display: flex;
|
|
@@ -718,7 +790,7 @@ textarea.p60-form-control {
|
|
|
718
790
|
margin-bottom: 0;
|
|
719
791
|
}
|
|
720
792
|
|
|
721
|
-
/* Searchable multi-select dropdown (MultiSelectDropdown)
|
|
793
|
+
/* Searchable multi-select dropdown (MultiSelectDropdown), the "pick many from a long list" widget. */
|
|
722
794
|
.p60-ms {
|
|
723
795
|
position: relative;
|
|
724
796
|
}
|
|
@@ -840,7 +912,7 @@ textarea.p60-form-control {
|
|
|
840
912
|
font-size: 0.9rem;
|
|
841
913
|
}
|
|
842
914
|
|
|
843
|
-
/* ---- Custom desktop date picker (DateField)
|
|
915
|
+
/* ---- Custom desktop date picker (DateField), native <input type=date> is used on touch ---- */
|
|
844
916
|
.p60-date {
|
|
845
917
|
position: relative;
|
|
846
918
|
}
|
|
@@ -971,7 +1043,7 @@ textarea.p60-form-control {
|
|
|
971
1043
|
background: transparent;
|
|
972
1044
|
}
|
|
973
1045
|
|
|
974
|
-
/* (hero / impact / band
|
|
1046
|
+
/* (hero / impact / band, the home page's Classic presentation, live in templates/default/theme.ts) */
|
|
975
1047
|
|
|
976
1048
|
/* ---------- donation widget ---------- */
|
|
977
1049
|
|
|
@@ -985,7 +1057,7 @@ textarea.p60-form-control {
|
|
|
985
1057
|
gap: 1rem;
|
|
986
1058
|
}
|
|
987
1059
|
|
|
988
|
-
/* MOBILE BREAKOUT (owner, 2026-08-17): on phones the nesting stack squashes the card badly
|
|
1060
|
+
/* MOBILE BREAKOUT (owner, 2026-08-17): on phones the nesting stack squashes the card badly ,
|
|
989
1061
|
measured on Sanctuary: 390px viewport → 346 container → 294 aside → 249px card → ~195px of
|
|
990
1062
|
actual controls. A donate form is a working control surface; it gets the full screen width
|
|
991
1063
|
(edge to edge, side borders/radius dropped, its own padding kept). The negative-margin trick
|
|
@@ -1202,7 +1274,7 @@ textarea.p60-form-control {
|
|
|
1202
1274
|
color: var(--primary-strong);
|
|
1203
1275
|
}
|
|
1204
1276
|
|
|
1205
|
-
/* Named suggested amounts
|
|
1277
|
+
/* Named suggested amounts, a vertical list with the amount + its label (e.g. "Feeds a family"). */
|
|
1206
1278
|
.amount-list {
|
|
1207
1279
|
display: grid;
|
|
1208
1280
|
gap: 0.6rem;
|
|
@@ -1275,6 +1347,12 @@ textarea.p60-form-control {
|
|
|
1275
1347
|
padding-left: 1.8rem;
|
|
1276
1348
|
}
|
|
1277
1349
|
|
|
1350
|
+
.cover-costs-row {
|
|
1351
|
+
display: flex;
|
|
1352
|
+
gap: 0.5rem;
|
|
1353
|
+
align-items: flex-start;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1278
1356
|
.donor-fields {
|
|
1279
1357
|
display: grid;
|
|
1280
1358
|
grid-template-columns: 1fr 1fr;
|
|
@@ -1427,7 +1505,7 @@ textarea.p60-form-control {
|
|
|
1427
1505
|
margin-top: 0.4rem;
|
|
1428
1506
|
}
|
|
1429
1507
|
|
|
1430
|
-
/* (about-page .prose/.value-grid
|
|
1508
|
+
/* (about-page .prose/.value-grid, Classic's section presentation, live in templates/default/theme.ts) */
|
|
1431
1509
|
|
|
1432
1510
|
/* ---------- responsive ---------- */
|
|
1433
1511
|
|
|
@@ -1615,11 +1693,11 @@ textarea.p60-form-control {
|
|
|
1615
1693
|
/* --- Articles (public) --- */
|
|
1616
1694
|
/* The blog is long-form READING (unlike the full-width marketing Services pages): the article body
|
|
1617
1695
|
sits in a ~70ch measure with article chrome (byline, reading time), and the theme owns all
|
|
1618
|
-
typography
|
|
1696
|
+
typography, content only carries semantic structure (mark, pull quotes, captions, tables,
|
|
1619
1697
|
embeds), styled here. */
|
|
1620
1698
|
.article-article {
|
|
1621
1699
|
/* The page FRAME matches every other page's container (hero image, engagement bar span it);
|
|
1622
|
-
the running text keeps its own readable measure via .article-body/.article-article-head
|
|
1700
|
+
the running text keeps its own readable measure via .article-body/.article-article-head ,
|
|
1623
1701
|
so navigating article ↔ other pages no longer visibly narrows the page. */
|
|
1624
1702
|
max-width: var(--container);
|
|
1625
1703
|
margin: 0 auto;
|
|
@@ -1673,7 +1751,7 @@ textarea.p60-form-control {
|
|
|
1673
1751
|
}
|
|
1674
1752
|
|
|
1675
1753
|
.article-body {
|
|
1676
|
-
/* Fills the container
|
|
1754
|
+
/* Fills the container, same call as .service-body ("widened by preference"): the page reads as
|
|
1677
1755
|
one full-width surface; line-height carries the readability. */
|
|
1678
1756
|
margin: 0;
|
|
1679
1757
|
color: var(--ink);
|
|
@@ -1728,7 +1806,7 @@ textarea.p60-form-control {
|
|
|
1728
1806
|
.article-body img.size-full {
|
|
1729
1807
|
max-width: 100%;
|
|
1730
1808
|
}
|
|
1731
|
-
/* The semantic highlight
|
|
1809
|
+
/* The semantic highlight, theme-tinted, never an author-picked colour. */
|
|
1732
1810
|
.article-body mark {
|
|
1733
1811
|
background: color-mix(in srgb, var(--gold) 38%, transparent);
|
|
1734
1812
|
color: inherit;
|
|
@@ -1741,7 +1819,7 @@ textarea.p60-form-control {
|
|
|
1741
1819
|
padding: 0.25rem 1rem;
|
|
1742
1820
|
color: var(--muted);
|
|
1743
1821
|
}
|
|
1744
|
-
/* The pull quote
|
|
1822
|
+
/* The pull quote, a stand-out breath in the reading flow. */
|
|
1745
1823
|
.article-body blockquote.pull {
|
|
1746
1824
|
border-inline-start: none;
|
|
1747
1825
|
border-top: 2px solid var(--line-strong);
|
|
@@ -1834,7 +1912,7 @@ textarea.p60-form-control {
|
|
|
1834
1912
|
margin: 1.5rem 0 0;
|
|
1835
1913
|
}
|
|
1836
1914
|
|
|
1837
|
-
/* Engagement bar under the article. Wraps
|
|
1915
|
+
/* Engagement bar under the article. Wraps, never scrolls sideways. */
|
|
1838
1916
|
.article-engage {
|
|
1839
1917
|
margin: 1.5rem 0;
|
|
1840
1918
|
display: flex;
|
|
@@ -1870,7 +1948,7 @@ textarea.p60-form-control {
|
|
|
1870
1948
|
font-size: 0.95rem;
|
|
1871
1949
|
}
|
|
1872
1950
|
|
|
1873
|
-
/* The share row
|
|
1951
|
+
/* The share row, plain share-intent buttons (no network SDKs). Wraps with the bar. */
|
|
1874
1952
|
.article-share-group {
|
|
1875
1953
|
display: flex;
|
|
1876
1954
|
align-items: center;
|
|
@@ -1900,7 +1978,7 @@ textarea.p60-form-control {
|
|
|
1900
1978
|
border-color: var(--accent);
|
|
1901
1979
|
color: var(--accent-strong);
|
|
1902
1980
|
}
|
|
1903
|
-
/* Brand tints on hover
|
|
1981
|
+
/* Brand tints on hover, recognisable without shouting at rest (and dark-theme safe: the
|
|
1904
1982
|
at-rest button is theme ink on theme surface). */
|
|
1905
1983
|
.article-share-btn--facebook:hover { color: #1877f2; border-color: #1877f2; }
|
|
1906
1984
|
.article-share-btn--x:hover { color: var(--ink); border-color: var(--ink); }
|
|
@@ -2014,7 +2092,7 @@ textarea.p60-form-control {
|
|
|
2014
2092
|
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
2015
2093
|
gap: 1.5rem;
|
|
2016
2094
|
}
|
|
2017
|
-
/* MOBILE: the stacked grid becomes an edge-to-edge SWIPE ROW with a peek (owner, 2026-08-17)
|
|
2095
|
+
/* MOBILE: the stacked grid becomes an edge-to-edge SWIPE ROW with a peek (owner, 2026-08-17) ,
|
|
2018
2096
|
the scroller bleeds to the screen edges, each card keeps its padding, the first card aligns to
|
|
2019
2097
|
the text gutter, and the cut-off next card IS the "swipe me" affordance (the reference maps'
|
|
2020
2098
|
card idiom). Snap keeps cards settling cleanly; the scrollbar is hidden, the peek replaces it. */
|
|
@@ -2095,7 +2173,7 @@ textarea.p60-form-control {
|
|
|
2095
2173
|
.article-card-counts {
|
|
2096
2174
|
margin-inline-start: 0.6rem;
|
|
2097
2175
|
}
|
|
2098
|
-
/* The featured (newest) card: a magazine lead
|
|
2176
|
+
/* The featured (newest) card: a magazine lead, image beside copy on wide screens. */
|
|
2099
2177
|
.article-card--featured {
|
|
2100
2178
|
display: grid;
|
|
2101
2179
|
grid-template-columns: 1.2fr 1fr;
|
|
@@ -2132,7 +2210,7 @@ textarea.p60-form-control {
|
|
|
2132
2210
|
color: var(--muted);
|
|
2133
2211
|
}
|
|
2134
2212
|
.article-more {
|
|
2135
|
-
/* Spans the page frame like the hero + back-link (the reading column stays 70ch)
|
|
2213
|
+
/* Spans the page frame like the hero + back-link (the reading column stays 70ch), one frame
|
|
2136
2214
|
edge + one reading edge, nothing floating at a third width. Grid auto-fills the row. */
|
|
2137
2215
|
max-width: var(--container);
|
|
2138
2216
|
margin: 2.5rem auto 0;
|
|
@@ -2178,7 +2256,7 @@ textarea.p60-form-control {
|
|
|
2178
2256
|
.event-card-image-placeholder {
|
|
2179
2257
|
display: grid;
|
|
2180
2258
|
place-items: center;
|
|
2181
|
-
/* Same fallback-tint convention as course cards
|
|
2259
|
+
/* Same fallback-tint convention as course cards, see .course-card-tint. */
|
|
2182
2260
|
background: var(--media-tint, hsl(210 34% 33%));
|
|
2183
2261
|
}
|
|
2184
2262
|
.event-card-image-placeholder span {
|
|
@@ -2212,7 +2290,7 @@ textarea.p60-form-control {
|
|
|
2212
2290
|
align-self: start;
|
|
2213
2291
|
}
|
|
2214
2292
|
|
|
2215
|
-
/* .event-detail carries NO max-width
|
|
2293
|
+
/* .event-detail carries NO max-width, page bodies fill var(--container) (the standing
|
|
2216
2294
|
full-width rule; the 760px reading measure was removed 2026-07-24, as on courses). */
|
|
2217
2295
|
.event-detail-image {
|
|
2218
2296
|
width: 100%;
|
|
@@ -2427,7 +2505,7 @@ textarea.p60-form-control {
|
|
|
2427
2505
|
align-items: center;
|
|
2428
2506
|
gap: 0.5rem;
|
|
2429
2507
|
}
|
|
2430
|
-
/* MOBILE: the rotator is MEDIA
|
|
2508
|
+
/* MOBILE: the rotator is MEDIA, it bleeds edge to edge like the hero and the map, with the
|
|
2431
2509
|
arrows overlaid on the image instead of eating width beside it. */
|
|
2432
2510
|
@media (max-width: 640px) {
|
|
2433
2511
|
.events-carousel {
|
|
@@ -2875,7 +2953,7 @@ textarea.p60-form-control {
|
|
|
2875
2953
|
|
|
2876
2954
|
/* ---- Members area (shell + sections; see components/members/) ----
|
|
2877
2955
|
Desktop: left rail + content. Small screens: the rail becomes a horizontal, scrollable pill
|
|
2878
|
-
strip above the content
|
|
2956
|
+
strip above the content, same registry, no separate mobile markup. */
|
|
2879
2957
|
.members-head {
|
|
2880
2958
|
margin-bottom: 1.6rem;
|
|
2881
2959
|
}
|
|
@@ -2911,7 +2989,7 @@ textarea.p60-form-control {
|
|
|
2911
2989
|
color: var(--ink);
|
|
2912
2990
|
text-align: left;
|
|
2913
2991
|
cursor: pointer;
|
|
2914
|
-
/* Labels WRAP inside the pill (never overflow it)
|
|
2992
|
+
/* Labels WRAP inside the pill (never overflow it), long names and translations both fit. */
|
|
2915
2993
|
line-height: 1.25;
|
|
2916
2994
|
}
|
|
2917
2995
|
.members-rail-item .members-rail-icon { flex: 0 0 auto; }
|
|
@@ -3050,7 +3128,7 @@ textarea.p60-form-control {
|
|
|
3050
3128
|
}
|
|
3051
3129
|
}
|
|
3052
3130
|
|
|
3053
|
-
/* Just above the burger point the full-size nav is tight
|
|
3131
|
+
/* Just above the burger point the full-size nav is tight, compact spacing spreads it cleanly
|
|
3054
3132
|
instead of letting anything drop. */
|
|
3055
3133
|
@media (min-width: 961px) and (max-width: 1120px) {
|
|
3056
3134
|
.site-nav {
|
|
@@ -3172,7 +3250,7 @@ textarea.p60-form-control {
|
|
|
3172
3250
|
|
|
3173
3251
|
/* ---- Members rail on mobile: a LEFT SLIDE-IN DRAWER behind a round user-icon button ----
|
|
3174
3252
|
The rail itself becomes the drawer (same items, same markup): fixed full-height panel translated
|
|
3175
|
-
off-canvas, sliding in over a scrim. The trigger is a slim bar
|
|
3253
|
+
off-canvas, sliding in over a scrim. The trigger is a slim bar, round user-icon button + the
|
|
3176
3254
|
current section name. Desktop hides all of this and shows the rail inline. */
|
|
3177
3255
|
.members-mobile-bar {
|
|
3178
3256
|
display: none;
|
|
@@ -3280,7 +3358,7 @@ textarea.p60-form-control {
|
|
|
3280
3358
|
}
|
|
3281
3359
|
|
|
3282
3360
|
/* ---- Articles front page: the newest article in full + a right sidebar (recent, topics,
|
|
3283
|
-
view-all). Newspaper-style
|
|
3361
|
+
view-all). Newspaper-style, the sidebar stacks below the article on small screens. ---- */
|
|
3284
3362
|
.article-front {
|
|
3285
3363
|
display: grid;
|
|
3286
3364
|
grid-template-columns: minmax(0, 1fr) 300px;
|
|
@@ -3383,7 +3461,7 @@ textarea.p60-form-control {
|
|
|
3383
3461
|
}
|
|
3384
3462
|
}
|
|
3385
3463
|
|
|
3386
|
-
/* ---- Consent banner + preference centre (platform-level, always on
|
|
3464
|
+
/* ---- Consent banner + preference centre (platform-level, always on, compliance is
|
|
3387
3465
|
platform-owned). Fixed bottom layer; the preference centre grows out of the same layer. ---- */
|
|
3388
3466
|
.consent-layer {
|
|
3389
3467
|
position: fixed;
|
|
@@ -3539,7 +3617,7 @@ textarea.p60-form-control {
|
|
|
3539
3617
|
color: inherit;
|
|
3540
3618
|
}
|
|
3541
3619
|
|
|
3542
|
-
/* ---- Marketing opt-in checkbox (the explicit reg-22 consent
|
|
3620
|
+
/* ---- Marketing opt-in checkbox (the explicit reg-22 consent, deliberately quiet, never
|
|
3543
3621
|
pre-ticked) + the members contact toggle. ---- */
|
|
3544
3622
|
.marketing-optin {
|
|
3545
3623
|
display: flex;
|
|
@@ -3608,11 +3686,11 @@ textarea.p60-form-control {
|
|
|
3608
3686
|
}
|
|
3609
3687
|
|
|
3610
3688
|
/* ---- Cross-document view transitions (MPA soft-feel) ----
|
|
3611
|
-
Every nav click is a full document navigation (Astro MPA
|
|
3689
|
+
Every nav click is a full document navigation (Astro MPA, no client router). This asks the
|
|
3612
3690
|
browser to HOLD the old frame and cross-fade to the new page once it's ready (Chrome 126+,
|
|
3613
3691
|
Safari 18+; others keep the instant swap): no blank frame between pages, and unchanged chrome
|
|
3614
|
-
(masthead/nav) cross-fades between identical pixels
|
|
3615
|
-
with persistent island state would be Astro's ClientRouter
|
|
3692
|
+
(masthead/nav) cross-fades between identical pixels, i.e. visually persists. True soft-nav
|
|
3693
|
+
with persistent island state would be Astro's ClientRouter, a later, bigger step. */
|
|
3616
3694
|
@view-transition {
|
|
3617
3695
|
navigation: auto;
|
|
3618
3696
|
}
|
|
@@ -3624,7 +3702,7 @@ textarea.p60-form-control {
|
|
|
3624
3702
|
}
|
|
3625
3703
|
}
|
|
3626
3704
|
|
|
3627
|
-
/* The article page's back-link needs air before the chips/title (detail page only
|
|
3705
|
+
/* The article page's back-link needs air before the chips/title (detail page only, the front
|
|
3628
3706
|
page's grid must keep its own alignment). */
|
|
3629
3707
|
.services-back + .article-article {
|
|
3630
3708
|
margin-top: 1.75rem;
|
|
@@ -3741,7 +3819,7 @@ textarea.p60-form-control {
|
|
|
3741
3819
|
mixed grids keep one card anatomy. The tint arrives as a CSS VARIABLE, not an inline background,
|
|
3742
3820
|
so a template whose palette collides with the green→indigo band can override this rule and
|
|
3743
3821
|
restyle the fallback its own way (the templates-conform contract). */
|
|
3744
|
-
/* Admin-entered prose can contain unbroken tokens (URLs, pasted refs)
|
|
3822
|
+
/* Admin-entered prose can contain unbroken tokens (URLs, pasted refs), never let one push a
|
|
3745
3823
|
container wide. Applies to every surface that renders tenant summaries/bodies. */
|
|
3746
3824
|
.event-detail-desc,
|
|
3747
3825
|
.event-about,
|
|
@@ -4023,7 +4101,7 @@ textarea.p60-form-control {
|
|
|
4023
4101
|
color: var(--muted);
|
|
4024
4102
|
white-space: pre-line;
|
|
4025
4103
|
}
|
|
4026
|
-
/* The members-area PILL BUTTON (user, 2026-07-22)
|
|
4104
|
+
/* The members-area PILL BUTTON (user, 2026-07-22), the one action idiom across member surfaces
|
|
4027
4105
|
(directions, household invite/remove, …): bordered pill, hover fill, danger modifier. */
|
|
4028
4106
|
.member-pill-btn {
|
|
4029
4107
|
display: inline-flex;
|
|
@@ -4046,7 +4124,7 @@ textarea.p60-form-control {
|
|
|
4046
4124
|
.member-pill-btn:disabled { opacity: 0.5; cursor: default; }
|
|
4047
4125
|
.member-pill-btn-danger { color: #c4462e; }
|
|
4048
4126
|
|
|
4049
|
-
/* Get directions = a proper pill button (user, 2026-07-22)
|
|
4127
|
+
/* Get directions = a proper pill button (user, 2026-07-22), the resource-chip idiom, so it
|
|
4050
4128
|
reads as an action rather than text among the venue lines. */
|
|
4051
4129
|
.member-course-directions {
|
|
4052
4130
|
display: inline-flex;
|
|
@@ -4067,7 +4145,7 @@ textarea.p60-form-control {
|
|
|
4067
4145
|
background: color-mix(in srgb, currentColor 8%, transparent);
|
|
4068
4146
|
text-decoration: none;
|
|
4069
4147
|
}
|
|
4070
|
-
/* The feedback-loop accordion (2026-07-21): latest note + attendance history
|
|
4148
|
+
/* The feedback-loop accordion (2026-07-21): latest note + attendance history, renders only when
|
|
4071
4149
|
a course runner actually recorded something. */
|
|
4072
4150
|
.member-course-feedback {
|
|
4073
4151
|
margin-top: 0.6rem;
|
|
@@ -4129,6 +4207,8 @@ textarea.p60-form-control {
|
|
|
4129
4207
|
}
|
|
4130
4208
|
.member-course-attendance li:last-child { border-bottom: none; }
|
|
4131
4209
|
.member-course-attendance li.is-absent { opacity: 0.7; }
|
|
4210
|
+
/* Which class this mark was, for a learner who attends more than one. */
|
|
4211
|
+
.member-course-attendance-class { display: block; font-size: 0.8em; font-style: normal; opacity: 0.75; }
|
|
4132
4212
|
|
|
4133
4213
|
/* C1.9 breaks (informational) + C1.8 course materials (presigned downloads). */
|
|
4134
4214
|
.member-course-breaks {
|
|
@@ -4147,7 +4227,7 @@ textarea.p60-form-control {
|
|
|
4147
4227
|
text-transform: uppercase;
|
|
4148
4228
|
opacity: 0.7;
|
|
4149
4229
|
}
|
|
4150
|
-
/* Download CHIPS (user, 2026-07-22): the whole pill is the button
|
|
4230
|
+
/* Download CHIPS (user, 2026-07-22): the whole pill is the button, unmistakably tappable. */
|
|
4151
4231
|
.member-resource-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.45rem; }
|
|
4152
4232
|
.member-resource-chip {
|
|
4153
4233
|
display: inline-flex;
|
|
@@ -4167,7 +4247,7 @@ textarea.p60-form-control {
|
|
|
4167
4247
|
}
|
|
4168
4248
|
.member-resource-chip-size { font-weight: 400; opacity: 0.65; font-size: 0.85rem; }
|
|
4169
4249
|
|
|
4170
|
-
/* "Billing & payment methods" (user, 2026-07-22): the billing half
|
|
4250
|
+
/* "Billing & payment methods" (user, 2026-07-22): the billing half, one line per ongoing
|
|
4171
4251
|
commitment (a family subscription = ONE line: total + who it covers). */
|
|
4172
4252
|
.members-subsection-title {
|
|
4173
4253
|
font-size: 1.05rem;
|
|
@@ -4193,7 +4273,7 @@ textarea.p60-form-control {
|
|
|
4193
4273
|
.member-billing-detail { font-size: 0.9rem; margin-top: 0.15rem; }
|
|
4194
4274
|
.member-billing-pastdue { color: var(--accent, #d33); font-weight: 600; }
|
|
4195
4275
|
|
|
4196
|
-
/* The course TITLE BAR (user, 2026-07-22): a distinct full-width band at the top of the card
|
|
4276
|
+
/* The course TITLE BAR (user, 2026-07-22): a distinct full-width band at the top of the card ,
|
|
4197
4277
|
bleeds to the card edges via negative margins, slightly larger type. */
|
|
4198
4278
|
.member-course-title-bar {
|
|
4199
4279
|
margin: -1rem -1.1rem 0.35rem;
|
|
@@ -4206,7 +4286,7 @@ textarea.p60-form-control {
|
|
|
4206
4286
|
}
|
|
4207
4287
|
|
|
4208
4288
|
/* Grouped course card (2026-07-22): the course owns venue/breaks/materials once; each PERSON is
|
|
4209
|
-
an ACCORDION row
|
|
4289
|
+
an ACCORDION row, a full-width, obviously-tappable bar (chevron + hover), default collapsed,
|
|
4210
4290
|
one open at a time. */
|
|
4211
4291
|
.member-course-people {
|
|
4212
4292
|
margin-top: 0.85rem;
|
|
@@ -4310,7 +4390,7 @@ textarea.p60-form-control {
|
|
|
4310
4390
|
flex-wrap: wrap;
|
|
4311
4391
|
}
|
|
4312
4392
|
|
|
4313
|
-
/* Courses picker refinement (2026-07-19): tap-to-select cards
|
|
4393
|
+
/* Courses picker refinement (2026-07-19): tap-to-select cards, the native checkbox/radio is
|
|
4314
4394
|
visually hidden (kept in the DOM for keyboard + screen-reader semantics); selection reads as
|
|
4315
4395
|
the highlighted card. The footer is an itemised order summary instead of a one-line count. */
|
|
4316
4396
|
.course-variant-card,
|
|
@@ -4430,7 +4510,7 @@ textarea.p60-form-control {
|
|
|
4430
4510
|
font-weight: 600;
|
|
4431
4511
|
}
|
|
4432
4512
|
|
|
4433
|
-
/* ---- Prayer timetable page (worship WP5)
|
|
4513
|
+
/* ---- Prayer timetable page (worship WP5), theme-neutral: borders/highlights derive from
|
|
4434
4514
|
currentColor so every template's palette carries through. ---- */
|
|
4435
4515
|
.pt-head {
|
|
4436
4516
|
display: flex;
|
|
@@ -4505,7 +4585,7 @@ textarea.p60-form-control {
|
|
|
4505
4585
|
opacity: 0.7;
|
|
4506
4586
|
}
|
|
4507
4587
|
|
|
4508
|
-
/* Small screens: the month table becomes stacked day cards
|
|
4588
|
+
/* Small screens: the month table becomes stacked day cards, no horizontal scrolling. */
|
|
4509
4589
|
.pt-cards {
|
|
4510
4590
|
display: none;
|
|
4511
4591
|
list-style: none;
|
|
@@ -4583,7 +4663,7 @@ textarea.p60-form-control {
|
|
|
4583
4663
|
font-size: 0.92rem;
|
|
4584
4664
|
}
|
|
4585
4665
|
|
|
4586
|
-
/* ── People / team cards
|
|
4666
|
+
/* ── People / team cards, desktop grid, single column on phones ───────────────────────────── */
|
|
4587
4667
|
.people-grid {
|
|
4588
4668
|
display: grid;
|
|
4589
4669
|
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
|
|
@@ -4614,29 +4694,29 @@ textarea.p60-form-control {
|
|
|
4614
4694
|
.people-grid { grid-template-columns: 1fr; }
|
|
4615
4695
|
}
|
|
4616
4696
|
|
|
4617
|
-
/* ── Impact map island (WP4)
|
|
4697
|
+
/* ── Impact map island (WP4), the OVERLAY borrows the theme: pins wear --marker (a brand accent by
|
|
4618
4698
|
default), the card is a themed --surface. The BASEMAP colour is derived by the map island from the
|
|
4619
|
-
theme + --map-mode (see lib/mapTheme.ts). Brand on the overlay, neutrals on the map
|
|
4699
|
+
theme + --map-mode (see lib/mapTheme.ts). Brand on the overlay, neutrals on the map, the recipe
|
|
4620
4700
|
that stays legible on any theme. Templates restyle any of this via the tokens or these classes. */
|
|
4621
4701
|
.impact-map { margin: 24px 0; }
|
|
4622
4702
|
.impact-map-head h2 { margin: 0 0 6px; }
|
|
4623
4703
|
.impact-map-intro { margin: 0 0 14px; opacity: 0.85; }
|
|
4624
4704
|
.impact-map-stats { margin: 0 0 14px; color: var(--muted); font-weight: 600; letter-spacing: 0.01em; }
|
|
4625
4705
|
/* The stable stage, shaped like THE WORLD BAND ITSELF: the island's planet view is all 360° of
|
|
4626
|
-
longitude by 84°N
|
|
4627
|
-
Web Mercator is a 1.497:1 box
|
|
4706
|
+
longitude by 84°N-58°S (whole Greenland in, only the polar void and Antarctica trimmed), which in
|
|
4707
|
+
Web Mercator is a 1.497:1 box, so a frame with that exact ratio holds the full planet edge to
|
|
4628
4708
|
edge, full width AND full height, at any screen size. A ratio wider than the band (a max-height
|
|
4629
4709
|
clamp once made it so on large screens) turns the fit height-constrained and the world renders
|
|
4630
|
-
NARROWER than the frame
|
|
4710
|
+
NARROWER than the frame, dead bars at the sides; a narrower ratio (min-height on phones) just
|
|
4631
4711
|
adds benign vertical margin. Relative + clipped so MapLibre always has a real box and can never
|
|
4632
4712
|
escape it. Keep this ratio in step with the island's planet bounds. */
|
|
4633
4713
|
.impact-map-stage { position: relative; width: 100%; aspect-ratio: 1.497; min-height: 300px;
|
|
4634
4714
|
border-radius: 14px; overflow: hidden; }
|
|
4635
4715
|
/* width:100% is LOAD-BEARING: with height pinned by min-height and width left auto, CSS derives
|
|
4636
|
-
width FROM the aspect-ratio (300 x 1.497 = 449px)
|
|
4716
|
+
width FROM the aspect-ratio (300 x 1.497 = 449px), on phones the stage overflowed the page
|
|
4637
4717
|
sideways, shoving every other section into a lopsided "left with a right gutter" layout. Width
|
|
4638
4718
|
pinned, the ratio yields height and min-height only ever makes the stage TALLER. */
|
|
4639
|
-
/* MOBILE BREAKOUT: a map is a canvas
|
|
4719
|
+
/* MOBILE BREAKOUT: a map is a canvas, every pixel is information, nothing needs a margin, so on
|
|
4640
4720
|
phones it bleeds edge to edge (media bleeds, prose gutters: the hero already sets the rhythm).
|
|
4641
4721
|
Cooperative gestures keep page-scrolling safe over the full-width canvas. */
|
|
4642
4722
|
@media (max-width: 640px) {
|
|
@@ -4662,7 +4742,7 @@ textarea.p60-form-control {
|
|
|
4662
4742
|
card on every screen size, as it always has. */
|
|
4663
4743
|
.impact-map-card--small-screens { display: none; }
|
|
4664
4744
|
@media (max-width: 640px) {
|
|
4665
|
-
/* Full width, flush under the full-bleed map
|
|
4745
|
+
/* Full width, flush under the full-bleed map, the two read as one attached sheet (the same
|
|
4666
4746
|
breakout as the donate card; the hairline top border is the seam between map and card). */
|
|
4667
4747
|
.impact-map-card--small-screens {
|
|
4668
4748
|
display: block;
|
|
@@ -4685,10 +4765,10 @@ textarea.p60-form-control {
|
|
|
4685
4765
|
Sized with width/height (NOT inset) because MapLibre forces position:relative on this element,
|
|
4686
4766
|
which would defeat absolute insets and collapse the box to zero height. */
|
|
4687
4767
|
.impact-map-gl { width: 100%; height: 100%; }
|
|
4688
|
-
/* Live-map markers are a MapLibre circle layer (WebGL)
|
|
4689
|
-
from --marker (circle-color)
|
|
4768
|
+
/* Live-map markers are a MapLibre circle layer (WebGL), they scale with zoom and take their colour
|
|
4769
|
+
from --marker (circle-color), so there is no DOM marker element to style here. The pin canvas
|
|
4690
4770
|
fallback above keeps its own .impact-map-pin dots for the no-tiles case. */
|
|
4691
|
-
/* The INLINE marker card (a MapLibre popup anchored at the clicked marker
|
|
4771
|
+
/* The INLINE marker card (a MapLibre popup anchored at the clicked marker, where "See more"
|
|
4692
4772
|
lives): the shell takes the theme's surface; the tip is recoloured per anchor side to match. */
|
|
4693
4773
|
.impact-map-popup .maplibregl-popup-content { background: var(--surface); color: var(--ink);
|
|
4694
4774
|
border: 1px solid var(--line); border-radius: var(--radius-sm); box-shadow: var(--shadow);
|