{"spec_id":"marimekko-basic","library":"makie","language":"julia","code":"# anyplot.ai\n# marimekko-basic: Basic Marimekko Chart\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 86/100 | Created: 2026-07-24\n\nusing CairoMakie\nusing Colors\n\n# --- Theme tokens -----------------------------------------------------------\nconst THEME    = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG  = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst INK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\", colorant\"#C475FD\", colorant\"#4467A3\", colorant\"#BD8233\",\n    colorant\"#AE3030\", colorant\"#2ABCCD\", colorant\"#954477\", colorant\"#99B314\",\n]\nconst WHITE_TEXT = colorant\"#FFFDF6\"\nconst DARK_TEXT  = colorant\"#1A1A17\"\n\n# --- Data: digital ad spend ($K) by channel (width) and objective (stack) --\nx_categories = [\"Social\", \"Search\", \"Video\", \"Display\", \"Audio\"]\ny_categories = [\"Brand Awareness\", \"Performance\", \"Retention\"]\n\n# rows = y_categories (stack order, bottom to top), cols = x_categories\nvalues = [\n    150  40 190  70 30\n    220 260  90  50 15\n    80   60  30  20  5\n]\n\nn_x = length(x_categories)\nn_y = length(y_categories)\ncol_totals = vec(sum(values; dims = 1))\ngrand_total = sum(col_totals)\n\n# Largest single channel/objective segment — called out with a bolder stroke\n# below to give the eye one clear focal point among otherwise-equal columns.\nmax_j, max_i = Tuple(argmax(values))\n\n# Bar widths proportional to column totals, with a thin gap between bars.\ngap = 0.015\nusable_width = 1.0 - gap * (n_x - 1)\nwidths = col_totals ./ grand_total .* usable_width\n\nx_starts = zeros(n_x)\nfor i in 2:n_x\n    x_starts[i] = x_starts[i - 1] + widths[i - 1] + gap\nend\n\n# Segment fill colors: green first, then canonical order.\nSEGMENT_COLORS = IMPRINT_PALETTE[1:n_y]\nTEXT_ON_FILL = [WHITE_TEXT, DARK_TEXT, WHITE_TEXT]  # contrast per SEGMENT_COLORS entry\n\n# --- Figure -------------------------------------------------------------\nfig = Figure(\n    resolution      = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"marimekko-basic · julia · makie · anyplot.ai\",\n    titlesize          = 29,\n    titlecolor         = INK,\n    xlabel             = \"Channel  (bar width ∝ total ad spend)\",\n    ylabel             = \"Share of Channel Spend\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelsize     = 13,\n    yticklabelsize     = 12,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    xtickcolor         = INK_SOFT,\n    ytickcolor         = INK_SOFT,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xticksvisible      = false,\n    ygridvisible       = true,\n    xgridvisible       = false,\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n)\n\nax.xticks = (x_starts .+ widths ./ 2, x_categories)\nax.yticks = (0:0.25:1, [\"0%\", \"25%\", \"50%\", \"75%\", \"100%\"])\n\nxlims!(ax, -0.02, 1.02)\nylims!(ax, 0, 1.06)\n\n# Label threshold: only annotate segments that are large enough to hold text.\nlabel_threshold = 0.04 * grand_total\n\nfor i in 1:n_x\n    y0 = 0.0\n    for j in 1:n_y\n        value = values[j, i]\n        frac = value / col_totals[i]\n        is_focal = i == max_i && j == max_j\n        poly!(\n            ax,\n            Rect2f(x_starts[i], y0, widths[i], frac);\n            color = SEGMENT_COLORS[j],\n            strokecolor = is_focal ? INK : PAGE_BG,\n            strokewidth = is_focal ? 5 : 3,\n        )\n        if value >= label_threshold\n            text!(\n                ax,\n                x_starts[i] + widths[i] / 2,\n                y0 + frac / 2;\n                text = is_focal ? \"★ \\$$(value)K\" : \"\\$$(value)K\",\n                color = TEXT_ON_FILL[j],\n                fontsize = 15,\n                font = is_focal ? :bold : :regular,\n                align = (:center, :center),\n            )\n        end\n        y0 += frac\n    end\n    # Column-total annotation above each bar, reinforcing \"width = total\".\n    text!(\n        ax,\n        x_starts[i] + widths[i] / 2,\n        1.03;\n        text = \"\\$$(col_totals[i])K\",\n        color = INK_SOFT,\n        fontsize = 13,\n        align = (:center, :center),\n    )\nend\n\nLegend(\n    fig[1, 2],\n    [PolyElement(color = c) for c in SEGMENT_COLORS],\n    y_categories,\n    \"Objective\";\n    framevisible = false,\n    backgroundcolor = :transparent,\n    labelcolor = INK,\n    titlecolor = INK,\n)\n\ncolsize!(fig.layout, 1, Relative(0.82))\n\n# --- Save ---------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}