1Overdrafted account
Vicky orders expensive sunglasses online and overdraws her account. Facing bills and a negative balance, she panics and tells her bank the card was stolen.
Annual Research Report · Web Publication · 2025
The Cardholder Dispute Index is a flagship annual consumer study: payment behavior, dispute patterns, and the systemic forces behind friendly fraud. The 2025 edition got a full revamp: a new layout, the template rebuilt on the shared SASS and JS system, and an interactive Dispute Disparity Scale tuned frame by frame. I moved 43 PDF designed pages into interactive PHP templates, 105 SVG charts got animated, 60-plus Illustrator exports had to be repaired before any of them could be used, and the whole thing runs on one 1,037-line SASS system that has carried every edition since.
The frame holds the shipped layout, rebuilt from the same component vocabulary: sticky contents rail, full-bleed red section bands, pull quotes on a yellow rule, inline stat figures. It creeps down the document on a timer, so the rail can be seen tracking the active chapter standing still.
Rebuilt is the operative word. This frame and the gate further down are reconstructions, not screenshots of the client's site, and every number inside them is invented. The charts are the genuine production SVGs: the findings they carry, and the name of the Dispute Disparity Scale, come from the published edition and remain the publisher's, shown here as evidence of the build rather than as content. Nothing unpublished or confidential appears on this page.
Respondents ranked the routes they would take after an unrecognized charge, from contacting the merchant through to filing a formal dispute with the issuing bank.
Fig. 3.1: Preferred resolution route
Filing a dispute has drifted from a last resort to a first instinct, and the shift is sharpest among repeat filers.
The pattern holds across every age bracket in the sample and widens among cardholders who have disputed at least once before.
TL;DR
Most of the sample names the issuing bank as the preferred route. Fewer than half took it the last time a charge went wrong.
Asked where they would rather settle a disputed charge, most of the sample names the issuing bank. Asked what they did the last time it happened, fewer than half say the same thing.
The distance between the route cardholders say they prefer and the one they actually take is the widest single measure in the sample.
Two things appear to drive the gap. The bank route is understood to be slower, and the merchant route is the one already open on screen at the moment of friction. Convenience wins on the day even where trust does not.
Median disputed transaction value across the sample, up 7.2% on the prior wave.
Source: Cardholder Dispute Index
The effect compounds with value. Below the median, cardholders lean on whichever route closes fastest; above it, the stated preference and the action converge again.
Fig. 4.2: Preference against action
Issuers are scored on three axes: how quickly a dispute is acknowledged, how clearly its progress is communicated, and whether the outcome landed in the cardholder's favor. The spread between first and last is narrower in this wave than in any prior one.
Compression at the top is the more interesting movement. The leaders have not pulled further ahead; the trailing issuers have closed most of the distance, and almost all of that gain came from acknowledgement time rather than from outcomes.
Fig. 5.1: Satisfaction index, sample issuers
Speed of acknowledgement moved satisfaction more than the final outcome did.
Sample figures in this frame are illustrative placeholders, not survey results.
The Brief
Marketing didn't want a PDF with a landing page bolted on in front of it. They wanted the report itself on the site, styled to the designer's original layout, and capturing leads while readers were still inside the content. That meant reproducing 43 pages of mixed layouts (pie charts, horizontal bar comparisons, pull quotes, two-column tables, full-bleed section dividers) as responsive HTML and SASS, from a 1440px desktop down to a 375px phone.
It also meant treating the whole thing as a funnel rather than a document: enough of the report visible to build curiosity, then a gated wall feeding straight into the CRM.
Shipped as a PDF
Shipped as a page
The Hard Part
The labor here wasn't the layout. It was repairing what Illustrator did on the way out. Every character of exported text arrived as its own <tspan>, positioned by an explicit x-coordinate to preserve Illustrator's custom kerning. That is how Illustrator remembers letter spacing, and it is also why the SVG was unreadable as text, invisible to screen readers, and immune to a CSS font-weight change.
Fixing it meant opening each file, consolidating the character fragments into one <tspan> per line, and recalculating the centering math Illustrator had baked into individual glyph offsets. A second class of damage was worse: some labels came through as outlined path data with no <text> element at all. Those had to be rebuilt as live text, anchored off the path coordinate origins. Sixty-plus files got this treatment before a single chart could be animated.
Same label, before and after
<!-- Before: one <tspan> per glyph --><tspan x="9.76">I</tspan><tspan x="13.96">n</tspan><tspan x="18.9">t</tspan><tspan x="21.76">e</tspan><tspan x="26.7">n</tspan><!-- ...six more tspans for one word --><!-- After: consolidated, live, readable --><tspan x="0" y="0">Intentional chargeback fraud</tspan>
One line of markup doing the work of eleven <tspan> fragments.
Interactive
The code sample makes it look like a formatting nit. It isn't. Flip the switch below to see the same eleven characters as the browser receives them, with Illustrator's real x-coordinates from the file.
Eleven glyphs from one word in one label. The report has 105 charts.
The Signature Chart
The report's central argument in one figure, and the chart everything after it builds on. It draws its two bars in sequence on scroll, so the contrast registers before a reader has time to skim past it.
That distance between preference and action is where merchants lose the narrative.
Six More, From 105
These are the production SVGs, each capped to the proportions it was drawn for. All six animate themselves, and all six point at the same hosted SVGator runtime rather than each bundling a copy, so the first chart to load pays for the player and the rest play free.
Where the report opens: how consumers actually prefer to pay, across card types, wallets, BNPL and emerging alternatives. It is the widest chart in the set, and the one the later sections keep referring back to.
Physical goods and retail at 63%, double the next category, down to ticketing and events at 8.75%. Five circles scaled straight to their values, so the drop-off reads without an axis or a legend.
A bell curve with three markers on it: merchants under 25 chargebacks a month sit at 0.44%, the average lands at 0.56%, and merchants past 250 run 0.75%. The rate climbs with volume rather than flattening out.
72% of merchants reported an increase in friendly fraud. The number the whole report circles back to, and the reason the gate exists at all.
The forward-looking chart the report closes on: card fraud losses projected out to 2028, with the bars drawing in year by year as the reader arrives.
Dollar losses, year-on-year change and CNP's share of all card fraud on one axis. Losses eased in 2024, but the share kept climbing to 74%.
The System
The CDI and a parallel 62-chart annual publication share a single 1,037-line SASS file. Everything in it hangs off one block, .p-study. A new report means a new PHP template, not a new stylesheet. Here is the whole vocabulary, rendered as itself.
&__section-title
Protecting buyers often leaves merchants absorbing the cost of misuse.
&__pull-quote
TL;DR
Merchants underestimate friendly fraud: 74.4% call it a moderate or significant threat.
&__callout
&__did-you-know
Surveyed cardholders across the US and UK, weighted by card ownership.
&__red-heading
Share of respondents who had filed more than one dispute in the preceding twelve months.
Source: Cardholder Dispute Index
&__number
Six of the eight elements under .p-study, rebuilt here from the same rules. The other two, &__graph and &__graph-title, are the wrapper and label that go around every chart in the report.
Navigation
Forty-three pages of scroll needs a position indicator, so the report carries a sticky table of contents. A scroll handler reads the offset of every h2[id^="section-"] and toggles .active on the matching link. That part is ordinary.
The part that took the tuning was the rail's own behavior at the bottom of the document. It flips between is-stuck and is-absolute depending on how much sidebar is left, so it pins to the floor of its column instead of sliding over the footer. The same handler serves both publications.
Scroll spy, condensed
var $sections = $('h2[id^="section-"]');$(window).on('scroll', function () { var y = $(window).scrollTop() + 120; var id; $sections.each(function () { if (y >= $(this).offset().top) id = this.id; }); $('.p-study__toc a') .removeClass('active') .filter('[href="#' + id + '"]') .addClass('active');});
The rail in the browser frame at the top of this page runs the same active-link logic on a timer.
The Hardest Interaction
The Dispute Disparity Scale is the report's original framing device: for eight everyday situations it plots how appropriate a chargeback looks to the merchant against how appropriate it looks to the cardholder. The interesting part is that the two almost never agree, and the gap widens exactly where the dispute is most arguable.
It ships as one tall SVGator timeline rather than eight separate graphics, which means the browser has to be told where in that timeline to stop. A scroll handler tracks which scenario is in view, compares the current offset against the last one to work out which way the reader is travelling, then seeks the player to that scenario's frame and plays forward or in reverse to meet it. The frames in that table started out hand-scrubbed, which meant every re-export broke them silently. They are now read straight out of the timeline the export ships, so a new version is re-derived instead of re-timed.
Pick a scenario to drive the same player the report uses. The card beside the scale is the situation it is scoring.
Vicky orders expensive sunglasses online and overdraws her account. Facing bills and a negative balance, she panics and tells her bank the card was stolen.
Sarah lets her child play unsupervised on her phone. The child spends almost $100 in-game. She tells the bank she never authorized it, and does not mention the child.
David buys an NFT, then researches it and regrets the purchase. It is now worth far less than he paid. Feeling misled, he contacts his bank rather than the seller.
Nick can only cancel by phone during business hours, and he is busy all day. The membership renews, so he challenges the charge in his banking app.
Andrew enters his card to cover shipping on a free trial, without noticing he is also agreeing to be billed. The terms were on the page, small, at the very bottom.
George receives a product that does not match the listing photos. Returning it means paying the postage himself, so he goes to his bank to avoid the cost.
Christy is two weeks into a seven-day delivery with no word from the seller. She gives up after ten minutes on hold and contacts her bank.
Justin sees a charge on his statement he does not recognize. Fearing the account is compromised, he calls his bank to report possible fraud.
The production asset, running the shared player. On the report this is pinned beside eight full-height scenario blocks and driven purely by scroll position; here the same calls are wired to the list instead.
Calibration
A timeline has no concept of “scenario four”. It only has milliseconds. So the build gives every scenario its own hitbox on the timeline: an entry frame and a run duration, held in a lookup the scroll handler reads. Direction is part of the key, because arriving at a scenario from above covers a different stretch of animation than arriving from below, and each gets its own pair.
That makes the whole interaction declarative. Retiming a scenario, reordering them, or dropping one in is a line in the table rather than a rewrite of the handler, and the calibration pass that set those frames was a single sweep against the animation rather than a running fight with it.
It is also why the same graphic and the same table drop straight into both annual reports: the scale was calibrated once and the second title inherited it whole.
Direction-aware seek
var STEPS = { example1: { down: [2950, 700], up: [5050, 600] }, example2: { down: [4450, 600], up: [6550, 600] }, /* ...six more, read from the export */};function show(id, forward) { var f = STEPS[id][forward ? 'down' : 'up']; player.stop(); player.seekTo(f[0]); forward ? player.play() : player.reverse(); // stop it on the frame this scenario belongs to setTimeout(player.pause, f[1]);}
The report compares the current scroll offset against the previous one to decide which pair to use.
Lead Capture
The Index earns its readers on the findings alone, and marketing values the contact those findings can earn just as much, so the second half asks for a work email before it continues. Readers see enough of the study first to judge whether the rest is worth the exchange, and the ask arrives with the reason attached.
The prompt is anchored to a chapter boundary, the start of the second report section, so it appears once a complete argument has landed rather than after an arbitrary page count or a timer. It is a real lock, not a cosmetic cover: the rest of the report simply isn't in the page until it is unlocked. Submitting writes an unlock key to localStorage, so a returning reader is never asked twice, and one component parameterized by data-gate-key covers both publications.
The demo alongside runs the real mechanic: unlock it, reload this page, and it stays unlocked until you clear it.
Keep reading the 2025 Index
A work email unlocks the rest of the report.
What started as “build the CDI page” became a reusable publication system. A second annual title, 62 charts across its own 43 pages, shipped on the same SASS foundation without a single new stylesheet line (a couple of inline tweaks aside). Every edition since has been an additive build rather than a rebuild, and the cycle repeats each year.
The gate gives marketing a lead mechanism tied to content people actually want. The animated charts give the data a presence it never had as a download. And the consolidated live text, recovered one file at a time from Illustrator's glyph fragments, means the report is finally searchable, selectable and readable by assistive technology, the way a research report on a website should have been all along.