{"spec_id":"area-basic","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\narea-basic: Basic Area Chart\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 93/100 | Updated: 2026-05-28\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nimport plotly.graph_objects as go\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\nBRAND = \"#009E73\"\n\n# Data - daily website visitors over a quarter\nnp.random.seed(42)\ndates = pd.date_range(\"2024-01-01\", periods=90, freq=\"D\").strftime(\"%Y-%m-%d\").tolist()\nbase = 5000\ntrend_offset = np.linspace(0, 2500, 90)\nweekly_pattern = 1200 * np.sin(np.arange(90) * 2 * np.pi / 7)\nnoise = np.random.randn(90) * 400\nvisitors = base + trend_offset + weekly_pattern + noise\nvisitors = np.maximum(visitors, 1500).astype(int)\n\n# Fit linear trend line for annotation anchor\ntrend_fit = np.polyfit(np.arange(90), visitors, 1)\ntrend_vals = np.polyval(trend_fit, np.arange(90))\n\n# Title font size (scale to 67-char baseline)\ntitle = \"Daily Website Visitors · area-basic · python · plotly · anyplot.ai\"\ntitle_fontsize = round(16 * (67 / len(title))) if len(title) > 67 else 16\n\n# Fill colors (stronger gradient for visible area effect)\nfill_top = \"rgba(0,158,115,0.45)\" if THEME == \"light\" else \"rgba(0,158,115,0.35)\"\nfill_bot = \"rgba(0,158,115,0.06)\"\n\n# Plot\nfig = go.Figure()\n\nfig.add_trace(\n    go.Scatter(\n        x=dates,\n        y=visitors,\n        mode=\"lines\",\n        fill=\"tozeroy\",\n        fillcolor=fill_top,\n        fillgradient={\"type\": \"vertical\", \"colorscale\": [[0.0, fill_bot], [1.0, fill_top]]},\n        line={\"color\": BRAND, \"width\": 2.5, \"shape\": \"spline\"},\n        name=\"Daily Visitors\",\n        hovertemplate=\"<b>%{x|%b %d, %Y}</b><br>Visitors: %{y:,}<extra></extra>\",\n    )\n)\n\n# Subtle dotted trend reference line\nfig.add_trace(\n    go.Scatter(\n        x=dates,\n        y=trend_vals,\n        mode=\"lines\",\n        line={\"color\": INK_SOFT, \"width\": 1.5, \"dash\": \"dot\"},\n        showlegend=False,\n        hoverinfo=\"skip\",\n    )\n)\n\n# Peak annotation\npeak_idx = int(np.argmax(visitors))\nfig.add_annotation(\n    x=dates[peak_idx],\n    y=visitors[peak_idx],\n    text=f\"Peak: {visitors[peak_idx]:,}\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1.5,\n    ax=0,\n    ay=-40,\n    font={\"size\": 12, \"color\": BRAND},\n    bordercolor=BRAND,\n    borderwidth=1.5,\n    borderpad=4,\n    bgcolor=ELEVATED_BG,\n)\n\n# Trend annotation anchored to a point on the trend line\nanchor_idx = 65\nfig.add_annotation(\n    x=dates[anchor_idx],\n    y=trend_vals[anchor_idx],\n    text=\"Upward trend +50%\",\n    showarrow=True,\n    arrowhead=2,\n    arrowsize=1,\n    ax=35,\n    ay=-50,\n    arrowcolor=INK_SOFT,\n    font={\"size\": 12, \"color\": INK_SOFT},\n    bgcolor=ELEVATED_BG,\n    bordercolor=INK_SOFT,\n    borderwidth=1,\n    borderpad=3,\n)\n\n# Layout\nfig.update_layout(\n    autosize=False,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    title={\"text\": title, \"font\": {\"size\": title_fontsize, \"color\": INK}, \"x\": 0.5, \"xanchor\": \"center\"},\n    xaxis={\n        \"title\": {\"text\": \"Date (Q1 2024)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"showgrid\": True,\n        \"gridcolor\": GRID,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n        \"dtick\": \"M1\",\n        \"tickformat\": \"%b %Y\",\n        \"spikemode\": \"across\",\n        \"spikethickness\": 1,\n        \"spikecolor\": \"rgba(0,158,115,0.4)\",\n        \"spikedash\": \"dot\",\n        \"rangeslider\": {\"visible\": False},\n        \"rangeselector\": {\n            \"buttons\": [\n                {\"count\": 7, \"label\": \"1W\", \"step\": \"day\", \"stepmode\": \"backward\"},\n                {\"count\": 1, \"label\": \"1M\", \"step\": \"month\", \"stepmode\": \"backward\"},\n                {\"step\": \"all\", \"label\": \"All\"},\n            ],\n            \"font\": {\"size\": 10},\n            \"bgcolor\": ELEVATED_BG,\n            \"bordercolor\": INK_SOFT,\n        },\n    },\n    yaxis={\n        \"title\": {\"text\": \"Visitors (daily count)\", \"font\": {\"size\": 12, \"color\": INK}},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"showgrid\": True,\n        \"gridcolor\": GRID,\n        \"linecolor\": INK_SOFT,\n        \"zerolinecolor\": INK_SOFT,\n        \"tickformat\": \",\",\n        \"spikemode\": \"across\",\n        \"spikethickness\": 1,\n        \"spikecolor\": \"rgba(0,158,115,0.4)\",\n        \"spikedash\": \"dot\",\n    },\n    showlegend=True,\n    legend={\n        \"x\": 0.02,\n        \"y\": 0.98,\n        \"font\": {\"size\": 10, \"color\": INK_SOFT},\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n    },\n    margin={\"l\": 80, \"r\": 40, \"t\": 80, \"b\": 60},\n    hovermode=\"x unified\",\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\n\nfig.update_layout(xaxis_rangeslider_visible=True)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}