# EVENT-DECK.md — co-branded event-deck variant > **Scope**: this file documents a **sub-variant of the editorial deck** — a paged, co-branded presentation built for a live event (working breakfast, partner session, roadshow). Distilled from `desayuno.flat101.business` (Flat 101 × Programads, "Measurement Confidence Score", 27 slides). It inherits everything in `RULES.md` (color, type, spacing, radii, shadows, focus) and adds: a second partner brand, five full-bleed slide surfaces, a small editorial data-viz kit, a chip/badge catalog, and a **CSS-driven reveal choreography** that does not depend on `motion/react`. Read `RULES.md` first; this file only documents the deltas. ## When to use this variant Use it for a deck that is: - **Co-presented** — two brands share authorship (host + partner). Needs a controlled second hue and a dual-brand footer. - **Paged, not scrolled** — one slide on screen at a time, advanced by keyboard / on-screen buttons, projected at an event. Not a long-scroll site. The motion model is a per-slide state machine (`is-active`), not viewport-triggered `Reveal`. - **Data-dense** — bar charts, donuts, pyramids, step flows reconstructed natively (no chart library, no screenshots) in the system's visual language. For a single-brand long-scroll narrative on the web, stay on the base editorial variant (`RULES.md` + `MOTION.md`). For dashboards / tools, use `PRODUCT-UI.md`. This variant can be delivered as a static HTML/CSS/JS bundle (no build) or reproduced inside the Next.js stack. ## Co-brand: the controlled second hue The base rule is **one accent only** (`ANTIPATTERNS.md`: "Two saturated colors in same slide — keep accent singular"). The co-brand variant relaxes it **once**, with intent: - The **partner brand color** (`--brand-pa: #007dff`, navy `--brand-pa-navy: #364462` for the worked example) appears **only on elements that belong to the partner** — the channel they own, their product label, their top-border on a card. It is never used decoratively, never on the host's content, never as a gradient. - The yellow accent (`--accent-500`) stays the deck's only *editorial* accent: headlines, highlights, KPI emphasis, chips. The partner hue is a **brand mark**, not a second accent. - One partner hue maximum. Adding a third saturated color is still banned. ```css /* tokens — co-brand partner surfaces (add alongside --brand-flat etc.) */ --brand-pa: #007dff; /* partner brand (Programads in the worked example) */ --brand-pa-navy: #364462; /* partner deep tone */ ``` Usage is surgical: ```css .chans__col--audio { border-top-color: var(--brand-pa); } /* the partner-owned channel card */ .rtg__dsp { color: var(--brand-pa); } /* the partner's product label */ ``` Litmus test (from the anti-AI-slop checklist): *"Did you add a second hue for variety? Remove it."* The partner hue survives that test only because it carries brand meaning, not variety. ## Full-bleed slide surfaces (five new variants) The base deck has three surfaces: `slide-paper`, `slide-tone`, `slide-feature` (dark). The event deck adds five **full-bleed** surfaces. All keep the slide skeleton from `RULES.md` (padding, `max-width: 1664px` inner) and the dual-brand footer. ### 1. Cover — dark event identity Dark navy radial ground with a single offset yellow disc bleeding off the left edge. Pill-outline eyebrow, dual logos, serif italic title where the accent and white swap roles. ```css .cover { background: radial-gradient(125% 135% at 0% 0%, #1a2f57 0%, #0d1c3a 48%, #070f24 100%); color: #fff; overflow: hidden; } .cover__shape { /* the disc: position absolute, ~26vw, bleeds off-canvas left */ position: absolute; left: clamp(-460px, -20vw, -340px); top: 50%; transform: translateY(-50%); width: clamp(300px, 26vw, 440px); aspect-ratio: 1; border-radius: 50%; background: var(--accent-500); } .cover .slide__title { color: var(--accent-500); font-size: var(--fs-display); max-width: 16ch; } .cover .slide__title em { color: #fff; } /* accent ⇄ white role-swap on the emphasized word */ .cover .eyebrow { /* pill-outline eyebrow, accent on dark */ color: var(--accent-500); padding: 7px 16px; border: 1px solid rgba(250,204,13,.5); border-radius: var(--radius-pill); } ``` ### 2. Section divider — dark Same dark navy radial ground as the cover, content top-left, used to open a thematic block. Eyebrow + serif white title (accent on the emphasized word) + a one-line `divider__lead`. ```css .divider { background: radial-gradient(125% 135% at 0% 0%, #1a2f57 0%, #0d1c3a 48%, #070f24 100%); color: #fff; } .divider .slide__title { color: #fff; font-size: var(--fs-display); max-width: 18ch; } .divider .slide__title em { color: var(--accent-500); } .divider .eyebrow, .divider .eyebrow::before { color: var(--accent-500); background: var(--accent-500); } ``` ### 3. Level divider — accent (yellow) The inverse: a **solid yellow** surface with a giant serif number (`clamp(140px, 20vw, 320px)`) beside a kicker + title + lead. Used to mark a numbered level/section. Ink-900 text on accent; logos go dark. ```css .divider2 { background: var(--accent-500); color: var(--ink-900); } .divider2__main { display: grid; grid-template-columns: auto 1fr; gap: clamp(28px,5vw,84px); align-items: center; } .divider2__num { font-family: var(--font-display); font-size: clamp(140px,20vw,320px); line-height: .76; } .divider2__kicker { border-bottom: 2px solid var(--ink-900); /* UPPERCASE 0.14em, weight 800 */ } ``` ### 4. Statement — dark, centered Dark navy ground (center-origin radial), a single large serif line centered, revealed **word by word**. For a charged one-sentence claim that opens or closes a block. See the word-reveal pattern under *Reveal choreography*. ```css .statement { background: radial-gradient(125% 135% at 50% 0%, #16284a 0%, #0d1c3a 50%, #070f24 100%); color: #fff; } .statement__text { font-family: var(--font-display); font-size: clamp(34px,4.4vw,68px); max-width: 24ch; text-wrap: balance; } .statement__text em { color: var(--accent-500); font-style: italic; } ``` ### 5. Takeaways — near-black closing A flatter near-black (`#0a0a0b`) ground for the closing "ideas to take home" list. Centered underlined serif title (accent underline), then a vertical list of numbered ideas separated by hairline rules. ```css .takeaways { background: #0a0a0b; color: #fff; } .takeaways .slide__title { text-decoration: underline; text-decoration-color: var(--accent-500); text-decoration-thickness: 3px; text-underline-offset: 10px; } .tkw__num { font-family: var(--font-display); font-size: clamp(44px,5.6vw,88px); color: var(--accent-500); } .tkw__item { border-bottom: 1px solid rgba(255,255,255,.14); } ``` **Rhythm**: full-bleed surfaces are punctuation, not paragraphs. Open with `cover`, break blocks with `divider` / `divider2`, land a claim with `statement`, close with `takeaways`. Between them, the bulk of the deck stays on `slide-paper` / `slide-tone`. Never two full-bleed darks back to back unless one is a deliberate cover→statement beat. ## Editorial data-viz kit Charts are **reconstructed natively** in the system's language — no chart library, no pasted screenshots. Four primitives cover most decks. All animate on `is-active` (see choreography). ### Bar chart Equal-flex columns; each fill height is a CSS var `--h`; the last bar gets the solid accent, the rest a soft `accent-100 → accent-200` gradient. Fill grows with `scaleY` from the baseline; the value label fades in after the bar lands. ```css .bar__fill { height: var(--h); border-radius: 8px 8px 0 0; background: linear-gradient(180deg, var(--accent-100), var(--accent-200)); transform: scaleY(0); transform-origin: bottom; transition: transform 1.3s var(--ease-strong); transition-delay: var(--bd, 0s); } .bar--last .bar__fill { background: var(--accent-500); } .slide.is-active .bar__fill { transform: scaleY(1); } ``` Pair with a `chartbox` grid (`grid-template-columns: auto 1fr`) when a y-axis scale is needed; the axis column is `flex-direction: column-reverse` so labels read bottom-up. ### Donut (share split) A `conic-gradient` ring punched out by a `::after` white disc. Two stops express a part/whole split (e.g. ink-900 share vs accent share vs ink-100 remainder). Big serif number centered. ```css .donut { --pb: 64; --py: 100; /* stop percentages */ aspect-ratio: 1; border-radius: 50%; background: conic-gradient( var(--ink-900) 0 calc(var(--pb)*1%), var(--accent-500) calc(var(--pb)*1%) calc(var(--py)*1%), var(--ink-100) calc(var(--py)*1%) 100%); display: grid; place-items: center; } .donut::after { content: ""; position: absolute; inset: 21%; background: var(--paper); border-radius: 50%; } ``` ### Staircase pyramid Stacked rows of decreasing width (`100% → 56%`), each a paper card outlined in accent, with a level pill, a title, optional KPI pills (ink-900 bg, accent text), and capability chips. Rows reveal one after another (`--d` stagger). Use for a maturity / levels model. ```css .plevel--0 { width: 100%; } .plevel--1 { width: 89%; } .plevel--2 { width: 78%; } .plevel--3 { width: 67%; } .plevel--4 { width: 56%; } .plevel { border: 2px solid var(--accent-500); border-radius: var(--radius-lg); background: var(--paper); } .stage.is-active .plevel { transition-delay: calc(0.2s + var(--d,0) * 1.1s); } ``` ### Dotted connector flow A row of equal cells (steps) joined by a dotted rule drawn from the center of each cell to the next via `::after` on the cell, width = the grid gap (held in `--flow-gap` / `--behav-gap`). Ink-300 dots for neutral journeys; accent dots for an emphasized pipeline. ```css .bint__cell:not(:last-child) .bint__imgwrap::after { content: ""; position: absolute; top: 50%; left: 100%; width: var(--flow-gap); border-top: 2px dotted var(--accent-500); transform: translateY(-50%); z-index: 0; } ``` ## Chips, badges & pills (catalog) The event deck leans on small high-contrast tokens. One catalog, consistent shapes: | Class | Shape | Use | |---|---|---| | `.chip` | pill, paper + `--shadow-rest` | meta tag on the cover (date, place) | | `.chip--accent` | pill, accent bg, ink-900 | the one chip that matters | | `.chip-level` / `.nivel-pill` | small pill, accent bg, ink-900, weight 800 | level marker inside an eyebrow or pyramid row | | `.kpi-pill` | small pill, **ink-900 bg, accent-400 text** | a metric badge on a dark-on-card row | | `.bdg--y` / `.bdg--d` | square-ish badge, accent / ink-900 | inline emphasis under a mockup | | `.tag` | pill, `accent-50` bg, `accent-200` border | quiet keyword tag | | `.tchip--web/app/omni` | square chip with semantic tint (green / blue / purple) | channel taxonomy **only** (data-viz semantic, like chart colors) | Rules: pills are `--radius-pill`; square chips/badges are `--radius-sm`. Eyebrow letter-spacing carries to the all-caps ones. The semantic `tchip` tints are the one place a non-accent hue is allowed, and only as **data-viz category color** (same carve-out as chart series in `RULES.md`). ## Inline KPI cluster Lighter than `kpi-trio`: a flex-wrap row of figure + label, no cards. Serif figure, accent on the unit/emphasis via `em`. ```css .kpi__num { font-family: var(--font-display); font-size: clamp(44px,6vw,92px); line-height: .95; color: var(--ink-900); } .kpi__num em { font-style: normal; color: var(--accent-600); } /* the unit / delta */ .kpi__label { color: var(--ink-500); max-width: 22ch; } ``` ## Dual-brand footer Every slide carries a bottom strip with **both** brands: host monogram + 1 px separator + partner logo. On dark surfaces the host mark drops to `rgba(255,255,255,.65)` and the separator to `rgba(255,255,255,.22)`; on the accent level-divider both go ink-900. ```css .slide__foot { display: flex; align-items: center; gap: var(--space-5); } .foot__sep { width: 1px; height: 22px; background: var(--ink-200); } ``` ## Paged nav chrome This variant is paged, so it swaps the long-scroll chrome (scroll-progress bar + indicator dots from `RULES.md`) for: - **Top progress bar** — same 3 px accent bar, but driven by `current / total` (`scaleX`), not scroll position. - **Bottom-right nav** — a serif `current / total` counter (`deck__counter`, accent-on-ink current digit) plus two round `.navbtn` prev/next buttons (paper, 1 px border, `--shadow-rest`, lift on hover, `scale(.94)` on press, `opacity .35` disabled). ```css .deck__progress { position: fixed; top: 0; height: 3px; transform-origin: left; background: var(--accent-500); } .navbtn { width: 40px; height: 40px; border-radius: var(--radius-pill); border: 1px solid var(--ink-200); box-shadow: var(--shadow-rest); } ``` Keyboard map matches `MOTION.md` (arrows / space / Home / End). The on-screen counter digits may "roll" on change (per-digit spans) but that is optional polish, not required. ## Reveal choreography (CSS-driven, no framework) This is the variant's defining motion model. Where the base deck uses `motion/react` components triggered by viewport, the event deck runs a **per-slide state machine in pure CSS**, keyed off classes the controller toggles: `is-active` (on screen), `is-enter` (just mounted, pre-animation freeze), `is-leaving` (crossfading out), and a deck-level `intro` (first paint). One JS file flips the classes; all motion is CSS. This makes the deck portable to a no-build static bundle and keeps animation off the main thread. Beats, in order, on the active slide: 1. **Slide crossfade** — `.slide.is-active` fades in (`opacity` keyframe, 380 ms). The leaving slide holds its final state under it (`is-leaving`, `z-index:1`, no transition). 2. **Title mask-reveal** — the protagonist. `clip-path: inset(0 100% 0 0)` → `inset(0 -8% -30% 0)` plus a small `translateX`, over `0.85s var(--ease-strong)`. This is the CSS twin of the `MaskReveal` component, done with `clip-path` instead of an overflow mask. 3. **Eyebrow rule** — the 28 px accent bar before the eyebrow scales in (`scaleX(0)→1`, 0.5 s, delay 0.12 s). 4. **Body reveal** — every `[data-reveal]` element lifts in with `opacity` + `translateY(16px)` + `blur(4px)` → clear, over `var(--dur-reveal)` (700 ms), staggered by `--i`: `transition-delay: calc(.18s + var(--i,0) * 70ms)`. CSS analogue of `Reveal` + `StaggerList`. 5. **Underline grow** — inline `` draws its accent underline via `background-size: 0% 2px → 100% 2px` (0.6 s, delay 0.55 s), so the key word underlines after the line reads. 6. **Data-viz** — bars `scaleY`, pyramid rows / journey cards cascade via their own `--d` / `--i` delays (1.1 s and 0.6 s steps for slow, deliberate builds). ```css [data-reveal] { opacity: 0; transform: translateY(16px); filter: blur(4px); transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out), filter var(--dur-reveal) var(--ease-out); } .slide.is-active [data-reveal] { opacity: 1; transform: none; filter: none; transition-delay: calc(0.18s + var(--i, 0) * 70ms); } .slide__title { clip-path: inset(0 100% 0 0); opacity: 0; transform: translateX(-0.12em); transition: clip-path .85s var(--ease-strong), transform .85s var(--ease-strong), opacity .5s ease; } .slide.is-active .slide__title { clip-path: inset(0 -8% -30% 0); opacity: 1; transform: none; } ``` ### Statement word-reveal Each word is a `` (mark key ones `w--hl` / underline `w--u`), lifted with `opacity` + `translateY(.5em)`, staggered by index `--wi` at 0.16 s — slower than list stagger, because the sentence is the content. Highlighted words flip color to accent on a trailing delay so the emphasis "lands" after the word is already up. ```css .statement__text .w { opacity: 0; transform: translateY(.5em); transition: opacity .5s var(--ease-out), transform .5s var(--ease-out), color .45s ease; } .slide.is-active .statement__text .w { opacity: 1; transform: none; transition-delay: calc(.3s + var(--wi) * .16s); } .slide.is-active .statement__text .w--hl { color: var(--accent-500); } ``` ### Entry / leave freeze states To replay cleanly on every navigation, the controller adds `is-enter` to a slide the frame it mounts: it pins every animated element back to its hidden state **with `transition: none`**, then removes the class next frame so the real transition runs. `is-leaving` does the opposite — pins to the *final* state, no transition, so the outgoing slide does not re-animate while it fades. Mirror each animated property (`[data-reveal]`, `.slide__title`, `.cap__media`, `.bar__fill`, ``, `.eyebrow::before`) in both states. ### Reduced motion Honor `prefers-reduced-motion: reduce`: force the **final** state on every animated element (`opacity:1`, `transform:none`, `filter:none`, `clip-path:none`, underline `100%`, eyebrow rule `scaleX(1)`), and disable the slide fade and chrome transitions. The deck must be fully legible with zero motion. ```css @media (prefers-reduced-motion: reduce) { [data-reveal], .slide__title, .cap__media { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; transition: none !important; } u { background-size: 100% 2px !important; } .eyebrow::before { transform: scaleX(1) !important; } .slide.is-active { animation: none !important; } } ``` ## Reproducing in the Next.js stack The system ships three React components for the data-viz + index animations, used by the human-facing showcase (`componentes.sd.michelvalles.com` / `usos.sd.michelvalles.com`): - `components/index-roll.tsx` — ``: the giant level index, counts `00 → N` with a per-digit elevator roll (only the changed digit rides up). Pair with `font-display` at a large size. - `components/bar-chart.tsx` — ``: the native bar chart; fills grow with `scaleY` (1.3 s, ease-strong, 120 ms stagger), values fade in once landed, the reference bar takes the solid accent. - `components/donut-chart.tsx` — `} />`: the two-phase conic donut (ink wedge grows, then accent fills), with a counted figure in the centre. If you build this variant inside the React stack rather than as a static bundle: - Use those components (or keep the surfaces and data-viz as plain CSS classes on top of `files/globals.css`; both are framework-agnostic). Do **not** rebuild bars/donuts/pyramids with a chart library. - You may drive the `is-active` state machine from a paged controller, or substitute the existing `motion/react` primitives (`MaskReveal` for the title, `Reveal` / `StaggerList` for `[data-reveal]`, `Counter` for KPIs). Pick one model per deck; do not mix CSS-state and viewport triggers on the same slide. - The co-brand token, chip catalog and dual-brand footer carry over unchanged. ## Carve-outs this variant introduces (record, do not reflex-copy) Per `ANTIPATTERNS.md` "Override only with intent", these are the deliberate exceptions the event-deck variant adds. They are licensed **here**, scoped to their purpose, and must not be duplicated elsewhere by reflex: - **Second saturated hue** — the partner brand color, on partner-owned elements only. - **Semantic `tchip` tints** — green/blue/purple, as data-viz category color only. - **Full-bleed dark/accent surfaces** — cover, dividers, statement, takeaways. Punctuation, not the default surface. - **Side-stripe accents** — `border-left: 4px` appears on note/box recipes (`cstep__note--value`, `search__box`). Same status as the base `rule-card-y`: allowed, not to be sprayed.