{"spec_id":"point-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' point-basic: Point Estimate Plot\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 93/100 | Created: 2026-09-05\n\nlibrary(ggplot2)\nlibrary(dplyr)\nlibrary(ragg)\n\nset.seed(42)\n\n# --- Theme tokens -------------------------------------------------------\nTHEME    <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG  <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nINK      <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nMUTED    <- if (THEME == \"light\") \"#6B6A63\" else \"#A8A79F\" # semantic anchor — not statistically significant\nGRID_COL <- paste0(INK, \"26\") # ~15% opacity tint, per style-guide subtle-grid guidance\nBRAND    <- \"#009E73\" # Imprint palette position 1 — ALWAYS first series\n\n# --- Data -----------------------------------------------------------------\n# Simulated standardized mean difference (effect size) from a multi-site\n# clinical trial. Each site draws its own sample, so the 95% CI width varies\n# naturally with sample size rather than being hand-picked.\nsites <- sprintf(\"Site %02d\", 1:10)\nn_per_site <- c(40, 65, 120, 30, 200, 55, 90, 150, 45, 75)\ntrue_effect <- 0.35\n\ntrial_results <- lapply(seq_along(sites), function(i) {\n  n <- n_per_site[i]\n  sample_effect <- rnorm(n, mean = true_effect, sd = 1)\n  se <- sd(sample_effect) / sqrt(n)\n  estimate <- mean(sample_effect)\n  tibble::tibble(\n    site = sites[i],\n    estimate = estimate,\n    lower_bound = estimate - qt(0.975, df = n - 1) * se,\n    upper_bound = estimate + qt(0.975, df = n - 1) * se\n  )\n})\n\ndf <- bind_rows(trial_results) %>%\n  arrange(estimate) %>%\n  mutate(\n    site = factor(site, levels = site),\n    significant = lower_bound > 0 | upper_bound < 0,\n    point_color = if_else(significant, BRAND, MUTED)\n  )\n\n# --- Plot -------------------------------------------------------------------\np <- ggplot(df, aes(x = estimate, y = site)) +\n  geom_vline(xintercept = 0, linetype = \"dashed\", linewidth = 0.5, color = INK_SOFT) +\n  geom_errorbar(\n    aes(xmin = lower_bound, xmax = upper_bound, color = point_color),\n    orientation = \"y\", width = 0.25, linewidth = 0.8\n  ) +\n  geom_point(aes(color = point_color), size = 3.5) +\n  scale_color_identity() +\n  labs(\n    x = \"Standardized Effect Size (95% CI)\",\n    y = NULL,\n    title = \"point-basic · r · ggplot2 · anyplot.ai\"\n  ) +\n  theme_minimal(base_size = 8) +\n  theme(\n    plot.background   = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background  = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid.major.y = element_blank(),\n    panel.grid.minor  = element_blank(),\n    panel.grid.major.x = element_line(color = GRID_COL, linewidth = 0.2),\n    axis.title        = element_text(color = INK, size = 10),\n    axis.text         = element_text(color = INK_SOFT, size = 8),\n    axis.ticks        = element_blank(),\n    plot.title        = element_text(color = INK, size = 12),\n    plot.margin       = margin(12, 16, 12, 12)\n  )\n\n# --- Save -------------------------------------------------------------------\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 8,\n  height   = 4.5,\n  units    = \"in\",\n  dpi      = 400\n)\n"}