[{"data":1,"prerenderedAt":5174},["ShallowReactive",2],{"docs:\u002Ftutorials\u002Fcombo-chart":3},{"id":4,"title":5,"body":6,"description":5164,"extension":5165,"meta":5166,"navigation":5168,"path":5170,"seo":5171,"stem":5172,"__hash__":5173},"docs\u002Ftutorials\u002Fcombo-chart.md","Revenue and Stock Price Combo Chart",{"type":7,"value":8,"toc":5145},"minimark",[9,13,17,20,26,31,34,76,80,83,108,111,119,130,133,163,166,172,176,183,989,996,1000,1007,1449,1452,1456,1459,1604,1608,1622,1800,1807,1811,1814,1823,1826,2200,2203,2208,2266,2269,2273,2276,2475,2481,2485,2491,2654,2657,2660,2802,2812,2815,3131,3138,3142,3145,3269,3272,3602,3605,3608,3756,3760,3763,4040,4050,4054,4057,4217,4220,4224,4227,4760,4776,4780,4783,5009,5012,5015,5027,5032,5036,5039,5067,5073,5077,5080,5100,5103,5107,5110,5127,5134,5141],[10,11,5],"h1",{"id":12},"revenue-and-stock-price-combo-chart",[14,15,16],"p",{},"This tutorial builds a dual-axis combination chart with Python and\npyDreamplet. Annual revenue is shown as blue columns, while monthly stock\nprices form a smooth green line. The translucent area below the line is visible\nonly inside the columns.",[14,18,19],{},"The visual treatment was inspired by one of the charts published by Visual\nCapitalist.",[21,22],"svg-preview",{"alt":23,"dark-src":24,"src":25},"Apple annual revenue columns combined with a monthly stock price line from 2014 through 2025.","\u002Fshowcase\u002Fcombo_chart_dark.svg","\u002Fshowcase\u002Fcombo_chart_light.svg",[27,28,30],"h2",{"id":29},"what-you-will-learn","What You Will Learn",[14,32,33],{},"By the end of the tutorial, you will know how to:",[35,36,37,41,53,56,67,70,73],"ul",{},[38,39,40],"li",{},"read two time series with different frequencies from one CSV file,",[38,42,43,44,48,49,52],{},"use a ",[45,46,47],"code",{},"BandScale"," for annual columns and a ",[45,50,51],{},"PointScale"," for monthly values,",[38,54,55],{},"plot two measures with independent vertical scales,",[38,57,58,59,62,63,66],{},"reuse geometry with SVG ",[45,60,61],{},"\u003Cdefs>"," and ",[45,64,65],{},"\u003Cuse>",",",[38,68,69],{},"clip an area chart to the shape of the revenue columns,",[38,71,72],{},"create ticks, grid lines, labels, gradients, and embedded SVG icons,",[38,74,75],{},"generate light and dark versions from the same drawing code.",[27,77,79],{"id":78},"project-setup","Project Setup",[14,81,82],{},"This tutorial requires Python 3.12 or newer and pyDreamplet:",[84,85,90],"pre",{"className":86,"code":87,"language":88,"meta":89,"style":89},"language-bash shiki shiki-themes material-theme-lighter github-light-high-contrast github-dark","pip install pydreamplet\n","bash","",[45,91,92],{"__ignoreMap":89},[93,94,97,101,105],"span",{"class":95,"line":96},"line",1,[93,98,100],{"class":99},"sp6cl","pip",[93,102,104],{"class":103},"s_jvP"," install",[93,106,107],{"class":103}," pydreamplet\n",[14,109,110],{},"Create the following directory structure:",[84,112,117],{"className":113,"code":115,"language":116,"meta":89},[114],"language-text","combo-chart\u002F\n├── assets\u002F\n│   ├── revenue.svg\n│   └── stock_price.svg\n├── data\u002F\n│   └── apple.csv\n├── data_reader.py\n└── main.py\n","text",[45,118,115],{"__ignoreMap":89},[14,120,121,122,129],{},"The complete data and icon files are available in the\n",[123,124,128],"a",{"href":125,"rel":126},"https:\u002F\u002Fgithub.com\u002Fmarepilc\u002Fpydreamplet-showcase\u002Ftree\u002Fmaster\u002Fscripts\u002Fcombo_chart",[127],"nofollow","combo chart showcase directory",".",[14,131,132],{},"The CSV combines monthly closing prices with annual revenue records:",[84,134,138],{"className":135,"code":136,"language":137,"meta":89,"style":89},"language-csv shiki shiki-themes material-theme-lighter github-light-high-contrast github-dark","date,monthly_close,fiscal_year,annual_revenue\n2014-01-31,12.094000,,\n2014-02-28,16.320667,,\n2014-12-31,14.827333,2014,3198356000\n","csv",[45,139,140,145,151,157],{"__ignoreMap":89},[93,141,142],{"class":95,"line":96},[93,143,144],{},"date,monthly_close,fiscal_year,annual_revenue\n",[93,146,148],{"class":95,"line":147},2,[93,149,150],{},"2014-01-31,12.094000,,\n",[93,152,154],{"class":95,"line":153},3,[93,155,156],{},"2014-02-28,16.320667,,\n",[93,158,160],{"class":95,"line":159},4,[93,161,162],{},"2014-12-31,14.827333,2014,3198356000\n",[14,164,165],{},"Most rows contain only a monthly price. The row that closes a fiscal year also\ncontains its year and annual revenue. Keeping the values in one file makes the\nexample easy to distribute, while the reader still separates them into two\nclean series.",[167,168,169],"blockquote",{},[14,170,171],{},"The bundled CSV is suitable for reproducing this example. For a production\nchart, document the source, adjustment method, reporting currency, and update\ndate of your financial data.",[27,173,175],{"id":174},"read-and-structure-the-data","Read and Structure the Data",[14,177,178,179,182],{},"Create ",[45,180,181],{},"data_reader.py",". Small frozen dataclasses give every value a clear name\nand prevent accidental changes after loading.",[84,184,188],{"className":185,"code":186,"language":187,"meta":89,"style":89},"language-python shiki shiki-themes material-theme-lighter github-light-high-contrast github-dark","import csv\nfrom dataclasses import dataclass\nfrom datetime import date\nfrom pathlib import Path\n\n\n@dataclass(frozen=True, slots=True)\nclass StockDataPoint:\n    date: date\n    close: float\n\n\n@dataclass(frozen=True, slots=True)\nclass AnnualRevenue:\n    fiscal_year: int\n    period_end: date\n    revenue: int\n\n\n@dataclass(frozen=True, slots=True)\nclass ComboChartData:\n    monthly_prices: list[StockDataPoint]\n    annual_revenue: list[AnnualRevenue]\n\n\ndef read_combo_chart_data(csv_path: Path) -> ComboChartData:\n    monthly_prices: list[StockDataPoint] = []\n    annual_revenue: list[AnnualRevenue] = []\n\n    with csv_path.open(newline=\"\", encoding=\"utf-8\") as file:\n        for row in csv.DictReader(file):\n            row_date = date.fromisoformat(row[\"date\"])\n\n            if row[\"monthly_close\"]:\n                monthly_prices.append(\n                    StockDataPoint(\n                        date=row_date,\n                        close=float(row[\"monthly_close\"]),\n                    )\n                )\n\n            if row[\"annual_revenue\"]:\n                annual_revenue.append(\n                    AnnualRevenue(\n                        fiscal_year=int(row[\"fiscal_year\"]),\n                        period_end=row_date,\n                        revenue=int(row[\"annual_revenue\"]),\n                    )\n                )\n\n    if not monthly_prices or not annual_revenue:\n        raise ValueError(\"The CSV must contain price and revenue data\")\n\n    return ComboChartData(\n        monthly_prices=monthly_prices,\n        annual_revenue=annual_revenue,\n    )\n","python",[45,189,190,200,213,225,237,244,249,288,301,312,324,329,334,359,369,380,390,400,405,410,435,445,465,482,487,492,522,544,563,568,620,648,681,686,707,721,729,743,769,775,781,786,804,816,824,850,862,886,891,896,901,923,943,948,958,971,983],{"__ignoreMap":89},[93,191,192,196],{"class":95,"line":96},[93,193,195],{"class":194},"sED7I","import",[93,197,199],{"class":198},"soTeR"," csv\n",[93,201,202,205,208,210],{"class":95,"line":147},[93,203,204],{"class":194},"from",[93,206,207],{"class":198}," dataclasses ",[93,209,195],{"class":194},[93,211,212],{"class":198}," dataclass\n",[93,214,215,217,220,222],{"class":95,"line":153},[93,216,204],{"class":194},[93,218,219],{"class":198}," datetime ",[93,221,195],{"class":194},[93,223,224],{"class":198}," date\n",[93,226,227,229,232,234],{"class":95,"line":159},[93,228,204],{"class":194},[93,230,231],{"class":198}," pathlib ",[93,233,195],{"class":194},[93,235,236],{"class":198}," Path\n",[93,238,240],{"class":95,"line":239},5,[93,241,243],{"emptyLinePlaceholder":242},true,"\n",[93,245,247],{"class":95,"line":246},6,[93,248,243],{"emptyLinePlaceholder":242},[93,250,252,256,260,264,268,272,276,278,281,283,285],{"class":95,"line":251},7,[93,253,255],{"class":254},"sd4UE","@",[93,257,259],{"class":258},"synEm","dataclass",[93,261,263],{"class":262},"sVsmf","(",[93,265,267],{"class":266},"sYEV4","frozen",[93,269,271],{"class":270},"sWKEy","=",[93,273,275],{"class":274},"sTy78","True",[93,277,66],{"class":262},[93,279,280],{"class":266}," slots",[93,282,271],{"class":270},[93,284,275],{"class":274},[93,286,287],{"class":262},")\n",[93,289,291,295,298],{"class":95,"line":290},8,[93,292,294],{"class":293},"sfdCM","class",[93,296,297],{"class":99}," StockDataPoint",[93,299,300],{"class":262},":\n",[93,302,304,307,310],{"class":95,"line":303},9,[93,305,306],{"class":198},"    date",[93,308,309],{"class":262},":",[93,311,224],{"class":198},[93,313,315,318,320],{"class":95,"line":314},10,[93,316,317],{"class":198},"    close",[93,319,309],{"class":262},[93,321,323],{"class":322},"s-tzF"," float\n",[93,325,327],{"class":95,"line":326},11,[93,328,243],{"emptyLinePlaceholder":242},[93,330,332],{"class":95,"line":331},12,[93,333,243],{"emptyLinePlaceholder":242},[93,335,337,339,341,343,345,347,349,351,353,355,357],{"class":95,"line":336},13,[93,338,255],{"class":254},[93,340,259],{"class":258},[93,342,263],{"class":262},[93,344,267],{"class":266},[93,346,271],{"class":270},[93,348,275],{"class":274},[93,350,66],{"class":262},[93,352,280],{"class":266},[93,354,271],{"class":270},[93,356,275],{"class":274},[93,358,287],{"class":262},[93,360,362,364,367],{"class":95,"line":361},14,[93,363,294],{"class":293},[93,365,366],{"class":99}," AnnualRevenue",[93,368,300],{"class":262},[93,370,372,375,377],{"class":95,"line":371},15,[93,373,374],{"class":198},"    fiscal_year",[93,376,309],{"class":262},[93,378,379],{"class":322}," int\n",[93,381,383,386,388],{"class":95,"line":382},16,[93,384,385],{"class":198},"    period_end",[93,387,309],{"class":262},[93,389,224],{"class":198},[93,391,393,396,398],{"class":95,"line":392},17,[93,394,395],{"class":198},"    revenue",[93,397,309],{"class":262},[93,399,379],{"class":322},[93,401,403],{"class":95,"line":402},18,[93,404,243],{"emptyLinePlaceholder":242},[93,406,408],{"class":95,"line":407},19,[93,409,243],{"emptyLinePlaceholder":242},[93,411,413,415,417,419,421,423,425,427,429,431,433],{"class":95,"line":412},20,[93,414,255],{"class":254},[93,416,259],{"class":258},[93,418,263],{"class":262},[93,420,267],{"class":266},[93,422,271],{"class":270},[93,424,275],{"class":274},[93,426,66],{"class":262},[93,428,280],{"class":266},[93,430,271],{"class":270},[93,432,275],{"class":274},[93,434,287],{"class":262},[93,436,438,440,443],{"class":95,"line":437},21,[93,439,294],{"class":293},[93,441,442],{"class":99}," ComboChartData",[93,444,300],{"class":262},[93,446,448,451,453,456,459,462],{"class":95,"line":447},22,[93,449,450],{"class":198},"    monthly_prices",[93,452,309],{"class":262},[93,454,455],{"class":198}," list",[93,457,458],{"class":262},"[",[93,460,461],{"class":198},"StockDataPoint",[93,463,464],{"class":262},"]\n",[93,466,468,471,473,475,477,480],{"class":95,"line":467},23,[93,469,470],{"class":198},"    annual_revenue",[93,472,309],{"class":262},[93,474,455],{"class":198},[93,476,458],{"class":262},[93,478,479],{"class":198},"AnnualRevenue",[93,481,464],{"class":262},[93,483,485],{"class":95,"line":484},24,[93,486,243],{"emptyLinePlaceholder":242},[93,488,490],{"class":95,"line":489},25,[93,491,243],{"emptyLinePlaceholder":242},[93,493,495,498,501,503,507,509,512,515,518,520],{"class":95,"line":494},26,[93,496,497],{"class":293},"def",[93,499,500],{"class":258}," read_combo_chart_data",[93,502,263],{"class":262},[93,504,506],{"class":505},"s1VEa","csv_path",[93,508,309],{"class":262},[93,510,511],{"class":198}," Path",[93,513,514],{"class":262},")",[93,516,517],{"class":262}," ->",[93,519,442],{"class":198},[93,521,300],{"class":262},[93,523,525,527,529,531,533,535,538,541],{"class":95,"line":524},27,[93,526,450],{"class":198},[93,528,309],{"class":262},[93,530,455],{"class":198},[93,532,458],{"class":262},[93,534,461],{"class":198},[93,536,537],{"class":262},"]",[93,539,540],{"class":270}," =",[93,542,543],{"class":262}," []\n",[93,545,547,549,551,553,555,557,559,561],{"class":95,"line":546},28,[93,548,470],{"class":198},[93,550,309],{"class":262},[93,552,455],{"class":198},[93,554,458],{"class":262},[93,556,479],{"class":198},[93,558,537],{"class":262},[93,560,540],{"class":270},[93,562,543],{"class":262},[93,564,566],{"class":95,"line":565},29,[93,567,243],{"emptyLinePlaceholder":242},[93,569,571,574,577,579,583,585,588,590,594,596,599,601,604,607,609,611,614,618],{"class":95,"line":570},30,[93,572,573],{"class":194},"    with",[93,575,576],{"class":198}," csv_path",[93,578,129],{"class":262},[93,580,582],{"class":581},"sAK04","open",[93,584,263],{"class":262},[93,586,587],{"class":266},"newline",[93,589,271],{"class":270},[93,591,593],{"class":592},"sqo_7","\"\"",[93,595,66],{"class":262},[93,597,598],{"class":266}," encoding",[93,600,271],{"class":270},[93,602,603],{"class":592},"\"",[93,605,606],{"class":103},"utf-8",[93,608,603],{"class":592},[93,610,514],{"class":262},[93,612,613],{"class":194}," as",[93,615,617],{"class":616},"sAJHR"," file",[93,619,300],{"class":262},[93,621,623,626,629,632,635,637,640,642,645],{"class":95,"line":622},31,[93,624,625],{"class":194},"        for",[93,627,628],{"class":198}," row ",[93,630,631],{"class":194},"in",[93,633,634],{"class":198}," csv",[93,636,129],{"class":262},[93,638,639],{"class":581},"DictReader",[93,641,263],{"class":262},[93,643,644],{"class":616},"file",[93,646,647],{"class":262},"):\n",[93,649,651,654,656,659,661,664,666,669,671,673,676,678],{"class":95,"line":650},32,[93,652,653],{"class":198},"            row_date ",[93,655,271],{"class":270},[93,657,658],{"class":198}," date",[93,660,129],{"class":262},[93,662,663],{"class":581},"fromisoformat",[93,665,263],{"class":262},[93,667,668],{"class":581},"row",[93,670,458],{"class":262},[93,672,603],{"class":592},[93,674,675],{"class":103},"date",[93,677,603],{"class":592},[93,679,680],{"class":262},"])\n",[93,682,684],{"class":95,"line":683},33,[93,685,243],{"emptyLinePlaceholder":242},[93,687,689,692,695,697,699,702,704],{"class":95,"line":688},34,[93,690,691],{"class":194},"            if",[93,693,694],{"class":198}," row",[93,696,458],{"class":262},[93,698,603],{"class":592},[93,700,701],{"class":103},"monthly_close",[93,703,603],{"class":592},[93,705,706],{"class":262},"]:\n",[93,708,710,713,715,718],{"class":95,"line":709},35,[93,711,712],{"class":198},"                monthly_prices",[93,714,129],{"class":262},[93,716,717],{"class":581},"append",[93,719,720],{"class":262},"(\n",[93,722,724,727],{"class":95,"line":723},36,[93,725,726],{"class":581},"                    StockDataPoint",[93,728,720],{"class":262},[93,730,732,735,737,740],{"class":95,"line":731},37,[93,733,734],{"class":266},"                        date",[93,736,271],{"class":270},[93,738,739],{"class":581},"row_date",[93,741,742],{"class":262},",\n",[93,744,746,749,751,754,756,758,760,762,764,766],{"class":95,"line":745},38,[93,747,748],{"class":266},"                        close",[93,750,271],{"class":270},[93,752,753],{"class":322},"float",[93,755,263],{"class":262},[93,757,668],{"class":581},[93,759,458],{"class":262},[93,761,603],{"class":592},[93,763,701],{"class":103},[93,765,603],{"class":592},[93,767,768],{"class":262},"]),\n",[93,770,772],{"class":95,"line":771},39,[93,773,774],{"class":262},"                    )\n",[93,776,778],{"class":95,"line":777},40,[93,779,780],{"class":262},"                )\n",[93,782,784],{"class":95,"line":783},41,[93,785,243],{"emptyLinePlaceholder":242},[93,787,789,791,793,795,797,800,802],{"class":95,"line":788},42,[93,790,691],{"class":194},[93,792,694],{"class":198},[93,794,458],{"class":262},[93,796,603],{"class":592},[93,798,799],{"class":103},"annual_revenue",[93,801,603],{"class":592},[93,803,706],{"class":262},[93,805,807,810,812,814],{"class":95,"line":806},43,[93,808,809],{"class":198},"                annual_revenue",[93,811,129],{"class":262},[93,813,717],{"class":581},[93,815,720],{"class":262},[93,817,819,822],{"class":95,"line":818},44,[93,820,821],{"class":581},"                    AnnualRevenue",[93,823,720],{"class":262},[93,825,827,830,832,835,837,839,841,843,846,848],{"class":95,"line":826},45,[93,828,829],{"class":266},"                        fiscal_year",[93,831,271],{"class":270},[93,833,834],{"class":322},"int",[93,836,263],{"class":262},[93,838,668],{"class":581},[93,840,458],{"class":262},[93,842,603],{"class":592},[93,844,845],{"class":103},"fiscal_year",[93,847,603],{"class":592},[93,849,768],{"class":262},[93,851,853,856,858,860],{"class":95,"line":852},46,[93,854,855],{"class":266},"                        period_end",[93,857,271],{"class":270},[93,859,739],{"class":581},[93,861,742],{"class":262},[93,863,865,868,870,872,874,876,878,880,882,884],{"class":95,"line":864},47,[93,866,867],{"class":266},"                        revenue",[93,869,271],{"class":270},[93,871,834],{"class":322},[93,873,263],{"class":262},[93,875,668],{"class":581},[93,877,458],{"class":262},[93,879,603],{"class":592},[93,881,799],{"class":103},[93,883,603],{"class":592},[93,885,768],{"class":262},[93,887,889],{"class":95,"line":888},48,[93,890,774],{"class":262},[93,892,894],{"class":95,"line":893},49,[93,895,780],{"class":262},[93,897,899],{"class":95,"line":898},50,[93,900,243],{"emptyLinePlaceholder":242},[93,902,904,907,910,913,916,918,921],{"class":95,"line":903},51,[93,905,906],{"class":194},"    if",[93,908,909],{"class":270}," not",[93,911,912],{"class":198}," monthly_prices ",[93,914,915],{"class":270},"or",[93,917,909],{"class":270},[93,919,920],{"class":198}," annual_revenue",[93,922,300],{"class":262},[93,924,926,929,932,934,936,939,941],{"class":95,"line":925},52,[93,927,928],{"class":194},"        raise",[93,930,931],{"class":322}," ValueError",[93,933,263],{"class":262},[93,935,603],{"class":592},[93,937,938],{"class":103},"The CSV must contain price and revenue data",[93,940,603],{"class":592},[93,942,287],{"class":262},[93,944,946],{"class":95,"line":945},53,[93,947,243],{"emptyLinePlaceholder":242},[93,949,951,954,956],{"class":95,"line":950},54,[93,952,953],{"class":194},"    return",[93,955,442],{"class":581},[93,957,720],{"class":262},[93,959,961,964,966,969],{"class":95,"line":960},55,[93,962,963],{"class":266},"        monthly_prices",[93,965,271],{"class":270},[93,967,968],{"class":581},"monthly_prices",[93,970,742],{"class":262},[93,972,974,977,979,981],{"class":95,"line":973},56,[93,975,976],{"class":266},"        annual_revenue",[93,978,271],{"class":270},[93,980,799],{"class":581},[93,982,742],{"class":262},[93,984,986],{"class":95,"line":985},57,[93,987,988],{"class":262},"    )\n",[14,990,991,992,995],{},"The two ",[45,993,994],{},"if"," statements are independent because one CSV row may contain both a\nmonthly price and an annual revenue value.",[27,997,999],{"id":998},"create-the-canvas","Create the Canvas",[14,1001,1002,1003,1006],{},"Start ",[45,1004,1005],{},"main.py"," with the imports, file paths, theme, and canvas:",[84,1008,1010],{"className":185,"code":1009,"language":187,"meta":89,"style":89},"from pathlib import Path\n\nimport pydreamplet as dp\nfrom pydreamplet.markers import TICK_BOTTOM, Marker\nfrom pydreamplet.utils import calculate_ticks\n\nfrom data_reader import read_combo_chart_data\n\n\nBASE_DIR = Path(__file__).parent\nDATA_PATH = BASE_DIR \u002F \"data\" \u002F \"apple.csv\"\nOUTPUT_PATH = BASE_DIR \u002F \"apple_combo_chart.svg\"\n\ntheme = dp.Theme()\ndata = read_combo_chart_data(DATA_PATH)\n\nsvg = dp.SVG(\n    1024,\n    680,\n    font_family=theme.font_family,\n    font_size=theme.font_size,\n)\n\nmargin = {\"left\": 88, \"right\": 88, \"top\": 112, \"bottom\": 72}\nplot_left = margin[\"left\"]\nplot_right = svg.w - margin[\"right\"]\nplot_top = margin[\"top\"]\nplot_bottom = svg.h - margin[\"bottom\"]\n",[45,1011,1012,1022,1026,1039,1062,1078,1082,1094,1098,1102,1123,1154,1172,1176,1194,1210,1214,1230,1238,1245,1262,1278,1282,1286,1352,1372,1402,1421],{"__ignoreMap":89},[93,1013,1014,1016,1018,1020],{"class":95,"line":96},[93,1015,204],{"class":194},[93,1017,231],{"class":198},[93,1019,195],{"class":194},[93,1021,236],{"class":198},[93,1023,1024],{"class":95,"line":147},[93,1025,243],{"emptyLinePlaceholder":242},[93,1027,1028,1030,1033,1036],{"class":95,"line":153},[93,1029,195],{"class":194},[93,1031,1032],{"class":198}," pydreamplet ",[93,1034,1035],{"class":194},"as",[93,1037,1038],{"class":198}," dp\n",[93,1040,1041,1043,1046,1048,1051,1053,1057,1059],{"class":95,"line":159},[93,1042,204],{"class":194},[93,1044,1045],{"class":198}," pydreamplet",[93,1047,129],{"class":262},[93,1049,1050],{"class":198},"markers ",[93,1052,195],{"class":194},[93,1054,1056],{"class":1055},"sXSbw"," TICK_BOTTOM",[93,1058,66],{"class":262},[93,1060,1061],{"class":198}," Marker\n",[93,1063,1064,1066,1068,1070,1073,1075],{"class":95,"line":239},[93,1065,204],{"class":194},[93,1067,1045],{"class":198},[93,1069,129],{"class":262},[93,1071,1072],{"class":198},"utils ",[93,1074,195],{"class":194},[93,1076,1077],{"class":198}," calculate_ticks\n",[93,1079,1080],{"class":95,"line":246},[93,1081,243],{"emptyLinePlaceholder":242},[93,1083,1084,1086,1089,1091],{"class":95,"line":251},[93,1085,204],{"class":194},[93,1087,1088],{"class":198}," data_reader ",[93,1090,195],{"class":194},[93,1092,1093],{"class":198}," read_combo_chart_data\n",[93,1095,1096],{"class":95,"line":290},[93,1097,243],{"emptyLinePlaceholder":242},[93,1099,1100],{"class":95,"line":303},[93,1101,243],{"emptyLinePlaceholder":242},[93,1103,1104,1107,1109,1111,1113,1116,1119],{"class":95,"line":314},[93,1105,1106],{"class":1055},"BASE_DIR",[93,1108,540],{"class":270},[93,1110,511],{"class":581},[93,1112,263],{"class":262},[93,1114,1115],{"class":1055},"__file__",[93,1117,1118],{"class":262},").",[93,1120,1122],{"class":1121},"sm80-","parent\n",[93,1124,1125,1128,1130,1133,1136,1139,1142,1144,1146,1148,1151],{"class":95,"line":326},[93,1126,1127],{"class":1055},"DATA_PATH",[93,1129,540],{"class":270},[93,1131,1132],{"class":1055}," BASE_DIR",[93,1134,1135],{"class":270}," \u002F",[93,1137,1138],{"class":592}," \"",[93,1140,1141],{"class":103},"data",[93,1143,603],{"class":592},[93,1145,1135],{"class":270},[93,1147,1138],{"class":592},[93,1149,1150],{"class":103},"apple.csv",[93,1152,1153],{"class":592},"\"\n",[93,1155,1156,1159,1161,1163,1165,1167,1170],{"class":95,"line":331},[93,1157,1158],{"class":1055},"OUTPUT_PATH",[93,1160,540],{"class":270},[93,1162,1132],{"class":1055},[93,1164,1135],{"class":270},[93,1166,1138],{"class":592},[93,1168,1169],{"class":103},"apple_combo_chart.svg",[93,1171,1153],{"class":592},[93,1173,1174],{"class":95,"line":336},[93,1175,243],{"emptyLinePlaceholder":242},[93,1177,1178,1181,1183,1186,1188,1191],{"class":95,"line":361},[93,1179,1180],{"class":198},"theme ",[93,1182,271],{"class":270},[93,1184,1185],{"class":198}," dp",[93,1187,129],{"class":262},[93,1189,1190],{"class":581},"Theme",[93,1192,1193],{"class":262},"()\n",[93,1195,1196,1199,1201,1203,1205,1208],{"class":95,"line":371},[93,1197,1198],{"class":198},"data ",[93,1200,271],{"class":270},[93,1202,500],{"class":581},[93,1204,263],{"class":262},[93,1206,1127],{"class":1207},"sBTIf",[93,1209,287],{"class":262},[93,1211,1212],{"class":95,"line":382},[93,1213,243],{"emptyLinePlaceholder":242},[93,1215,1216,1219,1221,1223,1225,1228],{"class":95,"line":392},[93,1217,1218],{"class":198},"svg ",[93,1220,271],{"class":270},[93,1222,1185],{"class":198},[93,1224,129],{"class":262},[93,1226,1227],{"class":581},"SVG",[93,1229,720],{"class":262},[93,1231,1232,1236],{"class":95,"line":402},[93,1233,1235],{"class":1234},"sNpir","    1024",[93,1237,742],{"class":262},[93,1239,1240,1243],{"class":95,"line":407},[93,1241,1242],{"class":1234},"    680",[93,1244,742],{"class":262},[93,1246,1247,1250,1252,1255,1257,1260],{"class":95,"line":412},[93,1248,1249],{"class":266},"    font_family",[93,1251,271],{"class":270},[93,1253,1254],{"class":581},"theme",[93,1256,129],{"class":262},[93,1258,1259],{"class":1121},"font_family",[93,1261,742],{"class":262},[93,1263,1264,1267,1269,1271,1273,1276],{"class":95,"line":437},[93,1265,1266],{"class":266},"    font_size",[93,1268,271],{"class":270},[93,1270,1254],{"class":581},[93,1272,129],{"class":262},[93,1274,1275],{"class":1121},"font_size",[93,1277,742],{"class":262},[93,1279,1280],{"class":95,"line":447},[93,1281,287],{"class":262},[93,1283,1284],{"class":95,"line":467},[93,1285,243],{"emptyLinePlaceholder":242},[93,1287,1288,1291,1293,1296,1298,1301,1303,1305,1308,1310,1312,1315,1317,1319,1321,1323,1325,1328,1330,1332,1335,1337,1339,1342,1344,1346,1349],{"class":95,"line":484},[93,1289,1290],{"class":198},"margin ",[93,1292,271],{"class":270},[93,1294,1295],{"class":262}," {",[93,1297,603],{"class":592},[93,1299,1300],{"class":103},"left",[93,1302,603],{"class":592},[93,1304,309],{"class":262},[93,1306,1307],{"class":1234}," 88",[93,1309,66],{"class":262},[93,1311,1138],{"class":592},[93,1313,1314],{"class":103},"right",[93,1316,603],{"class":592},[93,1318,309],{"class":262},[93,1320,1307],{"class":1234},[93,1322,66],{"class":262},[93,1324,1138],{"class":592},[93,1326,1327],{"class":103},"top",[93,1329,603],{"class":592},[93,1331,309],{"class":262},[93,1333,1334],{"class":1234}," 112",[93,1336,66],{"class":262},[93,1338,1138],{"class":592},[93,1340,1341],{"class":103},"bottom",[93,1343,603],{"class":592},[93,1345,309],{"class":262},[93,1347,1348],{"class":1234}," 72",[93,1350,1351],{"class":262},"}\n",[93,1353,1354,1357,1359,1362,1364,1366,1368,1370],{"class":95,"line":489},[93,1355,1356],{"class":198},"plot_left ",[93,1358,271],{"class":270},[93,1360,1361],{"class":198}," margin",[93,1363,458],{"class":262},[93,1365,603],{"class":592},[93,1367,1300],{"class":103},[93,1369,603],{"class":592},[93,1371,464],{"class":262},[93,1373,1374,1377,1379,1382,1384,1387,1390,1392,1394,1396,1398,1400],{"class":95,"line":494},[93,1375,1376],{"class":198},"plot_right ",[93,1378,271],{"class":270},[93,1380,1381],{"class":198}," svg",[93,1383,129],{"class":262},[93,1385,1386],{"class":1121},"w",[93,1388,1389],{"class":270}," -",[93,1391,1361],{"class":198},[93,1393,458],{"class":262},[93,1395,603],{"class":592},[93,1397,1314],{"class":103},[93,1399,603],{"class":592},[93,1401,464],{"class":262},[93,1403,1404,1407,1409,1411,1413,1415,1417,1419],{"class":95,"line":524},[93,1405,1406],{"class":198},"plot_top ",[93,1408,271],{"class":270},[93,1410,1361],{"class":198},[93,1412,458],{"class":262},[93,1414,603],{"class":592},[93,1416,1327],{"class":103},[93,1418,603],{"class":592},[93,1420,464],{"class":262},[93,1422,1423,1426,1428,1430,1432,1435,1437,1439,1441,1443,1445,1447],{"class":95,"line":546},[93,1424,1425],{"class":198},"plot_bottom ",[93,1427,271],{"class":270},[93,1429,1381],{"class":198},[93,1431,129],{"class":262},[93,1433,1434],{"class":1121},"h",[93,1436,1389],{"class":270},[93,1438,1361],{"class":198},[93,1440,458],{"class":262},[93,1442,603],{"class":592},[93,1444,1341],{"class":103},[93,1446,603],{"class":592},[93,1448,464],{"class":262},[14,1450,1451],{},"The larger top margin leaves room for the title and legend-like icon labels.\nThe left and right margins reserve space for two independent vertical axes.",[27,1453,1455],{"id":1454},"add-the-title","Add the Title",[14,1457,1458],{},"The chart title is centered in the header area rather than inside the plotting\nrectangle:",[84,1460,1462],{"className":185,"code":1461,"language":187,"meta":89,"style":89},"svg.append(\n    dp.Text(\n        \"Apple\",\n        pos=(svg.w \u002F 2, margin[\"top\"] \u002F 2),\n        text_anchor=\"middle\",\n        font_size=32,\n        fill=theme.ink,\n        font_weight=600,\n    )\n)\n",[45,1463,1464,1475,1487,1499,1540,1556,1568,1584,1596,1600],{"__ignoreMap":89},[93,1465,1466,1469,1471,1473],{"class":95,"line":96},[93,1467,1468],{"class":198},"svg",[93,1470,129],{"class":262},[93,1472,717],{"class":581},[93,1474,720],{"class":262},[93,1476,1477,1480,1482,1485],{"class":95,"line":147},[93,1478,1479],{"class":581},"    dp",[93,1481,129],{"class":262},[93,1483,1484],{"class":581},"Text",[93,1486,720],{"class":262},[93,1488,1489,1492,1495,1497],{"class":95,"line":153},[93,1490,1491],{"class":592},"        \"",[93,1493,1494],{"class":103},"Apple",[93,1496,603],{"class":592},[93,1498,742],{"class":262},[93,1500,1501,1504,1506,1508,1510,1512,1514,1516,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537],{"class":95,"line":159},[93,1502,1503],{"class":266},"        pos",[93,1505,271],{"class":270},[93,1507,263],{"class":262},[93,1509,1468],{"class":581},[93,1511,129],{"class":262},[93,1513,1386],{"class":1121},[93,1515,1135],{"class":270},[93,1517,1518],{"class":1234}," 2",[93,1520,66],{"class":262},[93,1522,1361],{"class":581},[93,1524,458],{"class":262},[93,1526,603],{"class":592},[93,1528,1327],{"class":103},[93,1530,603],{"class":592},[93,1532,537],{"class":262},[93,1534,1135],{"class":270},[93,1536,1518],{"class":1234},[93,1538,1539],{"class":262},"),\n",[93,1541,1542,1545,1547,1549,1552,1554],{"class":95,"line":239},[93,1543,1544],{"class":266},"        text_anchor",[93,1546,271],{"class":270},[93,1548,603],{"class":592},[93,1550,1551],{"class":103},"middle",[93,1553,603],{"class":592},[93,1555,742],{"class":262},[93,1557,1558,1561,1563,1566],{"class":95,"line":246},[93,1559,1560],{"class":266},"        font_size",[93,1562,271],{"class":270},[93,1564,1565],{"class":1234},"32",[93,1567,742],{"class":262},[93,1569,1570,1573,1575,1577,1579,1582],{"class":95,"line":251},[93,1571,1572],{"class":266},"        fill",[93,1574,271],{"class":270},[93,1576,1254],{"class":581},[93,1578,129],{"class":262},[93,1580,1581],{"class":1121},"ink",[93,1583,742],{"class":262},[93,1585,1586,1589,1591,1594],{"class":95,"line":290},[93,1587,1588],{"class":266},"        font_weight",[93,1590,271],{"class":270},[93,1592,1593],{"class":1234},"600",[93,1595,742],{"class":262},[93,1597,1598],{"class":95,"line":303},[93,1599,988],{"class":262},[93,1601,1602],{"class":95,"line":314},[93,1603,287],{"class":262},[27,1605,1607],{"id":1606},"build-the-revenue-scales","Build the Revenue Scales",[14,1609,1610,1611,1613,1614,1617,1618,1621],{},"Revenue has one value per fiscal year. A ",[45,1612,47],{}," assigns each year a\nhorizontal band and exposes the computed column width through ",[45,1615,1616],{},"bandwidth",".\nA ",[45,1619,1620],{},"LinearScale"," maps revenue from zero to the tallest column.",[84,1623,1625],{"className":185,"code":1624,"language":187,"meta":89,"style":89},"revenue_years = [item.fiscal_year for item in data.annual_revenue]\nrevenue_values = [item.revenue for item in data.annual_revenue]\nmax_revenue = max(revenue_values)\n\nx_revenue_scale = dp.BandScale(\n    revenue_years,\n    (plot_left, plot_right),\n)\ny_revenue_scale = dp.LinearScale(\n    (0, max_revenue),\n    (plot_bottom, plot_top),\n)\n",[45,1626,1627,1661,1691,1708,1712,1727,1734,1749,1753,1768,1782,1796],{"__ignoreMap":89},[93,1628,1629,1632,1634,1637,1640,1642,1644,1647,1650,1652,1655,1657,1659],{"class":95,"line":96},[93,1630,1631],{"class":198},"revenue_years ",[93,1633,271],{"class":270},[93,1635,1636],{"class":262}," [",[93,1638,1639],{"class":198},"item",[93,1641,129],{"class":262},[93,1643,845],{"class":1121},[93,1645,1646],{"class":194}," for",[93,1648,1649],{"class":198}," item ",[93,1651,631],{"class":194},[93,1653,1654],{"class":198}," data",[93,1656,129],{"class":262},[93,1658,799],{"class":1121},[93,1660,464],{"class":262},[93,1662,1663,1666,1668,1670,1672,1674,1677,1679,1681,1683,1685,1687,1689],{"class":95,"line":147},[93,1664,1665],{"class":198},"revenue_values ",[93,1667,271],{"class":270},[93,1669,1636],{"class":262},[93,1671,1639],{"class":198},[93,1673,129],{"class":262},[93,1675,1676],{"class":1121},"revenue",[93,1678,1646],{"class":194},[93,1680,1649],{"class":198},[93,1682,631],{"class":194},[93,1684,1654],{"class":198},[93,1686,129],{"class":262},[93,1688,799],{"class":1121},[93,1690,464],{"class":262},[93,1692,1693,1696,1698,1701,1703,1706],{"class":95,"line":153},[93,1694,1695],{"class":198},"max_revenue ",[93,1697,271],{"class":270},[93,1699,1700],{"class":1207}," max",[93,1702,263],{"class":262},[93,1704,1705],{"class":581},"revenue_values",[93,1707,287],{"class":262},[93,1709,1710],{"class":95,"line":159},[93,1711,243],{"emptyLinePlaceholder":242},[93,1713,1714,1717,1719,1721,1723,1725],{"class":95,"line":239},[93,1715,1716],{"class":198},"x_revenue_scale ",[93,1718,271],{"class":270},[93,1720,1185],{"class":198},[93,1722,129],{"class":262},[93,1724,47],{"class":581},[93,1726,720],{"class":262},[93,1728,1729,1732],{"class":95,"line":246},[93,1730,1731],{"class":581},"    revenue_years",[93,1733,742],{"class":262},[93,1735,1736,1739,1742,1744,1747],{"class":95,"line":251},[93,1737,1738],{"class":262},"    (",[93,1740,1741],{"class":581},"plot_left",[93,1743,66],{"class":262},[93,1745,1746],{"class":581}," plot_right",[93,1748,1539],{"class":262},[93,1750,1751],{"class":95,"line":290},[93,1752,287],{"class":262},[93,1754,1755,1758,1760,1762,1764,1766],{"class":95,"line":303},[93,1756,1757],{"class":198},"y_revenue_scale ",[93,1759,271],{"class":270},[93,1761,1185],{"class":198},[93,1763,129],{"class":262},[93,1765,1620],{"class":581},[93,1767,720],{"class":262},[93,1769,1770,1772,1775,1777,1780],{"class":95,"line":314},[93,1771,1738],{"class":262},[93,1773,1774],{"class":1234},"0",[93,1776,66],{"class":262},[93,1778,1779],{"class":581}," max_revenue",[93,1781,1539],{"class":262},[93,1783,1784,1786,1789,1791,1794],{"class":95,"line":326},[93,1785,1738],{"class":262},[93,1787,1788],{"class":581},"plot_bottom",[93,1790,66],{"class":262},[93,1792,1793],{"class":581}," plot_top",[93,1795,1539],{"class":262},[93,1797,1798],{"class":95,"line":331},[93,1799,287],{"class":262},[14,1801,1802,1803,1806],{},"The vertical output range is reversed. In SVG, ",[45,1804,1805],{},"y=0"," is at the top, so larger\ndata values must map to smaller screen coordinates.",[27,1808,1810],{"id":1809},"define-the-columns-once","Define the Columns Once",[14,1812,1813],{},"The same column geometry serves two purposes:",[1815,1816,1817,1820],"ol",{},[38,1818,1819],{},"it draws the blue revenue columns,",[38,1821,1822],{},"it becomes a clipping path for the green area.",[14,1824,1825],{},"Create both definitions in one loop:",[84,1827,1829],{"className":185,"code":1828,"language":187,"meta":89,"style":89},"defs = svg.ensure_defs()\n\nrevenue_shape = dp.G(id=\"revenue-shape\")\nrevenue_clip = dp.ClipPath(id=\"revenue-clip\")\n\nfor year, revenue in zip(revenue_years, revenue_values, strict=True):\n    x = x_revenue_scale.map(year)\n    y = y_revenue_scale.map(revenue)\n    height = plot_bottom - y\n\n    column = dp.Rect(\n        pos=(x, y),\n        width=x_revenue_scale.bandwidth,\n        height=height,\n    )\n    revenue_shape.append(column)\n\n    revenue_clip.append(\n        dp.Rect(\n            pos=(x, y),\n            width=x_revenue_scale.bandwidth,\n            height=height,\n        )\n    )\n\ndefs.append(revenue_shape, revenue_clip)\n",[45,1830,1831,1847,1851,1881,1910,1914,1953,1975,1995,2011,2015,2031,2049,2065,2077,2081,2097,2101,2112,2123,2140,2155,2166,2171,2175,2179],{"__ignoreMap":89},[93,1832,1833,1836,1838,1840,1842,1845],{"class":95,"line":96},[93,1834,1835],{"class":198},"defs ",[93,1837,271],{"class":270},[93,1839,1381],{"class":198},[93,1841,129],{"class":262},[93,1843,1844],{"class":581},"ensure_defs",[93,1846,1193],{"class":262},[93,1848,1849],{"class":95,"line":147},[93,1850,243],{"emptyLinePlaceholder":242},[93,1852,1853,1856,1858,1860,1862,1865,1867,1870,1872,1874,1877,1879],{"class":95,"line":153},[93,1854,1855],{"class":198},"revenue_shape ",[93,1857,271],{"class":270},[93,1859,1185],{"class":198},[93,1861,129],{"class":262},[93,1863,1864],{"class":581},"G",[93,1866,263],{"class":262},[93,1868,1869],{"class":266},"id",[93,1871,271],{"class":270},[93,1873,603],{"class":592},[93,1875,1876],{"class":103},"revenue-shape",[93,1878,603],{"class":592},[93,1880,287],{"class":262},[93,1882,1883,1886,1888,1890,1892,1895,1897,1899,1901,1903,1906,1908],{"class":95,"line":159},[93,1884,1885],{"class":198},"revenue_clip ",[93,1887,271],{"class":270},[93,1889,1185],{"class":198},[93,1891,129],{"class":262},[93,1893,1894],{"class":581},"ClipPath",[93,1896,263],{"class":262},[93,1898,1869],{"class":266},[93,1900,271],{"class":270},[93,1902,603],{"class":592},[93,1904,1905],{"class":103},"revenue-clip",[93,1907,603],{"class":592},[93,1909,287],{"class":262},[93,1911,1912],{"class":95,"line":239},[93,1913,243],{"emptyLinePlaceholder":242},[93,1915,1916,1919,1922,1924,1927,1929,1932,1934,1937,1939,1942,1944,1947,1949,1951],{"class":95,"line":246},[93,1917,1918],{"class":194},"for",[93,1920,1921],{"class":198}," year",[93,1923,66],{"class":262},[93,1925,1926],{"class":198}," revenue ",[93,1928,631],{"class":194},[93,1930,1931],{"class":1207}," zip",[93,1933,263],{"class":262},[93,1935,1936],{"class":581},"revenue_years",[93,1938,66],{"class":262},[93,1940,1941],{"class":581}," revenue_values",[93,1943,66],{"class":262},[93,1945,1946],{"class":266}," strict",[93,1948,271],{"class":270},[93,1950,275],{"class":274},[93,1952,647],{"class":262},[93,1954,1955,1958,1960,1963,1965,1968,1970,1973],{"class":95,"line":251},[93,1956,1957],{"class":198},"    x ",[93,1959,271],{"class":270},[93,1961,1962],{"class":198}," x_revenue_scale",[93,1964,129],{"class":262},[93,1966,1967],{"class":581},"map",[93,1969,263],{"class":262},[93,1971,1972],{"class":581},"year",[93,1974,287],{"class":262},[93,1976,1977,1980,1982,1985,1987,1989,1991,1993],{"class":95,"line":290},[93,1978,1979],{"class":198},"    y ",[93,1981,271],{"class":270},[93,1983,1984],{"class":198}," y_revenue_scale",[93,1986,129],{"class":262},[93,1988,1967],{"class":581},[93,1990,263],{"class":262},[93,1992,1676],{"class":581},[93,1994,287],{"class":262},[93,1996,1997,2000,2002,2005,2008],{"class":95,"line":303},[93,1998,1999],{"class":198},"    height ",[93,2001,271],{"class":270},[93,2003,2004],{"class":198}," plot_bottom ",[93,2006,2007],{"class":270},"-",[93,2009,2010],{"class":198}," y\n",[93,2012,2013],{"class":95,"line":314},[93,2014,243],{"emptyLinePlaceholder":242},[93,2016,2017,2020,2022,2024,2026,2029],{"class":95,"line":326},[93,2018,2019],{"class":198},"    column ",[93,2021,271],{"class":270},[93,2023,1185],{"class":198},[93,2025,129],{"class":262},[93,2027,2028],{"class":581},"Rect",[93,2030,720],{"class":262},[93,2032,2033,2035,2037,2039,2042,2044,2047],{"class":95,"line":331},[93,2034,1503],{"class":266},[93,2036,271],{"class":270},[93,2038,263],{"class":262},[93,2040,2041],{"class":581},"x",[93,2043,66],{"class":262},[93,2045,2046],{"class":581}," y",[93,2048,1539],{"class":262},[93,2050,2051,2054,2056,2059,2061,2063],{"class":95,"line":336},[93,2052,2053],{"class":266},"        width",[93,2055,271],{"class":270},[93,2057,2058],{"class":581},"x_revenue_scale",[93,2060,129],{"class":262},[93,2062,1616],{"class":1121},[93,2064,742],{"class":262},[93,2066,2067,2070,2072,2075],{"class":95,"line":361},[93,2068,2069],{"class":266},"        height",[93,2071,271],{"class":270},[93,2073,2074],{"class":581},"height",[93,2076,742],{"class":262},[93,2078,2079],{"class":95,"line":371},[93,2080,988],{"class":262},[93,2082,2083,2086,2088,2090,2092,2095],{"class":95,"line":382},[93,2084,2085],{"class":198},"    revenue_shape",[93,2087,129],{"class":262},[93,2089,717],{"class":581},[93,2091,263],{"class":262},[93,2093,2094],{"class":581},"column",[93,2096,287],{"class":262},[93,2098,2099],{"class":95,"line":392},[93,2100,243],{"emptyLinePlaceholder":242},[93,2102,2103,2106,2108,2110],{"class":95,"line":402},[93,2104,2105],{"class":198},"    revenue_clip",[93,2107,129],{"class":262},[93,2109,717],{"class":581},[93,2111,720],{"class":262},[93,2113,2114,2117,2119,2121],{"class":95,"line":407},[93,2115,2116],{"class":581},"        dp",[93,2118,129],{"class":262},[93,2120,2028],{"class":581},[93,2122,720],{"class":262},[93,2124,2125,2128,2130,2132,2134,2136,2138],{"class":95,"line":412},[93,2126,2127],{"class":266},"            pos",[93,2129,271],{"class":270},[93,2131,263],{"class":262},[93,2133,2041],{"class":581},[93,2135,66],{"class":262},[93,2137,2046],{"class":581},[93,2139,1539],{"class":262},[93,2141,2142,2145,2147,2149,2151,2153],{"class":95,"line":437},[93,2143,2144],{"class":266},"            width",[93,2146,271],{"class":270},[93,2148,2058],{"class":581},[93,2150,129],{"class":262},[93,2152,1616],{"class":1121},[93,2154,742],{"class":262},[93,2156,2157,2160,2162,2164],{"class":95,"line":447},[93,2158,2159],{"class":266},"            height",[93,2161,271],{"class":270},[93,2163,2074],{"class":581},[93,2165,742],{"class":262},[93,2167,2168],{"class":95,"line":467},[93,2169,2170],{"class":262},"        )\n",[93,2172,2173],{"class":95,"line":484},[93,2174,988],{"class":262},[93,2176,2177],{"class":95,"line":489},[93,2178,243],{"emptyLinePlaceholder":242},[93,2180,2181,2184,2186,2188,2190,2193,2195,2198],{"class":95,"line":494},[93,2182,2183],{"class":198},"defs",[93,2185,129],{"class":262},[93,2187,717],{"class":581},[93,2189,263],{"class":262},[93,2191,2192],{"class":581},"revenue_shape",[93,2194,66],{"class":262},[93,2196,2197],{"class":581}," revenue_clip",[93,2199,287],{"class":262},[14,2201,2202],{},"An SVG element cannot have two parents, which is why the clipping path receives\nits own rectangles instead of reusing the same Python objects.",[14,2204,2205,2206,309],{},"The visible columns can now reference the group with ",[45,2207,65],{},[84,2209,2211],{"className":185,"code":2210,"language":187,"meta":89,"style":89},"revenue_layer = dp.G().append(\n    dp.Use(revenue_shape, fill=theme.blue)\n)\n",[45,2212,2213,2233,2262],{"__ignoreMap":89},[93,2214,2215,2218,2220,2222,2224,2226,2229,2231],{"class":95,"line":96},[93,2216,2217],{"class":198},"revenue_layer ",[93,2219,271],{"class":270},[93,2221,1185],{"class":198},[93,2223,129],{"class":262},[93,2225,1864],{"class":581},[93,2227,2228],{"class":262},"().",[93,2230,717],{"class":581},[93,2232,720],{"class":262},[93,2234,2235,2237,2239,2242,2244,2246,2248,2251,2253,2255,2257,2260],{"class":95,"line":147},[93,2236,1479],{"class":581},[93,2238,129],{"class":262},[93,2240,2241],{"class":581},"Use",[93,2243,263],{"class":262},[93,2245,2192],{"class":581},[93,2247,66],{"class":262},[93,2249,2250],{"class":266}," fill",[93,2252,271],{"class":270},[93,2254,1254],{"class":581},[93,2256,129],{"class":262},[93,2258,2259],{"class":1121},"blue",[93,2261,287],{"class":262},[93,2263,2264],{"class":95,"line":153},[93,2265,287],{"class":262},[14,2267,2268],{},"This keeps the generated SVG easier to inspect and makes the relationship\nbetween the visible bars and clipping geometry explicit.",[27,2270,2272],{"id":2271},"add-the-area-gradient","Add the Area Gradient",[14,2274,2275],{},"The stock area fades vertically from opaque green to a lighter transparent\ngreen:",[84,2277,2279],{"className":185,"code":2278,"language":187,"meta":89,"style":89},"area_gradient = dp.LinearGradient(\n    id=\"area-gradient\",\n    x1=0,\n    y1=plot_top,\n    x2=0,\n    y2=plot_bottom,\n)\narea_gradient.attrs({\"gradientUnits\": \"userSpaceOnUse\"})\narea_gradient.add_stop(\"0%\", theme.lime, 1)\narea_gradient.add_stop(\"100%\", theme.lime, 0.25)\ndefs.append(area_gradient)\n",[45,2280,2281,2297,2313,2324,2336,2347,2358,2362,2394,2429,2461],{"__ignoreMap":89},[93,2282,2283,2286,2288,2290,2292,2295],{"class":95,"line":96},[93,2284,2285],{"class":198},"area_gradient ",[93,2287,271],{"class":270},[93,2289,1185],{"class":198},[93,2291,129],{"class":262},[93,2293,2294],{"class":581},"LinearGradient",[93,2296,720],{"class":262},[93,2298,2299,2302,2304,2306,2309,2311],{"class":95,"line":147},[93,2300,2301],{"class":266},"    id",[93,2303,271],{"class":270},[93,2305,603],{"class":592},[93,2307,2308],{"class":103},"area-gradient",[93,2310,603],{"class":592},[93,2312,742],{"class":262},[93,2314,2315,2318,2320,2322],{"class":95,"line":153},[93,2316,2317],{"class":266},"    x1",[93,2319,271],{"class":270},[93,2321,1774],{"class":1234},[93,2323,742],{"class":262},[93,2325,2326,2329,2331,2334],{"class":95,"line":159},[93,2327,2328],{"class":266},"    y1",[93,2330,271],{"class":270},[93,2332,2333],{"class":581},"plot_top",[93,2335,742],{"class":262},[93,2337,2338,2341,2343,2345],{"class":95,"line":239},[93,2339,2340],{"class":266},"    x2",[93,2342,271],{"class":270},[93,2344,1774],{"class":1234},[93,2346,742],{"class":262},[93,2348,2349,2352,2354,2356],{"class":95,"line":246},[93,2350,2351],{"class":266},"    y2",[93,2353,271],{"class":270},[93,2355,1788],{"class":581},[93,2357,742],{"class":262},[93,2359,2360],{"class":95,"line":251},[93,2361,287],{"class":262},[93,2363,2364,2367,2369,2372,2375,2377,2380,2382,2384,2386,2389,2391],{"class":95,"line":290},[93,2365,2366],{"class":198},"area_gradient",[93,2368,129],{"class":262},[93,2370,2371],{"class":581},"attrs",[93,2373,2374],{"class":262},"({",[93,2376,603],{"class":592},[93,2378,2379],{"class":103},"gradientUnits",[93,2381,603],{"class":592},[93,2383,309],{"class":262},[93,2385,1138],{"class":592},[93,2387,2388],{"class":103},"userSpaceOnUse",[93,2390,603],{"class":592},[93,2392,2393],{"class":262},"})\n",[93,2395,2396,2398,2400,2403,2405,2407,2410,2412,2414,2417,2419,2422,2424,2427],{"class":95,"line":303},[93,2397,2366],{"class":198},[93,2399,129],{"class":262},[93,2401,2402],{"class":581},"add_stop",[93,2404,263],{"class":262},[93,2406,603],{"class":592},[93,2408,2409],{"class":103},"0%",[93,2411,603],{"class":592},[93,2413,66],{"class":262},[93,2415,2416],{"class":581}," theme",[93,2418,129],{"class":262},[93,2420,2421],{"class":1121},"lime",[93,2423,66],{"class":262},[93,2425,2426],{"class":1234}," 1",[93,2428,287],{"class":262},[93,2430,2431,2433,2435,2437,2439,2441,2444,2446,2448,2450,2452,2454,2456,2459],{"class":95,"line":314},[93,2432,2366],{"class":198},[93,2434,129],{"class":262},[93,2436,2402],{"class":581},[93,2438,263],{"class":262},[93,2440,603],{"class":592},[93,2442,2443],{"class":103},"100%",[93,2445,603],{"class":592},[93,2447,66],{"class":262},[93,2449,2416],{"class":581},[93,2451,129],{"class":262},[93,2453,2421],{"class":1121},[93,2455,66],{"class":262},[93,2457,2458],{"class":1234}," 0.25",[93,2460,287],{"class":262},[93,2462,2463,2465,2467,2469,2471,2473],{"class":95,"line":326},[93,2464,2183],{"class":198},[93,2466,129],{"class":262},[93,2468,717],{"class":581},[93,2470,263],{"class":262},[93,2472,2366],{"class":581},[93,2474,287],{"class":262},[14,2476,2477,2480],{},[45,2478,2479],{},"gradientUnits=\"userSpaceOnUse\""," makes the gradient follow the chart's\ncoordinate system. Without it, SVG would calculate the gradient relative to\nthe bounding box of each painted shape.",[27,2482,2484],{"id":2483},"draw-the-stock-price-series","Draw the Stock Price Series",[14,2486,2487,2488,2490],{},"Monthly prices need a denser horizontal scale. Converting dates to ordinal\nintegers gives ",[45,2489,51],{}," simple, ordered domain values:",[84,2492,2494],{"className":185,"code":2493,"language":187,"meta":89,"style":89},"stock_months = [item.date.toordinal() for item in data.monthly_prices]\nstock_values = [item.close for item in data.monthly_prices]\n\nstock_x_scale = dp.PointScale(\n    stock_months,\n    (plot_left, plot_right),\n)\nstock_y_scale = dp.LinearScale(\n    (0, max(stock_values)),\n    (plot_bottom, plot_top),\n)\n",[45,2495,2496,2533,2563,2567,2582,2589,2601,2605,2620,2638,2650],{"__ignoreMap":89},[93,2497,2498,2501,2503,2505,2507,2509,2511,2513,2516,2519,2521,2523,2525,2527,2529,2531],{"class":95,"line":96},[93,2499,2500],{"class":198},"stock_months ",[93,2502,271],{"class":270},[93,2504,1636],{"class":262},[93,2506,1639],{"class":198},[93,2508,129],{"class":262},[93,2510,675],{"class":1121},[93,2512,129],{"class":262},[93,2514,2515],{"class":581},"toordinal",[93,2517,2518],{"class":262},"()",[93,2520,1646],{"class":194},[93,2522,1649],{"class":198},[93,2524,631],{"class":194},[93,2526,1654],{"class":198},[93,2528,129],{"class":262},[93,2530,968],{"class":1121},[93,2532,464],{"class":262},[93,2534,2535,2538,2540,2542,2544,2546,2549,2551,2553,2555,2557,2559,2561],{"class":95,"line":147},[93,2536,2537],{"class":198},"stock_values ",[93,2539,271],{"class":270},[93,2541,1636],{"class":262},[93,2543,1639],{"class":198},[93,2545,129],{"class":262},[93,2547,2548],{"class":1121},"close",[93,2550,1646],{"class":194},[93,2552,1649],{"class":198},[93,2554,631],{"class":194},[93,2556,1654],{"class":198},[93,2558,129],{"class":262},[93,2560,968],{"class":1121},[93,2562,464],{"class":262},[93,2564,2565],{"class":95,"line":153},[93,2566,243],{"emptyLinePlaceholder":242},[93,2568,2569,2572,2574,2576,2578,2580],{"class":95,"line":159},[93,2570,2571],{"class":198},"stock_x_scale ",[93,2573,271],{"class":270},[93,2575,1185],{"class":198},[93,2577,129],{"class":262},[93,2579,51],{"class":581},[93,2581,720],{"class":262},[93,2583,2584,2587],{"class":95,"line":239},[93,2585,2586],{"class":581},"    stock_months",[93,2588,742],{"class":262},[93,2590,2591,2593,2595,2597,2599],{"class":95,"line":246},[93,2592,1738],{"class":262},[93,2594,1741],{"class":581},[93,2596,66],{"class":262},[93,2598,1746],{"class":581},[93,2600,1539],{"class":262},[93,2602,2603],{"class":95,"line":251},[93,2604,287],{"class":262},[93,2606,2607,2610,2612,2614,2616,2618],{"class":95,"line":290},[93,2608,2609],{"class":198},"stock_y_scale ",[93,2611,271],{"class":270},[93,2613,1185],{"class":198},[93,2615,129],{"class":262},[93,2617,1620],{"class":581},[93,2619,720],{"class":262},[93,2621,2622,2624,2626,2628,2630,2632,2635],{"class":95,"line":303},[93,2623,1738],{"class":262},[93,2625,1774],{"class":1234},[93,2627,66],{"class":262},[93,2629,1700],{"class":1207},[93,2631,263],{"class":262},[93,2633,2634],{"class":581},"stock_values",[93,2636,2637],{"class":262},")),\n",[93,2639,2640,2642,2644,2646,2648],{"class":95,"line":314},[93,2641,1738],{"class":262},[93,2643,1788],{"class":581},[93,2645,66],{"class":262},[93,2647,1793],{"class":581},[93,2649,1539],{"class":262},[93,2651,2652],{"class":95,"line":326},[93,2653,287],{"class":262},[14,2655,2656],{},"The revenue and stock series intentionally use different vertical scales.\nTheir units and magnitudes are unrelated: revenue is measured in billions of\ndollars, while the share price is measured in dollars per share.",[14,2658,2659],{},"Build the monthly points:",[84,2661,2663],{"className":185,"code":2662,"language":187,"meta":89,"style":89},"stock_points: list[tuple[float, float]] = []\n\nfor month, value in zip(stock_months, stock_values, strict=True):\n    x = stock_x_scale.map(month)\n    assert x is not None\n    stock_points.append((x, stock_y_scale.map(value)))\n",[45,2664,2665,2695,2699,2735,2755,2771],{"__ignoreMap":89},[93,2666,2667,2670,2672,2674,2676,2679,2681,2683,2685,2688,2691,2693],{"class":95,"line":96},[93,2668,2669],{"class":198},"stock_points",[93,2671,309],{"class":262},[93,2673,455],{"class":198},[93,2675,458],{"class":262},[93,2677,2678],{"class":198},"tuple",[93,2680,458],{"class":262},[93,2682,753],{"class":322},[93,2684,66],{"class":262},[93,2686,2687],{"class":322}," float",[93,2689,2690],{"class":262},"]]",[93,2692,540],{"class":270},[93,2694,543],{"class":262},[93,2696,2697],{"class":95,"line":147},[93,2698,243],{"emptyLinePlaceholder":242},[93,2700,2701,2703,2706,2708,2711,2713,2715,2717,2720,2722,2725,2727,2729,2731,2733],{"class":95,"line":153},[93,2702,1918],{"class":194},[93,2704,2705],{"class":198}," month",[93,2707,66],{"class":262},[93,2709,2710],{"class":198}," value ",[93,2712,631],{"class":194},[93,2714,1931],{"class":1207},[93,2716,263],{"class":262},[93,2718,2719],{"class":581},"stock_months",[93,2721,66],{"class":262},[93,2723,2724],{"class":581}," stock_values",[93,2726,66],{"class":262},[93,2728,1946],{"class":266},[93,2730,271],{"class":270},[93,2732,275],{"class":274},[93,2734,647],{"class":262},[93,2736,2737,2739,2741,2744,2746,2748,2750,2753],{"class":95,"line":159},[93,2738,1957],{"class":198},[93,2740,271],{"class":270},[93,2742,2743],{"class":198}," stock_x_scale",[93,2745,129],{"class":262},[93,2747,1967],{"class":581},[93,2749,263],{"class":262},[93,2751,2752],{"class":581},"month",[93,2754,287],{"class":262},[93,2756,2757,2760,2763,2766,2768],{"class":95,"line":239},[93,2758,2759],{"class":194},"    assert",[93,2761,2762],{"class":198}," x ",[93,2764,2765],{"class":270},"is",[93,2767,909],{"class":270},[93,2769,2770],{"class":274}," None\n",[93,2772,2773,2776,2778,2780,2783,2785,2787,2790,2792,2794,2796,2799],{"class":95,"line":246},[93,2774,2775],{"class":198},"    stock_points",[93,2777,129],{"class":262},[93,2779,717],{"class":581},[93,2781,2782],{"class":262},"((",[93,2784,2041],{"class":581},[93,2786,66],{"class":262},[93,2788,2789],{"class":581}," stock_y_scale",[93,2791,129],{"class":262},[93,2793,1967],{"class":581},[93,2795,263],{"class":262},[93,2797,2798],{"class":581},"value",[93,2800,2801],{"class":262},")))\n",[14,2803,2804,2807,2808,2811],{},[45,2805,2806],{},"PointScale.map()"," returns ",[45,2809,2810],{},"None"," for a value outside its domain. Every month in\nthis loop came from that domain, so the assertion documents a valid invariant\nand helps static type checkers.",[14,2813,2814],{},"Generate a smooth line and a matching area:",[84,2816,2818],{"className":185,"code":2817,"language":187,"meta":89,"style":89},"line_generator = dp.LineGenerator(curve=\"basis\")\narea_generator = dp.AreaGenerator(\n    y0=lambda _point, _index: plot_bottom,\n    curve=\"basis\",\n)\n\nline_path = line_generator(stock_points)\narea_path = area_generator(stock_points)\n\nstock_layer = dp.G().append(\n    dp.Path(\n        d=area_path,\n        fill=\"url(#area-gradient)\",\n        stroke=theme.transparent,\n        clip_path=\"url(#revenue-clip)\",\n    ),\n    dp.Path(\n        d=line_path,\n        fill=theme.transparent,\n        stroke=dp.tone(theme.green, -0.5),\n        stroke_width=3,\n    ),\n)\n",[45,2819,2820,2850,2866,2891,2906,2910,2914,2930,2946,2950,2969,2980,2992,3007,3023,3039,3044,3054,3065,3079,3111,3123,3127],{"__ignoreMap":89},[93,2821,2822,2825,2827,2829,2831,2834,2836,2839,2841,2843,2846,2848],{"class":95,"line":96},[93,2823,2824],{"class":198},"line_generator ",[93,2826,271],{"class":270},[93,2828,1185],{"class":198},[93,2830,129],{"class":262},[93,2832,2833],{"class":581},"LineGenerator",[93,2835,263],{"class":262},[93,2837,2838],{"class":266},"curve",[93,2840,271],{"class":270},[93,2842,603],{"class":592},[93,2844,2845],{"class":103},"basis",[93,2847,603],{"class":592},[93,2849,287],{"class":262},[93,2851,2852,2855,2857,2859,2861,2864],{"class":95,"line":147},[93,2853,2854],{"class":198},"area_generator ",[93,2856,271],{"class":270},[93,2858,1185],{"class":198},[93,2860,129],{"class":262},[93,2862,2863],{"class":581},"AreaGenerator",[93,2865,720],{"class":262},[93,2867,2868,2871,2873,2876,2879,2881,2884,2886,2889],{"class":95,"line":153},[93,2869,2870],{"class":266},"    y0",[93,2872,271],{"class":270},[93,2874,2875],{"class":293},"lambda",[93,2877,2878],{"class":505}," _point",[93,2880,66],{"class":262},[93,2882,2883],{"class":505}," _index",[93,2885,309],{"class":262},[93,2887,2888],{"class":581}," plot_bottom",[93,2890,742],{"class":262},[93,2892,2893,2896,2898,2900,2902,2904],{"class":95,"line":159},[93,2894,2895],{"class":266},"    curve",[93,2897,271],{"class":270},[93,2899,603],{"class":592},[93,2901,2845],{"class":103},[93,2903,603],{"class":592},[93,2905,742],{"class":262},[93,2907,2908],{"class":95,"line":239},[93,2909,287],{"class":262},[93,2911,2912],{"class":95,"line":246},[93,2913,243],{"emptyLinePlaceholder":242},[93,2915,2916,2919,2921,2924,2926,2928],{"class":95,"line":251},[93,2917,2918],{"class":198},"line_path ",[93,2920,271],{"class":270},[93,2922,2923],{"class":581}," line_generator",[93,2925,263],{"class":262},[93,2927,2669],{"class":581},[93,2929,287],{"class":262},[93,2931,2932,2935,2937,2940,2942,2944],{"class":95,"line":290},[93,2933,2934],{"class":198},"area_path ",[93,2936,271],{"class":270},[93,2938,2939],{"class":581}," area_generator",[93,2941,263],{"class":262},[93,2943,2669],{"class":581},[93,2945,287],{"class":262},[93,2947,2948],{"class":95,"line":303},[93,2949,243],{"emptyLinePlaceholder":242},[93,2951,2952,2955,2957,2959,2961,2963,2965,2967],{"class":95,"line":314},[93,2953,2954],{"class":198},"stock_layer ",[93,2956,271],{"class":270},[93,2958,1185],{"class":198},[93,2960,129],{"class":262},[93,2962,1864],{"class":581},[93,2964,2228],{"class":262},[93,2966,717],{"class":581},[93,2968,720],{"class":262},[93,2970,2971,2973,2975,2978],{"class":95,"line":326},[93,2972,1479],{"class":581},[93,2974,129],{"class":262},[93,2976,2977],{"class":581},"Path",[93,2979,720],{"class":262},[93,2981,2982,2985,2987,2990],{"class":95,"line":331},[93,2983,2984],{"class":266},"        d",[93,2986,271],{"class":270},[93,2988,2989],{"class":581},"area_path",[93,2991,742],{"class":262},[93,2993,2994,2996,2998,3000,3003,3005],{"class":95,"line":336},[93,2995,1572],{"class":266},[93,2997,271],{"class":270},[93,2999,603],{"class":592},[93,3001,3002],{"class":103},"url(#area-gradient)",[93,3004,603],{"class":592},[93,3006,742],{"class":262},[93,3008,3009,3012,3014,3016,3018,3021],{"class":95,"line":361},[93,3010,3011],{"class":266},"        stroke",[93,3013,271],{"class":270},[93,3015,1254],{"class":581},[93,3017,129],{"class":262},[93,3019,3020],{"class":1121},"transparent",[93,3022,742],{"class":262},[93,3024,3025,3028,3030,3032,3035,3037],{"class":95,"line":371},[93,3026,3027],{"class":266},"        clip_path",[93,3029,271],{"class":270},[93,3031,603],{"class":592},[93,3033,3034],{"class":103},"url(#revenue-clip)",[93,3036,603],{"class":592},[93,3038,742],{"class":262},[93,3040,3041],{"class":95,"line":382},[93,3042,3043],{"class":262},"    ),\n",[93,3045,3046,3048,3050,3052],{"class":95,"line":392},[93,3047,1479],{"class":581},[93,3049,129],{"class":262},[93,3051,2977],{"class":581},[93,3053,720],{"class":262},[93,3055,3056,3058,3060,3063],{"class":95,"line":402},[93,3057,2984],{"class":266},[93,3059,271],{"class":270},[93,3061,3062],{"class":581},"line_path",[93,3064,742],{"class":262},[93,3066,3067,3069,3071,3073,3075,3077],{"class":95,"line":407},[93,3068,1572],{"class":266},[93,3070,271],{"class":270},[93,3072,1254],{"class":581},[93,3074,129],{"class":262},[93,3076,3020],{"class":1121},[93,3078,742],{"class":262},[93,3080,3081,3083,3085,3088,3090,3093,3095,3097,3099,3102,3104,3106,3109],{"class":95,"line":412},[93,3082,3011],{"class":266},[93,3084,271],{"class":270},[93,3086,3087],{"class":581},"dp",[93,3089,129],{"class":262},[93,3091,3092],{"class":581},"tone",[93,3094,263],{"class":262},[93,3096,1254],{"class":581},[93,3098,129],{"class":262},[93,3100,3101],{"class":1121},"green",[93,3103,66],{"class":262},[93,3105,1389],{"class":270},[93,3107,3108],{"class":1234},"0.5",[93,3110,1539],{"class":262},[93,3112,3113,3116,3118,3121],{"class":95,"line":437},[93,3114,3115],{"class":266},"        stroke_width",[93,3117,271],{"class":270},[93,3119,3120],{"class":1234},"3",[93,3122,742],{"class":262},[93,3124,3125],{"class":95,"line":447},[93,3126,3043],{"class":262},[93,3128,3129],{"class":95,"line":467},[93,3130,287],{"class":262},[14,3132,3133,3134,3137],{},"The area exists across the whole plotting region, but\n",[45,3135,3136],{},"clip_path=\"url(#revenue-clip)\""," reveals it only where it overlaps a revenue\ncolumn. The line is not clipped, so it remains readable between columns.",[27,3139,3141],{"id":3140},"draw-the-horizontal-axis","Draw the Horizontal Axis",[14,3143,3144],{},"Create a separate group for axes and grid lines:",[84,3146,3148],{"className":185,"code":3147,"language":187,"meta":89,"style":89},"axis_layer = dp.G()\naxis_y = plot_bottom\n\naxis_layer.append(\n    dp.Line(\n        x1=plot_left,\n        y1=axis_y,\n        x2=plot_right,\n        y2=axis_y,\n        stroke=theme.ink,\n    )\n)\n",[45,3149,3150,3165,3175,3179,3190,3201,3212,3224,3236,3247,3261,3265],{"__ignoreMap":89},[93,3151,3152,3155,3157,3159,3161,3163],{"class":95,"line":96},[93,3153,3154],{"class":198},"axis_layer ",[93,3156,271],{"class":270},[93,3158,1185],{"class":198},[93,3160,129],{"class":262},[93,3162,1864],{"class":581},[93,3164,1193],{"class":262},[93,3166,3167,3170,3172],{"class":95,"line":147},[93,3168,3169],{"class":198},"axis_y ",[93,3171,271],{"class":270},[93,3173,3174],{"class":198}," plot_bottom\n",[93,3176,3177],{"class":95,"line":153},[93,3178,243],{"emptyLinePlaceholder":242},[93,3180,3181,3184,3186,3188],{"class":95,"line":159},[93,3182,3183],{"class":198},"axis_layer",[93,3185,129],{"class":262},[93,3187,717],{"class":581},[93,3189,720],{"class":262},[93,3191,3192,3194,3196,3199],{"class":95,"line":239},[93,3193,1479],{"class":581},[93,3195,129],{"class":262},[93,3197,3198],{"class":581},"Line",[93,3200,720],{"class":262},[93,3202,3203,3206,3208,3210],{"class":95,"line":246},[93,3204,3205],{"class":266},"        x1",[93,3207,271],{"class":270},[93,3209,1741],{"class":581},[93,3211,742],{"class":262},[93,3213,3214,3217,3219,3222],{"class":95,"line":251},[93,3215,3216],{"class":266},"        y1",[93,3218,271],{"class":270},[93,3220,3221],{"class":581},"axis_y",[93,3223,742],{"class":262},[93,3225,3226,3229,3231,3234],{"class":95,"line":290},[93,3227,3228],{"class":266},"        x2",[93,3230,271],{"class":270},[93,3232,3233],{"class":581},"plot_right",[93,3235,742],{"class":262},[93,3237,3238,3241,3243,3245],{"class":95,"line":303},[93,3239,3240],{"class":266},"        y2",[93,3242,271],{"class":270},[93,3244,3221],{"class":581},[93,3246,742],{"class":262},[93,3248,3249,3251,3253,3255,3257,3259],{"class":95,"line":314},[93,3250,3011],{"class":266},[93,3252,271],{"class":270},[93,3254,1254],{"class":581},[93,3256,129],{"class":262},[93,3258,1581],{"class":1121},[93,3260,742],{"class":262},[93,3262,3263],{"class":95,"line":326},[93,3264,988],{"class":262},[93,3266,3267],{"class":95,"line":331},[93,3268,287],{"class":262},[14,3270,3271],{},"Place one tick at the center of each revenue band:",[84,3273,3275],{"className":185,"code":3274,"language":187,"meta":89,"style":89},"year_x_values = [\n    x_revenue_scale.map(year) + x_revenue_scale.bandwidth \u002F 2\n    for year in revenue_years\n]\n\ntick_points = [\n    coordinate\n    for x in year_x_values\n    for coordinate in (x, axis_y)\n]\n\ntick_path = dp.Polyline(\n    tick_points,\n    stroke=\"none\",\n    fill=\"none\",\n)\naxis_layer.append(tick_path)\n\nbottom_tick = Marker(\n    \"bottom-tick\",\n    TICK_BOTTOM,\n    10,\n    10,\n    fill=theme.ink,\n)\ndefs.append(bottom_tick)\n\ntick_path.marker_start = bottom_tick.url\ntick_path.marker_mid = bottom_tick.url\ntick_path.marker_end = bottom_tick.url\n",[45,3276,3277,3287,3316,3329,3333,3337,3346,3351,3362,3383,3387,3391,3407,3414,3430,3445,3449,3464,3468,3480,3492,3499,3506,3512,3526,3530,3545,3549,3568,3585],{"__ignoreMap":89},[93,3278,3279,3282,3284],{"class":95,"line":96},[93,3280,3281],{"class":198},"year_x_values ",[93,3283,271],{"class":270},[93,3285,3286],{"class":262}," [\n",[93,3288,3289,3292,3294,3296,3298,3300,3302,3305,3307,3309,3311,3313],{"class":95,"line":147},[93,3290,3291],{"class":198},"    x_revenue_scale",[93,3293,129],{"class":262},[93,3295,1967],{"class":581},[93,3297,263],{"class":262},[93,3299,1972],{"class":581},[93,3301,514],{"class":262},[93,3303,3304],{"class":270}," +",[93,3306,1962],{"class":198},[93,3308,129],{"class":262},[93,3310,1616],{"class":1121},[93,3312,1135],{"class":270},[93,3314,3315],{"class":1234}," 2\n",[93,3317,3318,3321,3324,3326],{"class":95,"line":153},[93,3319,3320],{"class":194},"    for",[93,3322,3323],{"class":198}," year ",[93,3325,631],{"class":194},[93,3327,3328],{"class":198}," revenue_years\n",[93,3330,3331],{"class":95,"line":159},[93,3332,464],{"class":262},[93,3334,3335],{"class":95,"line":239},[93,3336,243],{"emptyLinePlaceholder":242},[93,3338,3339,3342,3344],{"class":95,"line":246},[93,3340,3341],{"class":198},"tick_points ",[93,3343,271],{"class":270},[93,3345,3286],{"class":262},[93,3347,3348],{"class":95,"line":251},[93,3349,3350],{"class":198},"    coordinate\n",[93,3352,3353,3355,3357,3359],{"class":95,"line":290},[93,3354,3320],{"class":194},[93,3356,2762],{"class":198},[93,3358,631],{"class":194},[93,3360,3361],{"class":198}," year_x_values\n",[93,3363,3364,3366,3369,3371,3374,3376,3378,3381],{"class":95,"line":303},[93,3365,3320],{"class":194},[93,3367,3368],{"class":198}," coordinate ",[93,3370,631],{"class":194},[93,3372,3373],{"class":262}," (",[93,3375,2041],{"class":198},[93,3377,66],{"class":262},[93,3379,3380],{"class":198}," axis_y",[93,3382,287],{"class":262},[93,3384,3385],{"class":95,"line":314},[93,3386,464],{"class":262},[93,3388,3389],{"class":95,"line":326},[93,3390,243],{"emptyLinePlaceholder":242},[93,3392,3393,3396,3398,3400,3402,3405],{"class":95,"line":331},[93,3394,3395],{"class":198},"tick_path ",[93,3397,271],{"class":270},[93,3399,1185],{"class":198},[93,3401,129],{"class":262},[93,3403,3404],{"class":581},"Polyline",[93,3406,720],{"class":262},[93,3408,3409,3412],{"class":95,"line":336},[93,3410,3411],{"class":581},"    tick_points",[93,3413,742],{"class":262},[93,3415,3416,3419,3421,3423,3426,3428],{"class":95,"line":361},[93,3417,3418],{"class":266},"    stroke",[93,3420,271],{"class":270},[93,3422,603],{"class":592},[93,3424,3425],{"class":103},"none",[93,3427,603],{"class":592},[93,3429,742],{"class":262},[93,3431,3432,3435,3437,3439,3441,3443],{"class":95,"line":371},[93,3433,3434],{"class":266},"    fill",[93,3436,271],{"class":270},[93,3438,603],{"class":592},[93,3440,3425],{"class":103},[93,3442,603],{"class":592},[93,3444,742],{"class":262},[93,3446,3447],{"class":95,"line":382},[93,3448,287],{"class":262},[93,3450,3451,3453,3455,3457,3459,3462],{"class":95,"line":392},[93,3452,3183],{"class":198},[93,3454,129],{"class":262},[93,3456,717],{"class":581},[93,3458,263],{"class":262},[93,3460,3461],{"class":581},"tick_path",[93,3463,287],{"class":262},[93,3465,3466],{"class":95,"line":402},[93,3467,243],{"emptyLinePlaceholder":242},[93,3469,3470,3473,3475,3478],{"class":95,"line":407},[93,3471,3472],{"class":198},"bottom_tick ",[93,3474,271],{"class":270},[93,3476,3477],{"class":581}," Marker",[93,3479,720],{"class":262},[93,3481,3482,3485,3488,3490],{"class":95,"line":412},[93,3483,3484],{"class":592},"    \"",[93,3486,3487],{"class":103},"bottom-tick",[93,3489,603],{"class":592},[93,3491,742],{"class":262},[93,3493,3494,3497],{"class":95,"line":437},[93,3495,3496],{"class":1207},"    TICK_BOTTOM",[93,3498,742],{"class":262},[93,3500,3501,3504],{"class":95,"line":447},[93,3502,3503],{"class":1234},"    10",[93,3505,742],{"class":262},[93,3507,3508,3510],{"class":95,"line":467},[93,3509,3503],{"class":1234},[93,3511,742],{"class":262},[93,3513,3514,3516,3518,3520,3522,3524],{"class":95,"line":484},[93,3515,3434],{"class":266},[93,3517,271],{"class":270},[93,3519,1254],{"class":581},[93,3521,129],{"class":262},[93,3523,1581],{"class":1121},[93,3525,742],{"class":262},[93,3527,3528],{"class":95,"line":489},[93,3529,287],{"class":262},[93,3531,3532,3534,3536,3538,3540,3543],{"class":95,"line":494},[93,3533,2183],{"class":198},[93,3535,129],{"class":262},[93,3537,717],{"class":581},[93,3539,263],{"class":262},[93,3541,3542],{"class":581},"bottom_tick",[93,3544,287],{"class":262},[93,3546,3547],{"class":95,"line":524},[93,3548,243],{"emptyLinePlaceholder":242},[93,3550,3551,3553,3555,3558,3560,3563,3565],{"class":95,"line":546},[93,3552,3461],{"class":198},[93,3554,129],{"class":262},[93,3556,3557],{"class":1121},"marker_start",[93,3559,540],{"class":270},[93,3561,3562],{"class":198}," bottom_tick",[93,3564,129],{"class":262},[93,3566,3567],{"class":1121},"url\n",[93,3569,3570,3572,3574,3577,3579,3581,3583],{"class":95,"line":565},[93,3571,3461],{"class":198},[93,3573,129],{"class":262},[93,3575,3576],{"class":1121},"marker_mid",[93,3578,540],{"class":270},[93,3580,3562],{"class":198},[93,3582,129],{"class":262},[93,3584,3567],{"class":1121},[93,3586,3587,3589,3591,3594,3596,3598,3600],{"class":95,"line":570},[93,3588,3461],{"class":198},[93,3590,129],{"class":262},[93,3592,3593],{"class":1121},"marker_end",[93,3595,540],{"class":270},[93,3597,3562],{"class":198},[93,3599,129],{"class":262},[93,3601,3567],{"class":1121},[14,3603,3604],{},"A marker avoids drawing a separate short line for every tick. The invisible\npolyline supplies the positions, and SVG repeats the marker at every point.",[14,3606,3607],{},"Add the year labels:",[84,3609,3611],{"className":185,"code":3610,"language":187,"meta":89,"style":89},"for year, x in zip(revenue_years, year_x_values, strict=True):\n    axis_layer.append(\n        dp.Text(\n            str(year),\n            x=x,\n            y=axis_y + 30,\n            text_anchor=\"middle\",\n            font_size=12,\n            fill=theme.ink,\n        )\n    )\n",[45,3612,3613,3646,3657,3667,3678,3689,3706,3721,3733,3748,3752],{"__ignoreMap":89},[93,3614,3615,3617,3619,3621,3623,3625,3627,3629,3631,3633,3636,3638,3640,3642,3644],{"class":95,"line":96},[93,3616,1918],{"class":194},[93,3618,1921],{"class":198},[93,3620,66],{"class":262},[93,3622,2762],{"class":198},[93,3624,631],{"class":194},[93,3626,1931],{"class":1207},[93,3628,263],{"class":262},[93,3630,1936],{"class":581},[93,3632,66],{"class":262},[93,3634,3635],{"class":581}," year_x_values",[93,3637,66],{"class":262},[93,3639,1946],{"class":266},[93,3641,271],{"class":270},[93,3643,275],{"class":274},[93,3645,647],{"class":262},[93,3647,3648,3651,3653,3655],{"class":95,"line":147},[93,3649,3650],{"class":198},"    axis_layer",[93,3652,129],{"class":262},[93,3654,717],{"class":581},[93,3656,720],{"class":262},[93,3658,3659,3661,3663,3665],{"class":95,"line":153},[93,3660,2116],{"class":581},[93,3662,129],{"class":262},[93,3664,1484],{"class":581},[93,3666,720],{"class":262},[93,3668,3669,3672,3674,3676],{"class":95,"line":159},[93,3670,3671],{"class":322},"            str",[93,3673,263],{"class":262},[93,3675,1972],{"class":581},[93,3677,1539],{"class":262},[93,3679,3680,3683,3685,3687],{"class":95,"line":239},[93,3681,3682],{"class":266},"            x",[93,3684,271],{"class":270},[93,3686,2041],{"class":581},[93,3688,742],{"class":262},[93,3690,3691,3694,3696,3698,3701,3704],{"class":95,"line":246},[93,3692,3693],{"class":266},"            y",[93,3695,271],{"class":270},[93,3697,3169],{"class":581},[93,3699,3700],{"class":270},"+",[93,3702,3703],{"class":1234}," 30",[93,3705,742],{"class":262},[93,3707,3708,3711,3713,3715,3717,3719],{"class":95,"line":251},[93,3709,3710],{"class":266},"            text_anchor",[93,3712,271],{"class":270},[93,3714,603],{"class":592},[93,3716,1551],{"class":103},[93,3718,603],{"class":592},[93,3720,742],{"class":262},[93,3722,3723,3726,3728,3731],{"class":95,"line":290},[93,3724,3725],{"class":266},"            font_size",[93,3727,271],{"class":270},[93,3729,3730],{"class":1234},"12",[93,3732,742],{"class":262},[93,3734,3735,3738,3740,3742,3744,3746],{"class":95,"line":303},[93,3736,3737],{"class":266},"            fill",[93,3739,271],{"class":270},[93,3741,1254],{"class":581},[93,3743,129],{"class":262},[93,3745,1581],{"class":1121},[93,3747,742],{"class":262},[93,3749,3750],{"class":95,"line":314},[93,3751,2170],{"class":262},[93,3753,3754],{"class":95,"line":326},[93,3755,988],{"class":262},[27,3757,3759],{"id":3758},"add-the-revenue-axis-and-grid","Add the Revenue Axis and Grid",[14,3761,3762],{},"The left axis uses blue labels to connect it visually to the revenue columns:",[84,3764,3766],{"className":185,"code":3765,"language":187,"meta":89,"style":89},"for tick in calculate_ticks(0, max_revenue, 5):\n    y = y_revenue_scale.map(tick)\n    axis_layer.append(\n        dp.Line(\n            x1=plot_left,\n            y1=y,\n            x2=plot_right,\n            y2=y,\n            stroke=theme.ink,\n            opacity=0.15,\n        ),\n        dp.Text(\n            f\"${tick \u002F 1_000_000_000:.0f}B\",\n            x=plot_left - 10,\n            y=y,\n            text_anchor=\"end\",\n            dominant_baseline=\"middle\",\n            font_size=12,\n            fill=theme.blue,\n        ),\n    )\n",[45,3767,3768,3795,3814,3824,3834,3845,3857,3868,3879,3894,3906,3911,3921,3953,3968,3978,3993,4008,4018,4032,4036],{"__ignoreMap":89},[93,3769,3770,3772,3775,3777,3780,3782,3784,3786,3788,3790,3793],{"class":95,"line":96},[93,3771,1918],{"class":194},[93,3773,3774],{"class":198}," tick ",[93,3776,631],{"class":194},[93,3778,3779],{"class":581}," calculate_ticks",[93,3781,263],{"class":262},[93,3783,1774],{"class":1234},[93,3785,66],{"class":262},[93,3787,1779],{"class":581},[93,3789,66],{"class":262},[93,3791,3792],{"class":1234}," 5",[93,3794,647],{"class":262},[93,3796,3797,3799,3801,3803,3805,3807,3809,3812],{"class":95,"line":147},[93,3798,1979],{"class":198},[93,3800,271],{"class":270},[93,3802,1984],{"class":198},[93,3804,129],{"class":262},[93,3806,1967],{"class":581},[93,3808,263],{"class":262},[93,3810,3811],{"class":581},"tick",[93,3813,287],{"class":262},[93,3815,3816,3818,3820,3822],{"class":95,"line":153},[93,3817,3650],{"class":198},[93,3819,129],{"class":262},[93,3821,717],{"class":581},[93,3823,720],{"class":262},[93,3825,3826,3828,3830,3832],{"class":95,"line":159},[93,3827,2116],{"class":581},[93,3829,129],{"class":262},[93,3831,3198],{"class":581},[93,3833,720],{"class":262},[93,3835,3836,3839,3841,3843],{"class":95,"line":239},[93,3837,3838],{"class":266},"            x1",[93,3840,271],{"class":270},[93,3842,1741],{"class":581},[93,3844,742],{"class":262},[93,3846,3847,3850,3852,3855],{"class":95,"line":246},[93,3848,3849],{"class":266},"            y1",[93,3851,271],{"class":270},[93,3853,3854],{"class":581},"y",[93,3856,742],{"class":262},[93,3858,3859,3862,3864,3866],{"class":95,"line":251},[93,3860,3861],{"class":266},"            x2",[93,3863,271],{"class":270},[93,3865,3233],{"class":581},[93,3867,742],{"class":262},[93,3869,3870,3873,3875,3877],{"class":95,"line":290},[93,3871,3872],{"class":266},"            y2",[93,3874,271],{"class":270},[93,3876,3854],{"class":581},[93,3878,742],{"class":262},[93,3880,3881,3884,3886,3888,3890,3892],{"class":95,"line":303},[93,3882,3883],{"class":266},"            stroke",[93,3885,271],{"class":270},[93,3887,1254],{"class":581},[93,3889,129],{"class":262},[93,3891,1581],{"class":1121},[93,3893,742],{"class":262},[93,3895,3896,3899,3901,3904],{"class":95,"line":314},[93,3897,3898],{"class":266},"            opacity",[93,3900,271],{"class":270},[93,3902,3903],{"class":1234},"0.15",[93,3905,742],{"class":262},[93,3907,3908],{"class":95,"line":326},[93,3909,3910],{"class":262},"        ),\n",[93,3912,3913,3915,3917,3919],{"class":95,"line":331},[93,3914,2116],{"class":581},[93,3916,129],{"class":262},[93,3918,1484],{"class":581},[93,3920,720],{"class":262},[93,3922,3923,3926,3929,3933,3936,3939,3942,3945,3948,3951],{"class":95,"line":336},[93,3924,3925],{"class":293},"            f",[93,3927,3928],{"class":103},"\"$",[93,3930,3932],{"class":3931},"smmm7","{",[93,3934,3935],{"class":581},"tick ",[93,3937,3938],{"class":270},"\u002F",[93,3940,3941],{"class":1234}," 1_000_000_000",[93,3943,3944],{"class":293},":.0f",[93,3946,3947],{"class":3931},"}",[93,3949,3950],{"class":103},"B\"",[93,3952,742],{"class":262},[93,3954,3955,3957,3959,3961,3963,3966],{"class":95,"line":361},[93,3956,3682],{"class":266},[93,3958,271],{"class":270},[93,3960,1356],{"class":581},[93,3962,2007],{"class":270},[93,3964,3965],{"class":1234}," 10",[93,3967,742],{"class":262},[93,3969,3970,3972,3974,3976],{"class":95,"line":371},[93,3971,3693],{"class":266},[93,3973,271],{"class":270},[93,3975,3854],{"class":581},[93,3977,742],{"class":262},[93,3979,3980,3982,3984,3986,3989,3991],{"class":95,"line":382},[93,3981,3710],{"class":266},[93,3983,271],{"class":270},[93,3985,603],{"class":592},[93,3987,3988],{"class":103},"end",[93,3990,603],{"class":592},[93,3992,742],{"class":262},[93,3994,3995,3998,4000,4002,4004,4006],{"class":95,"line":392},[93,3996,3997],{"class":266},"            dominant_baseline",[93,3999,271],{"class":270},[93,4001,603],{"class":592},[93,4003,1551],{"class":103},[93,4005,603],{"class":592},[93,4007,742],{"class":262},[93,4009,4010,4012,4014,4016],{"class":95,"line":402},[93,4011,3725],{"class":266},[93,4013,271],{"class":270},[93,4015,3730],{"class":1234},[93,4017,742],{"class":262},[93,4019,4020,4022,4024,4026,4028,4030],{"class":95,"line":407},[93,4021,3737],{"class":266},[93,4023,271],{"class":270},[93,4025,1254],{"class":581},[93,4027,129],{"class":262},[93,4029,2259],{"class":1121},[93,4031,742],{"class":262},[93,4033,4034],{"class":95,"line":412},[93,4035,3910],{"class":262},[93,4037,4038],{"class":95,"line":437},[93,4039,988],{"class":262},[14,4041,4042,4045,4046,4049],{},[45,4043,4044],{},"calculate_ticks()"," chooses readable values across the requested range. Dividing\nby one billion keeps labels such as ",[45,4047,4048],{},"$20B"," compact.",[27,4051,4053],{"id":4052},"add-the-stock-price-axis","Add the Stock Price Axis",[14,4055,4056],{},"The right axis uses the stock scale and green labels. It does not need another\nset of grid lines because those would imply that the two vertical scales share\nthe same intervals.",[84,4058,4060],{"className":185,"code":4059,"language":187,"meta":89,"style":89},"for tick in calculate_ticks(0, max(stock_values), 5):\n    y = stock_y_scale.map(tick)\n    axis_layer.append(\n        dp.Text(\n            f\"${tick:.0f}\",\n            x=plot_right + 10,\n            y=y,\n            dominant_baseline=\"middle\",\n            font_size=12,\n            fill=theme.green,\n        )\n    )\n",[45,4061,4062,4091,4109,4119,4129,4147,4161,4171,4185,4195,4209,4213],{"__ignoreMap":89},[93,4063,4064,4066,4068,4070,4072,4074,4076,4078,4080,4082,4084,4087,4089],{"class":95,"line":96},[93,4065,1918],{"class":194},[93,4067,3774],{"class":198},[93,4069,631],{"class":194},[93,4071,3779],{"class":581},[93,4073,263],{"class":262},[93,4075,1774],{"class":1234},[93,4077,66],{"class":262},[93,4079,1700],{"class":1207},[93,4081,263],{"class":262},[93,4083,2634],{"class":581},[93,4085,4086],{"class":262},"),",[93,4088,3792],{"class":1234},[93,4090,647],{"class":262},[93,4092,4093,4095,4097,4099,4101,4103,4105,4107],{"class":95,"line":147},[93,4094,1979],{"class":198},[93,4096,271],{"class":270},[93,4098,2789],{"class":198},[93,4100,129],{"class":262},[93,4102,1967],{"class":581},[93,4104,263],{"class":262},[93,4106,3811],{"class":581},[93,4108,287],{"class":262},[93,4110,4111,4113,4115,4117],{"class":95,"line":153},[93,4112,3650],{"class":198},[93,4114,129],{"class":262},[93,4116,717],{"class":581},[93,4118,720],{"class":262},[93,4120,4121,4123,4125,4127],{"class":95,"line":159},[93,4122,2116],{"class":581},[93,4124,129],{"class":262},[93,4126,1484],{"class":581},[93,4128,720],{"class":262},[93,4130,4131,4133,4135,4137,4139,4141,4143,4145],{"class":95,"line":239},[93,4132,3925],{"class":293},[93,4134,3928],{"class":103},[93,4136,3932],{"class":3931},[93,4138,3811],{"class":581},[93,4140,3944],{"class":293},[93,4142,3947],{"class":3931},[93,4144,603],{"class":103},[93,4146,742],{"class":262},[93,4148,4149,4151,4153,4155,4157,4159],{"class":95,"line":246},[93,4150,3682],{"class":266},[93,4152,271],{"class":270},[93,4154,1376],{"class":581},[93,4156,3700],{"class":270},[93,4158,3965],{"class":1234},[93,4160,742],{"class":262},[93,4162,4163,4165,4167,4169],{"class":95,"line":251},[93,4164,3693],{"class":266},[93,4166,271],{"class":270},[93,4168,3854],{"class":581},[93,4170,742],{"class":262},[93,4172,4173,4175,4177,4179,4181,4183],{"class":95,"line":290},[93,4174,3997],{"class":266},[93,4176,271],{"class":270},[93,4178,603],{"class":592},[93,4180,1551],{"class":103},[93,4182,603],{"class":592},[93,4184,742],{"class":262},[93,4186,4187,4189,4191,4193],{"class":95,"line":303},[93,4188,3725],{"class":266},[93,4190,271],{"class":270},[93,4192,3730],{"class":1234},[93,4194,742],{"class":262},[93,4196,4197,4199,4201,4203,4205,4207],{"class":95,"line":314},[93,4198,3737],{"class":266},[93,4200,271],{"class":270},[93,4202,1254],{"class":581},[93,4204,129],{"class":262},[93,4206,3101],{"class":1121},[93,4208,742],{"class":262},[93,4210,4211],{"class":95,"line":326},[93,4212,2170],{"class":262},[93,4214,4215],{"class":95,"line":331},[93,4216,988],{"class":262},[14,4218,4219],{},"Color is doing useful work here: blue belongs to revenue, green belongs to\nstock price. This is especially important in a dual-axis chart, where readers\nmust quickly identify which scale belongs to which series.",[27,4221,4223],{"id":4222},"add-the-icon-labels","Add the Icon Labels",[14,4225,4226],{},"The two small illustrations are ordinary SVG files loaded into the main SVG.\nThe helper recolors selected paths so the icons follow the active theme:",[84,4228,4230],{"className":185,"code":4229,"language":187,"meta":89,"style":89},"def icon_label(\n    filename: str,\n    label: str,\n    color: str,\n    pos: tuple[float, float],\n    text_x: float,\n    text_anchor: str = \"start\",\n) -> dp.G:\n    icon = dp.SVG.from_file(str(BASE_DIR \u002F \"assets\" \u002F filename))\n\n    # Nested SVG elements need explicit dimensions. Without them, browsers use\n    # the SVG default of 300 by 150 pixels.\n    icon.attrs({\"width\": 60, \"height\": 40})\n\n    icon.find(\"path\", id=\"background\").fill = dp.tone(theme.surface, 0.1)\n    icon.find(\"path\", id=\"background-strips\").fill = dp.tone(\n        theme.surface,\n        0.15,\n    )\n    icon.find(\"path\", id=\"frame\").fill = color\n    icon.find(\"path\", id=\"chart\").fill = color\n\n    return dp.G(pos=pos).append(\n        icon,\n        dp.Text(\n            label,\n            x=text_x,\n            y=30,\n            fill=color,\n            font_size=22,\n            text_anchor=text_anchor,\n        ),\n    )\n",[45,4231,4232,4241,4253,4264,4275,4296,4307,4327,4341,4386,4390,4396,4401,4439,4443,4504,4547,4558,4565,4569,4607,4644,4648,4673,4680,4690,4697,4708,4719,4730,4741,4752,4756],{"__ignoreMap":89},[93,4233,4234,4236,4239],{"class":95,"line":96},[93,4235,497],{"class":293},[93,4237,4238],{"class":258}," icon_label",[93,4240,720],{"class":262},[93,4242,4243,4246,4248,4251],{"class":95,"line":147},[93,4244,4245],{"class":505},"    filename",[93,4247,309],{"class":262},[93,4249,4250],{"class":322}," str",[93,4252,742],{"class":262},[93,4254,4255,4258,4260,4262],{"class":95,"line":153},[93,4256,4257],{"class":505},"    label",[93,4259,309],{"class":262},[93,4261,4250],{"class":322},[93,4263,742],{"class":262},[93,4265,4266,4269,4271,4273],{"class":95,"line":159},[93,4267,4268],{"class":505},"    color",[93,4270,309],{"class":262},[93,4272,4250],{"class":322},[93,4274,742],{"class":262},[93,4276,4277,4280,4282,4285,4287,4289,4291,4293],{"class":95,"line":239},[93,4278,4279],{"class":505},"    pos",[93,4281,309],{"class":262},[93,4283,4284],{"class":198}," tuple",[93,4286,458],{"class":262},[93,4288,753],{"class":322},[93,4290,66],{"class":262},[93,4292,2687],{"class":322},[93,4294,4295],{"class":262},"],\n",[93,4297,4298,4301,4303,4305],{"class":95,"line":246},[93,4299,4300],{"class":505},"    text_x",[93,4302,309],{"class":262},[93,4304,2687],{"class":322},[93,4306,742],{"class":262},[93,4308,4309,4312,4314,4316,4318,4320,4323,4325],{"class":95,"line":251},[93,4310,4311],{"class":505},"    text_anchor",[93,4313,309],{"class":262},[93,4315,4250],{"class":322},[93,4317,540],{"class":270},[93,4319,1138],{"class":592},[93,4321,4322],{"class":103},"start",[93,4324,603],{"class":592},[93,4326,742],{"class":262},[93,4328,4329,4331,4333,4335,4337,4339],{"class":95,"line":290},[93,4330,514],{"class":262},[93,4332,517],{"class":262},[93,4334,1185],{"class":198},[93,4336,129],{"class":262},[93,4338,1864],{"class":1121},[93,4340,300],{"class":262},[93,4342,4343,4346,4348,4350,4352,4355,4357,4360,4362,4365,4367,4369,4371,4373,4376,4378,4380,4383],{"class":95,"line":303},[93,4344,4345],{"class":198},"    icon ",[93,4347,271],{"class":270},[93,4349,1185],{"class":198},[93,4351,129],{"class":262},[93,4353,1227],{"class":4354},"sHgB6",[93,4356,129],{"class":262},[93,4358,4359],{"class":581},"from_file",[93,4361,263],{"class":262},[93,4363,4364],{"class":322},"str",[93,4366,263],{"class":262},[93,4368,1106],{"class":1207},[93,4370,1135],{"class":270},[93,4372,1138],{"class":592},[93,4374,4375],{"class":103},"assets",[93,4377,603],{"class":592},[93,4379,1135],{"class":270},[93,4381,4382],{"class":581}," filename",[93,4384,4385],{"class":262},"))\n",[93,4387,4388],{"class":95,"line":314},[93,4389,243],{"emptyLinePlaceholder":242},[93,4391,4392],{"class":95,"line":326},[93,4393,4395],{"class":4394},"sxl37","    # Nested SVG elements need explicit dimensions. Without them, browsers use\n",[93,4397,4398],{"class":95,"line":331},[93,4399,4400],{"class":4394},"    # the SVG default of 300 by 150 pixels.\n",[93,4402,4403,4406,4408,4410,4412,4414,4417,4419,4421,4424,4426,4428,4430,4432,4434,4437],{"class":95,"line":336},[93,4404,4405],{"class":198},"    icon",[93,4407,129],{"class":262},[93,4409,2371],{"class":581},[93,4411,2374],{"class":262},[93,4413,603],{"class":592},[93,4415,4416],{"class":103},"width",[93,4418,603],{"class":592},[93,4420,309],{"class":262},[93,4422,4423],{"class":1234}," 60",[93,4425,66],{"class":262},[93,4427,1138],{"class":592},[93,4429,2074],{"class":103},[93,4431,603],{"class":592},[93,4433,309],{"class":262},[93,4435,4436],{"class":1234}," 40",[93,4438,2393],{"class":262},[93,4440,4441],{"class":95,"line":361},[93,4442,243],{"emptyLinePlaceholder":242},[93,4444,4445,4447,4449,4452,4454,4456,4459,4461,4463,4466,4468,4470,4473,4475,4477,4480,4482,4484,4486,4488,4490,4492,4494,4497,4499,4502],{"class":95,"line":371},[93,4446,4405],{"class":198},[93,4448,129],{"class":262},[93,4450,4451],{"class":581},"find",[93,4453,263],{"class":262},[93,4455,603],{"class":592},[93,4457,4458],{"class":103},"path",[93,4460,603],{"class":592},[93,4462,66],{"class":262},[93,4464,4465],{"class":266}," id",[93,4467,271],{"class":270},[93,4469,603],{"class":592},[93,4471,4472],{"class":103},"background",[93,4474,603],{"class":592},[93,4476,1118],{"class":262},[93,4478,4479],{"class":1121},"fill",[93,4481,540],{"class":270},[93,4483,1185],{"class":198},[93,4485,129],{"class":262},[93,4487,3092],{"class":581},[93,4489,263],{"class":262},[93,4491,1254],{"class":581},[93,4493,129],{"class":262},[93,4495,4496],{"class":1121},"surface",[93,4498,66],{"class":262},[93,4500,4501],{"class":1234}," 0.1",[93,4503,287],{"class":262},[93,4505,4506,4508,4510,4512,4514,4516,4518,4520,4522,4524,4526,4528,4531,4533,4535,4537,4539,4541,4543,4545],{"class":95,"line":382},[93,4507,4405],{"class":198},[93,4509,129],{"class":262},[93,4511,4451],{"class":581},[93,4513,263],{"class":262},[93,4515,603],{"class":592},[93,4517,4458],{"class":103},[93,4519,603],{"class":592},[93,4521,66],{"class":262},[93,4523,4465],{"class":266},[93,4525,271],{"class":270},[93,4527,603],{"class":592},[93,4529,4530],{"class":103},"background-strips",[93,4532,603],{"class":592},[93,4534,1118],{"class":262},[93,4536,4479],{"class":1121},[93,4538,540],{"class":270},[93,4540,1185],{"class":198},[93,4542,129],{"class":262},[93,4544,3092],{"class":581},[93,4546,720],{"class":262},[93,4548,4549,4552,4554,4556],{"class":95,"line":392},[93,4550,4551],{"class":581},"        theme",[93,4553,129],{"class":262},[93,4555,4496],{"class":1121},[93,4557,742],{"class":262},[93,4559,4560,4563],{"class":95,"line":402},[93,4561,4562],{"class":1234},"        0.15",[93,4564,742],{"class":262},[93,4566,4567],{"class":95,"line":407},[93,4568,988],{"class":262},[93,4570,4571,4573,4575,4577,4579,4581,4583,4585,4587,4589,4591,4593,4596,4598,4600,4602,4604],{"class":95,"line":412},[93,4572,4405],{"class":198},[93,4574,129],{"class":262},[93,4576,4451],{"class":581},[93,4578,263],{"class":262},[93,4580,603],{"class":592},[93,4582,4458],{"class":103},[93,4584,603],{"class":592},[93,4586,66],{"class":262},[93,4588,4465],{"class":266},[93,4590,271],{"class":270},[93,4592,603],{"class":592},[93,4594,4595],{"class":103},"frame",[93,4597,603],{"class":592},[93,4599,1118],{"class":262},[93,4601,4479],{"class":1121},[93,4603,540],{"class":270},[93,4605,4606],{"class":198}," color\n",[93,4608,4609,4611,4613,4615,4617,4619,4621,4623,4625,4627,4629,4631,4634,4636,4638,4640,4642],{"class":95,"line":437},[93,4610,4405],{"class":198},[93,4612,129],{"class":262},[93,4614,4451],{"class":581},[93,4616,263],{"class":262},[93,4618,603],{"class":592},[93,4620,4458],{"class":103},[93,4622,603],{"class":592},[93,4624,66],{"class":262},[93,4626,4465],{"class":266},[93,4628,271],{"class":270},[93,4630,603],{"class":592},[93,4632,4633],{"class":103},"chart",[93,4635,603],{"class":592},[93,4637,1118],{"class":262},[93,4639,4479],{"class":1121},[93,4641,540],{"class":270},[93,4643,4606],{"class":198},[93,4645,4646],{"class":95,"line":447},[93,4647,243],{"emptyLinePlaceholder":242},[93,4649,4650,4652,4654,4656,4658,4660,4663,4665,4667,4669,4671],{"class":95,"line":467},[93,4651,953],{"class":194},[93,4653,1185],{"class":198},[93,4655,129],{"class":262},[93,4657,1864],{"class":581},[93,4659,263],{"class":262},[93,4661,4662],{"class":266},"pos",[93,4664,271],{"class":270},[93,4666,4662],{"class":581},[93,4668,1118],{"class":262},[93,4670,717],{"class":581},[93,4672,720],{"class":262},[93,4674,4675,4678],{"class":95,"line":484},[93,4676,4677],{"class":581},"        icon",[93,4679,742],{"class":262},[93,4681,4682,4684,4686,4688],{"class":95,"line":489},[93,4683,2116],{"class":581},[93,4685,129],{"class":262},[93,4687,1484],{"class":581},[93,4689,720],{"class":262},[93,4691,4692,4695],{"class":95,"line":494},[93,4693,4694],{"class":581},"            label",[93,4696,742],{"class":262},[93,4698,4699,4701,4703,4706],{"class":95,"line":524},[93,4700,3682],{"class":266},[93,4702,271],{"class":270},[93,4704,4705],{"class":581},"text_x",[93,4707,742],{"class":262},[93,4709,4710,4712,4714,4717],{"class":95,"line":546},[93,4711,3693],{"class":266},[93,4713,271],{"class":270},[93,4715,4716],{"class":1234},"30",[93,4718,742],{"class":262},[93,4720,4721,4723,4725,4728],{"class":95,"line":565},[93,4722,3737],{"class":266},[93,4724,271],{"class":270},[93,4726,4727],{"class":581},"color",[93,4729,742],{"class":262},[93,4731,4732,4734,4736,4739],{"class":95,"line":570},[93,4733,3725],{"class":266},[93,4735,271],{"class":270},[93,4737,4738],{"class":1234},"22",[93,4740,742],{"class":262},[93,4742,4743,4745,4747,4750],{"class":95,"line":622},[93,4744,3710],{"class":266},[93,4746,271],{"class":270},[93,4748,4749],{"class":581},"text_anchor",[93,4751,742],{"class":262},[93,4753,4754],{"class":95,"line":650},[93,4755,3910],{"class":262},[93,4757,4758],{"class":95,"line":683},[93,4759,988],{"class":262},[14,4761,4762,4763,62,4765,4767,4768,4771,4772,4775],{},"Explicit ",[45,4764,4416],{},[45,4766,2074],{}," are essential for nested ",[45,4769,4770],{},"\u003Csvg>"," elements. A\n",[45,4773,4774],{},"viewBox"," controls the internal coordinate system, but it does not by itself\nset the element's rendered size.",[27,4777,4779],{"id":4778},"assemble-and-save-the-chart","Assemble and Save the Chart",[14,4781,4782],{},"Append the layers in visual order:",[84,4784,4786],{"className":185,"code":4785,"language":187,"meta":89,"style":89},"svg.append(\n    axis_layer,\n    revenue_layer,\n    stock_layer,\n)\n\nsvg.append(\n    icon_label(\n        \"revenue.svg\",\n        \"Total Revenue\",\n        theme.blue,\n        (30, 40),\n        70,\n    ),\n    icon_label(\n        \"stock_price.svg\",\n        \"Stock Price\",\n        theme.green,\n        (svg.w - 90, 40),\n        -10,\n        \"end\",\n    ),\n)\n\nsvg.save(str(OUTPUT_PATH))\n",[45,4787,4788,4798,4804,4811,4818,4822,4826,4836,4843,4854,4865,4875,4888,4895,4899,4905,4916,4927,4937,4958,4968,4978,4982,4986,4990],{"__ignoreMap":89},[93,4789,4790,4792,4794,4796],{"class":95,"line":96},[93,4791,1468],{"class":198},[93,4793,129],{"class":262},[93,4795,717],{"class":581},[93,4797,720],{"class":262},[93,4799,4800,4802],{"class":95,"line":147},[93,4801,3650],{"class":581},[93,4803,742],{"class":262},[93,4805,4806,4809],{"class":95,"line":153},[93,4807,4808],{"class":581},"    revenue_layer",[93,4810,742],{"class":262},[93,4812,4813,4816],{"class":95,"line":159},[93,4814,4815],{"class":581},"    stock_layer",[93,4817,742],{"class":262},[93,4819,4820],{"class":95,"line":239},[93,4821,287],{"class":262},[93,4823,4824],{"class":95,"line":246},[93,4825,243],{"emptyLinePlaceholder":242},[93,4827,4828,4830,4832,4834],{"class":95,"line":251},[93,4829,1468],{"class":198},[93,4831,129],{"class":262},[93,4833,717],{"class":581},[93,4835,720],{"class":262},[93,4837,4838,4841],{"class":95,"line":290},[93,4839,4840],{"class":581},"    icon_label",[93,4842,720],{"class":262},[93,4844,4845,4847,4850,4852],{"class":95,"line":303},[93,4846,1491],{"class":592},[93,4848,4849],{"class":103},"revenue.svg",[93,4851,603],{"class":592},[93,4853,742],{"class":262},[93,4855,4856,4858,4861,4863],{"class":95,"line":314},[93,4857,1491],{"class":592},[93,4859,4860],{"class":103},"Total Revenue",[93,4862,603],{"class":592},[93,4864,742],{"class":262},[93,4866,4867,4869,4871,4873],{"class":95,"line":326},[93,4868,4551],{"class":581},[93,4870,129],{"class":262},[93,4872,2259],{"class":1121},[93,4874,742],{"class":262},[93,4876,4877,4880,4882,4884,4886],{"class":95,"line":331},[93,4878,4879],{"class":262},"        (",[93,4881,4716],{"class":1234},[93,4883,66],{"class":262},[93,4885,4436],{"class":1234},[93,4887,1539],{"class":262},[93,4889,4890,4893],{"class":95,"line":336},[93,4891,4892],{"class":1234},"        70",[93,4894,742],{"class":262},[93,4896,4897],{"class":95,"line":361},[93,4898,3043],{"class":262},[93,4900,4901,4903],{"class":95,"line":371},[93,4902,4840],{"class":581},[93,4904,720],{"class":262},[93,4906,4907,4909,4912,4914],{"class":95,"line":382},[93,4908,1491],{"class":592},[93,4910,4911],{"class":103},"stock_price.svg",[93,4913,603],{"class":592},[93,4915,742],{"class":262},[93,4917,4918,4920,4923,4925],{"class":95,"line":392},[93,4919,1491],{"class":592},[93,4921,4922],{"class":103},"Stock Price",[93,4924,603],{"class":592},[93,4926,742],{"class":262},[93,4928,4929,4931,4933,4935],{"class":95,"line":402},[93,4930,4551],{"class":581},[93,4932,129],{"class":262},[93,4934,3101],{"class":1121},[93,4936,742],{"class":262},[93,4938,4939,4941,4943,4945,4947,4949,4952,4954,4956],{"class":95,"line":407},[93,4940,4879],{"class":262},[93,4942,1468],{"class":581},[93,4944,129],{"class":262},[93,4946,1386],{"class":1121},[93,4948,1389],{"class":270},[93,4950,4951],{"class":1234}," 90",[93,4953,66],{"class":262},[93,4955,4436],{"class":1234},[93,4957,1539],{"class":262},[93,4959,4960,4963,4966],{"class":95,"line":412},[93,4961,4962],{"class":270},"        -",[93,4964,4965],{"class":1234},"10",[93,4967,742],{"class":262},[93,4969,4970,4972,4974,4976],{"class":95,"line":437},[93,4971,1491],{"class":592},[93,4973,3988],{"class":103},[93,4975,603],{"class":592},[93,4977,742],{"class":262},[93,4979,4980],{"class":95,"line":447},[93,4981,3043],{"class":262},[93,4983,4984],{"class":95,"line":467},[93,4985,287],{"class":262},[93,4987,4988],{"class":95,"line":484},[93,4989,243],{"emptyLinePlaceholder":242},[93,4991,4992,4994,4996,4999,5001,5003,5005,5007],{"class":95,"line":489},[93,4993,1468],{"class":198},[93,4995,129],{"class":262},[93,4997,4998],{"class":581},"save",[93,5000,263],{"class":262},[93,5002,4364],{"class":322},[93,5004,263],{"class":262},[93,5006,1158],{"class":1207},[93,5008,4385],{"class":262},[14,5010,5011],{},"The axes are appended first, the columns second, and the stock layer last. This\nkeeps the stock line visible above the columns while the subtle grid remains in\nthe background.",[14,5013,5014],{},"Run the script:",[84,5016,5018],{"className":86,"code":5017,"language":88,"meta":89,"style":89},"python main.py\n",[45,5019,5020],{"__ignoreMap":89},[93,5021,5022,5024],{"class":95,"line":96},[93,5023,187],{"class":99},[93,5025,5026],{"class":103}," main.py\n",[14,5028,5029,5030,129],{},"The generated file is ",[45,5031,1169],{},[27,5033,5035],{"id":5034},"generate-a-dark-version","Generate a Dark Version",[14,5037,5038],{},"The showcase uses pyDreamplet theme files to generate light and dark variants.\nThe drawing code does not need to change; only the theme does:",[84,5040,5042],{"className":185,"code":5041,"language":187,"meta":89,"style":89},"theme = dp.Theme(\"path\u002Fto\u002Fdark-theme.json\")\n",[45,5043,5044],{"__ignoreMap":89},[93,5045,5046,5048,5050,5052,5054,5056,5058,5060,5063,5065],{"class":95,"line":96},[93,5047,1180],{"class":198},[93,5049,271],{"class":270},[93,5051,1185],{"class":198},[93,5053,129],{"class":262},[93,5055,1190],{"class":581},[93,5057,263],{"class":262},[93,5059,603],{"class":592},[93,5061,5062],{"class":103},"path\u002Fto\u002Fdark-theme.json",[93,5064,603],{"class":592},[93,5066,287],{"class":262},[14,5068,5069,5070,5072],{},"All important colors come from ",[45,5071,1254],{},", including the canvas text, series\ncolors, icon fills, and grid lines. Keeping literal colors out of the drawing\nlogic makes theme variants predictable.",[27,5074,5076],{"id":5075},"why-this-chart-works","Why This Chart Works",[14,5078,5079],{},"Combination charts can become confusing quickly. This design stays readable\nbecause it follows a few constraints:",[35,5081,5082,5085,5088,5091,5094,5097],{},[38,5083,5084],{},"each measure has a distinct mark: columns for revenue and a line for price,",[38,5086,5087],{},"each vertical axis uses the same color as its series,",[38,5089,5090],{},"only the revenue scale produces grid lines,",[38,5092,5093],{},"annual and monthly data use independent horizontal scales over the same plot,",[38,5095,5096],{},"the clipped gradient connects the two series without hiding the columns,",[38,5098,5099],{},"the title and series labels sit outside the data region.",[14,5101,5102],{},"The chart compares patterns, not equivalent quantities. A rise in both series\ndoes not prove that revenue caused a stock-price movement. The dual axes help\nfit two histories into one graphic, but they should not be used to imply a\nmathematical relationship.",[27,5104,5106],{"id":5105},"next-steps","Next Steps",[14,5108,5109],{},"The complete showcase version supports Apple, Amazon, Microsoft, Nvidia, and\nTesla. To extend this tutorial:",[1815,5111,5112,5115,5121,5124],{},[38,5113,5114],{},"add another CSV file with the same columns,",[38,5116,5117,5118,66],{},"pass its path to ",[45,5119,5120],{},"read_combo_chart_data()",[38,5122,5123],{},"change the title and output filename,",[38,5125,5126],{},"keep the symbol explicit when reproducible output matters.",[14,5128,5129,5130,5133],{},"You can also replace the local CSV reader with an API or database query. Keep\nthe ",[45,5131,5132],{},"ComboChartData"," structure unchanged and the drawing code will not need to\nknow where the values came from.",[14,5135,5136,5137,129],{},"The complete source is available in the\n",[123,5138,5140],{"href":125,"rel":5139},[127],"pyDreamplet showcase repository",[5142,5143,5144],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sp6cl, html code.shiki .sp6cl{--shiki-light:#E2931D;--shiki-default:#702C00;--shiki-dark:#B392F0}html pre.shiki code .s_jvP, html code.shiki .s_jvP{--shiki-light:#91B859;--shiki-default:#032563;--shiki-dark:#9ECBFF}html pre.shiki code .sED7I, html code.shiki .sED7I{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#A0111F;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .soTeR, html code.shiki .soTeR{--shiki-light:#90A4AE;--shiki-default:#0E1116;--shiki-dark:#E1E4E8}html pre.shiki code .sd4UE, html code.shiki .sd4UE{--shiki-light:#39ADB5;--shiki-default:#622CBC;--shiki-dark:#B392F0}html pre.shiki code .synEm, html code.shiki .synEm{--shiki-light:#6182B8;--shiki-default:#622CBC;--shiki-dark:#B392F0}html pre.shiki code .sVsmf, html code.shiki .sVsmf{--shiki-light:#39ADB5;--shiki-default:#0E1116;--shiki-dark:#E1E4E8}html pre.shiki code .sYEV4, html code.shiki .sYEV4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#702C00;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sWKEy, html code.shiki .sWKEy{--shiki-light:#39ADB5;--shiki-default:#A0111F;--shiki-dark:#F97583}html pre.shiki code .sTy78, html code.shiki .sTy78{--shiki-light:#39ADB5;--shiki-default:#023B95;--shiki-dark:#79B8FF}html pre.shiki code .sfdCM, html code.shiki .sfdCM{--shiki-light:#9C3EDA;--shiki-default:#A0111F;--shiki-dark:#F97583}html pre.shiki code .s-tzF, html code.shiki .s-tzF{--shiki-light:#E2931D;--shiki-default:#023B95;--shiki-dark:#79B8FF}html pre.shiki code .s1VEa, html code.shiki .s1VEa{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#0E1116;--shiki-default-font-style:inherit;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit}html pre.shiki code .sAK04, html code.shiki .sAK04{--shiki-light:#6182B8;--shiki-default:#0E1116;--shiki-dark:#E1E4E8}html pre.shiki code .sqo_7, html code.shiki .sqo_7{--shiki-light:#39ADB5;--shiki-default:#032563;--shiki-dark:#9ECBFF}html pre.shiki code .sAJHR, html code.shiki .sAJHR{--shiki-light:#90A4AE;--shiki-default:#702C00;--shiki-dark:#FFAB70}html pre.shiki code .sXSbw, html code.shiki .sXSbw{--shiki-light:#90A4AE;--shiki-default:#023B95;--shiki-dark:#79B8FF}html pre.shiki code .sm80-, html code.shiki .sm80-{--shiki-light:#E53935;--shiki-default:#0E1116;--shiki-dark:#E1E4E8}html pre.shiki code .sBTIf, html code.shiki .sBTIf{--shiki-light:#6182B8;--shiki-default:#023B95;--shiki-dark:#79B8FF}html pre.shiki code .sNpir, html code.shiki .sNpir{--shiki-light:#F76D47;--shiki-default:#023B95;--shiki-dark:#79B8FF}html pre.shiki code .smmm7, html code.shiki .smmm7{--shiki-light:#F76D47;--shiki-default:#A0111F;--shiki-dark:#79B8FF}html pre.shiki code .sHgB6, html code.shiki .sHgB6{--shiki-light:#E53935;--shiki-default:#023B95;--shiki-dark:#79B8FF}html pre.shiki code .sxl37, html code.shiki .sxl37{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#66707B;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}",{"title":89,"searchDepth":153,"depth":153,"links":5146},[5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163],{"id":29,"depth":147,"text":30},{"id":78,"depth":147,"text":79},{"id":174,"depth":147,"text":175},{"id":998,"depth":147,"text":999},{"id":1454,"depth":147,"text":1455},{"id":1606,"depth":147,"text":1607},{"id":1809,"depth":147,"text":1810},{"id":2271,"depth":147,"text":2272},{"id":2483,"depth":147,"text":2484},{"id":3140,"depth":147,"text":3141},{"id":3758,"depth":147,"text":3759},{"id":4052,"depth":147,"text":4053},{"id":4222,"depth":147,"text":4223},{"id":4778,"depth":147,"text":4779},{"id":5034,"depth":147,"text":5035},{"id":5075,"depth":147,"text":5076},{"id":5105,"depth":147,"text":5106},"Build a dual-axis SVG chart with annual revenue bars, a monthly stock price curve, gradients, clipping, custom ticks, and embedded icons.","md",{"category":5167},"tutorials",{"title":5169},"Revenue and stock price","\u002Ftutorials\u002Fcombo-chart",{"title":5,"description":5164},"tutorials\u002Fcombo-chart","csKqJTopaULbyXjydyEWSOIsVXN2V5RisghnD5HGIJg",1781452408241]