$show_key_cardsDetailed inventory of every object in the key-cards carousel: DOM structure, CSS custom-property tokens, JS tuning constants, the PHP data model, and the CSV column schema — each with its reference name and default value.
Despite living under the $show_cards group in the index, the carousel is physically included by the hero partial, not the cards partial. So it renders whenever the hero renders — it does not require $show_cards to be true. The $show_key_cards flag is declared but the carousel partial itself contains no if($show_key_cards) guard; gating is handled upstream / via the kc-hidden body class CSS.
blue = class hook, purple = element id (JS handle).
Reference name + default value. These drive sizing, colour and motion of the component.
| Token | Default | Controls |
|---|---|---|
| Geometry | ||
| --kc-card-w | min(400px, 92vw) | Card width |
| --kc-card-h | calc(--kc-card-w × 4/3) | Card height (3:4 portrait) |
| --kc-gap | 24px | Gap between cards (JS step = width + 24) |
| --kc-mat-w | 15px | Brown mat reveal around the tile |
| --kc-fade-h | 70px | Ivory→dark fade height, top & bottom |
| Colour | ||
| --kc-backing | #C2622E | Orange placeholder behind a fading card |
| --kc-taupe | #A1937F | Upcoming dots + forward arrow colour |
| --kc-mat | #46331E | Warm espresso brown mat |
| Typography | ||
| --kc-num-size | 0.60rem | Roman-numeral eyebrow (currently display:none) |
| --kc-title-size | 1.45rem | Card title |
| --kc-body-size | 1.20rem | Verbiage body |
| --kc-body-lh | 1.6 | Body line-height |
| --kc-label-spacing | 0.18em | Label-word letter-spacing (inactive) |
| --kc-label-spacing-active | 0.24em | Label-word letter-spacing (active) |
| State / motion | ||
| --kc-inactive-opacity | 0 | Side-card opacity (temp 0; was 0.90) |
| --kc-inactive-scale | 0.86 | Side-card scale |
| --kc-auto-ms | 3800 | Legacy auto-advance ms "keep in sync" — but JS reads per-card CSV, not this |
| Reference | Default | Role |
|---|---|---|
| Timing | ||
| KC_STAY_MS[i] | per-card (CSV) | Dwell per card, from keycard_staytime × 1000 |
| stay fallback | 4000 | Used when a card's staytime is blank/invalid |
| FADE_OUT_MS | 420 | Outgoing card fade-out duration |
| FADE_IN_MS | 560 | Incoming card fade-in duration |
| EASE | cubic-bezier(0.22,1,0.36,1) | Transition easing (cinematic) |
| resetProgress delay | 650 | Pause before re-arming the next cycle |
| Loop / layout | ||
| pad | 2 | Cards cloned at each end for the infinite wrap |
| getStep cw fallback | 340 | Assumed card width if measure = 0 |
| step pad | +24 | Width + gap when neighbour measure unavailable |
| swipe threshold | 40px | Min touch delta to trigger prev/next |
| slide offset (dx) | ±54px | Horizontal nudge during fade |
| settle scale | 0.985 → 1 | Incoming card scale-up |
| Runtime state | ||
| cur | = pad (2) | Index of centred card (first real card) |
| busy | false | Blocks overlapping transitions |
| paused | false | Frozen by clicking centre card's picture |
| STEP | null | Cached {cw,st,sw} measurement; cleared on resize/load |
| Reference | Default | Role |
|---|---|---|
| $kcCsvPath | img/kc/keycard_content.csv | Card data source (header-name matched) |
| $KC_DEFAULT_FIELDS | [title,image,subtitle,verbiage,note] | Fields shown for unknown/blank type |
| default type | slide | Fallback when keycard_type blank |
| $lnk (card link) | SITE_BASE . '01/' | Title/subtitle/verbiage link target (hardcoded for now) |
| $stayMs fallback | 4000 | Per-card dwell when staytime invalid |
Type is normalised from aliases, drives both the fields rendered and the picture-frame style.
| Type | Aliases accepted | style | Fields rendered (top→bottom) |
|---|---|---|---|
| main | 0 · cardMain · main | 0 embossed | title · image · verbiage · note subtitle omitted |
| slide | 1 · cardSlide · slide | 1 raised | title · image · subtitle · verbiage · note |
| cardmedia | 2 · cardMedia | 2 window | title · image · note media-forward |
| (unknown) | — | 1 raised | $KC_DEFAULT_FIELDS (full slide) |
Dot height by type (CSS): main 22 · slide 14 · cardMedia 8. Dot width ∝ staytime via flex-grow:<seconds> over a 3px basis.
Matched by header NAME (order-independent). One card per row with a numeric keycard_number; cards display in CSV row order.
| Column | Default if blank | Meaning |
|---|---|---|
| keycard_number | required | Per-row index → roman eyebrow; non-numeric rows skipped |
| keycard_type | slide | main / slide / cardMedia (or aliases) |
| keycard_staytime | 4 (s) | Seconds the card dwells before auto-advance |
| keycard_title | '' | Large title text (linked) |
| keycard_note | '' | Small caption at card bottom |
| keycard_subtitle | '' | Label under picture + the label-row word (hidden on main) |
| keycard_verbiage | '' | Body sentence (linked) |
| keycard_image_url | '' | Image src, mirror-prefixed by kc_url() |
| keycard_link_url | '' | Link target parsed but card currently hardcodes SITE_BASE.'01/' |
KC_STAY_MS from the CSV (with a 4000ms fallback) and never reads the CSS var. The 3800 value is effectively dead.SITE_BASE.'01/'; the per-card CSV link column is loaded into $c['link'] but not rendered.0 (was 0.90), so the "half a card on each side" effect described in the file header isn't currently showing..kc-label-word / .kc-dot counts in sync (one each per card) or indicators misalign.kc* translation keys (kcWord_N, kcTitle_N…) aren't defined in the JSON, so cards show hardcoded English in every language..kc-num is generated from keycard_number but set display:none in CSS — value is ready if re-enabled.