DARX · Component Design Inventory

Key-Cards Carousel — $show_key_cards

Detailed 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.

Toggle flag
$show_key_cards = true
Master gate
$show_cards (false)
Source partial
element_webpage_home_carousel_key_cards.php
Included from
element_webpage_home_hero.php (line 42)
Data source
img/kc/keycard_content.csv
Cards in CSV
32 rows

0 Wiring

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.

1 DOM object tree reference names = id / class

blue = class hook, purple = element id (JS handle).

<section> .kc-section └─ .kc-inner ├─ .kc-label-row // cycling active-word strip │ ├─ .kc-label-word [data-idx] // one per card (= subtitle) │ └─ .kc-label-sep · // separators between words ├─ .kc-slider #kcSlider │ ├─ .kc-backing // orange reveal behind a fading card │ ├─ .kc-track #kcTrack // translated on X; holds all cards + clones │ │ └─ .kc-card .kc-card--{type} .kc-cardstyle{n} │ │ └─ .kc-tile // raised tile in the brown mat │ │ ├─ .kc-head.kc-num (roman) + a.kc-title.kc-link │ │ ├─ .kc-imgwrap .kc-imgwrap--style{n}img.kc-img │ │ ├─ a.kc-subtitle.kc-link │ │ ├─ p.kc-bodya.kc-link (verbiage) │ │ └─ p.kc-note │ └─ .kc-pause-ind // ▮▮ shown while .kc-paused └─ .kc-bar // dots assembly with arrow bookends ├─ button.kc-prev #kcPrev ├─ .kc-dots #kcDots │ ├─ .kc-progress-wrap.kc-progress #kcProgress // gilded base rail │ └─ .kc-dot .kc-dot--{type} [style=flex-grow] ▸ .kc-dot-fill └─ button.kc-next #kcNext (.kc-next--end on last)

2 CSS custom-property tokens :root in carousel CSS

Reference name + default value. These drive sizing, colour and motion of the component.

TokenDefaultControls
Geometry
--kc-card-wmin(400px, 92vw)Card width
--kc-card-hcalc(--kc-card-w × 4/3)Card height (3:4 portrait)
--kc-gap24pxGap between cards (JS step = width + 24)
--kc-mat-w15pxBrown mat reveal around the tile
--kc-fade-h70pxIvory→dark fade height, top & bottom
Colour
--kc-backing#C2622EOrange placeholder behind a fading card
--kc-taupe#A1937FUpcoming dots + forward arrow colour
--kc-mat#46331EWarm espresso brown mat
Typography
--kc-num-size0.60remRoman-numeral eyebrow (currently display:none)
--kc-title-size1.45remCard title
--kc-body-size1.20remVerbiage body
--kc-body-lh1.6Body line-height
--kc-label-spacing0.18emLabel-word letter-spacing (inactive)
--kc-label-spacing-active0.24emLabel-word letter-spacing (active)
State / motion
--kc-inactive-opacity0Side-card opacity (temp 0; was 0.90)
--kc-inactive-scale0.86Side-card scale
--kc-auto-ms3800Legacy auto-advance ms "keep in sync" — but JS reads per-card CSV, not this

3 JS tuning constants & state inline script

ReferenceDefaultRole
Timing
KC_STAY_MS[i]per-card (CSV)Dwell per card, from keycard_staytime × 1000
stay fallback4000Used when a card's staytime is blank/invalid
FADE_OUT_MS420Outgoing card fade-out duration
FADE_IN_MS560Incoming card fade-in duration
EASEcubic-bezier(0.22,1,0.36,1)Transition easing (cinematic)
resetProgress delay650Pause before re-arming the next cycle
Loop / layout
pad2Cards cloned at each end for the infinite wrap
getStep cw fallback340Assumed card width if measure = 0
step pad+24Width + gap when neighbour measure unavailable
swipe threshold40pxMin touch delta to trigger prev/next
slide offset (dx)±54pxHorizontal nudge during fade
settle scale0.985 → 1Incoming card scale-up
Runtime state
cur= pad (2)Index of centred card (first real card)
busyfalseBlocks overlapping transitions
pausedfalseFrozen by clicking centre card's picture
STEPnullCached {cw,st,sw} measurement; cleared on resize/load

4 PHP data model & defaults

ReferenceDefaultRole
$kcCsvPathimg/kc/keycard_content.csvCard data source (header-name matched)
$KC_DEFAULT_FIELDS[title,image,subtitle,verbiage,note]Fields shown for unknown/blank type
default typeslideFallback when keycard_type blank
$lnk (card link)SITE_BASE . '01/'Title/subtitle/verbiage link target (hardcoded for now)
$stayMs fallback4000Per-card dwell when staytime invalid

5 Card-type system single source of truth

Type is normalised from aliases, drives both the fields rendered and the picture-frame style.

TypeAliases acceptedstyleFields rendered (top→bottom)
main0 · cardMain · main0 embossedtitle · image · verbiage · note subtitle omitted
slide1 · cardSlide · slide1 raisedtitle · image · subtitle · verbiage · note
cardmedia2 · cardMedia2 windowtitle · 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.

6 CSV column schema keycard_content.csv

Matched by header NAME (order-independent). One card per row with a numeric keycard_number; cards display in CSV row order.

ColumnDefault if blankMeaning
keycard_numberrequiredPer-row index → roman eyebrow; non-numeric rows skipped
keycard_typeslidemain / slide / cardMedia (or aliases)
keycard_staytime4 (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/'

7 Inventory notes

  • Two auto-advance values can drift. The CSS token --kc-auto-ms:3800 is labelled "used in JS too — keep in sync", but the JS actually reads per-card KC_STAY_MS from the CSV (with a 4000ms fallback) and never reads the CSS var. The 3800 value is effectively dead.
  • keycard_link_url is parsed but unused. Every card's title/subtitle/verbiage link is hardcoded to SITE_BASE.'01/'; the per-card CSV link column is loaded into $c['link'] but not rendered.
  • Side cards are invisible. --kc-inactive-opacity is temporarily 0 (was 0.90), so the "half a card on each side" effect described in the file header isn't currently showing.
  • Card count grew. The file header comment says "18 image cards"; the CSV now holds 32 rows. The loop reads the count from the DOM, so it's correct — but keep .kc-label-word / .kc-dot counts in sync (one each per card) or indicators misalign.
  • i18n not wired. kc* translation keys (kcWord_N, kcTitle_N…) aren't defined in the JSON, so cards show hardcoded English in every language.
  • Roman numeral hidden. .kc-num is generated from keycard_number but set display:none in CSS — value is ready if re-enabled.