# ── Install missing packages automatically ──────────────────────────────────
pkgs <- c("tidyverse", "scales", "ggtext", "patchwork",
          "knitr", "kableExtra", "gt", "RColorBrewer")

installed <- rownames(installed.packages())
for (p in pkgs) {
  if (!p %in% installed) install.packages(p, repos = "https://cloud.r-project.org")
}

library(tidyverse)
library(scales)
library(ggtext)
library(patchwork)
library(knitr)
library(kableExtra)
library(gt)
# ── Brand colors ────────────────────────────────────────────────────────────
CLR_INK   <- "#0f0e0c"
CLR_CREAM <- "#f5f0e8"
CLR_RUST  <- "#c0392b"
CLR_SAND  <- "#e8dcc8"
CLR_SAGE  <- "#4a6741"
CLR_AMBER <- "#d4851a"
CLR_SLATE <- "#3d4a5c"
CLR_PALE  <- "#faf7f2"
CLR_LGREY <- "#eeebe5"

# ── Custom ggplot2 theme ────────────────────────────────────────────────────
theme_unequal <- function(base_size = 11) {
  theme_minimal(base_size = base_size) +
    theme(
      plot.background    = element_rect(fill = CLR_PALE,  color = NA),
      panel.background   = element_rect(fill = "white",   color = NA),
      panel.grid.major   = element_line(color = CLR_LGREY, linewidth = 0.4),
      panel.grid.minor   = element_blank(),
      axis.ticks         = element_blank(),
      axis.text          = element_text(color = "#555555", size = 9),
      axis.title         = element_text(color = "#555555", size = 9, face = "plain"),
      plot.title         = element_text(color = CLR_INK,  size = 14, face = "bold",
                                        margin = margin(b = 4)),
      plot.subtitle      = element_text(color = "#555555", size = 9,
                                        margin = margin(b = 12)),
      plot.caption       = element_text(color = "#999999", size = 7.5,
                                        hjust = 0, margin = margin(t = 10)),
      legend.position    = "top",
      legend.key.size    = unit(0.45, "cm"),
      legend.text        = element_text(size = 8.5, color = "#444"),
      legend.title       = element_blank(),
      strip.text         = element_text(face = "bold", color = CLR_INK),
      plot.margin        = margin(16, 16, 16, 16)
    )
}

theme_set(theme_unequal())

Introduction

“Nearly all countries (93%) take some approach to prohibiting gender discrimination at work — yet women from marginalized groups often lack full legal protections.” — WORLD Policy Analysis Center (2023)

This report examines how race, gender, disability, religion, social class, migration status, sexual orientation, and age intersect to produce compounding workplace disadvantages. Drawing on data from the U.S. Bureau of Labor Statistics, the U.S. Census Bureau, and the WORLD Policy Analysis Center’s Discrimination at Work Database, we present six visualizations and a set of evidence-based policy recommendations.


Key Findings

At a Glance

findings <- tibble::tribble(
  ~Statistic, ~Finding,
  "93%",  "of countries prohibit gender-based employment discrimination — yet women from marginalized groups frequently lack full legal protection in practice.",
  "17%",  "of countries protect workers from discrimination based on gender identity, leaving the vast majority of transgender workers without recourse.",
  "82¢",  "Women in the U.S. earn for every $1 earned by men — a gap that widens sharply when race is factored in.",
  "56¢",  "'Racialized' women in Canada earn for each dollar earned by White men — a stark illustration of intersecting disadvantage.",
  "2×",   "Migrant women's income disadvantage in China exceeds the combined individual penalties of being female and being an unregistered migrant.",
  "35%",  "of countries ban employment discrimination based on sexual orientation — leaving the majority of LGBTQ+ workers unprotected."
)

findings |>
  gt() |>
  tab_header(
    title    = md("**Key Findings at a Glance**"),
    subtitle = "Unequal Ground: Workplace Discrimination & The Gender Pay Gap"
  ) |>
  cols_label(Statistic = "Statistic", Finding = "Finding") |>
  tab_style(
    style = list(
      cell_fill(color = CLR_RUST),
      cell_text(color = "white", weight = "bold", size = px(16))
    ),
    locations = cells_body(columns = Statistic)
  ) |>
  tab_style(
    style = cell_text(size = px(13)),
    locations = cells_body(columns = Finding)
  ) |>
  tab_style(
    style = list(
      cell_fill(color = CLR_INK),
      cell_text(color = CLR_CREAM, weight = "bold")
    ),
    locations = cells_column_labels()
  ) |>
  tab_options(
    table.width             = pct(100),
    table.border.top.color  = CLR_RUST,
    table.border.top.width  = px(3),
    row.striping.background = CLR_PALE,
    row.striping.include_table_body = TRUE
  )
Key Findings at a Glance
Unequal Ground: Workplace Discrimination & The Gender Pay Gap
Statistic Finding
93% of countries prohibit gender-based employment discrimination — yet women from marginalized groups frequently lack full legal protection in practice.
17% of countries protect workers from discrimination based on gender identity, leaving the vast majority of transgender workers without recourse.
82¢ Women in the U.S. earn for every $1 earned by men — a gap that widens sharply when race is factored in.
56¢ 'Racialized' women in Canada earn for each dollar earned by White men — a stark illustration of intersecting disadvantage.
Migrant women's income disadvantage in China exceeds the combined individual penalties of being female and being an unregistered migrant.
35% of countries ban employment discrimination based on sexual orientation — leaving the majority of LGBTQ+ workers unprotected.

Visualization 1 — Gender Wage Gap by Race & Ethnicity

Data

# ── U.S. BLS Usual Weekly Earnings, Q4 2023 ─────────────────────────────────
# Expressed as cents per dollar earned by White men (baseline = 100)
wage_gap <- tibble(
  group = c(
    "White Men", "Asian Men", "White Women", "Black Men",
    "Hispanic Men", "Asian Women", "Black Women", "Hispanic Women"
  ),
  earnings_pct = c(100, 115, 82, 73, 68, 93, 67, 58),
  gender = c("Men", "Men", "Women", "Men", "Men", "Women", "Women", "Women"),
  race = c("White", "Asian", "White", "Black",
           "Hispanic", "Asian", "Black", "Hispanic")
) |>
  mutate(
    group = fct_reorder(group, earnings_pct),
    bar_color = case_when(
      gender == "Women" ~ CLR_RUST,
      group == "White Men" ~ CLR_INK,
      TRUE ~ CLR_SLATE
    )
  )

wage_gap |>
  select(group, gender, race, earnings_pct) |>
  arrange(desc(earnings_pct)) |>
  kable(
    col.names = c("Group", "Gender", "Race/Ethnicity", "Earnings (¢ per $1)"),
    caption   = "Median Weekly Earnings as % of White Men's Earnings (U.S., Q4 2023)"
  ) |>
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE) |>
  row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE)
Median Weekly Earnings as % of White Men’s Earnings (U.S., Q4 2023)
Group Gender Race/Ethnicity Earnings (¢ per $1)
Asian Men Men Asian 115
White Men Men White 100
Asian Women Women Asian 93
White Women Women White 82
Black Men Men Black 73
Hispanic Men Men Hispanic 68
Black Women Women Black 67
Hispanic Women Women Hispanic 58

Chart

p1 <- ggplot(wage_gap, aes(x = group, y = earnings_pct, fill = bar_color)) +
  geom_col(width = 0.72, show.legend = FALSE) +
  geom_hline(yintercept = 100, color = CLR_RUST,
             linetype = "dashed", linewidth = 0.8) +
  geom_text(aes(label = paste0(earnings_pct, "¢"),
                vjust = ifelse(earnings_pct < 20, -0.4, 1.4)),
            color = "white", fontface = "bold", size = 3.3) +
  annotate("text", x = 8.4, y = 101.5, label = "White men baseline ($1.00)",
           color = CLR_RUST, size = 2.8, hjust = 1, fontface = "italic") +
  scale_fill_identity() +
  scale_y_continuous(
    limits = c(0, 125),
    labels = function(x) paste0(x, "¢"),
    expand = c(0, 0)
  ) +
  coord_flip() +
  labs(
    title    = "Median Earnings as % of White Men's Earnings (U.S., 2023)",
    subtitle = "Red bars = women; dark bars = men. Dashed line = White men baseline ($1.00).",
    x        = NULL,
    y        = "Cents per dollar earned by White men",
    caption  = "Source: U.S. Bureau of Labor Statistics, Usual Weekly Earnings, Q4 2023"
  )

p1


Visualization 2 — Historical Wage Gap Trend (1980–2023)

Data

# ── U.S. Census Bureau, Current Population Survey ───────────────────────────
wage_trend <- tibble(
  year     = c(1980, 1985, 1990, 1995, 2000, 2005,
               2010, 2015, 2018, 2020, 2022, 2023),
  earnings = c(60,   64,   71,   71,   73,   76,
               77,   80,   81,   82,   82,   82)
)

wage_trend |>
  kable(
    col.names = c("Year", "Women's Earnings (¢ per $1 earned by men)"),
    caption   = "Gender Pay Ratio Trend, U.S. Full-Time Workers, 1980–2023"
  ) |>
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) |>
  row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE)
Gender Pay Ratio Trend, U.S. Full-Time Workers, 1980–2023
Year Women’s Earnings (¢ per $1 earned by men)
1980 60
1985 64
1990 71
1995 71
2000 73
2005 76
2010 77
2015 80
2018 81
2020 82
2022 82
2023 82

Chart

# Annotate key policy milestones
milestones <- tibble(
  year  = c(1963, 1978, 1993, 2009),
  label = c("Equal Pay Act", "Pregnancy\nDiscrimination Act",
            "Family &\nMedical Leave", "Lilly Ledbetter\nFair Pay Act"),
  y     = c(62, 66, 74, 80)
)

p2 <- ggplot(wage_trend, aes(x = year, y = earnings)) +
  geom_ribbon(aes(ymin = 55, ymax = earnings),
              fill = CLR_RUST, alpha = 0.12) +
  geom_line(color = CLR_RUST, linewidth = 1.8) +
  geom_point(color = CLR_RUST, size = 3, shape = 21,
             fill = "white", stroke = 2) +
  geom_text(aes(label = paste0(earnings, "¢")),
            vjust = -0.9, size = 2.8, color = CLR_RUST, fontface = "bold") +
  scale_x_continuous(breaks = seq(1980, 2023, 5)) +
  scale_y_continuous(
    limits = c(55, 100),
    labels = function(x) paste0(x, "¢"),
    breaks = seq(60, 100, 10)
  ) +
  labs(
    title    = "Women's Earnings Relative to Men's — U.S., 1980–2023",
    subtitle = "Despite 40+ years of progress, the gap stalled at ~82¢ after 2018.",
    x        = "Year",
    y        = "Cents per dollar earned by men",
    caption  = "Source: U.S. Census Bureau, Current Population Survey"
  )

p2


Visualization 3 — Global Legal Protections by Category

Data

protections <- tibble(
  category = c(
    "Gender & Religion", "Gender & Race/Ethnicity", "Gender & Disability",
    "Gender & Age", "Gender & Social Class", "Gender & Foreign Origin",
    "Gender & Migration Status", "Sexual Orientation", "Gender Identity"
  ),
  pct_2016 = c(80, 80, 74, 65, 60, 42, 40, 28, 12),
  pct_2021 = c(83, 82, 80, 65, 64, 48, 47, 35, 17)
) |>
  mutate(
    change   = pct_2021 - pct_2016,
    category = fct_reorder(category, pct_2021)
  )

protections |>
  arrange(desc(pct_2021)) |>
  mutate(change = paste0(ifelse(change > 0, "+", ""), change, " pp")) |>
  kable(
    col.names = c("Category", "2016 (%)", "2021 (%)", "Change"),
    caption   = "Country-Level Employment Discrimination Protections (% of 193 countries)"
  ) |>
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = FALSE) |>
  row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE) |>
  column_spec(4, bold = TRUE, color = CLR_SAGE)
Country-Level Employment Discrimination Protections (% of 193 countries)
Category 2016 (%) 2021 (%) Change
Gender & Religion 80 83 +3 pp
Gender & Race/Ethnicity 80 82 +2 pp
Gender & Disability 74 80 +6 pp
Gender & Age 65 65 0 pp
Gender & Social Class 60 64 +4 pp
Gender & Foreign Origin 42 48 +6 pp
Gender & Migration Status 40 47 +7 pp
Sexual Orientation 28 35 +7 pp
Gender Identity 12 17 +5 pp

Chart

prot_long <- protections |>
  pivot_longer(cols = c(pct_2016, pct_2021),
               names_to  = "year",
               values_to = "pct") |>
  mutate(year = recode(year, pct_2016 = "2016", pct_2021 = "2021"))

p3 <- ggplot(prot_long,
             aes(x = pct, y = category, fill = year)) +
  geom_col(position = position_dodge(width = 0.7),
           width = 0.6, show.legend = TRUE) +
  geom_text(aes(label = paste0(pct, "%")),
            position = position_dodge(width = 0.7),
            hjust = -0.15, size = 2.8, color = CLR_INK) +
  scale_fill_manual(values = c("2016" = CLR_SLATE, "2021" = CLR_RUST)) +
  scale_x_continuous(
    limits = c(0, 105),
    labels = function(x) paste0(x, "%"),
    expand = c(0, 0)
  ) +
  labs(
    title    = "% of Countries Prohibiting Workplace Discrimination by Category",
    subtitle = "2016 vs. 2021 — progress is real but gaps in LGBTQ+ protections remain severe.",
    x        = "% of 193 countries",
    y        = NULL,
    caption  = "Source: WORLD Policy Analysis Center, Discrimination at Work Database"
  )

p3


Visualization 4 — Disability & Age Penalties

Data

# Involuntary job loss risk — U.S., workers with disabilities vs. without
disability_risk <- tibble(
  group      = c("Men with\ndisabilities", "Women with\ndisabilities"),
  pct_higher = c(75, 89),
  gender     = c("Men", "Women")
)

# Employer-funded training among 50+ workers — 9-country EU study
training <- tibble(
  category   = c("Men (employer-funded)", "Women (employer-funded)",
                 "Women (self-funded)"),
  proportion = c(58, 32, 10),
  fill_color = c(CLR_SLATE, CLR_RUST, CLR_AMBER)
)

Charts

p4a <- ggplot(disability_risk,
              aes(x = group, y = pct_higher, fill = gender)) +
  geom_col(width = 0.5, show.legend = FALSE) +
  geom_text(aes(label = paste0("+", pct_higher, "%")),
            vjust = -0.5, fontface = "bold", size = 4.5, color = CLR_INK) +
  scale_fill_manual(values = c("Men" = CLR_SLATE, "Women" = CLR_RUST)) +
  scale_y_continuous(
    limits = c(0, 105),
    labels = function(x) paste0("+", x, "%"),
    expand = c(0, 0)
  ) +
  labs(
    title    = "Involuntary Job Loss Risk\n(Workers with Disabilities, U.S.)",
    subtitle = "% MORE likely vs. workers without disabilities",
    x        = NULL,
    y        = "Increased risk",
    caption  = "Source: WORLD Policy Analysis Center (2023)"
  )

p4b <- ggplot(training,
              aes(x = "", y = proportion, fill = fill_color)) +
  geom_col(width = 0.6, color = "white", linewidth = 0.8) +
  geom_text(aes(label = paste0(category, "\n", proportion, "%")),
            position = position_stack(vjust = 0.5),
            size = 2.8, color = "white", fontface = "bold") +
  scale_fill_identity() +
  coord_polar(theta = "y") +
  labs(
    title    = "Employer-Funded Training\n(Workers Age 50+, 9-Country EU Study)",
    subtitle = "Men significantly more likely to receive employer-funded training",
    caption  = "Source: WORLD Policy Analysis Center (2023)"
  ) +
  theme_void() +
  theme(
    plot.title    = element_text(face = "bold", size = 12, hjust = 0.5,
                                 color = CLR_INK),
    plot.subtitle = element_text(size = 8.5, hjust = 0.5, color = "#555"),
    plot.caption  = element_text(size = 7.5, hjust = 0.5, color = "#999",
                                 margin = margin(t = 8)),
    plot.background = element_rect(fill = CLR_PALE, color = NA)
  )

p4a + p4b +
  plot_annotation(
    title   = "Visualization 4 — Disability and Age: Compounding Penalties",
    caption = "Workers with disabilities and older workers — particularly women — face layered disadvantages.",
    theme   = theme(
      plot.title   = element_text(face = "bold", size = 14, color = CLR_INK),
      plot.caption = element_text(size = 8.5, color = "#666",
                                  margin = margin(t = 6))
    )
  )


Visualization 5 — Intersectional Discrimination Table

matrix_df <- tibble::tribble(
  ~`Identity Intersection`, ~`Key Evidence`,                                                                                        ~`Countries Protected`,
  "Race + Gender",          "Arab/N.African women in Belgium less likely selected for cognitive-role interviews than men of same background.", "82%",
  "Religion + Gender",      "Muslim women in Britain are the most economically disadvantaged group (2011 census analysis).",                  "83%",
  "Disability + Gender",    "Women of color with disabilities face highest workplace harassment rates (multiple studies).",                    "80%",
  "SOGIESC + Gender",       "60% of trans women in EU reported job-search discrimination in 2012 (EU FRA survey).",                          "35%",
  "Migration + Gender",     "In China, migrant women's disadvantage exceeds the combined individual penalties of gender + migration status.",  "47%",
  "Social Class + Gender",  "In U.S., 'higher-class' men got callbacks 16% of the time vs. 4% for 'higher-class' women.",                   "64%",
  "Age + Gender",           "In Germany, unexplained gender wage gap grows after age 45, suggesting compounding discrimination.",             "65%",
  "Caste + Gender",         "In India, women from disadvantaged castes experience greater wage inequality than other women.",                  "Varies"
)

matrix_df |>
  gt() |>
  tab_header(
    title    = md("**Visualization 5 — Intersectional Discrimination Matrix**"),
    subtitle = "Where multiple marginalized identities converge to compound disadvantage"
  ) |>
  cols_label(
    `Identity Intersection`  = "Identity Intersection",
    `Key Evidence`           = "Key Evidence",
    `Countries Protected`    = "% Countries w/ Protection"
  ) |>
  tab_style(
    style = list(
      cell_fill(color = CLR_RUST),
      cell_text(color = "white", weight = "bold")
    ),
    locations = cells_body(columns = `Identity Intersection`)
  ) |>
  tab_style(
    style = list(
      cell_fill(color = CLR_INK),
      cell_text(color = CLR_CREAM, weight = "bold")
    ),
    locations = cells_column_labels()
  ) |>
  tab_style(
    style = cell_text(weight = "bold", color = CLR_RUST),
    locations = cells_body(columns = `Countries Protected`)
  ) |>
  tab_style(
    style = cell_fill(color = CLR_PALE),
    locations = cells_body(rows = seq(1, nrow(matrix_df), 2))
  ) |>
  tab_options(
    table.width            = pct(100),
    table.border.top.color = CLR_RUST,
    table.border.top.width = px(3)
  )
Visualization 5 — Intersectional Discrimination Matrix
Where multiple marginalized identities converge to compound disadvantage
Identity Intersection Key Evidence % Countries w/ Protection
Race + Gender Arab/N.African women in Belgium less likely selected for cognitive-role interviews than men of same background. 82%
Religion + Gender Muslim women in Britain are the most economically disadvantaged group (2011 census analysis). 83%
Disability + Gender Women of color with disabilities face highest workplace harassment rates (multiple studies). 80%
SOGIESC + Gender 60% of trans women in EU reported job-search discrimination in 2012 (EU FRA survey). 35%
Migration + Gender In China, migrant women's disadvantage exceeds the combined individual penalties of gender + migration status. 47%
Social Class + Gender In U.S., 'higher-class' men got callbacks 16% of the time vs. 4% for 'higher-class' women. 64%
Age + Gender In Germany, unexplained gender wage gap grows after age 45, suggesting compounding discrimination. 65%
Caste + Gender In India, women from disadvantaged castes experience greater wage inequality than other women. Varies

Visualization 6 — Protections by Country Income Group

Data

income_df <- tibble::tribble(
  ~category,                  ~high, ~middle, ~low,   ~status,
  "Gender & Disability",       86,    75,      67,    "Partial gap",
  "Gender & Religion",         79,    85,      85,    "Broad coverage",
  "Gender & Race/Ethnicity",   82,    80,      78,    "Partial gap",
  "Gender & Social Class",     40,    77,      60,    "Significant gap",
  "Gender & Migration Status", 45,    50,      56,    "Significant gap",
  "Sexual Orientation",        62,    22,       7,    "Critical gap",
  "Gender Identity",           36,    10,       4,    "Critical gap"
)

Chart

income_long <- income_df |>
  pivot_longer(cols = c(high, middle, low),
               names_to  = "income_group",
               values_to = "pct") |>
  mutate(
    income_group = factor(income_group,
                          levels = c("high", "middle", "low"),
                          labels = c("High Income", "Middle Income", "Low Income")),
    category = fct_reorder(category, pct, .fun = max)
  )

p6 <- ggplot(income_long,
             aes(x = pct, y = category, fill = income_group)) +
  geom_col(position = position_dodge(width = 0.75), width = 0.65) +
  geom_text(aes(label = paste0(pct, "%")),
            position = position_dodge(width = 0.75),
            hjust = -0.15, size = 2.6, color = CLR_INK) +
  scale_fill_manual(
    values = c("High Income"   = CLR_SLATE,
               "Middle Income" = CLR_AMBER,
               "Low Income"    = CLR_RUST)
  ) +
  scale_x_continuous(
    limits = c(0, 105),
    labels = function(x) paste0(x, "%"),
    expand = c(0, 0)
  ) +
  labs(
    title    = "Legal Protections by Country Income Group (2021)",
    subtitle = "High-income countries lead on LGBTQ+ protections; low-income lead on religion and migration.",
    x        = "% of countries with protections",
    y        = NULL,
    fill     = "Income Group",
    caption  = "Source: WORLD Policy Analysis Center, Discrimination at Work Database (2021)"
  )

p6

Table

income_df |>
  select(-status) |>
  rename(
    "Protection Category" = category,
    "High Income (%)"     = high,
    "Middle Income (%)"   = middle,
    "Low Income (%)"      = low
  ) |>
  gt() |>
  tab_header(
    title    = md("**Protections by Country Income Group**"),
    subtitle = "% of countries with employment discrimination protections (2021)"
  ) |>
  tab_style(
    style = list(
      cell_fill(color = CLR_INK),
      cell_text(color = CLR_CREAM, weight = "bold")
    ),
    locations = cells_column_labels()
  ) |>
  data_color(
    columns = c(`High Income (%)`, `Middle Income (%)`, `Low Income (%)`),
    palette = c(CLR_CREAM, CLR_RUST),
    domain  = c(0, 100)
  ) |>
  tab_options(
    table.width            = pct(100),
    table.border.top.color = CLR_RUST,
    table.border.top.width = px(3)
  )
Protections by Country Income Group
% of countries with employment discrimination protections (2021)
Protection Category High Income (%) Middle Income (%) Low Income (%)
Gender & Disability 86 75 67
Gender & Religion 79 85 85
Gender & Race/Ethnicity 82 80 78
Gender & Social Class 40 77 60
Gender & Migration Status 45 50 56
Sexual Orientation 62 22 7
Gender Identity 36 10 4

Policy Recommendations

recs <- tibble::tribble(
  ~`#`, ~Recommendation, ~Evidence_Base,
  "1",  "Mandate intersectional protections.",
        "Anti-discrimination law must explicitly cover combinations of identities — not just each category independently.",
  "2",  "Expand SOGIESC coverage.",
        "Only 35% of countries ban sexual orientation discrimination; 17% address gender identity.",
  "3",  "Guarantee reasonable accommodations.",
        "80% address gender-disability discrimination, but only 59% require accommodations.",
  "4",  "Protect migrant workers.",
        "Fewer than 47% of countries address gender discrimination for migrant workers.",
  "5",  "Require pay transparency.",
        "Salary disclosure enables detection of unexplained wage gaps at age and seniority intersections.",
  "6",  "Collect intersectional workforce data.",
        "Disaggregate data by race × gender, disability × gender, etc. to reveal compounding penalties.",
  "7",  "Address structural exclusions.",
        "Domestic and informal workers — disproportionately women of color — are often excluded from labor law.",
  "8",  "Fund enforcement mechanisms.",
        "Laws without enforcement are symbolic. Dedicated agencies with investigation authority are essential."
)

recs |>
  gt() |>
  tab_header(
    title    = md("**Policy Recommendations**"),
    subtitle = "What the Data Demands — Eight Evidence-Based Actions"
  ) |>
  cols_label(`#` = "#", Recommendation = "Recommendation",
             Evidence_Base = "Evidence Base") |>
  tab_style(
    style = list(
      cell_fill(color = CLR_RUST),
      cell_text(color = "white", weight = "bold", align = "center", size = px(15))
    ),
    locations = cells_body(columns = `#`)
  ) |>
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_body(columns = Recommendation)
  ) |>
  tab_style(
    style = list(
      cell_fill(color = CLR_INK),
      cell_text(color = CLR_CREAM, weight = "bold")
    ),
    locations = cells_column_labels()
  ) |>
  tab_style(
    style = cell_fill(color = CLR_PALE),
    locations = cells_body(rows = seq(1, nrow(recs), 2))
  ) |>
  tab_options(
    table.width            = pct(100),
    table.border.top.color = CLR_RUST,
    table.border.top.width = px(3)
  )
Policy Recommendations
What the Data Demands — Eight Evidence-Based Actions
# Recommendation Evidence Base
1 Mandate intersectional protections. Anti-discrimination law must explicitly cover combinations of identities — not just each category independently.
2 Expand SOGIESC coverage. Only 35% of countries ban sexual orientation discrimination; 17% address gender identity.
3 Guarantee reasonable accommodations. 80% address gender-disability discrimination, but only 59% require accommodations.
4 Protect migrant workers. Fewer than 47% of countries address gender discrimination for migrant workers.
5 Require pay transparency. Salary disclosure enables detection of unexplained wage gaps at age and seniority intersections.
6 Collect intersectional workforce data. Disaggregate data by race × gender, disability × gender, etc. to reveal compounding penalties.
7 Address structural exclusions. Domestic and informal workers — disproportionately women of color — are often excluded from labor law.
8 Fund enforcement mechanisms. Laws without enforcement are symbolic. Dedicated agencies with investigation authority are essential.

Data Sources

sources <- tibble::tribble(
  ~Source, ~Description, ~URL,
  "U.S. Bureau of Labor Statistics (BLS)",
    "Usual Weekly Earnings of Wage and Salary Workers, Q4 2023",
    "https://www.bls.gov/news.release/wkyeng.toc.htm",
  "U.S. Census Bureau",
    "Current Population Survey, Historical Income Tables, 1980–2023",
    "https://www.census.gov/topics/income-poverty/income/data/tables.html",
  "WORLD Policy Analysis Center",
    "Discrimination at Work Database, 2016 & 2021",
    "https://worldpolicycenter.org",
  "Heymann, Sprague & Raub (2023)",
    "Equality within Our Lifetimes — UC Press (Chapter 3)",
    "https://www.ucpress.edu/book/9780520387126",
  "OECD",
    "Employment Outlook 2023",
    "https://www.oecd.org/employment/outlook",
  "EU Fundamental Rights Agency",
    "LGBTQ Survey 2012 & Being LGBTIQ in the EU (2019)",
    "https://fra.europa.eu",
  "TidyTuesday / Kaggle / data.world",
    "Open data repositories used for supplemental exploration",
    "https://github.com/rfordatascience/tidytuesday"
)

sources |>
  kable(
    col.names = c("Source", "Description", "URL"),
    caption   = "Data Sources"
  ) |>
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = TRUE) |>
  row_spec(0, background = CLR_INK, color = CLR_CREAM, bold = TRUE) |>
  column_spec(3, link = sources$URL, color = CLR_RUST)
Data Sources
Source Description URL
U.S. Bureau of Labor Statistics (BLS) Usual Weekly Earnings of Wage and Salary Workers, Q4 2023 https://www.bls.gov/news.release/wkyeng.toc.htm
U.S. Census Bureau Current Population Survey, Historical Income Tables, 1980–2023 https://www.census.gov/topics/income-poverty/income/data/tables.html
WORLD Policy Analysis Center Discrimination at Work Database, 2016 & 2021 https://worldpolicycenter.org
Heymann, Sprague & Raub (2023) Equality within Our Lifetimes — UC Press (Chapter 3) https://www.ucpress.edu/book/9780520387126
OECD Employment Outlook 2023 https://www.oecd.org/employment/outlook
EU Fundamental Rights Agency LGBTQ Survey 2012 & Being LGBTIQ in the EU (2019) https://fra.europa.eu
TidyTuesday / Kaggle / data.world Open data repositories used for supplemental exploration https://github.com/rfordatascience/tidytuesday

SOPE 512 — Laboratory Coding, Software, & Data Collection Methods | Spring 2026 Analysis modeled after: WORLD Policy Analysis Center, “Addressing Multiple Sources of Discrimination at Work” (Feb. 2023)