// Case Study detail page — template used for all case studies.
// Matches Subpages system: paper bg, italic display headline, mono eyebrows.

// Official brand asset host (posters, logos) from the Ignited media inventory.
const IGN = "https://www.ignitedusa.com/wp-content/uploads";

// True for dark card backgrounds — handles any hex color (by luminance) or --ink tokens.
const isDarkBg = (bg) => {
  if (!bg) return false;
  if (/var\(--ink/.test(bg)) return true;
  const hex = bg.trim().match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
  if (hex) {
    let h = hex[1];
    if (h.length === 3) h = h.split("").map((c) => c + c).join("");
    const r = parseInt(h.slice(0, 2), 16),
      g = parseInt(h.slice(2, 4), 16),
      b = parseInt(h.slice(4, 6), 16);
    return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 < 0.4;
  }
  return false;
};

const CASE_STUDIES = (window.__CMS_DATA__ && window.__CMS_DATA__.cases) || {
  soylent: {
    slug: "soylent",
    client: "Soylent",
    industry: "Functional Nutrition · CPG",
    logo: "assets/clients/soylent.png",
    logoBg: "var(--paper-2)",
    services: ["Brand strategy", "Creative development", "Production", "Experiential", "Media planning"],
    headline: {
      lead: "Expanding a niche tech drink",
      accent: "to reach hustlers."
    },
    summary:
    "Soylent sought to expand their audience to reach like‑minded people who hustle hard, and often don’t make time to eat properly. We helped them develop messaging, reach new audiences in new ways, and launch meal bars to complement their famous meal replacement drinks.",
    challenge: [
    "As Soylent looked to scale beyond its early adopter audience of male tech‑industry workers, the brand faced the challenge of broadening awareness and driving sales without alienating core consumers.",
    "Soylent needed a cohesive omnichannel strategy that would position Ready‑to‑Drink beverages and Squared Nutrition Bars as convenient, complete nutrition for a broader audience of ambitious people with busy lifestyles.",
    "In an increasingly crowded wellness and functional nutrition market, Soylent also needed to break through cultural and media clutter with messaging that felt both informative and entertaining while supporting aggressive growth and expansion goals."],

    approach: [
    "Ignited developed an integrated awareness and performance campaign centered around the idea that “Soylent fuels your hustle.” We created a man‑on‑the‑street style campaign featuring the character “Dr. Fuelgood” engaging consumers in Times Square, resulting in an entertaining and engaging campaign with video, social, and out‑of‑home creative executions.",
    "To support the campaign, Ignited refreshed website messaging and imagery, activated social and digital media partnerships to drive awareness across key moments in consumers’ daily routines, and implemented a multi‑channel media strategy spanning programmatic display, connected TV, search, shopping, retail, and experiential integrations."],

    results: {
      copy:
      "The campaign successfully increased aided awareness, drove significant lifts in social brand metrics, boosted site traffic by 36%, and contributed to a 17% increase in dotcom revenue.",
      stats: [
      { value: "+36%", label: "Site traffic lift" },
      { value: "+17%", label: "increase dotcom revenue" }]

    },
    videos: [
    { id: "273804195", title: "Hero spot · Soylent fuels your hustle", poster: `${IGN}/2022/09/hero.png` },
    { id: "273802820", title: "Dr. Fuelgood · Times Square", poster: `${IGN}/2022/09/vid1.png` },
    { id: "276458204", title: "Need / Want · 30s", poster: `${IGN}/2022/09/vid2.png` },
    { id: "423468113", title: "Ready‑to‑Drink launch", poster: `${IGN}/2022/09/vid3.png` },
    { id: "740483066", title: "Soylent Squared launch", poster: `${IGN}/2022/09/vid4.png` },
    { id: "740483041", title: "Squared social cutdown", poster: `${IGN}/2022/09/vid5.png` }],

    next: "gfuel"
  },
  gfuel: {
    slug: "gfuel",
    client: "G FUEL",
    industry: "Beverages · Gaming",
    logo: "assets/clients/gfuel.png",
    logoInvert: false,
    logoBg: "#0A0A0F",
    services: ["Brand management", "Influencer management", "Concepting", "Production"],
    headline: { lead: "Reimagining the original", accent: "gamer drink brand." },
    summary:
    "Supporting G FUEL’s new leadership through a rebrand, new product launches, and a new generation of entertainment partnerships.",
    challenge: [
    "G FUEL launched in 2012 as a drink brand serving eSports athletes. Thirteen years later, the world of G FUEL, influencers, and branded entertainment beverages has exploded and evolved.",
    "Supporting the new leadership of the company, Ignited helped manage the rebranding of the company, the launch of new products, and the evolution of the company’s partnerships."],

    approach: [
    "G FUEL’s unique approach was to launch products in partnership with influencers and well-known entertainment brands. The company entered into a partnership with the team behind the Scream movies to bring out a new flavor inspired by the GhostFace character.",
    "To bring this idea to life, we developed a short film under the premise that GhostFace now has an agent and has become a big-time influencer — which is true. The campaign was augmented with dozens of videos from prominent influencers."],

    results: {
      copy:
      "The campaign racked up millions of views and helped deliver a profitable success for the company.",
      stats: [
      { value: "Millions", label: "Video views across the campaign" },
      { value: "Profit", label: "A profitable success for the brand" }]

    },
    videos: [
    { id: "1050919969", title: "G FUEL 2024 · Brand spot", poster: `${IGN}/2015/01/poster-gfuel-2024.jpg` },
    { id: "1050919857", title: "GhostFace × G FUEL · Short film", poster: `${IGN}/2015/01/poster-gfuel-ghostface.jpg` },
    { id: "1050918929", title: "GhostFace · 30s cutdown", poster: `${IGN}/2015/01/poster-gfuel-ghostface-30.jpg` },
    { id: "1052375147", title: "Hydration + Protein", poster: `${IGN}/2015/01/poster-gfuel-hydration-protein.jpg` },
    { id: "1050918944", title: "Shrek × G FUEL", poster: `${IGN}/2015/01/poster-gfuel-shrek.jpg` },
    { id: "1051690552", title: "Shrek · Fairytale", poster: `${IGN}/2015/01/poster-gfuel-shrek-fairtale.jpg` },
    { id: "1051690568", title: "Shrek · Swamp", poster: `${IGN}/2015/01/poster-gfuel-shrek-swamp.jpg` },
    { id: "1051690606", title: "Shrek · Shaker", poster: `${IGN}/2015/01/poster-gfuel-shrek-shaker.jpg` },
    { id: "1051690711", title: "Shrek · Waffles", poster: `${IGN}/2015/01/poster-gfuel-shrek-waffles.jpg` },
    { id: "1051690775", title: "Shrek · Waffles II", poster: `${IGN}/2015/01/poster-gfuel-shrek-waffles.jpg` },
    { id: "1051690654", title: "Shrek · Waffles III", poster: `${IGN}/2015/01/poster-gfuel-shrek-waffles.jpg` },
    { id: "1050918895", title: "One Piece × G FUEL", poster: `${IGN}/2015/01/poster-gfuel-onepiece.jpg` },
    { id: "1051690837", title: "One Piece · Wanted", poster: `${IGN}/2015/01/poster-gfuel-onepiece-wanted.jpg` },
    { id: "1052374932", title: "Jynxzi × G FUEL", poster: `${IGN}/2015/01/poster-gfuel-jynxzi.jpg` }],

    next: "aerovironment"
  },
  aerovironment: {
    slug: "aerovironment",
    client: "AeroVironment",
    industry: "Aerospace & Defense",
    logo: `${IGN}/2025/02/logo_AV_Black.png`,
    logoInvert: true,
    logoBg: "#11161D",
    services: ["Brand strategy", "Creative development", "Creative production"],
    headline: { lead: "Introducing a drone leader to", accent: "the next generation of engineers." },
    summary:
    "Evolving a 50-year-old aerospace and defense brand to attract a new generation of engineering talent.",
    challenge: [
    "As a 50+ year-old aerospace and defense company, AV faced the challenge of evolving the brand and attracting a new generation of engineering talent in an increasingly competitive tech market.",
    "AV needed a positioning that reflected its leadership in next-generation autonomous systems, while modernizing perceptions beyond traditional defense audiences. At the same time, the company sought to strengthen recruitment by communicating a culture that combined the agility of a startup with the resources, stability, and mission-driven purpose of an established aerospace leader."],

    approach: [
    "To develop the new positioning, Ignited audited AV’s existing brand documents, held 12 stakeholder interviews across marketing, business development, talent acquisition, program management, engineering, and executive leadership, conducted a competitive analysis, moderated a 7-hour brand positioning workshop, and developed a report with findings and a brand framework.",
    "Building on the new positioning, Ignited created an integrated recruitment and awareness campaign centered on AV’s engineers and innovators. To attract top-tier talent, we launched the “Another Day at AV” social campaign — videos and social assets designed to humanize the brand, spotlight company culture, and reinforce AV’s role at the forefront of aerospace and autonomous technology."],

    results: {
      copy:
      "Ignited delivered a refined brand positioning and creative platform centered on AV’s engineers and innovators — activated through the integrated “Another Day at AV” recruitment and awareness campaign.",
      stats: [
      { value: "Exceeded", label: "recruitment goals" }]

    },
    videos: [
    { id: "1051721196", title: "Another Day at AV · Undisclosed", poster: `${IGN}/2025/01/poster-av-undisclosed.jpg` },
    { id: "1051721054", title: "Another Day at AV · Gigawatts", poster: `${IGN}/2025/01/poster-av-gigawatts.jpg` },
    { id: "1051721092", title: "Another Day at AV · Redacted", poster: `${IGN}/2025/01/poster-av-redacted.jpg` },
    { id: "1051721164", title: "Another Day at AV · Seriously", poster: `${IGN}/2025/01/poster-av-seriously.jpg` },
    { id: "1051721130", title: "Another Day at AV · Snack", poster: `${IGN}/2025/01/poster-av-snack.jpg` }],

    next: "chickenofthesea"
  },
  chickenofthesea: {
    slug: "chickenofthesea",
    client: "Chicken of the Sea",
    industry: "CPG · Seafood",
    logo: "assets/clients/chicken-of-the-sea.png",
    logoBg: "var(--paper-2)",
    services: ["Media strategy & investment", "Media analytics"],
    headline: { lead: "Turning a pop-culture moment into", accent: "a modern marketing success." },
    summary:
    "Twenty years after Jessica Simpson’s “Is this chicken or tuna?” moment, we reignited cultural relevance for Chicken of the Sea.",
    challenge: [
    "Chicken of the Sea faced the challenge of standing out in the highly competitive canned-seafood packet and pouch category, while modernizing perceptions and introducing its new flavored tuna packets to younger consumers without alienating its loyal base.",
    "To break through a crowded sea of tuna products and reignite cultural relevance, the brand leaned into one of the internet’s earliest viral moments — Jessica Simpson’s iconic “Is this chicken or tuna?” line from Newlyweds — using nostalgia, social-first storytelling, and creator-driven platforms."],

    approach: [
    "Although the moment occurred nearly 20 years ago, the brand’s search, social, and video monitoring consistently revealed strong consumer affinity for both Jessica and the brand. Sustained keyword volume and ongoing cultural relevance signaled an opportunity to reintroduce Jessica as a brand ambassador — and the 20th anniversary, paired with new music from Jessica, made the timing right.",
    "Rooted in the strategy “Social is the New Reality TV,” we deployed the largest and most targetable social channels — including launching the brand on TikTok for the first time. Channel tactics maximized visibility of the Jessica Simpson hero video, while the campaign was also designed to drive earned media value through social commentary and newsworthy discourse."],

    results: {
      copy:
      "262M paid impressions and 1.2B+ earned impressions turned a 20-year-old pop-culture moment into measurable brand lift.",
      stats: [
      { value: "262M", label: "Paid media impressions across Meta, TikTok & YouTube" },
      { value: "111M", label: "Unique users reached" },
      { value: "1.2B", label: "Additional earned impressions" },
      { value: "63.5M", label: "Video views · 80%+ YouTube completion rate" }]

    },
    videos: [
    { youtube: "1CRAoumL61c", title: "Jessica Simpson · Hero video" },
    { id: "828059064", title: "Is this chicken or tuna? · Social", poster: `${IGN}/2022/09/COS_Vid-1.png` },
    { id: "828058909", title: "TikTok launch · Cutdown", poster: `${IGN}/2022/09/COS_Vid-3.png` },
    { id: "828058754", title: "Anniversary spot · Horizontal", poster: `${IGN}/2022/09/COS_Vid_horiz-3.png` }],

    next: "archer"
  },
  archer: {
    slug: "archer",
    client: "Archer",
    industry: "CPG · Snacks",
    logo: "assets/clients/archer.png",
    logoBg: "var(--paper-2)",
    logoScale: 1.25,
    services: ["Media planning & buying", "Analytics"],
    headline: { lead: "Owning the pause —", accent: "turning streaming breaks into snack time." },
    summary:
    "A first-to-market CTV Pause Ads campaign that put Archer’s refreshed brand in front of viewers at the perfect snacking moment.",
    challenge: [
    "After undergoing a significant rebrand in 2025, Archer needed to accelerate awareness of its refreshed identity and stand out in an increasingly competitive meat-snacks category.",
    "The brand sought innovative media solutions that could introduce its modern positioning to consumers at scale."],

    approach: [
    "Archer partnered with GumGum and Ignited to launch a first-to-market CTV Pause Ads campaign, appearing only when viewers paused streaming content. The activation aligned Archer with high-attention, snack-relevant moments across connected TV — helping the brand stand out without interrupting the viewing experience.",
    "By targeting relaxation, entertainment, and food-focused content, the campaign connected with consumers during intentional breaks, when they were most receptive to snacking."],

    results: {
      copy:
      "A first-to-market programmatic CTV Pause Ad activation that drove double-digit lifts in awareness and purchase intent.",
      stats: [
      { value: "+11.5pt", label: "Lift in aided brand awareness" },
      { value: "+10pt", label: "Increase in purchase intent" },
      { value: "+5pt", label: "Increase in brand favorability" },
      { value: "1st", label: "First-to-market programmatic CTV Pause Ad" }]

    },
    videos: [
    { id: "1203622700", h: "3d813207ae", title: "Archer · CTV Pause Ad" },
    { id: "1203623939", h: "f98fba0571", title: "Archer · Brand campaign" }],

    next: "shu"
  },
  shu: {
    slug: "shu",
    client: "Sacred Heart University",
    industry: "Higher Education",
    logo: "assets/clients/sacred-heart-university.png",
    logoBg: "var(--paper-2)",
    services: ["Brand strategy", "Paid search & Meta", "Google PMAX", "Media planning", "Creative development", "Conversion tracking & analytics"],
    headline: { lead: "Navigating a competitive", accent: "higher-ed enrollment landscape." },
    summary:
    "Strengthening enrollment marketing performance while advancing long-term brand strategy for SHU.",
    challenge: [
    "Higher education institutions face increased pressure to drive enrollment efficiently amid rising competition, changing student expectations, and heightened scrutiny around marketing investment and ROI.",
    "Since July 2025, Ignited has partnered with SHU to strengthen enrollment marketing performance while advancing long-term brand strategy — balancing immediate lower-funnel enrollment goals with broader initiatives across SEO, creative development, audience strategy, and integrated media planning."],

    approach: [
    "Ignited combined performance-marketing optimization with foundational brand and audience work. We focused on lower-funnel performance across Google Search and Meta — streamlining campaign structures, removing redundancies, refining geographic targeting, and shifting bids toward conversion-focused objectives. We also expanded SHU into TikTok and implemented enhanced conversion tracking around “Apply Now,” “Request Info,” and “Schedule a Visit.”",
    "At the same time, we built a stronger strategic foundation — conducting competitive assessments, identifying whitespace in the higher-ed landscape, facilitating a brand workshop, developing messaging frameworks, advancing SEO recommendations, and creating integrated creative concepts for graduate and undergraduate enrollment campaigns."],

    results: {
      copy:
      "In collaboration with landing-page optimizations, 65% of graduate-program conversions are now attributable to paid media.",
      stats: [
      { value: "65%", label: "Of grad-program conversions attributable to paid media" },
      { value: "1st", label: "SHU’s first Google PMAX campaigns launched" },
      { value: "+", label: "Improved efficiency through streamlined account structures" }]

    },
    videos: [
    { id: "1203634719", h: "cdd1804666", title: "Sacred Heart · Enrollment campaign" },
    { id: "1203634718", h: "c3ba5129d9", title: "Sacred Heart · Brand spot" }],

    next: "razer"
  },
  razer: {
    slug: "razer",
    client: "Razer",
    industry: "Consumer Electronics",
    logo: "assets/clients/razer-dark.png",
    logoInvert: false,
    logoBg: "#0A0A0F",
    logoScale: 1.25,
    services: ["Strategy", "Creative development", "Creative production", "Paid media"],
    headline: { lead: "Repositioning a gaming icon", accent: "for the mainstream." },
    summary:
    "Launching the Razer Book — the brand’s first non-gaming device — to expand Razer beyond its core gaming audience.",
    challenge: [
    "Founded in 2005, Razer established itself as the leading lifestyle and consumer-electronics brand for gamers, building a loyal following through a premium ecosystem designed for gaming culture and youth audiences.",
    "With the launch of the Razer Book — a premium productivity laptop and the brand’s first non-gaming device — Razer faced the challenge of expanding beyond its core gaming audience to compete in the broader laptop category. The opportunity was to reposition Razer from a gaming-first brand into a mainstream premium lifestyle brand."],

    approach: [
    "To launch the Razer Book globally, Ignited developed an integrated campaign designed to evolve Razer’s perception from gaming powerhouse to premium productivity lifestyle brand. Grounded in the insight that Razer’s legacy of high-performance engineering and precision could naturally extend beyond gaming, the campaign positioned the Razer Book at the intersection of performance and productivity.",
    "We leaned into Razer’s bold, edgy heritage while showcasing the laptop’s premium capabilities through a digital-first campaign featuring cinematic trailer-style videos, paid social, dynamic digital banners, and a dedicated landing page — all crafted to resonate with a mainstream, urban audience seeking both style and performance."],

    results: {
      copy:
      "A cinematic, digital-first global launch that drove millions of views in its first two weeks in market.",
      stats: [
      { value: "Millions", label: "Video views in the first two weeks of launch" },
      { value: "Global", label: "Integrated launch across paid social & digital" }]

    },
    videos: [
    { id: "1203618586", h: "8d3fc8cc0f", title: "Razer Book · Launch film" }],

    next: "zico"
  },
  zico: {
    slug: "zico",
    client: "ZICO",
    industry: "Beverages · CPG",
    logo: "assets/clients/zico.png",
    logoBg: "var(--paper-2)",
    services: ["Strategy", "Creative development", "Creative production", "Paid media", "Experiential marketing"],
    headline: { lead: "A natural beverage that hydrates", accent: "everyday athletes." },
    summary:
    "The “Naturally Powered” platform that grew ZICO from an emerging coconut-water brand into a culturally relevant lifestyle brand.",
    challenge: [
    "ZICO entered an oversaturated sports-beverage market dominated by established competitors with significantly larger budgets, stronger distribution, and greater brand recognition.",
    "The challenge was not only to introduce a relatively new coconut-water brand, but to differentiate it in a category crowded with sugary, artificial sports drinks — building meaningful awareness, trial, and loyalty among active-lifestyle audiences with a platform that could compete on a national stage."],

    approach: [
    "Ignited developed the “Naturally Powered” strategic and creative platform to position ZICO as the hydration choice for consumers pursuing a natural, active lifestyle. Grounded in the insight that athletes and wellness-focused consumers were seeking cleaner alternatives, the campaign established a bold brand voice activated across social, digital, mobile, out-of-home, print, point-of-sale, celebrity partnerships, and experiential marketing.",
    "To bring the brand to life in-market, Ignited conceived and managed more than 700 activation and sampling events across Los Angeles, Miami, and New York — targeting “Natural Athletes” across yoga, running, cycling, surfing, and other active-lifestyle communities."],

    results: {
      copy:
      "An integrated campaign that tripled sales in half the anticipated timeframe and helped position ZICO for national distribution and sale to Coca-Cola.",
      stats: [
      { value: "3×", label: "Sales tripled in half the anticipated time" },
      { value: "700+", label: "Activation & sampling events across key U.S. markets" },
      { value: "705K+", label: "Product samples distributed" },
      { value: "4.4M+", label: "Impressions generated" }]

    },
    videos: [
    { id: "109757713", title: "“Naturally Powered” · Brand film", poster: `${IGN}/2022/09/zico_hero.png` },
    { id: "215739717", title: "Experiential activations · Recap", poster: `${IGN}/2022/09/zico1.png` }],

    next: "kevita"
  },
  kevita: {
    slug: "kevita",
    client: "KeVita",
    industry: "Probiotic Beverages · CPG",
    logo: "assets/clients/kevita.png",
    logoBg: "var(--paper-2)",
    logoScale: 0.82,
    services: ["Strategy", "Creative development", "Creative production", "Paid media"],
    headline: { lead: "Introducing kombucha", accent: "to the masses." },
    summary:
    "Transforming KeVita from a niche health brand into a mainstream wellness product following its acquisition by PepsiCo.",
    challenge: [
    "As KeVita entered a new phase of growth following its acquisition by PepsiCo, the brand faced the challenge of transforming from a niche beverage embraced primarily by health enthusiasts into a mainstream wellness product with broader household appeal.",
    "In a category dominated by entrenched competitors and polarized perceptions around taste and authenticity, KeVita needed to expand awareness, drive trial, and position its products as an approachable part of everyday gut-health routines — all while navigating strict limits on health claims and rapidly increasing distribution goals."],

    approach: [
    "Ignited developed an integrated digital campaign focused on awareness, education, and trial — positioning KeVita as a more approachable, better-tasting alternative within the kombucha and probiotic category. Grounded in the insight that consumers often became loyal fans once they tried the product, the campaign combined search, influencer partnerships, custom editorial and video content, paid social, and programmatic media.",
    "The program also launched KeVita’s first-ever Facebook chatbot experience — designed to educate consumers, increase engagement, and drive traffic to product pages, discounts, and store locators, while building a scalable content ecosystem to support rapid expansion."],

    results: {
      copy:
      "An education-led digital campaign that drove a major lift in store-locator traffic and nearly a million influencer engagements.",
      stats: [
      { value: "+428%", label: "Increase in website traffic to the store locator" },
      { value: "~1M", label: "Engagements from the influencer program" },
      { value: "↑", label: "Increased household penetration and sales lift" }]

    },
    videos: [],
    gallery: [
    { src: "assets/kevita-sauna.jpg", caption: "Sparkling Probiotic · brand photography" },
    { src: "assets/kevita-expowest.jpg", caption: "Expo West · “Alive Like You” activation" },
    { src: "assets/kevita-sampling.webp", caption: "Sampling tour · New York City" }],

    next: "pldt"
  },
  pldt: {
    slug: "pldt",
    client: "PLDT",
    industry: "Telecom",
    logo: "assets/clients/pldt.png",
    logoBg: "var(--paper-2)",
    services: ["Strategy", "Creative development", "Creative production", "Experiential marketing"],
    headline: { lead: "A bold rebrand to", accent: "win back market momentum." },
    summary:
    "A unified rebrand of the Philippines’ original phone company and its mobile brand, Smart — restoring pride and momentum.",
    challenge: [
    "PLDT was facing market-share erosion as aggressive competitors entered the mobile market against their brand, Smart.",
    "Ignited worked with the leadership team to analyze the opportunity to rebrand the original phone company — “Philippine Long Distance Telephone” — and its mobile brand, Smart, together in a unified branding and marketing campaign."],

    approach: [
    "The program took a year and resulted in a restoration of momentum for the brand, an increase in pride among their 10,000 employees, and a renewed focus on innovation and growth.",
    "The rebrand became a rallying point for the company, culminating in an event in Manila that brought the 1,500 leaders of the business together — and was reinforced through the rebrand of thousands of PLDT and Smart stores."],

    results: {
      copy:
      "A unified rebrand that became a rallying point for the company and put the brand back on a path to stability and growth.",
      stats: [
      { value: "10,000", label: "Employees re-energized around a new identity" },
      { value: "1,500", label: "Leaders united at the Manila relaunch" },
      { value: "1,000s", label: "Of PLDT & Smart stores rebranded" }]

    },
    videos: [
    { id: "208217928", title: "PLDT × Smart · Rebrand launch film", poster: `${IGN}/2022/09/PLDT_hero.png` },
    { id: "170329418", title: "Smart · Brand spot", poster: `${IGN}/2022/09/pldt1.png` },
    { id: "173808534", title: "Manila relaunch · Event", poster: `${IGN}/2022/09/pldt3.png` }],

    next: "universal"
  },
  universal: {
    slug: "universal",
    client: "Universal Pictures",
    industry: "Entertainment · Film",
    logo: "assets/clients/nbcuniversal-dark.png",
    logoBg: "#0A0A0F",
    services: ["Influencer strategy", "Paid media"],
    headline: { lead: "From social buzz to", accent: "sold-out theaters." },
    summary:
    "A socially driven influencer campaign that turned Pitch Perfect from an underdog release into a box-office hit.",
    challenge: [
    "Launching Pitch Perfect in a summer movie season dominated by blockbuster franchises, celebrity-driven casts, and massive studio marketing budgets, Universal Pictures needed to generate awareness and excitement for a niche comedy centered on a cappella music, featuring an ensemble cast with no major box-office stars.",
    "To succeed, the campaign had to break through cultural noise and connect authentically with a highly social, digitally connected audience of young women who relied heavily on peer recommendations and online conversations to discover entertainment."],

    approach: [
    "Ignited developed a socially driven influencer campaign designed to turn online conversations into real-world movie attendance. Grounded in the insight that word of mouth is one of the most powerful forces in entertainment marketing, the campaign partnered with influential digital creators and YouTube personalities to create organic engagement among the film’s core audience.",
    "A key execution included collaborating with popular a cappella creator Mike Tompkins on a crowd-sourced rendition of Nicki Minaj’s “Starships,” featuring participation from the Pitch Perfect cast. By integrating influencer content, user participation, and social sharing, Ignited transformed the film into a cultural conversation and box-office hit."],

    results: {
      copy:
      "Influencer-driven social buzz translated directly into box-office impact — with opening-weekend sales far outpacing the top films of the season.",
      stats: [
      { value: "+311%", label: "Opening-weekend ticket sales vs. the top-10 films’ average" },
      { value: "63M+", label: "Video views" },
      { value: "18–24", label: "Drove awareness among women ages 18–24" }]

    },
    videos: [
    { id: "106982255", title: "Pitch Perfect · Hero", poster: `${IGN}/2022/09/universal_hero.png` },
    { id: "106982117", title: "“Starships” · Crowd-sourced cover", poster: `${IGN}/2022/09/universal1.png` },
    { id: "215085356", title: "Influencer collabs · Social", poster: `${IGN}/2022/09/universal2.png` }],

    next: "soylent"
  }
};

// Normalize a case-study record so the page never crashes on partial content
// created through the CMS. Accepts both the rich legacy shape and simpler
// admin-entered shapes (e.g. headline as a string, results as a flat array).
function normalizeCase(raw) {
  const d = raw || {};
  const headline =
    typeof d.headline === "string"
      ? { lead: d.headline, accent: "" }
      : (d.headline && typeof d.headline === "object")
        ? { lead: d.headline.lead || "", accent: d.headline.accent || "" }
        : { lead: d.client || "Case study", accent: "" };

  const toParas = (v) => Array.isArray(v) ? v : (v ? [String(v)] : []);

  let results = d.results;
  if (Array.isArray(results)) {
    // Flat array of { stat/value, label } → expected { copy, stats:[{value,label}] }
    results = {
      copy: d.resultsCopy || "",
      stats: results.map((s) => ({ value: s.value || s.stat || "", label: s.label || "" })),
    };
  } else if (results && typeof results === "object") {
    results = { copy: results.copy || "", stats: Array.isArray(results.stats) ? results.stats : [] };
  } else {
    results = { copy: "", stats: [] };
  }

  return {
    slug: d.slug,
    client: d.client || "",
    industry: d.industry || "",
    logo: d.logo || "",
    logoBg: d.logoBg || "",
    logoInvert: d.logoInvert || false,
    logoScale: typeof d.logoScale === "number" ? d.logoScale : 1,
    headline,
    videos: Array.isArray(d.videos) ? d.videos : [],
    gallery: Array.isArray(d.gallery) ? d.gallery : [],
    challenge: toParas(d.challenge),
    approach: toParas(d.approach),
    results,
    next: d.next || "",
  };
}

const CaseStudyPage = ({ slug, onOpen }) => {
  const data = normalizeCase(CASE_STUDIES[slug] || CASE_STUDIES.soylent);

  return (
    <main style={{ background: "var(--paper)", paddingBottom: 0 }}>
      {/* Hero */}
      <section className="container r-page-head" style={{ paddingTop: 56, paddingBottom: 72 }}>
        <div className="mono" style={{ color: "var(--muted)", marginBottom: 28, display: "flex", gap: 18, alignItems: "center" }}>
          <a href="index.html#case-studies" style={{ color: "var(--muted)", display: "inline-flex", alignItems: "center", gap: 6 }}>
            <span style={{ display: "inline-block", transform: "rotate(180deg)" }}><ArrowRight size={10} /></span>
            All case studies
          </a>
          <span style={{ opacity: 0.4 }}>/</span>
          <span style={{ color: "var(--blue)" }}>◆</span>
          <span>Case study · {data.industry}</span>
        </div>

        <div className="r-cs-hero-grid" style={{ display: "grid", gridTemplateColumns: "minmax(120px, 170px) 1fr", gap: 48, alignItems: "center" }}>
          <ClientLogoCard logo={data.logo} client={data.client} bg={data.logoBg} invert={data.logoInvert} logoScale={data.logoScale} />
          <div>
            <h1
              className="display"
              style={{

                margin: 0,
                lineHeight: 0.94,
                letterSpacing: "-0.035em",
                textWrap: "balance", fontSize: "76px", padding: "9px 0px 0px"
              }}>
              
              {data.headline.lead}{" "}
              <span style={{ fontStyle: "italic", fontWeight: 500, color: "var(--blue)" }}>
                {data.headline.accent}
              </span>
            </h1>
          </div>
        </div>
      </section>

      {/* Work — videos (moved up, beneath hero, no section headline) */}
      {data.videos.length > 0 &&
      <section className="container r-page-section" style={{ paddingTop: 8, paddingBottom: 96 }}>
        <div
          className="r-cs-videos"
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(2, 1fr)",
            gap: 32
          }}>
          
          {data.videos.map((v, i) =>
          <VideoCard key={v.id || v.youtube || `ph-${i}`} index={i + 1} {...v} />
          )}
        </div>
      </section>
      }

      {/* Work — in-market photography gallery */}
      {data.gallery && data.gallery.length > 0 &&
      <section className="container r-page-section" style={{ paddingTop: data.videos.length > 0 ? 0 : 8, paddingBottom: 96 }}>
        <PhotoGallery items={data.gallery} />
      </section>
      }

      {/* Challenge + Approach */}
      <section className="container r-page-section" style={{ paddingTop: 96, paddingBottom: 96 }}>
        <div className="r-cs-two-col" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 96, alignItems: "start" }}>
          <ColBlock
            index="01"
            title="The Challenge"
            paras={data.challenge} />
          
          <ColBlock
            index="02"
            title="Our Approach"
            paras={data.approach} />
          
        </div>
      </section>

      {/* Results — dark slab */}
      <section style={{ background: "var(--ink)", color: "var(--paper)", padding: "112px 0" }}>
        <div className="container">
          <SectionEyebrow index="03" label="The Results" color="rgba(255,255,255,0.55)" />
          <div className="r-cs-results-grid" style={{ marginTop: 36, display: "grid", gridTemplateColumns: "1.05fr 1fr", gap: 80, alignItems: "end" }}>
            <h2
              className="display"
              style={{
                fontSize: "clamp(34px, 4.2vw, 64px)",
                margin: 0,
                lineHeight: 1.02,
                letterSpacing: "-0.025em",
                textWrap: "balance"
              }}>
              
              {data.results.copy}
            </h2>
            <div style={{ display: "grid", gridTemplateColumns: "1fr", gap: 0 }}>
              {data.results.stats.map((s, i) =>
              <StatRow key={i} value={s.value} label={s.label} first={i === 0} />
              )}
            </div>
          </div>
        </div>
      </section>

      {/* Next CS */}
      <section style={{ borderTop: "1px solid var(--rule)" }}>
        <div className="container" style={{ padding: "72px 0" }}>
          <NextCaseStudy slug={data.next} onOpen={onOpen} />
        </div>
      </section>
    </main>);

};

// ── Subcomponents ────────────────────────────────────────────────────

const ClientLogoCard = ({ logo, client, bg, invert, logoScale = 1 }) => {
  // If bg is dark, render light-on-dark; otherwise treat as a light card (no filter).
  const isDark = isDarkBg(bg);
  // Default: invert light logos to white on dark cards. Pass invert={false} for color logos.
  const doInvert = invert === undefined ? isDark : invert;
  return (
    <div
      style={{
        width: "100%",
        aspectRatio: "1 / 1",
        background: bg || "var(--paper-2)",
        border: "1px solid var(--rule-strong)",
        display: "grid",
        placeItems: "center",
        padding: 28,
        position: "relative"
      }}>
      
      <span
        className="mono"
        style={{
          position: "absolute",
          top: 12,
          left: 14,
          fontSize: 9,
          color: isDark ? "rgba(255,255,255,0.5)" : "var(--muted)"
        }}>
        
        ◆ Client
      </span>
      {logo ?
      <img
        src={logo}
        alt={client}
        style={{
          maxWidth: `${Math.min(80 * logoScale, 100)}%`,
          maxHeight: `${Math.min(60 * logoScale, 100)}%`,
          width: "auto",
          height: "auto",
          objectFit: "contain",
          filter: doInvert ? "brightness(0) invert(1)" : "none",
          mixBlendMode: isDark ? "normal" : "multiply"
        }} /> :


      <div
        className="display"
        style={{
          fontSize: 28,
          color: isDark ? "white" : "var(--ink)",
          letterSpacing: "-0.02em",
          textTransform: "uppercase"
        }}>
        
          {client}
        </div>
      }
    </div>);

};

const CsMeta = ({ label, value }) =>
<div>
    <div className="mono" style={{ color: "var(--muted)", marginBottom: 8 }}>{label}</div>
    <div style={{ fontSize: 15, lineHeight: 1.45, color: "var(--ink)", letterSpacing: "-0.005em" }}>{value}</div>
  </div>;


const ColBlock = ({ index, title, paras }) =>
<div>
    <SectionEyebrow index={index} label={title} />
    <div style={{ marginTop: 28, display: "flex", flexDirection: "column", gap: 18 }}>
      {paras.map((p, i) =>
    <p
      key={i}
      style={{
        margin: 0,
        fontSize: 17,
        lineHeight: 1.55,
        color: "var(--ink)",
        letterSpacing: "-0.005em",
        textWrap: "pretty"
      }}>
          {p}
        </p>
    )}
    </div>
  </div>;


const StatRow = ({ value, label, first }) =>
<div
  style={{
    display: "flex",
    alignItems: "baseline",
    gap: 24,
    padding: "22px 0",
    borderTop: first ? "1px solid var(--rule-on-dark)" : "none",
    borderBottom: "1px solid var(--rule-on-dark)"
  }}>
  
    <div
    className="display"
    style={{
      fontSize: 64,
      fontWeight: 700,
      letterSpacing: "-0.035em",
      lineHeight: 0.9,
      color: "var(--blue)",
      minWidth: 160
    }}>
    
      {value}
    </div>
    <div
    style={{
      fontSize: 14,
      lineHeight: 1.4,
      color: "rgba(255,255,255,0.7)",
      letterSpacing: "-0.005em"
    }}>
    
      {label}
    </div>
  </div>;


const PhotoGallery = ({ items }) => {
  const [feature, ...rest] = items;
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 32 }}>
      <PhotoCard {...feature} index={1} />
      {rest.length > 0 &&
        <div
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(" + Math.min(rest.length, 2) + ", 1fr)",
            gap: 32
          }}>
          {rest.map((p, i) => <PhotoCard key={i} {...p} index={i + 2} />)}
        </div>
      }
    </div>);
};

const PhotoCard = ({ src, alt, caption, index, ratio }) =>
  <figure
    style={{
      margin: 0,
      border: "1px solid var(--rule)",
      background: "var(--ink-soft)",
      overflow: "hidden"
    }}>
    <div style={{ position: "relative", aspectRatio: ratio || "16 / 9", background: "#000" }}>
      <img
        src={src}
        alt={alt || caption || ""}
        loading="lazy"
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
    </div>
    <figcaption
      style={{
        display: "flex",
        justifyContent: "space-between",
        alignItems: "center",
        padding: "14px 18px",
        background: "var(--paper-2)",
        borderTop: "1px solid var(--rule)"
      }}>
      <span className="mono" style={{ color: "var(--muted)" }}>PHOTO · {String(index).padStart(2, "0")}</span>
      <span style={{ fontSize: 13, color: "var(--ink)", letterSpacing: "-0.005em" }}>{caption}</span>
    </figcaption>
  </figure>;

const VideoCard = ({ id, youtube, h, placeholder, title, index, poster }) => {
  const [playing, setPlaying] = React.useState(false);
  const isPlaceholder = placeholder || (!id && !youtube);
  const embedSrc = youtube
    ? `https://www.youtube.com/embed/${youtube}?autoplay=1&rel=0`
    : `https://player.vimeo.com/video/${id}?autoplay=1&title=0&byline=0&portrait=0${h ? `&h=${h}` : ""}`;
  return (
    <article
      style={{
        position: "relative",
        background: "var(--ink-soft)",
        border: "1px solid var(--rule)",
        overflow: "hidden"
      }}>
      
      <div style={{ position: "relative", aspectRatio: "16 / 9", background: "#000" }}>
        {isPlaceholder ?
        <PlaceholderPoster title={title} /> :
        playing ?
        <iframe
          src={embedSrc}
          title={title}
          allow="autoplay; fullscreen; picture-in-picture"
          allowFullScreen
          style={{ position: "absolute", inset: 0, width: "100%", height: "100%", border: 0 }} /> :


        <VideoPoster id={id} youtube={youtube} poster={poster} title={title} onPlay={() => setPlaying(true)} />
        }
      </div>
      <div
        style={{
          display: "flex",
          justifyContent: "space-between",
          alignItems: "center",
          padding: "14px 18px",
          background: "var(--paper-2)",
          borderTop: "1px solid var(--rule)"
        }}>
        
        <span className="mono" style={{ color: "var(--muted)" }}>
          {isPlaceholder ? "VIDEO PLACEHOLDER" : "VIDEO"} · {String(index).padStart(2, "0")}
        </span>
        <span style={{ fontSize: 13, color: "var(--ink)", letterSpacing: "-0.005em" }}>{title}</span>
      </div>
    </article>);

};

const PlaceholderPoster = ({ title }) =>
<div
  style={{
    position: "absolute",
    inset: 0,
    display: "grid",
    placeItems: "center",
    background: "repeating-linear-gradient(135deg, #15151c 0 18px, #101015 18px 19px)"
  }}>
  
    <div style={{ textAlign: "center", color: "rgba(255,255,255,0.5)", padding: 24 }}>
      <span
      style={{
        width: 64,
        height: 64,
        borderRadius: 999,
        border: "1.5px solid rgba(255,255,255,0.35)",
        display: "grid",
        placeItems: "center",
        margin: "0 auto"
      }}>
      
        <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
          <path d="M8 5v14l11-7z" />
        </svg>
      </span>
      <div className="mono" style={{ marginTop: 16, fontSize: 11, letterSpacing: "0.08em" }}>
        Video coming soon
      </div>
    </div>
  </div>;

const VideoPoster = ({ id, youtube, poster, title, onPlay }) => {
  const [hover, setHover] = React.useState(false);
  const thumb = poster || (youtube ? `https://img.youtube.com/vi/${youtube}/hqdefault.jpg` : `https://vumbnail.com/${id}.jpg`);
  return (
    <button
      onClick={onPlay}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      aria-label={`Play ${title}`}
      style={{
        position: "absolute",
        inset: 0,
        width: "100%",
        height: "100%",
        padding: 0,
        margin: 0,
        border: 0,
        cursor: "pointer",
        background: `#000 center/cover no-repeat url(${thumb})`,
        backgroundImage: `linear-gradient(180deg, rgba(0,0,0,0.0) 40%, rgba(0,0,0,0.5) 100%), url(${thumb})`,
        display: "grid",
        placeItems: "center",
        transition: "filter .25s ease",
        filter: hover ? "brightness(1.05)" : "brightness(1)"
      }}>
      
      <span
        style={{
          width: 72,
          height: 72,
          borderRadius: 999,
          background: "var(--blue)",
          color: "white",
          display: "grid",
          placeItems: "center",
          boxShadow: "0 14px 40px rgba(0,0,0,0.35)",
          transform: hover ? "scale(1.08)" : "scale(1)",
          transition: "transform .25s ease"
        }}>
        
        <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
          <path d="M8 5v14l11-7z" />
        </svg>
      </span>
    </button>);

};

const NextCaseStudy = ({ slug, onOpen }) => {
  const next = CASE_STUDIES[slug];
  if (!next) return null;
  return (
    <a
      href={`#case/${slug}`}
      onClick={(e) => {
        if (onOpen) {
          e.preventDefault();
          onOpen(slug);
        }
      }}
      style={{
        display: "grid",
        gridTemplateColumns: "auto 1fr auto",
        alignItems: "center",
        gap: 28,
        padding: "32px 4px",
        color: "var(--ink)"
      }}
      onMouseEnter={(e) => {
        const arrow = e.currentTarget.querySelector(".cs-next-arrow");
        if (arrow) arrow.style.transform = "translate(6px,-6px)";
      }}
      onMouseLeave={(e) => {
        const arrow = e.currentTarget.querySelector(".cs-next-arrow");
        if (arrow) arrow.style.transform = "translate(0,0)";
      }}>
      
      <span className="mono" style={{ color: "var(--muted)" }}>Next case study →</span>
      <span
        className="display"
        style={{
          fontSize: "clamp(36px, 5.6vw, 88px)",
          letterSpacing: "-0.03em",
          lineHeight: 0.95,
          textTransform: "uppercase"
        }}>
        
        {next.client}
      </span>
      <span className="cs-next-arrow" style={{ color: "var(--blue)", transition: "transform .25s ease" }}>
        <ArrowUpRight size={48} />
      </span>
    </a>);

};

window.CaseStudyPage = CaseStudyPage;
window.CASE_STUDIES = CASE_STUDIES;
