{"spec_id":"line-styled","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' line-styled: Styled Line Plot\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 86/100 | Created: 2026-09-05\n\nlibrary(ggplot2)\nlibrary(ragg)\n\nset.seed(42)\n\n# --- Theme tokens -----------------------------------------------------------\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nELEVATED_BG <- if (THEME == \"light\") \"#FFFDF6\" else \"#242420\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nIMPRINT_PALETTE <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                     \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\")\n\n# --- Data --------------------------------------------------------------------\n# Quarterly revenue trend for four product lines, indexed to a common base\n# year so line-style distinction (not color) carries the reading for anyone\n# printing this chart in black and white.\nquarters <- 1:24\ndf <- tibble::tibble(\n  quarter    = rep(quarters, times = 4),\n  revenue    = c(\n    100 + cumsum(rnorm(24, mean = 2.6, sd = 3.0)),\n    100 + cumsum(rnorm(24, mean = 1.1, sd = 2.4)),\n    100 + cumsum(rnorm(24, mean = 0.4, sd = 3.4)),\n    100 + cumsum(rnorm(24, mean = -0.8, sd = 2.0))\n  ),\n  product = factor(\n    rep(c(\"Hardware\", \"Software\", \"Services\", \"Accessories\"), each = 24),\n    levels = c(\"Hardware\", \"Software\", \"Services\", \"Accessories\")\n  )\n)\n\n# Custom dash patterns (rather than the stock \"dotted\"/\"dotdash\") so the two\n# dot-based styles don't share a leading sub-pattern — the stock codes (\"13\"\n# and \"1343\") start identically and blur together at small/mobile scale.\nline_styles <- c(\n  \"Hardware\"    = \"solid\",\n  \"Software\"    = \"dashed\",\n  \"Services\"    = \"15\",\n  \"Accessories\" = \"6215\"\n)\n\n# Grid lines rendered as flat INK read as high-contrast rather than a subtle\n# guide; element_line() has no alpha in this ggplot2 version, so blend the\n# alpha into the hex color itself.\nGRID_COLOR <- grDevices::adjustcolor(INK, alpha.f = 0.2)\n\ntitle_str <- \"line-styled · r · ggplot2 · anyplot.ai\"\n\n# Highlight the focal series (Hardware) with an endpoint marker + annotation\n# instead of a heavier linewidth, since the spec calls for consistent line\n# width across all styles.\nhardware_data <- df[df$product == \"Hardware\", ]\nhardware_end   <- hardware_data[which.max(hardware_data$quarter), ]\n\n# --- Plot ---------------------------------------------------------------------\np <- ggplot(df, aes(x = quarter, y = revenue, color = product, linetype = product)) +\n  geom_line(linewidth = 1.1) +\n  geom_point(data = hardware_end, size = 2.4, show.legend = FALSE) +\n  annotate(\n    \"text\",\n    x        = hardware_end$quarter,\n    y        = hardware_end$revenue,\n    label    = sprintf(\"%+.0f%%\", hardware_end$revenue - 100),\n    color    = IMPRINT_PALETTE[1],\n    hjust    = -0.15,\n    size     = 2.8,\n    fontface = \"bold\"\n  ) +\n  scale_color_manual(values = IMPRINT_PALETTE[1:4]) +\n  scale_linetype_manual(values = line_styles) +\n  scale_x_continuous(expand = expansion(mult = c(0.02, 0.12))) +\n  labs(\n    title    = title_str,\n    x        = \"Quarter\",\n    y        = \"Revenue Index (base = 100)\",\n    color    = \"Product Line\",\n    linetype = \"Product Line\"\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_line(color = GRID_COLOR, linewidth = 0.3),\n    panel.grid.minor   = element_blank(),\n    panel.grid.major.x = element_blank(),\n    axis.title         = element_text(color = INK, size = 10),\n    axis.text          = element_text(color = INK_SOFT, size = 8),\n    axis.line          = element_line(color = INK_SOFT),\n    axis.ticks         = element_blank(),\n    plot.title         = element_text(color = INK, size = 12),\n    legend.background  = element_rect(fill = ELEVATED_BG, color = NA),\n    legend.key         = element_rect(fill = ELEVATED_BG, color = NA),\n    legend.text        = element_text(color = INK_SOFT, size = 8),\n    legend.title       = element_text(color = INK, size = 10),\n    legend.position    = \"right\"\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"}