@roastcodes/ttdash 6.2.0 → 6.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/AnomalyDetection-BdGl1xvC.js +1 -0
- package/dist/assets/{AutoImportModal-C8gA0_mL.js → AutoImportModal-bokip1Pn.js} +3 -3
- package/dist/assets/CacheROI-IyVKLGZu.js +1 -0
- package/dist/assets/ChartCard-CBUnItl-.js +2 -0
- package/dist/assets/ChartLegend-B64cJdDI.js +1 -0
- package/dist/assets/CorrelationAnalysis-Dnd0YUCO.js +1 -0
- package/dist/assets/CostByModelOverTime-C10Hr2xR.js +1 -0
- package/dist/assets/CostByWeekday-X20qjGNA.js +1 -0
- package/dist/assets/CostForecast-C--EIZ4B.js +1 -0
- package/dist/assets/CumulativeCost-D9v6GDcr.js +1 -0
- package/dist/assets/CustomTooltip-CBVU1pyK.js +1 -0
- package/dist/assets/DistributionAnalysis-Cdly0pAu.js +1 -0
- package/dist/assets/DrillDownModal-BXf7B9B8.js +1 -0
- package/dist/assets/HelpPanel-HNxQElT5.js +1 -0
- package/dist/assets/InfoButton-CTgLGzb9.js +1 -0
- package/dist/assets/InfoHeading-oi90uCR7.js +1 -0
- package/dist/assets/MetricCard-Drluz0b9.js +1 -0
- package/dist/assets/ModelEfficiency-CZ4ZzDtA.js +1 -0
- package/dist/assets/ModelMix-TDHxSk5H.js +1 -0
- package/dist/assets/PeriodComparison-B9WuoaCr.js +1 -0
- package/dist/assets/ProviderEfficiency-DpDIYr_l.js +1 -0
- package/dist/assets/ProviderLimitsSection-CSuisho_.js +1 -0
- package/dist/assets/RecentDays-Cz4Yd_-Q.js +1 -0
- package/dist/assets/RequestCacheHitRateByModel-5bkvg7Hx.js +1 -0
- package/dist/assets/RequestQuality-iUIOJrpr.js +1 -0
- package/dist/assets/RequestsOverTime-D10OssgN.js +1 -0
- package/dist/assets/SettingsModal-D9-T5heB.js +1 -0
- package/dist/assets/TokenEfficiency-CGeyr8Zq.js +1 -0
- package/dist/assets/TokenTypes-BiRBF9VP.js +1 -0
- package/dist/assets/TokensOverTime-DeT3D-aC.js +1 -0
- package/dist/assets/app-settings-C3i52ycx.js +1 -0
- package/dist/assets/button-D--hHeVj.js +1 -0
- package/dist/assets/calculations-GOdNqKo6.js +1 -0
- package/dist/assets/card-h-Z9EWBl.js +1 -0
- package/dist/assets/chart-theme-D5iCFDJg.js +1 -0
- package/dist/assets/constants-jyhBMReu.js +1 -0
- package/dist/assets/dialog-C0AeNKs8.js +1 -0
- package/dist/assets/formatted-value-rO0EpKbc.js +1 -0
- package/dist/assets/formatters-yKppUXb3.js +1 -0
- package/dist/assets/help-content-Bt5KCpWS.js +1 -0
- package/dist/assets/i18n-C88wS2Uy.js +1 -0
- package/dist/assets/index-DjMakAzD.js +3 -0
- package/dist/assets/index-DuoM1Ukq.css +2 -0
- package/dist/assets/model-utils-BIvGAFGz.js +1 -0
- package/dist/assets/motion-vendor-vKc6gXHZ.js +1 -0
- package/dist/assets/provider-limits-5e1fUwPl.js +1 -0
- package/dist/assets/section-header-DbV45zH5.js +1 -0
- package/dist/assets/ui-vendor-BolBXLiD.js +45 -0
- package/dist/assets/useTranslation-BSl7t2D6.js +1 -0
- package/dist/index.html +26 -8
- package/package.json +15 -5
- package/server/report/index.js +13 -11
- package/server.js +281 -56
- package/shared/dashboard-domain.d.ts +12 -0
- package/shared/dashboard-domain.js +79 -0
- package/shared/dashboard-types.d.ts +4 -0
- package/shared/model-colors.d.ts +7 -0
- package/shared/model-colors.js +27 -0
- package/src/locales/de/common.json +50 -5
- package/src/locales/en/common.json +50 -4
- package/dist/assets/CustomTooltip-CdIOw3Ep.js +0 -1
- package/dist/assets/DrillDownModal-d6hcut-I.js +0 -1
- package/dist/assets/button-B26tLVFw.js +0 -1
- package/dist/assets/dialog-CA-ZSHjK.js +0 -1
- package/dist/assets/index-BkGSNAne.css +0 -2
- package/dist/assets/index-CMtAn7c8.js +0 -4
- package/dist/assets/motion-vendor-BXI2L__C.js +0 -1
- package/dist/assets/ui-vendor-BGjRFQGY.js +0 -45
- /package/dist/assets/{icons-vendor-z59La6A4.js → icons-vendor-CIvT_-Pb.js} +0 -0
package/shared/model-colors.js
CHANGED
|
@@ -113,6 +113,12 @@ const MODEL_COLOR_RULES = [
|
|
|
113
113
|
|
|
114
114
|
const FALLBACK_HUES = [148, 168, 190, 208, 226, 248, 272, 332, 18, 30, 44]
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Normalizes an unknown theme value to a supported color theme.
|
|
118
|
+
*
|
|
119
|
+
* @param theme - The requested theme value.
|
|
120
|
+
* @returns The normalized shared color theme.
|
|
121
|
+
*/
|
|
116
122
|
function normalizeTheme(theme) {
|
|
117
123
|
return theme === 'light' ? 'light' : 'dark'
|
|
118
124
|
}
|
|
@@ -164,6 +170,13 @@ function fallbackColor(name, theme) {
|
|
|
164
170
|
}
|
|
165
171
|
}
|
|
166
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Returns the shared color spec for a normalized model name.
|
|
175
|
+
*
|
|
176
|
+
* @param name - The model name to resolve.
|
|
177
|
+
* @param options - The theme and alpha options for color resolution.
|
|
178
|
+
* @returns The resolved HSL color spec.
|
|
179
|
+
*/
|
|
167
180
|
function getModelColorSpec(name, options = {}) {
|
|
168
181
|
const theme = normalizeTheme(options.theme)
|
|
169
182
|
const known = findKnownColor(name)
|
|
@@ -218,12 +231,26 @@ function hslToRgb(spec) {
|
|
|
218
231
|
}
|
|
219
232
|
}
|
|
220
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Returns the shared model color as an HSL string.
|
|
236
|
+
*
|
|
237
|
+
* @param name - The model name to resolve.
|
|
238
|
+
* @param options - The theme and alpha options for color resolution.
|
|
239
|
+
* @returns The resolved CSS color string.
|
|
240
|
+
*/
|
|
221
241
|
function getModelColor(name, options = {}) {
|
|
222
242
|
const spec = getModelColorSpec(name, options)
|
|
223
243
|
const alpha = normalizeAlpha(options.alpha)
|
|
224
244
|
return alpha === null ? toHslString(spec) : toHslaString(spec, alpha)
|
|
225
245
|
}
|
|
226
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Returns the shared model color as an RGB string.
|
|
249
|
+
*
|
|
250
|
+
* @param name - The model name to resolve.
|
|
251
|
+
* @param options - The theme and alpha options for color resolution.
|
|
252
|
+
* @returns The resolved CSS RGB color string.
|
|
253
|
+
*/
|
|
227
254
|
function getModelColorRgb(name, options = {}) {
|
|
228
255
|
const spec = getModelColorSpec(name, options)
|
|
229
256
|
const { r, g, b } = hslToRgb(spec)
|
|
@@ -179,6 +179,10 @@
|
|
|
179
179
|
"title": "Tabellen",
|
|
180
180
|
"description": "Detaillierte Aufschlüsselungen"
|
|
181
181
|
},
|
|
182
|
+
"lazySectionError": {
|
|
183
|
+
"title": "Sektion nicht verfügbar",
|
|
184
|
+
"description": "Diese Dashboard-Sektion konnte gerade nicht geladen werden."
|
|
185
|
+
},
|
|
182
186
|
"cards": {
|
|
183
187
|
"periodComparison": "Periodenvergleich",
|
|
184
188
|
"anomalyDetection": "Anomalie-Erkennung",
|
|
@@ -318,7 +322,7 @@
|
|
|
318
322
|
},
|
|
319
323
|
"peakWindow": {
|
|
320
324
|
"title": "Peak-Fenster",
|
|
321
|
-
"summary": "Stärkste 7-Tage-Phase von {{start}} bis {{end}}
|
|
325
|
+
"summary": "Stärkste 7-Tage-Phase von {{start}} bis {{end}}",
|
|
322
326
|
"fallback": "Kein 7-Tage-Fenster verfügbar, daher Fokus auf den teuersten Einzelwert.",
|
|
323
327
|
"peakDay": "Peak Tag",
|
|
324
328
|
"avgPerUnit": "Ø/{{unit}}",
|
|
@@ -345,7 +349,8 @@
|
|
|
345
349
|
"costByModel": {
|
|
346
350
|
"title": "Kosten nach Modell",
|
|
347
351
|
"subtitle": "Kostenverteilung nach Modell",
|
|
348
|
-
"total": "Gesamt"
|
|
352
|
+
"total": "Gesamt",
|
|
353
|
+
"otherModels": "Weitere Modelle"
|
|
349
354
|
},
|
|
350
355
|
"costByModelOverTime": {
|
|
351
356
|
"title": "Kosten nach Modell im Zeitverlauf",
|
|
@@ -944,15 +949,55 @@
|
|
|
944
949
|
}
|
|
945
950
|
},
|
|
946
951
|
"drillDown": {
|
|
947
|
-
"description": "Detaillierte
|
|
952
|
+
"description": "Detaillierte {{periodType}}-Ansicht mit Benchmarks, Modellaufschlüsselung, Anbieter-Zusammenfassung und Token-Verteilung.",
|
|
948
953
|
"cacheRate": "Cache-Rate",
|
|
949
954
|
"tokensPerRequest": "Tokens / Anfrage",
|
|
950
955
|
"costPerRequest": "Kosten / Anfrage",
|
|
951
956
|
"costRank": "Kosten-Rang",
|
|
952
957
|
"requestRank": "Anfragen-Rang",
|
|
958
|
+
"overview": "Überblick",
|
|
959
|
+
"benchmarks": "Benchmarks",
|
|
960
|
+
"periodType": "Typ: {{period}}",
|
|
961
|
+
"coverage": "Abdeckung",
|
|
962
|
+
"coverageDays": "{{count}} Rohdaten-Tag",
|
|
963
|
+
"coverageDays_other": "{{count}} Rohdaten-Tage",
|
|
964
|
+
"singlePeriod": "1 {{period}}",
|
|
965
|
+
"activeProviders": "Aktive Anbieter",
|
|
953
966
|
"topRequestModel": "Dominant nach Anfragen",
|
|
954
|
-
"
|
|
955
|
-
"
|
|
967
|
+
"topCostModel": "Top nach Kosten",
|
|
968
|
+
"topTokenModel": "Top nach Tokens",
|
|
969
|
+
"priciestPerMillionModel": "Höchstes $/1M",
|
|
970
|
+
"topCostShare": "Top-1 Kostenanteil",
|
|
971
|
+
"topThreeCostShare": "Top-3 Kostenanteil",
|
|
972
|
+
"modelBreakdown": "Modelle im Detail",
|
|
973
|
+
"providerSummary": "Anbieter-Zusammenfassung",
|
|
974
|
+
"providerCount": "{{count}} Anbieter",
|
|
975
|
+
"modelCount": "{{count}} Modell",
|
|
976
|
+
"modelCount_other": "{{count}} Modelle",
|
|
977
|
+
"activeModelsCount": "{{count}} aktives Modell",
|
|
978
|
+
"activeModelsCount_other": "{{count}} aktive Modelle",
|
|
979
|
+
"costShare": "Kostenanteil",
|
|
980
|
+
"tokenShare": "Tokenanteil",
|
|
981
|
+
"costShareByModel": "Kostenanteil nach Modell",
|
|
982
|
+
"costVsPrevious": "Kosten vs. vorher",
|
|
983
|
+
"tokensVsPrevious": "Tokens vs. vorher",
|
|
984
|
+
"requestsVsPrevious": "Anfragen vs. vorher",
|
|
985
|
+
"costPerMillionVsPrevious": "$/1M vs. vorher",
|
|
986
|
+
"previousDay": "Vorheriger Tag",
|
|
987
|
+
"nextDay": "Nächster Tag",
|
|
988
|
+
"previousPeriod": "Vorherige Periode",
|
|
989
|
+
"nextPeriod": "Nächste Periode",
|
|
990
|
+
"position": "{{current}} / {{total}}",
|
|
991
|
+
"keyboardHint": "Mit ← / → wechseln",
|
|
992
|
+
"costVsAverageWindow": "Kosten vs. {{window}}-Ø",
|
|
993
|
+
"requestsVsAverageWindow": "Anfragen vs. {{window}}-Ø",
|
|
994
|
+
"tokensVsAverageWindow": "Tokens vs. {{window}}-Ø",
|
|
995
|
+
"costPerMillionVsAverageWindow": "$/1M vs. {{window}}-Ø",
|
|
996
|
+
"windowUnit": {
|
|
997
|
+
"day": "T",
|
|
998
|
+
"month": "M",
|
|
999
|
+
"year": "J"
|
|
1000
|
+
},
|
|
956
1001
|
"tokenDistribution": "Token-Verteilung",
|
|
957
1002
|
"requestCountShort": "{{count}} Anfragen",
|
|
958
1003
|
"modelRequestSummary": "{{costPerRequest}} / Anfrage · {{tokensPerRequest}} / Anfrage",
|
|
@@ -179,6 +179,10 @@
|
|
|
179
179
|
"title": "Tables",
|
|
180
180
|
"description": "Detailed breakdowns"
|
|
181
181
|
},
|
|
182
|
+
"lazySectionError": {
|
|
183
|
+
"title": "Section unavailable",
|
|
184
|
+
"description": "This dashboard section could not be loaded right now."
|
|
185
|
+
},
|
|
182
186
|
"cards": {
|
|
183
187
|
"periodComparison": "Period comparison",
|
|
184
188
|
"anomalyDetection": "Anomaly detection",
|
|
@@ -345,7 +349,8 @@
|
|
|
345
349
|
"costByModel": {
|
|
346
350
|
"title": "Cost by model",
|
|
347
351
|
"subtitle": "Cost distribution by model",
|
|
348
|
-
"total": "Total"
|
|
352
|
+
"total": "Total",
|
|
353
|
+
"otherModels": "Other models"
|
|
349
354
|
},
|
|
350
355
|
"costByModelOverTime": {
|
|
351
356
|
"title": "Cost by model over time",
|
|
@@ -944,15 +949,56 @@
|
|
|
944
949
|
}
|
|
945
950
|
},
|
|
946
951
|
"drillDown": {
|
|
947
|
-
"description": "Detailed
|
|
952
|
+
"description": "Detailed {{periodType}} view with benchmarks, model breakdown, provider summary, and token distribution.",
|
|
948
953
|
"cacheRate": "Cache rate",
|
|
949
954
|
"tokensPerRequest": "Tokens / Req",
|
|
950
955
|
"costPerRequest": "Cost / Req",
|
|
951
956
|
"costRank": "Cost rank",
|
|
952
957
|
"requestRank": "Request rank",
|
|
958
|
+
"overview": "Overview",
|
|
959
|
+
"benchmarks": "Benchmarks",
|
|
960
|
+
"periodType": "Type: {{period}}",
|
|
961
|
+
"coverage": "Coverage",
|
|
962
|
+
"coverageDays": "{{count}} raw day",
|
|
963
|
+
"coverageDays_other": "{{count}} raw days",
|
|
964
|
+
"singlePeriod": "1 {{period}}",
|
|
965
|
+
"activeProviders": "Active providers",
|
|
953
966
|
"topRequestModel": "Top by requests",
|
|
954
|
-
"
|
|
955
|
-
"
|
|
967
|
+
"topCostModel": "Top by cost",
|
|
968
|
+
"topTokenModel": "Top by tokens",
|
|
969
|
+
"priciestPerMillionModel": "Highest $/1M",
|
|
970
|
+
"topCostShare": "Top 1 cost share",
|
|
971
|
+
"topThreeCostShare": "Top 3 cost share",
|
|
972
|
+
"modelBreakdown": "Model breakdown",
|
|
973
|
+
"providerSummary": "Provider summary",
|
|
974
|
+
"providerCount": "{{count}} provider",
|
|
975
|
+
"providerCount_other": "{{count}} providers",
|
|
976
|
+
"modelCount": "{{count}} model",
|
|
977
|
+
"modelCount_other": "{{count}} models",
|
|
978
|
+
"activeModelsCount": "{{count}} active model",
|
|
979
|
+
"activeModelsCount_other": "{{count}} active models",
|
|
980
|
+
"costShare": "Cost share",
|
|
981
|
+
"tokenShare": "Token share",
|
|
982
|
+
"costShareByModel": "Cost share by model",
|
|
983
|
+
"costVsPrevious": "Cost vs. previous",
|
|
984
|
+
"tokensVsPrevious": "Tokens vs. previous",
|
|
985
|
+
"requestsVsPrevious": "Requests vs. previous",
|
|
986
|
+
"costPerMillionVsPrevious": "$/1M vs. previous",
|
|
987
|
+
"previousDay": "Previous day",
|
|
988
|
+
"nextDay": "Next day",
|
|
989
|
+
"previousPeriod": "Previous period",
|
|
990
|
+
"nextPeriod": "Next period",
|
|
991
|
+
"position": "{{current}} / {{total}}",
|
|
992
|
+
"keyboardHint": "Use ← / →",
|
|
993
|
+
"costVsAverageWindow": "Cost vs. {{window}} avg",
|
|
994
|
+
"requestsVsAverageWindow": "Requests vs. {{window}} avg",
|
|
995
|
+
"tokensVsAverageWindow": "Tokens vs. {{window}} avg",
|
|
996
|
+
"costPerMillionVsAverageWindow": "$/1M vs. {{window}} avg",
|
|
997
|
+
"windowUnit": {
|
|
998
|
+
"day": "D",
|
|
999
|
+
"month": "M",
|
|
1000
|
+
"year": "Y"
|
|
1001
|
+
},
|
|
956
1002
|
"tokenDistribution": "Token distribution",
|
|
957
1003
|
"requestCountShort": "{{count}} Req",
|
|
958
1004
|
"modelRequestSummary": "{{costPerRequest}}/Req · {{tokensPerRequest}}/Req",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e,i as t,n,r,t as i}from"./rolldown-runtime-COnpUsM8.js";import{w as a}from"./charts-vendor-CiBqdKXh.js";import{r as o}from"./motion-vendor-BXI2L__C.js";import{C as s,S as c,b as l,x as u}from"./ui-vendor-BGjRFQGY.js";import{c as d,o as f,s as p}from"./dialog-CA-ZSHjK.js";var m=e(a()),h=o(),g=u,_=c,v=s,y=m.forwardRef(({className:e,sideOffset:t=4,...n},r)=>(0,h.jsx)(l,{ref:r,sideOffset:t,className:d(`z-50 overflow-hidden rounded-lg bg-popover/90 backdrop-blur-xl px-3 py-1.5 text-xs text-popover-foreground border border-border/50 shadow-lg shadow-black/10 animate-in fade-in-0 zoom-in-95 duration-200`,e),...n}));y.displayName=`TooltipContent`;var b=e=>typeof e==`string`,x=()=>{let e,t,n=new Promise((n,r)=>{e=n,t=r});return n.resolve=e,n.reject=t,n},S=e=>e==null?``:String(e),C=(e,t,n)=>{e.forEach(e=>{t[e]&&(n[e]=t[e])})},w=/###/g,T=e=>e&&e.includes(`###`)?e.replace(w,`.`):e,E=e=>!e||b(e),D=(e,t,n)=>{let r=b(t)?t.split(`.`):t,i=0;for(;i<r.length-1;){if(E(e))return{};let t=T(r[i]);!e[t]&&n&&(e[t]=new n),e=Object.prototype.hasOwnProperty.call(e,t)?e[t]:{},++i}return E(e)?{}:{obj:e,k:T(r[i])}},O=(e,t,n)=>{let{obj:r,k:i}=D(e,t,Object);if(r!==void 0||t.length===1){r[i]=n;return}let a=t[t.length-1],o=t.slice(0,t.length-1),s=D(e,o,Object);for(;s.obj===void 0&&o.length;)a=`${o[o.length-1]}.${a}`,o=o.slice(0,o.length-1),s=D(e,o,Object),s?.obj&&s.obj[`${s.k}.${a}`]!==void 0&&(s.obj=void 0);s.obj[`${s.k}.${a}`]=n},k=(e,t,n,r)=>{let{obj:i,k:a}=D(e,t,Object);i[a]=i[a]||[],i[a].push(n)},A=(e,t)=>{let{obj:n,k:r}=D(e,t);if(n&&Object.prototype.hasOwnProperty.call(n,r))return n[r]},ee=(e,t,n)=>{let r=A(e,n);return r===void 0?A(t,n):r},j=(e,t,n)=>{for(let r in t)r!==`__proto__`&&r!==`constructor`&&(r in e?b(e[r])||e[r]instanceof String||b(t[r])||t[r]instanceof String?n&&(e[r]=t[r]):j(e[r],t[r],n):e[r]=t[r]);return e},M=e=>e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,`\\$&`),N={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`,"/":`/`},P=e=>b(e)?e.replace(/[&<>"'\/]/g,e=>N[e]):e,F=class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){let t=this.regExpMap.get(e);if(t!==void 0)return t;let n=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,n),this.regExpQueue.push(e),n}},te=[` `,`,`,`?`,`!`,`;`],ne=new F(20),I=(e,t,n)=>{t||=``,n||=``;let r=te.filter(e=>!t.includes(e)&&!n.includes(e));if(r.length===0)return!0;let i=ne.getRegExp(`(${r.map(e=>e===`?`?`\\?`:e).join(`|`)})`),a=!i.test(e);if(!a){let t=e.indexOf(n);t>0&&!i.test(e.substring(0,t))&&(a=!0)}return a},L=(e,t,n=`.`)=>{if(!e)return;if(e[t])return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0;let r=t.split(n),i=e;for(let e=0;e<r.length;){if(!i||typeof i!=`object`)return;let t,a=``;for(let o=e;o<r.length;++o)if(o!==e&&(a+=n),a+=r[o],t=i[a],t!==void 0){if([`string`,`number`,`boolean`].includes(typeof t)&&o<r.length-1)continue;e+=o-e+1;break}i=t}return i},R=e=>e?.replace(/_/g,`-`),re={type:`logger`,log(e){this.output(`log`,e)},warn(e){this.output(`warn`,e)},error(e){this.output(`error`,e)},output(e,t){console?.[e]?.apply?.(console,t)}},z=new class e{constructor(e,t={}){this.init(e,t)}init(e,t={}){this.prefix=t.prefix||`i18next:`,this.logger=e||re,this.options=t,this.debug=t.debug}log(...e){return this.forward(e,`log`,``,!0)}warn(...e){return this.forward(e,`warn`,``,!0)}error(...e){return this.forward(e,`error`,``)}deprecate(...e){return this.forward(e,`warn`,`WARNING DEPRECATED: `,!0)}forward(e,t,n,r){return r&&!this.debug?null:(b(e[0])&&(e[0]=`${n}${this.prefix} ${e[0]}`),this.logger[t](e))}create(t){return new e(this.logger,{prefix:`${this.prefix}:${t}:`,...this.options})}clone(t){return t||=this.options,t.prefix=t.prefix||this.prefix,new e(this.logger,t)}},B=class{constructor(){this.observers={}}on(e,t){return e.split(` `).forEach(e=>{this.observers[e]||(this.observers[e]=new Map);let n=this.observers[e].get(t)||0;this.observers[e].set(t,n+1)}),this}off(e,t){if(this.observers[e]){if(!t){delete this.observers[e];return}this.observers[e].delete(t)}}once(e,t){let n=(...r)=>{t(...r),this.off(e,n)};return this.on(e,n),this}emit(e,...t){this.observers[e]&&Array.from(this.observers[e].entries()).forEach(([e,n])=>{for(let r=0;r<n;r++)e(...t)}),this.observers[`*`]&&Array.from(this.observers[`*`].entries()).forEach(([n,r])=>{for(let i=0;i<r;i++)n(e,...t)})}},ie=class extends B{constructor(e,t={ns:[`translation`],defaultNS:`translation`}){super(),this.data=e||{},this.options=t,this.options.keySeparator===void 0&&(this.options.keySeparator=`.`),this.options.ignoreJSONStructure===void 0&&(this.options.ignoreJSONStructure=!0)}addNamespaces(e){this.options.ns.includes(e)||this.options.ns.push(e)}removeNamespaces(e){let t=this.options.ns.indexOf(e);t>-1&&this.options.ns.splice(t,1)}getResource(e,t,n,r={}){let i=r.keySeparator===void 0?this.options.keySeparator:r.keySeparator,a=r.ignoreJSONStructure===void 0?this.options.ignoreJSONStructure:r.ignoreJSONStructure,o;e.includes(`.`)?o=e.split(`.`):(o=[e,t],n&&(Array.isArray(n)?o.push(...n):b(n)&&i?o.push(...n.split(i)):o.push(n)));let s=A(this.data,o);return!s&&!t&&!n&&e.includes(`.`)&&(e=o[0],t=o[1],n=o.slice(2).join(`.`)),s||!a||!b(n)?s:L(this.data?.[e]?.[t],n,i)}addResource(e,t,n,r,i={silent:!1}){let a=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,o=[e,t];n&&(o=o.concat(a?n.split(a):n)),e.includes(`.`)&&(o=e.split(`.`),r=t,t=o[1]),this.addNamespaces(t),O(this.data,o,r),i.silent||this.emit(`added`,e,t,n,r)}addResources(e,t,n,r={silent:!1}){for(let r in n)(b(n[r])||Array.isArray(n[r]))&&this.addResource(e,t,r,n[r],{silent:!0});r.silent||this.emit(`added`,e,t,n)}addResourceBundle(e,t,n,r,i,a={silent:!1,skipCopy:!1}){let o=[e,t];e.includes(`.`)&&(o=e.split(`.`),r=n,n=t,t=o[1]),this.addNamespaces(t);let s=A(this.data,o)||{};a.skipCopy||(n=JSON.parse(JSON.stringify(n))),r?j(s,n,i):s={...s,...n},O(this.data,o,s),a.silent||this.emit(`added`,e,t,n)}removeResourceBundle(e,t){this.hasResourceBundle(e,t)&&delete this.data[e][t],this.removeNamespaces(t),this.emit(`removed`,e,t)}hasResourceBundle(e,t){return this.getResource(e,t)!==void 0}getResourceBundle(e,t){return t||=this.options.defaultNS,this.getResource(e,t)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){let t=this.getDataByLanguage(e);return!!(t&&Object.keys(t)||[]).find(e=>t[e]&&Object.keys(t[e]).length>0)}toJSON(){return this.data}},ae={processors:{},addPostProcessor(e){this.processors[e.name]=e},handle(e,t,n,r,i){return e.forEach(e=>{t=this.processors[e]?.process(t,n,r,i)??t}),t}},oe=Symbol(`i18next/PATH_KEY`);function se(){let e=[],t=Object.create(null),n;return t.get=(r,i)=>(n?.revoke?.(),i===oe?e:(e.push(i),n=Proxy.revocable(r,t),n.proxy)),Proxy.revocable(Object.create(null),t).proxy}function V(e,t){let{[oe]:n}=e(se()),r=t?.keySeparator??`.`,i=t?.nsSeparator??`:`;if(n.length>1&&i){let e=t?.ns,a=Array.isArray(e)?e:null;if(a&&a.length>1&&a.slice(1).includes(n[0]))return`${n[0]}${i}${n.slice(1).join(r)}`}return n.join(r)}var H=e=>!b(e)&&typeof e!=`boolean`&&typeof e!=`number`,ce=class e extends B{constructor(e,t={}){super(),C([`resourceStore`,`languageUtils`,`pluralResolver`,`interpolator`,`backendConnector`,`i18nFormat`,`utils`],e,this),this.options=t,this.options.keySeparator===void 0&&(this.options.keySeparator=`.`),this.logger=z.create(`translator`),this.checkedLoadedFor={}}changeLanguage(e){e&&(this.language=e)}exists(e,t={interpolation:{}}){let n={...t};if(e==null)return!1;let r=this.resolve(e,n);if(r?.res===void 0)return!1;let i=H(r.res);return!(n.returnObjects===!1&&i)}extractFromKey(e,t){let n=t.nsSeparator===void 0?this.options.nsSeparator:t.nsSeparator;n===void 0&&(n=`:`);let r=t.keySeparator===void 0?this.options.keySeparator:t.keySeparator,i=t.ns||this.options.defaultNS||[],a=n&&e.includes(n),o=!this.options.userDefinedKeySeparator&&!t.keySeparator&&!this.options.userDefinedNsSeparator&&!t.nsSeparator&&!I(e,n,r);if(a&&!o){let t=e.match(this.interpolator.nestingRegexp);if(t&&t.length>0)return{key:e,namespaces:b(i)?[i]:i};let a=e.split(n);(n!==r||n===r&&this.options.ns.includes(a[0]))&&(i=a.shift()),e=a.join(r)}return{key:e,namespaces:b(i)?[i]:i}}translate(t,n,r){let i=typeof n==`object`?{...n}:n;if(typeof i!=`object`&&this.options.overloadTranslationOptionHandler&&(i=this.options.overloadTranslationOptionHandler(arguments)),typeof i==`object`&&(i={...i}),i||={},t==null)return``;typeof t==`function`&&(t=V(t,{...this.options,...i})),Array.isArray(t)||(t=[String(t)]),t=t.map(e=>typeof e==`function`?V(e,{...this.options,...i}):String(e));let a=i.returnDetails===void 0?this.options.returnDetails:i.returnDetails,o=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,{key:s,namespaces:c}=this.extractFromKey(t[t.length-1],i),l=c[c.length-1],u=i.nsSeparator===void 0?this.options.nsSeparator:i.nsSeparator;u===void 0&&(u=`:`);let d=i.lng||this.language,f=i.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(d?.toLowerCase()===`cimode`)return f?a?{res:`${l}${u}${s}`,usedKey:s,exactUsedKey:s,usedLng:d,usedNS:l,usedParams:this.getUsedParamsDetails(i)}:`${l}${u}${s}`:a?{res:s,usedKey:s,exactUsedKey:s,usedLng:d,usedNS:l,usedParams:this.getUsedParamsDetails(i)}:s;let p=this.resolve(t,i),m=p?.res,h=p?.usedKey||s,g=p?.exactUsedKey||s,_=[`[object Number]`,`[object Function]`,`[object RegExp]`],v=i.joinArrays===void 0?this.options.joinArrays:i.joinArrays,y=!this.i18nFormat||this.i18nFormat.handleAsObject,x=i.count!==void 0&&!b(i.count),S=e.hasDefaultValue(i),C=x?this.pluralResolver.getSuffix(d,i.count,i):``,w=i.ordinal&&x?this.pluralResolver.getSuffix(d,i.count,{ordinal:!1}):``,T=x&&!i.ordinal&&i.count===0,E=T&&i[`defaultValue${this.options.pluralSeparator}zero`]||i[`defaultValue${C}`]||i[`defaultValue${w}`]||i.defaultValue,D=m;y&&!m&&S&&(D=E);let O=H(D),k=Object.prototype.toString.apply(D);if(y&&D&&O&&!_.includes(k)&&!(b(v)&&Array.isArray(D))){if(!i.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn(`accessing an object - but returnObjects options is not enabled!`);let e=this.options.returnedObjectHandler?this.options.returnedObjectHandler(h,D,{...i,ns:c}):`key '${s} (${this.language})' returned an object instead of string.`;return a?(p.res=e,p.usedParams=this.getUsedParamsDetails(i),p):e}if(o){let e=Array.isArray(D),t=e?[]:{},n=e?g:h;for(let e in D)if(Object.prototype.hasOwnProperty.call(D,e)){let r=`${n}${o}${e}`;S&&!m?t[e]=this.translate(r,{...i,defaultValue:H(E)?E[e]:void 0,joinArrays:!1,ns:c}):t[e]=this.translate(r,{...i,joinArrays:!1,ns:c}),t[e]===r&&(t[e]=D[e])}m=t}}else if(y&&b(v)&&Array.isArray(m))m=m.join(v),m&&=this.extendTranslation(m,t,i,r);else{let e=!1,n=!1;!this.isValidLookup(m)&&S&&(e=!0,m=E),this.isValidLookup(m)||(n=!0,m=s);let a=(i.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&n?void 0:m,c=S&&E!==m&&this.options.updateMissing;if(n||e||c){if(this.logger.log(c?`updateKey`:`missingKey`,d,l,s,c?E:m),o){let e=this.resolve(s,{...i,keySeparator:!1});e&&e.res&&this.logger.warn(`Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.`)}let e=[],t=this.languageUtils.getFallbackCodes(this.options.fallbackLng,i.lng||this.language);if(this.options.saveMissingTo===`fallback`&&t&&t[0])for(let n=0;n<t.length;n++)e.push(t[n]);else this.options.saveMissingTo===`all`?e=this.languageUtils.toResolveHierarchy(i.lng||this.language):e.push(i.lng||this.language);let n=(e,t,n)=>{let r=S&&n!==m?n:a;this.options.missingKeyHandler?this.options.missingKeyHandler(e,l,t,r,c,i):this.backendConnector?.saveMissing&&this.backendConnector.saveMissing(e,l,t,r,c,i),this.emit(`missingKey`,e,l,t,m)};this.options.saveMissing&&(this.options.saveMissingPlurals&&x?e.forEach(e=>{let t=this.pluralResolver.getSuffixes(e,i);T&&i[`defaultValue${this.options.pluralSeparator}zero`]&&!t.includes(`${this.options.pluralSeparator}zero`)&&t.push(`${this.options.pluralSeparator}zero`),t.forEach(t=>{n([e],s+t,i[`defaultValue${t}`]||E)})}):n(e,s,E))}m=this.extendTranslation(m,t,i,p,r),n&&m===s&&this.options.appendNamespaceToMissingKey&&(m=`${l}${u}${s}`),(n||e)&&this.options.parseMissingKeyHandler&&(m=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${l}${u}${s}`:s,e?m:void 0,i))}return a?(p.res=m,p.usedParams=this.getUsedParamsDetails(i),p):m}extendTranslation(e,t,n,r,i){if(this.i18nFormat?.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...n},n.lng||this.language||r.usedLng,r.usedNS,r.usedKey,{resolved:r});else if(!n.skipInterpolation){n.interpolation&&this.interpolator.init({...n,interpolation:{...this.options.interpolation,...n.interpolation}});let a=b(e)&&(n?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:n.interpolation.skipOnVariables),o;if(a){let t=e.match(this.interpolator.nestingRegexp);o=t&&t.length}let s=n.replace&&!b(n.replace)?n.replace:n;if(this.options.interpolation.defaultVariables&&(s={...this.options.interpolation.defaultVariables,...s}),e=this.interpolator.interpolate(e,s,n.lng||this.language||r.usedLng,n),a){let t=e.match(this.interpolator.nestingRegexp),r=t&&t.length;o<r&&(n.nest=!1)}!n.lng&&r&&r.res&&(n.lng=this.language||r.usedLng),n.nest!==!1&&(e=this.interpolator.nest(e,(...e)=>i?.[0]===e[0]&&!n.context?(this.logger.warn(`It seems you are nesting recursively key: ${e[0]} in key: ${t[0]}`),null):this.translate(...e,t),n)),n.interpolation&&this.interpolator.reset()}let a=n.postProcess||this.options.postProcess,o=b(a)?[a]:a;return e!=null&&o?.length&&n.applyPostProcessor!==!1&&(e=ae.handle(o,e,t,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...r,usedParams:this.getUsedParamsDetails(n)},...n}:n,this)),e}resolve(e,t={}){let n,r,i,a,o;return b(e)&&(e=[e]),Array.isArray(e)&&(e=e.map(e=>typeof e==`function`?V(e,{...this.options,...t}):e)),e.forEach(e=>{if(this.isValidLookup(n))return;let s=this.extractFromKey(e,t),c=s.key;r=c;let l=s.namespaces;this.options.fallbackNS&&(l=l.concat(this.options.fallbackNS));let u=t.count!==void 0&&!b(t.count),d=u&&!t.ordinal&&t.count===0,f=t.context!==void 0&&(b(t.context)||typeof t.context==`number`)&&t.context!==``,p=t.lngs?t.lngs:this.languageUtils.toResolveHierarchy(t.lng||this.language,t.fallbackLng);l.forEach(e=>{this.isValidLookup(n)||(o=e,!this.checkedLoadedFor[`${p[0]}-${e}`]&&this.utils?.hasLoadedNamespace&&!this.utils?.hasLoadedNamespace(o)&&(this.checkedLoadedFor[`${p[0]}-${e}`]=!0,this.logger.warn(`key "${r}" for languages "${p.join(`, `)}" won't get resolved as namespace "${o}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`)),p.forEach(r=>{if(this.isValidLookup(n))return;a=r;let o=[c];if(this.i18nFormat?.addLookupKeys)this.i18nFormat.addLookupKeys(o,c,r,e,t);else{let e;u&&(e=this.pluralResolver.getSuffix(r,t.count,t));let n=`${this.options.pluralSeparator}zero`,i=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(u&&(t.ordinal&&e.startsWith(i)&&o.push(c+e.replace(i,this.options.pluralSeparator)),o.push(c+e),d&&o.push(c+n)),f){let r=`${c}${this.options.contextSeparator||`_`}${t.context}`;o.push(r),u&&(t.ordinal&&e.startsWith(i)&&o.push(r+e.replace(i,this.options.pluralSeparator)),o.push(r+e),d&&o.push(r+n))}}let s;for(;s=o.pop();)this.isValidLookup(n)||(i=s,n=this.getResource(r,e,s,t))}))})}),{res:n,usedKey:r,exactUsedKey:i,usedLng:a,usedNS:o}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e===``)}getResource(e,t,n,r={}){return this.i18nFormat?.getResource?this.i18nFormat.getResource(e,t,n,r):this.resourceStore.getResource(e,t,n,r)}getUsedParamsDetails(e={}){let t=[`defaultValue`,`ordinal`,`context`,`replace`,`lng`,`lngs`,`fallbackLng`,`ns`,`keySeparator`,`nsSeparator`,`returnObjects`,`returnDetails`,`joinArrays`,`postProcess`,`interpolation`],n=e.replace&&!b(e.replace),r=n?e.replace:e;if(n&&e.count!==void 0&&(r.count=e.count),this.options.interpolation.defaultVariables&&(r={...this.options.interpolation.defaultVariables,...r}),!n){r={...r};for(let e of t)delete r[e]}return r}static hasDefaultValue(e){for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t)&&t.startsWith(`defaultValue`)&&e[t]!==void 0)return!0;return!1}},le=class{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=z.create(`languageUtils`)}getScriptPartFromCode(e){if(e=R(e),!e||!e.includes(`-`))return null;let t=e.split(`-`);return t.length===2||(t.pop(),t[t.length-1].toLowerCase()===`x`)?null:this.formatLanguageCode(t.join(`-`))}getLanguagePartFromCode(e){if(e=R(e),!e||!e.includes(`-`))return e;let t=e.split(`-`);return this.formatLanguageCode(t[0])}formatLanguageCode(e){if(b(e)&&e.includes(`-`)){let t;try{t=Intl.getCanonicalLocales(e)[0]}catch{}return t&&this.options.lowerCaseLng&&(t=t.toLowerCase()),t||(this.options.lowerCaseLng?e.toLowerCase():e)}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}isSupportedCode(e){return(this.options.load===`languageOnly`||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.includes(e)}getBestMatchFromCodes(e){if(!e)return null;let t;return e.forEach(e=>{if(t)return;let n=this.formatLanguageCode(e);(!this.options.supportedLngs||this.isSupportedCode(n))&&(t=n)}),!t&&this.options.supportedLngs&&e.forEach(e=>{if(t)return;let n=this.getScriptPartFromCode(e);if(this.isSupportedCode(n))return t=n;let r=this.getLanguagePartFromCode(e);if(this.isSupportedCode(r))return t=r;t=this.options.supportedLngs.find(e=>e===r?!0:!e.includes(`-`)&&!r.includes(`-`)?!1:!!(e.includes(`-`)&&!r.includes(`-`)&&e.slice(0,e.indexOf(`-`))===r||e.startsWith(r)&&r.length>1))}),t||=this.getFallbackCodes(this.options.fallbackLng)[0],t}getFallbackCodes(e,t){if(!e)return[];if(typeof e==`function`&&(e=e(t)),b(e)&&(e=[e]),Array.isArray(e))return e;if(!t)return e.default||[];let n=e[t];return n||=e[this.getScriptPartFromCode(t)],n||=e[this.formatLanguageCode(t)],n||=e[this.getLanguagePartFromCode(t)],n||=e.default,n||[]}toResolveHierarchy(e,t){let n=this.getFallbackCodes((t===!1?[]:t)||this.options.fallbackLng||[],e),r=[],i=e=>{e&&(this.isSupportedCode(e)?r.push(e):this.logger.warn(`rejecting language code not found in supportedLngs: ${e}`))};return b(e)&&(e.includes(`-`)||e.includes(`_`))?(this.options.load!==`languageOnly`&&i(this.formatLanguageCode(e)),this.options.load!==`languageOnly`&&this.options.load!==`currentOnly`&&i(this.getScriptPartFromCode(e)),this.options.load!==`currentOnly`&&i(this.getLanguagePartFromCode(e))):b(e)&&i(this.formatLanguageCode(e)),n.forEach(e=>{r.includes(e)||i(this.formatLanguageCode(e))}),r}},ue={zero:0,one:1,two:2,few:3,many:4,other:5},de={select:e=>e===1?`one`:`other`,resolvedOptions:()=>({pluralCategories:[`one`,`other`]})},fe=class{constructor(e,t={}){this.languageUtils=e,this.options=t,this.logger=z.create(`pluralResolver`),this.pluralRulesCache={}}clearCache(){this.pluralRulesCache={}}getRule(e,t={}){let n=R(e===`dev`?`en`:e),r=t.ordinal?`ordinal`:`cardinal`,i=JSON.stringify({cleanedCode:n,type:r});if(i in this.pluralRulesCache)return this.pluralRulesCache[i];let a;try{a=new Intl.PluralRules(n,{type:r})}catch{if(typeof Intl>`u`)return this.logger.error(`No Intl support, please use an Intl polyfill!`),de;if(!e.match(/-|_/))return de;let n=this.languageUtils.getLanguagePartFromCode(e);a=this.getRule(n,t)}return this.pluralRulesCache[i]=a,a}needsPlural(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?.resolvedOptions().pluralCategories.length>1}getPluralFormsOfKey(e,t,n={}){return this.getSuffixes(e,n).map(e=>`${t}${e}`)}getSuffixes(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?n.resolvedOptions().pluralCategories.sort((e,t)=>ue[e]-ue[t]).map(e=>`${this.options.prepend}${t.ordinal?`ordinal${this.options.prepend}`:``}${e}`):[]}getSuffix(e,t,n={}){let r=this.getRule(e,n);return r?`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:``}${r.select(t)}`:(this.logger.warn(`no plural rule found for: ${e}`),this.getSuffix(`dev`,t,n))}},pe=(e,t,n,r=`.`,i=!0)=>{let a=ee(e,t,n);return!a&&i&&b(n)&&(a=L(e,n,r),a===void 0&&(a=L(t,n,r))),a},U=e=>e.replace(/\$/g,`$$$$`),me=class{constructor(e={}){this.logger=z.create(`interpolator`),this.options=e,this.format=e?.interpolation?.format||(e=>e),this.init(e)}init(e={}){e.interpolation||={escapeValue:!0};let{escape:t,escapeValue:n,useRawValueToEscape:r,prefix:i,prefixEscaped:a,suffix:o,suffixEscaped:s,formatSeparator:c,unescapeSuffix:l,unescapePrefix:u,nestingPrefix:d,nestingPrefixEscaped:f,nestingSuffix:p,nestingSuffixEscaped:m,nestingOptionsSeparator:h,maxReplaces:g,alwaysFormat:_}=e.interpolation;this.escape=t===void 0?P:t,this.escapeValue=n===void 0?!0:n,this.useRawValueToEscape=r===void 0?!1:r,this.prefix=i?M(i):a||`{{`,this.suffix=o?M(o):s||`}}`,this.formatSeparator=c||`,`,this.unescapePrefix=l?``:u||`-`,this.unescapeSuffix=this.unescapePrefix?``:l||``,this.nestingPrefix=d?M(d):f||M(`$t(`),this.nestingSuffix=p?M(p):m||M(`)`),this.nestingOptionsSeparator=h||`,`,this.maxReplaces=g||1e3,this.alwaysFormat=_===void 0?!1:_,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){let e=(e,t)=>e?.source===t?(e.lastIndex=0,e):new RegExp(t,`g`);this.regexp=e(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=e(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=e(this.nestingRegexp,`${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`)}interpolate(e,t,n,r){let i,a,o,s=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},c=e=>{if(!e.includes(this.formatSeparator)){let i=pe(t,s,e,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(i,void 0,n,{...r,...t,interpolationkey:e}):i}let i=e.split(this.formatSeparator),a=i.shift().trim(),o=i.join(this.formatSeparator).trim();return this.format(pe(t,s,a,this.options.keySeparator,this.options.ignoreJSONStructure),o,n,{...r,...t,interpolationkey:a})};this.resetRegExp();let l=r?.missingInterpolationHandler||this.options.missingInterpolationHandler,u=r?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:r.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>U(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?U(this.escape(e)):U(e)}].forEach(t=>{for(o=0;i=t.regex.exec(e);){let n=i[1].trim();if(a=c(n),a===void 0)if(typeof l==`function`){let t=l(e,i,r);a=b(t)?t:``}else if(r&&Object.prototype.hasOwnProperty.call(r,n))a=``;else if(u){a=i[0];continue}else this.logger.warn(`missed to pass in variable ${n} for interpolating ${e}`),a=``;else !b(a)&&!this.useRawValueToEscape&&(a=S(a));let s=t.safeValue(a);if(e=e.replace(i[0],s),u?(t.regex.lastIndex+=a.length,t.regex.lastIndex-=i[0].length):t.regex.lastIndex=0,o++,o>=this.maxReplaces)break}}),e}nest(e,t,n={}){let r,i,a,o=(e,t)=>{let n=this.nestingOptionsSeparator;if(!e.includes(n))return e;let r=e.split(RegExp(`${M(n)}[ ]*{`)),i=`{${r[1]}`;e=r[0],i=this.interpolate(i,a);let o=i.match(/'/g),s=i.match(/"/g);((o?.length??0)%2==0&&!s||(s?.length??0)%2!=0)&&(i=i.replace(/'/g,`"`));try{a=JSON.parse(i),t&&(a={...t,...a})}catch(t){return this.logger.warn(`failed parsing options string in nesting for key ${e}`,t),`${e}${n}${i}`}return a.defaultValue&&a.defaultValue.includes(this.prefix)&&delete a.defaultValue,e};for(;r=this.nestingRegexp.exec(e);){let s=[];a={...n},a=a.replace&&!b(a.replace)?a.replace:a,a.applyPostProcessor=!1,delete a.defaultValue;let c=/{.*}/.test(r[1])?r[1].lastIndexOf(`}`)+1:r[1].indexOf(this.formatSeparator);if(c!==-1&&(s=r[1].slice(c).split(this.formatSeparator).map(e=>e.trim()).filter(Boolean),r[1]=r[1].slice(0,c)),i=t(o.call(this,r[1].trim(),a),a),i&&r[0]===e&&!b(i))return i;b(i)||(i=S(i)),i||=(this.logger.warn(`missed to resolve ${r[1]} for nesting ${e}`),``),s.length&&(i=s.reduce((e,t)=>this.format(e,t,n.lng,{...n,interpolationkey:r[1].trim()}),i.trim())),e=e.replace(r[0],i),this.regexp.lastIndex=0}return e}},he=e=>{let t=e.toLowerCase().trim(),n={};if(e.includes(`(`)){let r=e.split(`(`);t=r[0].toLowerCase().trim();let i=r[1].slice(0,-1);t===`currency`&&!i.includes(`:`)?n.currency||=i.trim():t===`relativetime`&&!i.includes(`:`)?n.range||=i.trim():i.split(`;`).forEach(e=>{if(e){let[t,...r]=e.split(`:`),i=r.join(`:`).trim().replace(/^'+|'+$/g,``),a=t.trim();n[a]||(n[a]=i),i===`false`&&(n[a]=!1),i===`true`&&(n[a]=!0),isNaN(i)||(n[a]=parseInt(i,10))}})}return{formatName:t,formatOptions:n}},ge=e=>{let t={};return(n,r,i)=>{let a=i;i&&i.interpolationkey&&i.formatParams&&i.formatParams[i.interpolationkey]&&i[i.interpolationkey]&&(a={...a,[i.interpolationkey]:void 0});let o=r+JSON.stringify(a),s=t[o];return s||(s=e(R(r),i),t[o]=s),s(n)}},_e=e=>(t,n,r)=>e(R(n),r)(t),ve=class{constructor(e={}){this.logger=z.create(`formatter`),this.options=e,this.init(e)}init(e,t={interpolation:{}}){this.formatSeparator=t.interpolation.formatSeparator||`,`;let n=t.cacheInBuiltFormats?ge:_e;this.formats={number:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t});return e=>n.format(e)}),currency:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t,style:`currency`});return e=>n.format(e)}),datetime:n((e,t)=>{let n=new Intl.DateTimeFormat(e,{...t});return e=>n.format(e)}),relativetime:n((e,t)=>{let n=new Intl.RelativeTimeFormat(e,{...t});return e=>n.format(e,t.range||`day`)}),list:n((e,t)=>{let n=new Intl.ListFormat(e,{...t});return e=>n.format(e)})}}add(e,t){this.formats[e.toLowerCase().trim()]=t}addCached(e,t){this.formats[e.toLowerCase().trim()]=ge(t)}format(e,t,n,r={}){if(!t||e==null)return e;let i=t.split(this.formatSeparator);if(i.length>1&&i[0].indexOf(`(`)>1&&!i[0].includes(`)`)&&i.find(e=>e.includes(`)`))){let e=i.findIndex(e=>e.includes(`)`));i[0]=[i[0],...i.splice(1,e)].join(this.formatSeparator)}return i.reduce((e,t)=>{let{formatName:i,formatOptions:a}=he(t);if(this.formats[i]){let t=e;try{let o=r?.formatParams?.[r.interpolationkey]||{},s=o.locale||o.lng||r.locale||r.lng||n;t=this.formats[i](e,s,{...a,...r,...o})}catch(e){this.logger.warn(e)}return t}else this.logger.warn(`there was no format function for ${i}`);return e},e)}},ye=(e,t)=>{e.pending[t]!==void 0&&(delete e.pending[t],e.pendingCount--)},be=class extends B{constructor(e,t,n,r={}){super(),this.backend=e,this.store=t,this.services=n,this.languageUtils=n.languageUtils,this.options=r,this.logger=z.create(`backendConnector`),this.waitingReads=[],this.maxParallelReads=r.maxParallelReads||10,this.readingCalls=0,this.maxRetries=r.maxRetries>=0?r.maxRetries:5,this.retryTimeout=r.retryTimeout>=1?r.retryTimeout:350,this.state={},this.queue=[],this.backend?.init?.(n,r.backend,r)}queueLoad(e,t,n,r){let i={},a={},o={},s={};return e.forEach(e=>{let r=!0;t.forEach(t=>{let o=`${e}|${t}`;!n.reload&&this.store.hasResourceBundle(e,t)?this.state[o]=2:this.state[o]<0||(this.state[o]===1?a[o]===void 0&&(a[o]=!0):(this.state[o]=1,r=!1,a[o]===void 0&&(a[o]=!0),i[o]===void 0&&(i[o]=!0),s[t]===void 0&&(s[t]=!0)))}),r||(o[e]=!0)}),(Object.keys(i).length||Object.keys(a).length)&&this.queue.push({pending:a,pendingCount:Object.keys(a).length,loaded:{},errors:[],callback:r}),{toLoad:Object.keys(i),pending:Object.keys(a),toLoadLanguages:Object.keys(o),toLoadNamespaces:Object.keys(s)}}loaded(e,t,n){let r=e.split(`|`),i=r[0],a=r[1];t&&this.emit(`failedLoading`,i,a,t),!t&&n&&this.store.addResourceBundle(i,a,n,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,t&&n&&(this.state[e]=0);let o={};this.queue.forEach(n=>{k(n.loaded,[i],a),ye(n,e),t&&n.errors.push(t),n.pendingCount===0&&!n.done&&(Object.keys(n.loaded).forEach(e=>{o[e]||(o[e]={});let t=n.loaded[e];t.length&&t.forEach(t=>{o[e][t]===void 0&&(o[e][t]=!0)})}),n.done=!0,n.errors.length?n.callback(n.errors):n.callback())}),this.emit(`loaded`,o),this.queue=this.queue.filter(e=>!e.done)}read(e,t,n,r=0,i=this.retryTimeout,a){if(!e.length)return a(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:t,fcName:n,tried:r,wait:i,callback:a});return}this.readingCalls++;let o=(o,s)=>{if(this.readingCalls--,this.waitingReads.length>0){let e=this.waitingReads.shift();this.read(e.lng,e.ns,e.fcName,e.tried,e.wait,e.callback)}if(o&&s&&r<this.maxRetries){setTimeout(()=>{this.read(e,t,n,r+1,i*2,a)},i);return}a(o,s)},s=this.backend[n].bind(this.backend);if(s.length===2){try{let n=s(e,t);n&&typeof n.then==`function`?n.then(e=>o(null,e)).catch(o):o(null,n)}catch(e){o(e)}return}return s(e,t,o)}prepareLoading(e,t,n={},r){if(!this.backend)return this.logger.warn(`No backend was added via i18next.use. Will not load resources.`),r&&r();b(e)&&(e=this.languageUtils.toResolveHierarchy(e)),b(t)&&(t=[t]);let i=this.queueLoad(e,t,n,r);if(!i.toLoad.length)return i.pending.length||r(),null;i.toLoad.forEach(e=>{this.loadOne(e)})}load(e,t,n){this.prepareLoading(e,t,{},n)}reload(e,t,n){this.prepareLoading(e,t,{reload:!0},n)}loadOne(e,t=``){let n=e.split(`|`),r=n[0],i=n[1];this.read(r,i,`read`,void 0,void 0,(n,a)=>{n&&this.logger.warn(`${t}loading namespace ${i} for language ${r} failed`,n),!n&&a&&this.logger.log(`${t}loaded namespace ${i} for language ${r}`,a),this.loaded(e,n,a)})}saveMissing(e,t,n,r,i,a={},o=()=>{}){if(this.services?.utils?.hasLoadedNamespace&&!this.services?.utils?.hasLoadedNamespace(t)){this.logger.warn(`did not save key "${n}" as the namespace "${t}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`);return}if(!(n==null||n===``)){if(this.backend?.create){let s={...a,isUpdate:i},c=this.backend.create.bind(this.backend);if(c.length<6)try{let i;i=c.length===5?c(e,t,n,r,s):c(e,t,n,r),i&&typeof i.then==`function`?i.then(e=>o(null,e)).catch(o):o(null,i)}catch(e){o(e)}else c(e,t,n,r,o,s)}!e||!e[0]||this.store.addResource(e[0],t,n,r)}}},W=()=>({debug:!1,initAsync:!0,ns:[`translation`],defaultNS:[`translation`],fallbackLng:[`dev`],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:`all`,preload:!1,keySeparator:`.`,nsSeparator:`:`,pluralSeparator:`_`,contextSeparator:`_`,partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:`fallback`,saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:e=>{let t={};if(typeof e[1]==`object`&&(t=e[1]),b(e[1])&&(t.defaultValue=e[1]),b(e[2])&&(t.tDescription=e[2]),typeof e[2]==`object`||typeof e[3]==`object`){let n=e[3]||e[2];Object.keys(n).forEach(e=>{t[e]=n[e]})}return t},interpolation:{escapeValue:!0,prefix:`{{`,suffix:`}}`,formatSeparator:`,`,unescapePrefix:`-`,nestingPrefix:`$t(`,nestingSuffix:`)`,nestingOptionsSeparator:`,`,maxReplaces:1e3,skipOnVariables:!0},cacheInBuiltFormats:!0}),xe=e=>(b(e.ns)&&(e.ns=[e.ns]),b(e.fallbackLng)&&(e.fallbackLng=[e.fallbackLng]),b(e.fallbackNS)&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs&&!e.supportedLngs.includes(`cimode`)&&(e.supportedLngs=e.supportedLngs.concat([`cimode`])),e),G=()=>{},Se=e=>{Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach(t=>{typeof e[t]==`function`&&(e[t]=e[t].bind(e))})},K=class e extends B{constructor(e={},t){if(super(),this.options=xe(e),this.services={},this.logger=z,this.modules={external:[]},Se(this),t&&!this.isInitialized&&!e.isClone){if(!this.options.initAsync)return this.init(e,t),this;setTimeout(()=>{this.init(e,t)},0)}}init(e={},t){this.isInitializing=!0,typeof e==`function`&&(t=e,e={}),e.defaultNS==null&&e.ns&&(b(e.ns)?e.defaultNS=e.ns:e.ns.includes(`translation`)||(e.defaultNS=e.ns[0]));let n=W();this.options={...n,...this.options,...xe(e)},this.options.interpolation={...n.interpolation,...this.options.interpolation},e.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=e.keySeparator),e.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=e.nsSeparator),typeof this.options.overloadTranslationOptionHandler!=`function`&&(this.options.overloadTranslationOptionHandler=n.overloadTranslationOptionHandler);let r=e=>e?typeof e==`function`?new e:e:null;if(!this.options.isClone){this.modules.logger?z.init(r(this.modules.logger),this.options):z.init(null,this.options);let e;e=this.modules.formatter?this.modules.formatter:ve;let t=new le(this.options);this.store=new ie(this.options.resources,this.options);let n=this.services;n.logger=z,n.resourceStore=this.store,n.languageUtils=t,n.pluralResolver=new fe(t,{prepend:this.options.pluralSeparator}),e&&(n.formatter=r(e),n.formatter.init&&n.formatter.init(n,this.options),this.options.interpolation.format=n.formatter.format.bind(n.formatter)),n.interpolator=new me(this.options),n.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},n.backendConnector=new be(r(this.modules.backend),n.resourceStore,n,this.options),n.backendConnector.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.languageDetector&&(n.languageDetector=r(this.modules.languageDetector),n.languageDetector.init&&n.languageDetector.init(n,this.options.detection,this.options)),this.modules.i18nFormat&&(n.i18nFormat=r(this.modules.i18nFormat),n.i18nFormat.init&&n.i18nFormat.init(this)),this.translator=new ce(this.services,this.options),this.translator.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.external.forEach(e=>{e.init&&e.init(this)})}if(this.format=this.options.interpolation.format,t||=G,this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){let e=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);e.length>0&&e[0]!==`dev`&&(this.options.lng=e[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn(`init: no languageDetector is used and no lng is defined`),[`getResource`,`hasResourceBundle`,`getResourceBundle`,`getDataByLanguage`].forEach(e=>{this[e]=(...t)=>this.store[e](...t)}),[`addResource`,`addResources`,`addResourceBundle`,`removeResourceBundle`].forEach(e=>{this[e]=(...t)=>(this.store[e](...t),this)});let i=x(),a=()=>{let e=(e,n)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn(`init: i18next is already initialized. You should call init just once!`),this.isInitialized=!0,this.options.isClone||this.logger.log(`initialized`,this.options),this.emit(`initialized`,this.options),i.resolve(n),t(e,n)};if(this.languages&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initAsync?a():setTimeout(a,0),i}loadResources(e,t=G){let n=t,r=b(e)?e:this.language;if(typeof e==`function`&&(n=e),!this.options.resources||this.options.partialBundledLanguages){if(r?.toLowerCase()===`cimode`&&(!this.options.preload||this.options.preload.length===0))return n();let e=[],t=t=>{t&&t!==`cimode`&&this.services.languageUtils.toResolveHierarchy(t).forEach(t=>{t!==`cimode`&&(e.includes(t)||e.push(t))})};r?t(r):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>t(e)),this.options.preload?.forEach?.(e=>t(e)),this.services.backendConnector.load(e,this.options.ns,e=>{!e&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),n(e)})}else n(null)}reloadResources(e,t,n){let r=x();return typeof e==`function`&&(n=e,e=void 0),typeof t==`function`&&(n=t,t=void 0),e||=this.languages,t||=this.options.ns,n||=G,this.services.backendConnector.reload(e,t,e=>{r.resolve(),n(e)}),r}use(e){if(!e)throw Error(`You are passing an undefined module! Please check the object you are passing to i18next.use()`);if(!e.type)throw Error(`You are passing a wrong module! Please check the object you are passing to i18next.use()`);return e.type===`backend`&&(this.modules.backend=e),(e.type===`logger`||e.log&&e.warn&&e.error)&&(this.modules.logger=e),e.type===`languageDetector`&&(this.modules.languageDetector=e),e.type===`i18nFormat`&&(this.modules.i18nFormat=e),e.type===`postProcessor`&&ae.addPostProcessor(e),e.type===`formatter`&&(this.modules.formatter=e),e.type===`3rdParty`&&this.modules.external.push(e),this}setResolvedLanguage(e){if(!(!e||!this.languages)&&![`cimode`,`dev`].includes(e)){for(let e=0;e<this.languages.length;e++){let t=this.languages[e];if(![`cimode`,`dev`].includes(t)&&this.store.hasLanguageSomeTranslations(t)){this.resolvedLanguage=t;break}}!this.resolvedLanguage&&!this.languages.includes(e)&&this.store.hasLanguageSomeTranslations(e)&&(this.resolvedLanguage=e,this.languages.unshift(e))}}changeLanguage(e,t){this.isLanguageChangingTo=e;let n=x();this.emit(`languageChanging`,e);let r=e=>{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)},i=(i,a)=>{a?this.isLanguageChangingTo===e&&(r(a),this.translator.changeLanguage(a),this.isLanguageChangingTo=void 0,this.emit(`languageChanged`,a),this.logger.log(`languageChanged`,a)):this.isLanguageChangingTo=void 0,n.resolve((...e)=>this.t(...e)),t&&t(i,(...e)=>this.t(...e))},a=t=>{!e&&!t&&this.services.languageDetector&&(t=[]);let n=b(t)?t:t&&t[0],a=this.store.hasLanguageSomeTranslations(n)?n:this.services.languageUtils.getBestMatchFromCodes(b(t)?[t]:t);a&&(this.language||r(a),this.translator.language||this.translator.changeLanguage(a),this.services.languageDetector?.cacheUserLanguage?.(a)),this.loadResources(a,e=>{i(e,a)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?a(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(a):this.services.languageDetector.detect(a):a(e),n}getFixedT(e,t,n){let r=(e,t,...i)=>{let a;a=typeof t==`object`?{...t}:this.options.overloadTranslationOptionHandler([e,t].concat(i)),a.lng=a.lng||r.lng,a.lngs=a.lngs||r.lngs,a.ns=a.ns||r.ns,a.keyPrefix!==``&&(a.keyPrefix=a.keyPrefix||n||r.keyPrefix);let o={...this.options,...a};typeof a.keyPrefix==`function`&&(a.keyPrefix=V(a.keyPrefix,o));let s=this.options.keySeparator||`.`,c;return a.keyPrefix&&Array.isArray(e)?c=e.map(e=>(typeof e==`function`&&(e=V(e,o)),`${a.keyPrefix}${s}${e}`)):(typeof e==`function`&&(e=V(e,o)),c=a.keyPrefix?`${a.keyPrefix}${s}${e}`:e),this.t(c,a)};return b(e)?r.lng=e:r.lngs=e,r.ns=t,r.keyPrefix=n,r}t(...e){return this.translator?.translate(...e)}exists(...e){return this.translator?.exists(...e)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e,t={}){if(!this.isInitialized)return this.logger.warn(`hasLoadedNamespace: i18next was not initialized`,this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn(`hasLoadedNamespace: i18n.languages were undefined or empty`,this.languages),!1;let n=t.lng||this.resolvedLanguage||this.languages[0],r=this.options?this.options.fallbackLng:!1,i=this.languages[this.languages.length-1];if(n.toLowerCase()===`cimode`)return!0;let a=(e,t)=>{let n=this.services.backendConnector.state[`${e}|${t}`];return n===-1||n===0||n===2};if(t.precheck){let e=t.precheck(this,a);if(e!==void 0)return e}return!!(this.hasResourceBundle(n,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||a(n,e)&&(!r||a(i,e)))}loadNamespaces(e,t){let n=x();return this.options.ns?(b(e)&&(e=[e]),e.forEach(e=>{this.options.ns.includes(e)||this.options.ns.push(e)}),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}loadLanguages(e,t){let n=x();b(e)&&(e=[e]);let r=this.options.preload||[],i=e.filter(e=>!r.includes(e)&&this.services.languageUtils.isSupportedCode(e));return i.length?(this.options.preload=r.concat(i),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}dir(e){if(e||=this.resolvedLanguage||(this.languages?.length>0?this.languages[0]:this.language),!e)return`rtl`;try{let t=new Intl.Locale(e);if(t&&t.getTextInfo){let e=t.getTextInfo();if(e&&e.direction)return e.direction}}catch{}let t=`ar.shu.sqr.ssh.xaa.yhd.yud.aao.abh.abv.acm.acq.acw.acx.acy.adf.ads.aeb.aec.afb.ajp.apc.apd.arb.arq.ars.ary.arz.auz.avl.ayh.ayl.ayn.ayp.bbz.pga.he.iw.ps.pbt.pbu.pst.prp.prd.ug.ur.ydd.yds.yih.ji.yi.hbo.men.xmn.fa.jpr.peo.pes.prs.dv.sam.ckb`.split(`.`),n=this.services?.languageUtils||new le(W());return e.toLowerCase().indexOf(`-latn`)>1?`ltr`:t.includes(n.getLanguagePartFromCode(e))||e.toLowerCase().indexOf(`-arab`)>1?`rtl`:`ltr`}static createInstance(t={},n){let r=new e(t,n);return r.createInstance=e.createInstance,r}cloneInstance(t={},n=G){let r=t.forkResourceStore;r&&delete t.forkResourceStore;let i={...this.options,...t,isClone:!0},a=new e(i);if((t.debug!==void 0||t.prefix!==void 0)&&(a.logger=a.logger.clone(t)),[`store`,`services`,`language`].forEach(e=>{a[e]=this[e]}),a.services={...this.services},a.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},r&&(a.store=new ie(Object.keys(this.store.data).reduce((e,t)=>(e[t]={...this.store.data[t]},e[t]=Object.keys(e[t]).reduce((n,r)=>(n[r]={...e[t][r]},n),e[t]),e),{}),i),a.services.resourceStore=a.store),t.interpolation){let e={...W().interpolation,...this.options.interpolation,...t.interpolation},n={...i,interpolation:e};a.services.interpolator=new me(n)}return a.translator=new ce(a.services,i),a.translator.on(`*`,(e,...t)=>{a.emit(e,...t)}),a.init(i,n),a.translator.options=i,a.translator.backendConnector.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},a}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}.createInstance();K.createInstance,K.dir,K.init,K.loadResources,K.reloadResources,K.use,K.changeLanguage,K.getFixedT,K.t,K.exists,K.setDefaultNamespace,K.hasLoadedNamespace,K.loadNamespaces,K.loadLanguages;var Ce={app:{name:`TTDash`,language:`Sprache`,languages:{de:`Deutsch`,en:`Englisch`}},header:{import:`Import`,upload:`Upload`,limits:`Limits`,settings:`Einstellungen`,report:`Report`,csv:`CSV`,delete:`Löschen`,help:`Hilfe & Tastenkürzel`,loaded:`Geladen`,loadedAt:`Zuletzt geladen: {{time}}`,autoLoadActive:`Auto-Load beim Start`,autoLoadAt:`Beim Start automatisch geladen: {{time}}`,versionLinkTitle:`TTDash v{{version}} auf npm öffnen`,streak:`{{count}} Tage in Folge`},emptyState:{description:"Lade ein `toktrack`- oder Legacy-JSON hoch oder starte den lokalen Auto-Import mit lokalem `toktrack`, `bunx toktrack daily --json` oder `npx --yes toktrack daily --json`.",autoImport:`Auto-Import`,uploadFile:`Datei hochladen`,openSettings:`Einstellungen & Backups`,or:`oder`},loadError:{title:`Lokaler App-Zustand konnte nicht geladen werden`,settingsDescription:`Die lokalen Einstellungen konnten nicht geladen werden. Setze sie zurück oder lade den Zustand erneut.`,usageDescription:`Die gespeicherten Nutzungsdaten konnten nicht geladen werden. Entferne die defekten Daten oder lade den Zustand erneut.`,multipleDescription:`TTDash hat Probleme sowohl in den lokalen Einstellungen als auch in den gespeicherten Nutzungsdaten gefunden. Setze die betroffenen Daten zurück und lade den Zustand erneut.`,details:`Details`,retry:`Erneut laden`,resetSettings:`Einstellungen zurücksetzen`,deleteData:`Gespeicherte Daten löschen`,settingsCorrupted:`Die lokale Einstellungsdatei ist unlesbar oder beschädigt.`,usageCorrupted:`Die lokale Nutzungsdatei ist unlesbar oder beschädigt.`},viewModes:{daily:`Tagesansicht`,monthly:`Monatsansicht`,yearly:`Jahresansicht`},periods:{day:`Tag`,days:`Tage`,month:`Monat`,months:`Monate`,year:`Jahr`,years:`Jahre`,unitDay:`Tag`,unitMonth:`Mt.`,unitYear:`Jahr`},common:{all:`Alle`,none:`Keine`,reset:`Reset`,notAvailable:`n/v`,noData:`Keine Daten`,generated:`Generiert`,view:`Ansicht`,dateRange:`Zeitraum`,month:`Monat`,provider:`Anbieter`,providers:`Anbieter`,model:`Modell`,models:`Modelle`,cost:`Kosten`,costs:`Kosten`,tokens:`Tokens`,requests:`Anfragen`,today:`Heute`,currentMonth:`Monat`,yes:`Ja`,no:`Nein`,enabled:`Aktiv`,disabled:`Inaktiv`,visible:`Sichtbar`,hidden:`Versteckt`,open:`Öffnen`,close:`Schliessen`,previousMonth:`Vorheriger Monat`,nextMonth:`Nächster Monat`,startDate:`Startdatum`,endDate:`Enddatum`,selectedProviders:`Ausgewählte Anbieter`,selectedModels:`Ausgewählte Modelle`,allProviders:`Alle Anbieter`,allModels:`Alle Modelle`,allMonths:`Alle Monate`,noFilter:`Kein Filter`,focusMonth:`Fokusmonat`,showInfo:`Info anzeigen`,expand:`Vergrössern`,expandWithTitle:`{{title}} vergrössern`,expandedCardDescription:`Erweiterte Kartenansicht mit zusätzlichen Kennzahlen und vollständigem Inhalt.`,input:`Input`,output:`Output`,cacheWrite:`Cache Write`,cacheRead:`Cache Read`,thinking:`Thinking`,requestsShort:`Anf.`,request:`Anfrage`,share:`Anteil`,top:`Top`},filterBar:{status:`Filterstatus`,viewModeLabel:`Ansichtsmodus`,focusMonthLabel:`Fokusmonat`,providersActive:`{{count}} Anbieter aktiv`,modelsActive:`{{count}} Modelle aktiv`,dateFilterActive:`Datumsfilter aktiv`,clearDate:`{{label}} zurücksetzen`,presets:{"7d":`7T`,"30d":`30T`,month:`Monat`,year:`Jahr`,all:`Alle`},until:`bis`,resetDateRange:`Zeitraum zurücksetzen`,resetAll:`Alles zurücksetzen`,providers:`Anbieter`,models:`Modelle`,resetModels:`Modelle zurücksetzen`},dashboard:{insights:{title:`Einblicke`,badge:`Verdichtete Signale`,description:`Konzentrierte Aussagen aus Kosten-, Modell- und Anfragedaten`,quickRead:`Kurzfazit`},metrics:{title:`Metriken`,badge:`10 Kennzahlen`,description:`Wichtigste KPIs im Überblick`},activity:{title:`Aktivität`,dailyDescription:`Tägliche Nutzungsübersicht`,monthlyDescription:`Monatliche Nutzungsübersicht`,yearlyDescription:`Jährliche Nutzungsübersicht`},forecastCache:{title:`Prognose & Cache`,description:`Kostenprognose und Cache-Effizienz`},costAnalysis:{title:`Kostenanalyse`,description:`Detaillierte Kostenaufschlüsselung`},tokenAnalysis:{title:`Token-Analyse`,description:`Verbrauch nach Token-Typ`},requestAnalysis:{title:`Anfragen-Analyse`,description:`Anfragen gesamt, pro Modell und im Verlauf`},advancedAnalysis:{title:`Verteilungen & Risiko`,description:`Zusätzliche Signale zu Streuung, Korrelation und Abhängigkeiten`},comparisons:{title:`Vergleiche & Anomalien`,description:`Periodenvergleich und Ausreisser`},tables:{title:`Tabellen`,description:`Detaillierte Aufschlüsselungen`},cards:{periodComparison:`Periodenvergleich`,anomalyDetection:`Anomalie-Erkennung`,costForecast:`Kostenprognose`,cacheRoi:`Cache ROI`},stats:{min:`Min`,max:`Max`,avg:`Ø`,cacheHitRate:`Cache-Hit-Rate`,totalTokens:`Gesamt-Tokens`,cacheRead:`Cache Read`,dataPoints:`Datenpunkte`,avgCostPerUnit:`Ø Kosten/{{unit}}`,total:`Gesamt`,avgPerUnit:`Ø / {{unit}}`}},metricCards:{primary:{totalCost:`Gesamtkosten`,totalTokens:`Gesamt-Tokens`,activeDays:`Aktive Tage`,topModel:`Top Modell`,cacheHitRate:`Cache-Hit-Rate`,costPerMillion:`$/1M Tokens`,requests:`Anfragen`,thinking:`Thinking`,avgPerPeriod:`{{value}}/{{unit}} im Mittel`,tokensPerRequestAvg:`{{value}} pro Anfrage im Mittel`,coverageOfDays:`{{coverage}} Abdeckung von {{days}} Tagen`,providersActive:`{{count}} Anbieter aktiv`,share:`{{value}} Anteil`,requestLead:`Führend bei Anfragen: {{value}}`,allTokensViaCacheRead:`{{value}} aller Tokens via Cache Read`,requestCountersMissing:`Keine Anfragezähler im Datensatz`,thinkingShareOfVolume:`{{value}} des gesamten Tokenvolumens`,totalCostSubtitle:`Ø {{average}}/{{unit}} · {{costPerRequest}} pro Anfrage`,totalTokensSubtitle:`{{tokensPerRequest}} pro Anfrage`,totalTokensSubtitleWithRatio:`Input/Output-Verhältnis {{ratio}}:1 · {{tokensPerRequest}} pro Anfrage`,requestsSubtitle:`Ø {{requests}} / {{unit}} · {{cost}} pro Anfrage · σ {{volatility}}`,thinkingSubtitle:`{{share}} Anteil · {{tokens}} pro Anfrage`},secondary:{mostExpensiveDay:`Teuerster Tag`,mostExpensiveMonth:`Teuerster Monat`,mostExpensiveYear:`Teuerstes Jahr`,dominantProvider:`Dominanter Anbieter`,peak7Days:`Peak 7 Tage`,avgCostPerUnit:`Ø Kosten/{{unit}}`,spread:`Spanne: {{value}}`,medianPerUnit:`Median/{{unit}}`,vsAverage:`{{direction}}{{value}}% vs. Ø`,vsAverageWithVolatility:`{{direction}}{{value}}% vs. Ø · σ Anf. {{volatility}}`,medianInfo:`Der Median zeigt den typischen Wert und ist weniger anfällig für Ausreisser als der Durchschnitt.`,requestLeader:`{{model}} · {{requests}} Anfragen`,dominantProviderSubtitle:`{{share}} Anteil · {{cost}}{{requestLeader}}`},today:{title:`Heute — {{date}}`,description:`KPIs des aktuellen Tages`,costToday:`Kosten heute`,tokensToday:`Tokens heute`,models:`Modelle`,costPerMillion:`$/1M Tokens`,cacheHitRate:`Cache-Hit-Rate`,requests:`Anfragen`,thinking:`Thinking`,vsAverageShort:`vs. Ø`,overallAverage:`Gesamt-Ø: {{value}}`,cacheShare:`{{value}} Cache-Anteil`,requestsToday:`Anfragen heute`,avgPerDay:`Ø {{value}}/Tag`,ioRatio:`Input/Output-Verhältnis: {{value}}:1`,topModel:`Top: {{value}}`,requestsSubtitle:`{{value}} / Modell · {{cost}} pro Anfrage`,tokensInsight:`{{value}} pro Anfrage`,requestsInsight:`{{value}} pro Anfrage`,requestCountersMissing:`Keine Anfragezähler`,thinkingSubtitle:`{{value}} Anteil`},month:{title:`Monat — {{date}}`,badge:`{{count}} Tage`,description:`KPIs des laufenden Monats`,costMonth:`Kosten Monat`,tokensMonth:`Tokens Monat`,activeDays:`Aktive Tage`,models:`Modelle`,costPerMillion:`$/1M Tokens`,cacheHitRate:`Cache-Hit-Rate`,requests:`Anfragen`,thinking:`Thinking`,vsPreviousMonth:`vs. Vormonat`,coverage:`{{value}} Abdeckung`,requestsInMonth:`Anfragen im Monat`,avgPerDay:`Ø {{value}}/Tag`,ioRatio:`Input/Output-Verhältnis: {{value}}:1`,topModel:`Top: {{value}}`,cacheMix:`In: {{input}} / Out: {{output}}`,costPerRequest:`{{value}} pro Anfrage`,requestsSubtitle:`Ø {{value}}/Tag · {{cost}} pro Anfrage`,requestCountersMissing:`Keine Anfragezähler`,thinkingSubtitle:`{{value}} Anteil`}},insights:{concentration:{title:`Kostenkonzentration`,summary:`{{provider}} ist aktuell der dominante Anbieter im gewählten Ausschnitt, während {{model}} den grössten Einzelhebel setzt.`,fallback:`Noch keine stabile Anbieter-Verteilung verfügbar.`,topProvider:`Top Anbieter`,topModel:`Top Modell`,topModelShare:`Top Modell Anteil`,topThreeModels:`Top 3 Modelle`},requestEconomy:{title:`Anfrage-Ökonomie`,valueLabel:`Ø Kosten pro Anfrage`,summary:`Jede Anfrage kostet im Mittel {{cost}} und verarbeitet {{tokens}}. {{leader}}`,leader:`{{model}} führt aktuell beim Anfragevolumen.`,fallback:`Der geladene Datensatz enthält keine verlässlichen Anfragezähler. Anfrage-Ökonomie ist deshalb nicht verfügbar.`,avgRequests:`Ø Anfragen/{{unit}}`,avgTokensPerRequest:`Ø Tokens / Anfrage`,costPerMillion:`$/1M Tokens`,totalRequests:`Gesamt-Anfragen`},usagePatterns:{title:`Nutzungsmuster`,summaryWithCoverage:`{{activeDays}} von {{totalDays}} Kalendertagen enthalten Aktivität im gefilterten Zeitraum. Die Anfragen schwanken dabei um {{volatility}}.`,summaryWithoutCoverage:`{{activeDays}} aktive {{unit}} im gewählten Ausschnitt.`,avgModels:`Ø Modelle/Eintrag`,providersActive:`Anbieter aktiv`,weekendShare:`Wochenend-Anteil`,thinkingShare:`Thinking Anteil`},peakWindow:{title:`Peak-Fenster`,summary:`Stärkste 7-Tage-Phase von {{start}} bis {{end}}.`,fallback:`Kein 7-Tage-Fenster verfügbar, daher Fokus auf den teuersten Einzelwert.`,peakDay:`Peak Tag`,avgPerUnit:`Ø/{{unit}}`,peak7DayAverage:`Peak 7T Ø/Tag`,signal:`Signal`,signalStrong:`stark konzentriert`,signalModerate:`moderat konzentriert`,signalWide:`breit verteilt`},quickRead:{summary:`{{provider}} trägt {{providerShare}} der Kosten, während die Top-3-Modelle {{topThreeShare}} bündeln. {{requestLeader}}`,requestLeader:`{{requestModel}} führt bei den Anfragen, {{tokenModel}} beim Tokenvolumen.`,fallback:`Für den aktuellen Filterausschnitt sind noch nicht genug Daten für eine stabile Zusammenfassung vorhanden.`}},charts:{costOverTime:{title:`Kosten im Zeitverlauf + 7-Tage Ø`,subtitle:`Tageskosten mit 7-Tage gleitendem Durchschnitt`,summary:`Letzter Wert {{latest}} · Peak {{peak}} am {{date}}`,cost:`Kosten`,movingAverage:`7-Tage Ø`},costByModel:{title:`Kosten nach Modell`,subtitle:`Kostenverteilung nach Modell`,total:`Gesamt`},costByModelOverTime:{title:`Kosten nach Modell im Zeitverlauf`,subtitle:`Pro Modell über die Zeit`,topDriver:`Top Treiber: {{model}} · {{total}} kumuliert`,movingAverageHeading:`7-Tage Durchschnitt pro Modell`,movingAverageSuffix:`Ø`},cumulativeCost:{title:`Kumulative Kosten`,total:`Gesamt: {{value}}`,cumulative:`Kumulativ`,projection:`Projektion`},tokensOverTime:{title:`Tokens im Zeitverlauf`,subtitle:`Alle Token-Typen mit 7-Tage Ø`,allTypes:`Gesamt-Tokens (alle Typen)`,totalTokens:`Gesamt-Tokens`,movingAverage:`7-Tage Ø`,cacheTokens:`Cache Tokens`,inputOutputTokens:`Input / Output Tokens`,thinkingTokens:`Thinking Tokens`,averageSuffix:`Ø`},requestsOverTime:{title:`Anfragen im Zeitverlauf`,subtitle:`Anfragen gesamt, nach Modell und mit 7-Tage-Ø`,summary:`Gesamt {{total}} · Peak {{peak}} am {{date}}`,averagePerUnit:`Ø / {{unit}}`,trend:`Trend Ø`,movingAverage:`7-Tage Ø`,trendHeading:`Gleitender Durchschnitt pro Modell`,movingAverageHeading:`7-Tage Durchschnitt pro Modell`,totalMovingAverage:`Gesamt {{label}}`,requestsByModelTotal:`Anfragen nach Modell gesamt`,requestsInRange:`Anfragen im gewählten Zeitraum`,total:`Gesamt`,topModel:`Top Modell`,topShare:`Top Share`,totalRequestsSeries:`Gesamt-Anfragen`},requestCacheHitRate:{title:`Cache-Hit-Rate nach Modell`,subtitle:`Gesamt {{total}} · 7-Tage-Ø {{trailing}}`,totalRate:`Gesamt`,trailing7Rate:`7-Tage-Ø`,trendRate:`Trend-Ø`,topModel:`Top Modell`,models:`Modelle`,total:`Gesamt`,timelineHeading:`Cache-Hit-Rate im Zeitverlauf / {{unit}}`,modelBreakdownHeading:`Aktueller Modell-Snapshot`},heatmap:{costTitle:`Kosten-Heatmap`,requestsTitle:`Anfragen-Heatmap`,tokensTitle:`Token-Heatmap`,cellLabel:`{{date}}: {{value}}`,costEmpty:`Kosten-Heatmap nur in der Tagesansicht verfügbar`,requestsEmpty:`Anfragen-Heatmap nur in der Tagesansicht verfügbar`,tokensEmpty:`Token-Heatmap nur in der Tagesansicht verfügbar`,switchToDaily:`Wechsle zur Tagesansicht für die Kalender-Heatmap`,less:`Weniger`,more:`Mehr`},tokenTypes:{title:`Token-Typen`,subtitle:`Verteilung der Token-Typen`,total:`Gesamt`},modelMix:{title:`Modell-Mix`,subtitle:`Kostenanteil pro Modell über die Zeit`},distribution:{title:`Verteilungen`,requiresData:`Für Verteilungen werden mindestens 2 Datenpunkte im aktuellen Filter benötigt.`,costPerPeriod:`Kosten je {{period}}`,requestsPerPeriod:`Anfragen je {{period}}`,tokensPerRequest:`Tokens pro Anfrage`,interval:`Intervall`,dataPoints:`Datenpunkte`,buckets:`Buckets`},correlation:{title:`Korrelationen`,requiresData:`Für Korrelationen werden mindestens 2 Datenpunkte im aktuellen Filter benötigt.`,points:`{{count}} Punkte`,requestsVsCost:`Anfragen vs. Kosten`,cacheVsCostPerRequest:`Cache-Rate vs. Kosten / Anfrage`,requestsAxis:`Anfragen`,requestsLabel:`Anfragen`,tokensLabel:`Tokens`,costPerRequestAxis:`Kosten / Anfrage`,cost:`Kosten`,costPerRequest:`Kosten / Anfrage`,cacheRate:`Cache-Rate`,strongRequestCost:`Starker Zusammenhang: Mehr Anfragen treiben die Kosten sichtbar.`,mediumRequestCost:`Moderater Zusammenhang zwischen Last und Kosten.`,weakRequestCost:`Schwacher Zusammenhang: Kosten werden stärker von Modellmix und Tokenlast geprägt.`,negativeCache:`Negativer Zusammenhang: Höhere Cache-Rate senkt tendenziell die Kosten pro Anfrage.`,neutralCache:`Kaum linearer Effekt: Cache wirkt, aber nicht allein entscheidend.`,positiveCache:`Positiver Zusammenhang: Hohe Cache-Raten fallen hier nicht automatisch mit niedrigen Kosten pro Anfrage zusammen.`},costByWeekday:{title:`Kosten nach Wochentag`,subtitle:`Peak: {{peak}} · Low: {{low}} · Wochenende {{share}}`,averageCost:`Ø Kosten`},tokenEfficiency:{title:`Token-Effizienz ($/1M)`,subtitle:`Ø {{value}}/1M Tokens`,series:`$/1M Tokens`,movingAverage:`7T-Ø`}},risk:{title:`Konzentrationsrisiko`,modelDependency:`Modell-Abhängigkeit`,providerDependency:`Provider-Abhängigkeit`,high:`hoch`,medium:`mittel`,low:`niedrig`,modelHint:`HHI {{value}} · Hohe Werte sprechen für wenige dominante Modelle.`,providerHint:`HHI {{value}} · Zeigt die Abhängigkeit von einzelnen Anbietern.`},requestQuality:{title:`Anfragequalität`,tokensPerRequest:`Tokens / Anfrage`,costPerRequest:`Kosten / Anfrage`,cachePerRequest:`Cache / Anfrage`,thinkingPerRequest:`Thinking / Anfrage`,tokensHint:`Durchschnittliche Tokenlast pro Anfrage`,costHint:`Direkte Kosten pro Anfrage`,cacheHint:`Gelesene Cache-Tokens pro Anfrage`,thinkingHint:`Thinking-Tokens pro Anfrage`,requestDensity:`Anfragedichte`,averagePerActiveUnit:`Ø pro aktivem {{unit}}`,cacheHitRate:`Cache-Hit-Rate`,cacheHitHint:`Direkt aus Cache-Read relativ zu allen Tokens`,inputOutput:`Input / Output`,inputOutputHint:`Drift zwischen eingehenden und erzeugten Tokens`,topRequestModel:`Top-Anfragemodell`,noRequestLeader:`Kein führendes Anfragemodell`},forecast:{noData:`Keine Daten verfügbar`,noForecast:`Keine Prognose verfügbar`,requiresTwoDays:`Mindestens 2 Tage mit Daten benötigt`,avgMonthlyCost:`Ø Monatskosten`,avgYearlyCost:`Ø Jahreskosten`,totalOverPeriods:`Gesamt: {{total}} über {{count}} {{unit}}`,monthEndForecast:`Prognose Monatsende`,low:`niedrig`,medium:`mittel`,high:`hoch`,soFar:`Bisher: {{value}}`,remainingDays:`Resttage: {{count}}`,projectedPerDay:`Prognose {{value}}/Tag`,vsLastWeek:`vs. Vorwoche`,chartTitle:`Kostenprognose aktueller Monat`,chartSubtitle:`Monatsend-Prognose auf Basis geglätteter Kalender-Tageskosten`,lowerBound:`Untere Spanne`,uncertaintyBand:`Unsicherheitsband`,actualCost:`Ist-Kosten`,projection:`Prognose`},cacheRoi:{title:`Cache-Ersparnis (ROI)`,noData:`Keine Daten verfügbar`,heuristicFallback:`Für {{count}} {{modelsLabel}} ohne hinterlegte Preistabelle nutzt die ROI-Schätzung einen Heuristik-Fallback.`,model:`Modell`,models:`Modelle`,withoutCache:`Ohne Cache`,withCache:`Mit Cache`,withCacheActual:`Mit Cache (tatsächlich)`,savings:`Ersparnis`,avgCostPerUnit:`Ø Kosten/{{unit}}`,paid:`Bezahlt`,saved:`Gespart`},comparison:{title:`Perioden-Vergleich`,notEnoughData:`Nicht genügend Daten für einen Vergleich`,requiresDays:`Mindestens 7 Tage benötigt (aktuell: {{count}})`,thisWeek:`Diese Woche`,lastWeek:`Letzte Woche`,thisMonth:`Dieser Monat`,lastMonth:`Letzter Monat`,week:`Woche`,month:`Monat`,metric:`Metrik`,delta:`Delta`,cost:`Kosten`,tokens:`Tokens`,avgPerDay:`Ø/Tag`,cacheRate:`Cache-Rate`,days:`Tage`},anomaly:{title:`Auffällige {{period}}`,none:`Keine Anomalien erkannt`,withinStdDev:`Alle Kosten liegen innerhalb von 2 Standardabweichungen`,description:`{{period}} mit Kosten >2 Standardabweichungen vom Mittelwert ({{mean}} ± {{stdDev}})`,critical:`kritisch`},tables:{modelEfficiency:{title:`Modell-Effizienz`,count:`{{count}} Modelle`,topModel:`Top Modell`,mostEfficient:`Effizientestes Modell`,totalRequests:`Gesamt-Anfragen`,topModelTokens:`Top Modell Tokens`,share:`{{value}} Anteil`,perModel:`{{value}} / Modell`,more:`+{{count}} weitere`,model:`Modell`,cost:`Kosten`,tokens:`Tokens`,shareShort:`Anteil`,req:`Anfragen`,reqShare:`Anfragen %`,costPerReq:`Kosten / Anfrage`,tokensPerReq:`Tokens / Anfrage`,cacheShare:`Cache %`,thinkingShare:`Think %`,avgPerUnit:`Ø/{{unit}}`},providerEfficiency:{title:`Anbieter-Effizienz`,count:`{{count}} Anbieter`,leadProvider:`Führender Anbieter`,mostEfficient:`Effizientester Anbieter`,totalRequests:`Gesamt-Anfragen`,share:`{{value}} Anteil`,perProvider:`{{value}} / Anbieter`,avgPerUnit:`Ø/{{unit}}`,provider:`Anbieter`,cost:`Kosten`,shareShort:`Anteil`,req:`Anfragen`,tokens:`Tokens`,costPerReq:`Kosten / Anfrage`,costPerMillion:`$/1M`,cacheShare:`Cache %`},recentDays:{daysDetail:`Letzte Tage im Detail`,monthsDetail:`Monate im Detail`,yearsDetail:`Jahre im Detail`,showing:`Zeige {{shown}} von {{total}} {{unit}}`,showLess:`Weniger anzeigen`,showAll:`Alle anzeigen`,totalCost:`Gesamtkosten`,totalTokens:`Gesamt-Tokens`,requests:`Anfragen`,cacheReadShare:`Cache Read Anteil`,peak:`Peak`,previousDay:`Vortag`,avg7d:`7T-Ø`,reqAvg:`Anfragen-Ø`,date:`Datum`,cost:`Kosten`,tokens:`Tokens`,models:`Modelle`}},helpPanel:{projectLinks:{title:`Projekt-Links`,description:`Öffne das veröffentlichte npm-Paket für v{{version}}, das GitHub-Repository oder den Issue-Tracker.`,npm:`npm`,github:`GitHub`,issues:`GitHub Issues`},chartsAndFeatures:`Charts`,dashboardSectionsTitle:`Dashboard-Sektionen`,featuresTitle:`Features`,tablesTitle:`Tabellen`,metricLabels:{totalCost:`Gesamtkosten`,totalTokens:`Tokens gesamt`,activeDays:`Aktive Tage`,topModel:`Top-Modell`,cacheHitRate:`Cache-Hit-Rate`,costPerMillion:`Kosten / 1M Tokens`,mostExpensiveDay:`Teuerster Tag`,cheapestDay:`Günstigster Tag`,avgCostPerDay:`Ø Kosten / Tag`,outputTokens:`Output-Tokens`},chartLabels:{costOverTime:`Kosten über Zeit`,costByModel:`Kosten nach Modell`,costByModelOverTime:`Kosten/Modell über Zeit`,cumulativeCost:`Kumulative Kosten`,costByWeekday:`Kosten nach Wochentag`,tokensOverTime:`Tokens über Zeit`,requestsOverTime:`Anfragen im Zeitverlauf`,requestCacheHitRate:`Cache-Hit-Rate nach Modell`,tokenTypes:`Token-Typen`,tokenEfficiency:`Token-Effizienz`,modelMix:`Modell-Mix`,distributionAnalysis:`Verteilungen`,correlationAnalysis:`Korrelationen`,heatmap:`Kosten-Heatmap`,requestHeatmap:`Anfragen-Heatmap`,tokenHeatmap:`Token-Heatmap`,forecast:`Prognose`,cacheROI:`Cache-ROI`,providerLimitProgress:`Anbieter-Limit-Auslastung`,providerSubscriptionMix:`Anbieter-Abos vs. API-Kosten`,providerLimitTimeline:`Anbieterlimits im Zeitverlauf`,periodComparison:`Periodenvergleich`,anomalyDetection:`Anomalie-Erkennung`,cellLabel:`{{date}}: {{value}}`},sectionLabels:{insights:`Einblicke`,metrics:`Metriken`,today:`Heute`,currentMonth:`Monat`,activity:`Aktivität`,forecastCache:`Prognose & Cache`,costAnalysis:`Kostenanalyse`,tokenAnalysis:`Token-Analyse`,requestAnalysis:`Anfragen-Analyse`,advancedAnalysis:`Verteilungen & Risiko`,comparisons:`Vergleiche & Anomalien`,tables:`Tabellen`,limits:`Limits & Abonnements`},featureLabels:{requestQuality:`Anfragequalität`,providerLimits:`Anbieterlimits`,concentrationRisk:`Konzentrationsrisiko`,providerEfficiency:`Anbieter-Effizienz`,modelEfficiency:`Modell-Effizienz`,recentDays:`Zeiträume im Detail`}},autoImportModal:{title:`Toktrack Auto-Import`,description:"Importiert lokale Nutzungsdaten automatisch via lokalem `toktrack`, `bunx` oder `npm exec` und speichert sie nur auf diesem Gerät.",connecting:`Verbinde...`,checkingTool:`Prüfe {{tool}}...`,toolFound:`{{tool}} gefunden ({{method}}, v{{version}})`,toolNotFound:`{{tool}} nicht gefunden`,importedDays:`{{days}} Tage importiert ({{cost}} USD)`,checkingPrerequisites:`Prüfe Voraussetzungen...`,importingData:`Importiere Daten...`,startingLocalImport:`Starte lokalen toktrack-Import...`,loadingUsageData:`Lade Nutzungsdaten via {{command}}...`,processingUsageData:`Verarbeite Nutzungsdaten... ({{seconds}}s)`,serverConnectionLost:`Verbindung zum Server verloren.`,autoImportRunning:`Ein Auto-Import läuft bereits. Bitte warten.`,noRunnerFound:`Kein lokales toktrack, Bun oder npm exec gefunden.`,errorPrefix:`Fehler: {{message}}`,loadedDays:`{{days}} Tage geladen ({{cost}} USD)`,errorOccurred:`Fehler aufgetreten`,close:`Schliessen`},commandPalette:{title:`Command Palette`,description:`Tastaturgesteuerte Befehlsauswahl für Navigation und Aktionen im ttdash Dashboard.`,placeholder:`Befehl suchen...`,empty:`Kein Befehl gefunden.`,groups:{actions:`Aktionen`,filters:`Filter & Ansicht`,navigation:`Navigation`,view:`Ansicht`,language:`Sprache`,help:`Hilfe`,providers:`Anbieter`,models:`Modelle`},commands:{autoImport:{label:`Auto-Import starten`,description:`Lokalen toktrack Import ausführen`},openSettings:{label:`Einstellungen öffnen`,description:`Backups, App-Optionen und Anbieterlimits verwalten`},exportCsv:{label:`CSV exportieren`,description:`Aktuell gefilterte Daten exportieren`},generateReport:{label:`PDF-Report generieren`,labelLoading:`PDF-Report wird generiert`,description:`Aktuell gefilterte Daten als PDF exportieren`},upload:{label:`JSON hochladen`,description:`toktrack oder Legacy JSON importieren`},delete:{label:`Daten löschen`,description:`Lokalen Datensatz entfernen`},viewDaily:{label:`Zur Tagesansicht wechseln`,description:`Daten pro Tag anzeigen`},viewMonthly:{label:`Zur Monatsansicht wechseln`,description:`Daten pro Monat anzeigen`},viewYearly:{label:`Zur Jahresansicht wechseln`,description:`Daten pro Jahr anzeigen`},preset7d:{label:`Zeitraum: letzte 7 Tage`,description:`Setzt den Datumsfilter auf 7 Tage`},preset30d:{label:`Zeitraum: letzte 30 Tage`,description:`Setzt den Datumsfilter auf 30 Tage`},presetMonth:{label:`Zeitraum: aktueller Monat`,description:`Setzt den Datumsfilter auf den laufenden Monat`},presetYear:{label:`Zeitraum: aktuelles Jahr`,description:`Setzt den Datumsfilter auf das laufende Jahr`},presetAll:{label:`Zeitraum: alle Daten`,description:`Entfernt Preset-Zeitraumfilter`},clearProviders:{label:`Anbieterfilter zurücksetzen`,description:`Alle aktiven Anbieterfilter entfernen`},clearModels:{label:`Modellfilter zurücksetzen`,description:`Alle aktiven Modellfilter entfernen`},clearDates:{label:`Datumsfilter zurücksetzen`,description:`Start- und Enddatum entfernen`},resetAll:{label:`Alle Filter zurücksetzen`,description:`Den Standardzustand der Dashboard-Filter wiederherstellen`},scrollTop:{label:`Nach oben scrollen`,description:`Zum Seitenanfang springen`},scrollBottom:{label:`Nach unten scrollen`,description:`Zum Seitenende springen`},filters:{label:`Zu Filtern`,description:`Springt zur Filterleiste`},goToSection:{label:`Zu {{section}}`,description:`Springt zur Sektion {{section}}`},insights:{label:`Zu Einblicke`,description:`Springt zur Executive Summary`},metrics:{label:`Zu Metriken`,description:`Springt zu den KPI-Karten`},today:{label:`Zu Heute`,description:`Springt zu den KPIs des aktuellen Tages`},month:{label:`Zu Monat`,description:`Springt zu den KPIs des aktuellen Monats`},activity:{label:`Zu Aktivität`,description:`Springt zur Aktivitäts-Heatmap`},forecastCache:{label:`Zu Prognose & Cache`,description:`Springt zu Forecast und Cache ROI`},limits:{label:`Zu Limits & Abonnements`,description:`Springt zur Limits-Sektion`},charts:{label:`Zu Kostenanalyse`,description:`Springt zu den Kostencharts`},tokenAnalysis:{label:`Zu Token-Analyse`,description:`Springt zu Token-Charts und Verteilungen`},requestAnalysis:{label:`Zu Anfragen-Analyse`,description:`Springt zu Anfragen im Zeitverlauf und zur Anfragen-Verteilung`},comparisons:{label:`Zu Vergleiche & Anomalien`,description:`Springt zu Periodenvergleich und Auffälligkeiten`},tables:{label:`Zu Tabellen`,description:`Springt zu den Detailtabellen`},themeLight:{label:`Light Mode aktivieren`,description:`Zwischen hellem und dunklem Theme wechseln`},themeDark:{label:`Dark Mode aktivieren`,description:`Zwischen hellem und dunklem Theme wechseln`},languageGerman:{label:`Auf Deutsch wechseln`,description:`Die Dashboard-Sprache auf Deutsch umstellen`},languageEnglish:{label:`Auf Englisch wechseln`,description:`Die Dashboard-Sprache auf Englisch umstellen`},help:{label:`Hilfe & Tastenkürzel öffnen`,description:`Öffnet die Hilfeübersicht`}}},settings:{modal:{title:`Einstellungen`,description:`Verwalte App-Backups, gespeicherte Daten und Anbieterlimits an einem Ort.`,languageTitle:`Dashboard-Sprache`,languageDescription:`Lege fest, welche Sprache im Dashboard, in Dialogen und in Reports verwendet wird.`,dataStatus:`Datenstatus`,lastLoaded:`Zuletzt geladen`,loadedVia:`Geladen über`,cliAutoLoad:`CLI Auto-Load`,defaultFiltersTitle:`Standardfilter fürs Dashboard`,defaultFiltersDescription:`Lege den Filterzustand fest, der beim Öffnen des Dashboards und beim Zurücksetzen verwendet wird.`,defaultViewMode:`Standardansicht`,defaultDateRange:`Standardzeitraum`,filterProviders:`Standard-Anbieterfilter`,filterModels:`Standard-Modellfilter`,noModels:`Keine Modelle im geladenen Report gefunden.`,sectionVisibilityTitle:`Sichtbare Dashboard-Sektionen`,sectionVisibilityDescription:`Steuere, welche Sektionen im Dashboard gerendert werden und in welcher Reihenfolge sie erscheinen.`,sectionOrderHint:`Ziehe die Sektionen per Drag and Drop in die gewünschte Reihenfolge. Die aktuelle Reihenfolge ist das Standardlayout.`,positionLabel:`Position {{position}} von {{total}}`,moveSectionUp:`{{section}} nach oben verschieben`,moveSectionDown:`{{section}} nach unten verschieben`,settingsBackupTitle:`Einstellungen sichern`,settingsBackupDescription:`Exportiert und importiert Sprache, Theme, Limits und die gespeicherten Lade-Metadaten als versioniertes Backup.`,dataBackupTitle:`Daten sichern`,dataBackupDescription:`Exportiert den lokal gespeicherten Nutzungsstand als Backup und importiert Backups konservativ zurück.`,dataImportPolicy:`Beim Datenimport werden nur fehlende Tage ergänzt. Bestehende Tage mit abweichenden Werten bleiben lokal erhalten und werden als Konflikt gemeldet.`,dataImportReplaceHint:`Wenn du einen Datensatz vollständig ersetzen willst, nutze weiter den normalen JSON-Upload im Header.`,providerLimitsTitle:`Anbieterlimits`,providerLimitsDescription:`Definiere Abo und Monatslimit pro Anbieter. Nur Anbieter aus dem aktuell geladenen Report sind editierbar.`,noProviders:`Keine Anbieter im geladenen Report gefunden.`,exportSettings:`Einstellungen exportieren`,importSettings:`Einstellungen importieren`,exportData:`Daten exportieren`,importData:`Daten importieren`,close:`Schliessen`,save:`Speichern`,viewModes:{daily:`Täglich`,monthly:`Monatlich`,yearly:`Jährlich`},datePresets:{all:`Alle Daten`,"7d":`Letzte 7 Tage`,"30d":`Letzte 30 Tage`,month:`Aktueller Monat`,year:`Aktuelles Jahr`},sources:{file:`Datei-Upload`,"auto-import":`Auto-Import`,"cli-auto-load":`CLI Auto-Load`,unknown:`Unbekannt`}}},drillDown:{description:`Detaillierte Tagesansicht mit Token-Verteilung, Modellanteilen, Anfragen und Thinking-Tokens.`,cacheRate:`Cache-Rate`,tokensPerRequest:`Tokens / Anfrage`,costPerRequest:`Kosten / Anfrage`,costRank:`Kosten-Rang`,requestRank:`Anfragen-Rang`,topRequestModel:`Dominant nach Anfragen`,costVsAverage7d:`Kosten vs. 7T-Ø`,requestsVsAverage7d:`Anfragen vs. 7T-Ø`,tokenDistribution:`Token-Verteilung`,requestCountShort:`{{count}} Anfragen`,modelRequestSummary:`{{costPerRequest}} / Anfrage · {{tokensPerRequest}} / Anfrage`,noRequests:`Keine Anfragen`,tokenSegments:{cacheRead:`Cache Read`,cacheWrite:`Cache Write`}},chartCard:{expandedDescription:`Erweiterte Chart-Ansicht mit Kennzahlenübersicht und optionalem CSV-Export.`,exportCsv:`CSV exportieren`},customTooltip:{total:`Gesamt`,delta:`Delta`,vsPrevious:`vs. vorher`,vsAverage:`vs. Ø`},limits:{sectionTitle:`Limits & Abonnements`,sectionDescription:`Budget-Risiko getrennt von Abo-Wirkung im aktuellen Filterkontext`,providersBadge:`{{count}} Anbieter`,warningBanner:`{{count}} Anbieter haben ihr Monatslimit im aktuellen Ausschnitt erreicht oder überschritten.`,cards:{atLimit:`Anbieter am Limit`,nearLimit:`Nahe am Limit`,subscriptionVolume:`Abo-Volumen`,subscriptionValue:`Abo-Mehrwert`,nearLimitHint:`ab 80% Auslastung`,subscriptionVolumeHint:`fixe Kosten / Monat`,subscriptionValueHint:`Nutzung über dem Abo`,noMonth:`Kein Monat`},statuses:{limitExceeded:`Limit überschritten`,budgetTight:`Budget angespannt`,budgetStable:`Budget stabil`,noLimit:`Kein Limit gesetzt`,noSubscription:`Kein Abo`,subscriptionPaysOff:`Abo zahlt sich aus`,belowSubscription:`Noch unter dem Abo`},badge:{limit:`{{value}}% Limit`,subscription:`{{value}}% Abo`,open:`Offen`},tracks:{budgetTitle:`Budget-Status je Anbieter`,budgetSubtitle:`Jeder Track zeigt pro Anbieter direkt den Abstand bis zum Limit oder den bereits eingetretenen Überzug`,budgetNoMonth:`Kein Monat im aktuellen Ausschnitt`,subscriptionTitle:`Abo-Status je Anbieter`,subscriptionSubtitle:`Jeder Track zeigt pro Anbieter direkt den Abstand zum Break-even oder den bereits erreichten Mehrwert`,subscriptionNoMonth:`Kein Monat im aktuellen Ausschnitt`,portfolioTitle:`Portfolio-Entwicklung`,portfolioSubtitle:`Monatlicher Verlauf von Nutzung, konfigurierten Limits und Abo-Wirkung`,usage:`Nutzung`,limit:`Limit`,limits:`Limits`,subscription:`Abo`,subscriptions:`Abos`,breakEven:`Break-even`,currentlyUsed:`Aktuell verbraucht`,remainingToLimit:`Bis Limit offen`,alreadyOverLimit:`Schon darüber`,remainingToBreakEven:`Bis Break-even offen`,alreadyAboveBreakEven:`Schon darüber`,usageFocusMonth:`Kosten Fokusmonat`,limitSubscription:`Limit / Abo`,budgetRisk:`Budget-Risiko`,subscriptionEffect:`Abo-Wirkung`,stillToLimit:`Noch {{value}} bis zum Limit`,alreadyAboveLimit:`Schon {{value}} über Limit`,stillToBreakEven:`Noch {{value}} bis Break-even`,alreadyAboveBreakEvenText:`Schon {{value}} über Break-even`,noSubscriptionSet:`Kein Abo gesetzt`},modal:{title:`Anbieterlimits`,description:`Definiere pro Anbieter Abo und Monatslimit. Nur Anbieter aus dem aktuell geladenen Report sind editierbar. Ein Limit von 0 bedeutet kein Limit.`,dataStatus:`Datenstatus`,lastLoaded:`Zuletzt geladen`,loadedVia:`Geladen über`,cliAutoLoad:`CLI Auto-Load`,noProviders:`Keine Anbieter im geladenen Report gefunden.`,hasSubscription:`Abo vorhanden`,subscriptionPerMonth:`Abo $/Monat`,monthlyLimit:`Monatslimit $`,close:`Schliessen`,save:`Speichern`,sources:{file:`Datei-Upload`,"auto-import":`Auto-Import`,"cli-auto-load":`CLI Auto-Load`,unknown:`Unbekannt`}}},report:{title:`TTDash Report`,common:{notAvailable:`n/v`},header:{eyebrow:`TTDash PDF-Bericht`},summary:{peakPeriod:`Spitzenzeitraum`},sections:{overview:`Überblick`,insights:`Wichtigste Erkenntnisse`,filters:`Filter`,modelsProviders:`Modelle & Anbieter`,recentPeriods:`Letzte Zeiträume`,interpretation:`Interpretation`},fields:{dateRange:`Zeitraum`,view:`Ansicht`,generated:`Generiert`,month:`Monat`,selectedProviders:`Ausgewählte Anbieter`,selectedModels:`Ausgewählte Modelle`,startDate:`Startdatum`,endDate:`Enddatum`},filters:{all:`Alle`,noFilter:`Kein Filter`,andMore:`+{{count}} weitere`},tables:{topModels:`Top-Modelle`,providers:`Anbieter`,columns:{model:`Modell`,provider:`Anbieter`,cost:`Kosten`,tokens:`Tokens`,requests:`Anfragen`,period:`Zeitraum`}},charts:{costTrend:`Kostenverlauf`,topModels:`Top-Modelle nach Kosten`,tokenTrend:`Token-Mix pro Zeitraum`,costTrendAlt:`Liniendiagramm der Report-Kosten pro Zeitraum.`,costTrendSummary:`Letzter Wert {{latest}}. Peak {{peak}} am {{date}}.`,topModelsAlt:`Horizontales Balkendiagramm der teuersten Modelle im Report.`,topModelsSummary:`{{model}} führt mit {{cost}} und {{share}} der Report-Kosten.`,topModelsFullNames:`Vollständige Diagramm-Labels: {{names}}.`,tokenTrendAlt:`Gestapeltes Balkendiagramm des Token-Mix pro Report-Zeitraum.`,tokenTrendSummary:`Gesamt {{total}}. Höchstes Token-Volumen {{peak}} am {{date}}.`,noDataSummary:`Nicht genug Daten für eine belastbare Diagramm-Zusammenfassung.`},interpretation:{summary:`Dieser Report umfasst {{days}} Rohdaten-Tage und {{periods}} aggregierte Zeiträume. Spitzenzeitraum: {{peak}}. Top-Modell: {{topModel}}. Führender Anbieter: {{topProvider}}.`,footer:`Erstellt mit TTDash v{{version}} und serverseitiger Typst-Kompilierung.`},insights:{coverageTitle:`Datenbasis`,coverageBody:`Dieser Report basiert auf einer schmalen Datenbasis mit {{days}} Rohdaten-Tagen und {{periods}} aggregierten Zeiträumen. Trend-Aussagen sollten vorsichtig gelesen werden.`,providerTitle:`Anbieter-Konzentration`,providerBody:`{{provider}} steht für {{share}} der gesamten Report-Kosten.`,cacheTitle:`Cache-Beitrag`,cacheBody:`Cache-Reads machen im gewählten Zeitraum {{share}} der Token-Aktivität aus.`,peakWindowTitle:`Stärkstes 7-Tage-Fenster`,peakWindowBody:`Das stärkste rollierende 7-Tage-Fenster lag zwischen {{start}} und {{end}} mit insgesamt {{cost}} Kosten.`}},api:{fetchUsageFailed:`Fehler beim Laden der Daten`,fetchSettingsFailed:`Fehler beim Laden der Einstellungen`,uploadFailed:`Upload fehlgeschlagen`,deleteFailed:`Löschen fehlgeschlagen`,deleteSettingsFailed:`Einstellungen konnten nicht zurückgesetzt werden`,importUsageFailed:`Datenimport fehlgeschlagen`,importSettingsFailed:`Einstellungs-Import fehlgeschlagen`,saveSettingsFailed:`Einstellungen konnten nicht gespeichert werden`,pdfFailed:`PDF-Generierung fehlgeschlagen`},toasts:{fileLoaded:`Datei {{name}} erfolgreich geladen`,fileReadFailed:`Datei konnte nicht gelesen werden`,dataDeleted:`Daten gelöscht`,csvExported:`CSV exportiert`,dataImported:`Daten erfolgreich importiert`,settingsExported:`Einstellungs-Backup exportiert`,dataExported:`Daten-Backup exportiert`,noDataToExport:`Keine Daten zum Exportieren vorhanden`,settingsImported:`Einstellungen aus {{name}} importiert`,settingsReset:`Einstellungen zurückgesetzt`,settingsSaved:`Einstellungen gespeichert`,dataBackupImported:`Backup importiert: {{added}} neue Tage ergänzt, {{unchanged}} identische Tage übersprungen`,dataBackupImportedWithConflicts:`Backup importiert: {{added}} neue Tage ergänzt, {{conflicts}} Konflikttage lokal beibehalten`}},we={app:{name:`TTDash`,language:`Language`,languages:{de:`German`,en:`English`}},header:{import:`Import`,upload:`Upload`,limits:`Limits`,settings:`Settings`,report:`Report`,csv:`CSV`,delete:`Delete`,help:`Help & shortcuts`,loaded:`Loaded`,loadedAt:`Last loaded: {{time}}`,autoLoadActive:`Auto-load on start`,autoLoadAt:`Automatically loaded on start: {{time}}`,versionLinkTitle:`Open TTDash v{{version}} on npm`,streak:`{{count}}D streak`},emptyState:{description:"Upload a `toktrack` or legacy JSON file, or start local auto-import with local `toktrack`, `bunx toktrack daily --json`, or `npx --yes toktrack daily --json`.",autoImport:`Auto import`,uploadFile:`Upload file`,openSettings:`Settings & backups`,or:`or`},loadError:{title:`Could not load local app state`,settingsDescription:`The local settings could not be loaded. Reset them or retry the load.`,usageDescription:`The stored usage data could not be loaded. Remove the broken data or retry the load.`,multipleDescription:`TTDash found problems in both local settings and stored usage data. Reset the affected state and retry the load.`,details:`Details`,retry:`Retry load`,resetSettings:`Reset settings`,deleteData:`Delete stored data`,settingsCorrupted:`The local settings file is unreadable or corrupted.`,usageCorrupted:`The local usage data file is unreadable or corrupted.`},viewModes:{daily:`Daily view`,monthly:`Monthly view`,yearly:`Yearly view`},periods:{day:`day`,days:`days`,month:`month`,months:`months`,year:`year`,years:`years`,unitDay:`day`,unitMonth:`mo.`,unitYear:`year`},common:{all:`All`,none:`None`,reset:`Reset`,notAvailable:`n/a`,noData:`No data`,generated:`Generated`,view:`View`,dateRange:`Date range`,month:`Month`,provider:`Provider`,providers:`Providers`,model:`Model`,models:`Models`,cost:`Cost`,costs:`Costs`,tokens:`Tokens`,requests:`Requests`,today:`Today`,currentMonth:`Month`,yes:`Yes`,no:`No`,enabled:`Enabled`,disabled:`Disabled`,visible:`Visible`,hidden:`Hidden`,open:`Open`,close:`Close`,previousMonth:`Previous month`,nextMonth:`Next month`,startDate:`Start date`,endDate:`End date`,selectedProviders:`Selected providers`,selectedModels:`Selected models`,allProviders:`All providers`,allModels:`All models`,allMonths:`All months`,noFilter:`No filter`,focusMonth:`Focus month`,showInfo:`Show info`,expand:`Expand`,expandWithTitle:`{{title}} expand`,expandedCardDescription:`Expanded card view with additional metrics and full content.`,input:`Input`,output:`Output`,cacheWrite:`Cache write`,cacheRead:`Cache read`,thinking:`Thinking`,requestsShort:`Req`,request:`Request`,share:`Share`,top:`Top`},filterBar:{status:`Filter status`,viewModeLabel:`View mode`,focusMonthLabel:`Focus month`,providersActive:`{{count}} providers active`,modelsActive:`{{count}} models active`,dateFilterActive:`Date filter active`,clearDate:`Clear {{label}}`,presets:{"7d":`7D`,"30d":`30D`,month:`Month`,year:`Year`,all:`All`},until:`to`,resetDateRange:`Reset date range`,resetAll:`Reset all`,providers:`Providers`,models:`Models`,resetModels:`Reset models`},dashboard:{insights:{title:`Insights`,badge:`Condensed signals`,description:`Focused signals from cost, model, and request data`,quickRead:`Quick read`},metrics:{title:`Metrics`,badge:`10 metrics`,description:`Core KPIs at a glance`},activity:{title:`Activity`,dailyDescription:`Daily usage overview`,monthlyDescription:`Monthly usage overview`,yearlyDescription:`Yearly usage overview`},forecastCache:{title:`Forecast & Cache`,description:`Cost forecast and cache efficiency`},costAnalysis:{title:`Cost analysis`,description:`Detailed cost breakdown`},tokenAnalysis:{title:`Token analysis`,description:`Usage by token type`},requestAnalysis:{title:`Request analysis`,description:`Requests overall, by model, and over time`},advancedAnalysis:{title:`Distributions & Risk`,description:`Additional signals for spread, correlation, and dependencies`},comparisons:{title:`Comparisons & Anomalies`,description:`Period comparison and outliers`},tables:{title:`Tables`,description:`Detailed breakdowns`},cards:{periodComparison:`Period comparison`,anomalyDetection:`Anomaly detection`,costForecast:`Cost forecast`,cacheRoi:`Cache ROI`},stats:{min:`Min`,max:`Max`,avg:`Avg`,cacheHitRate:`Cache hit rate`,totalTokens:`Total tokens`,cacheRead:`Cache read`,dataPoints:`Data points`,avgCostPerUnit:`Avg cost/{{unit}}`,total:`Total`,avgPerUnit:`Avg / {{unit}}`}},metricCards:{primary:{totalCost:`Total cost`,totalTokens:`Total tokens`,activeDays:`Active days`,topModel:`Top model`,cacheHitRate:`Cache hit rate`,costPerMillion:`$/1M tokens`,requests:`Requests`,thinking:`Thinking`,avgPerPeriod:`{{value}}/{{unit}} avg`,tokensPerRequestAvg:`{{value}} average per request`,coverageOfDays:`{{coverage}} coverage across {{days}} days`,providersActive:`{{count}} providers active`,share:`{{value}} share`,requestLead:`Req lead: {{value}}`,allTokensViaCacheRead:`{{value}} of all tokens via cache read`,requestCountersMissing:`No request counters in the dataset`,thinkingShareOfVolume:`{{value}} of total token volume`,totalCostSubtitle:`Avg {{average}}/{{unit}} · {{costPerRequest}} per request`,totalTokensSubtitle:`{{tokensPerRequest}} per request`,totalTokensSubtitleWithRatio:`Input/Output {{ratio}}:1 · {{tokensPerRequest}} per request`,requestsSubtitle:`Avg {{requests}} / {{unit}} · {{cost}} / req · σ {{volatility}}`,thinkingSubtitle:`{{share}} share · {{tokens}} / request`},secondary:{mostExpensiveDay:`Most expensive day`,mostExpensiveMonth:`Most expensive month`,mostExpensiveYear:`Most expensive year`,dominantProvider:`Dominant provider`,peak7Days:`Peak 7 days`,avgCostPerUnit:`Avg cost/{{unit}}`,spread:`Spread: {{value}}`,medianPerUnit:`Median/{{unit}}`,vsAverage:`{{direction}}{{value}}% vs avg`,vsAverageWithVolatility:`{{direction}}{{value}}% vs avg · σ Req {{volatility}}`,medianInfo:`The median shows the typical value and is less sensitive to outliers than the average.`,requestLeader:`{{model}} · {{requests}} req`,dominantProviderSubtitle:`{{share}} share · {{cost}}{{requestLeader}}`},today:{title:`Today — {{date}}`,description:`KPIs for the current day`,costToday:`Cost today`,tokensToday:`Tokens today`,models:`Models`,costPerMillion:`$/1M tokens`,cacheHitRate:`Cache hit rate`,requests:`Requests`,thinking:`Thinking`,vsAverageShort:`vs avg`,overallAverage:`Overall avg: {{value}}`,cacheShare:`{{value}} cache share`,requestsToday:`Requests today`,avgPerDay:`Avg {{value}}/day`,ioRatio:`I/O ratio: {{value}}:1`,topModel:`Top: {{value}}`,requestsSubtitle:`{{value}} / model · {{cost}}/req`,tokensInsight:`{{value}} per request`,requestsInsight:`{{value}} per request`,requestCountersMissing:`No request counters`,thinkingSubtitle:`{{value}} share`},month:{title:`Month — {{date}}`,badge:`{{count}} days`,description:`KPIs for the current month`,costMonth:`Month cost`,tokensMonth:`Month tokens`,activeDays:`Active days`,models:`Models`,costPerMillion:`$/1M tokens`,cacheHitRate:`Cache hit rate`,requests:`Requests`,thinking:`Thinking`,vsPreviousMonth:`vs previous month`,coverage:`{{value}} coverage`,requestsInMonth:`Requests this month`,avgPerDay:`Avg {{value}}/day`,ioRatio:`I/O ratio: {{value}}:1`,topModel:`Top: {{value}}`,cacheMix:`In: {{input}} / Out: {{output}}`,costPerRequest:`{{value}} / req`,requestsSubtitle:`Avg {{value}}/day · {{cost}}/req`,requestCountersMissing:`No request counters`,thinkingSubtitle:`{{value}} share`}},insights:{concentration:{title:`Cost concentration`,summary:`{{provider}} is currently the dominant provider in the selected slice, while {{model}} is the strongest single lever.`,fallback:`No stable provider distribution is available yet.`,topProvider:`Top provider`,topModel:`Top model`,topModelShare:`Top model share`,topThreeModels:`Top 3 models`},requestEconomy:{title:`Request economy`,valueLabel:`Avg cost per request`,summary:`Each request costs {{cost}} on average and processes {{tokens}}. {{leader}}`,leader:`{{model}} currently leads on request volume.`,fallback:`The loaded dataset does not contain reliable request counters. Request economy is therefore unavailable.`,avgRequests:`Avg req/{{unit}}`,avgTokensPerRequest:`Avg tokens/req`,costPerMillion:`$/1M tokens`,totalRequests:`Total requests`},usagePatterns:{title:`Usage patterns`,summaryWithCoverage:`{{activeDays}} of {{totalDays}} calendar days contain activity in the filtered range. Requests vary by {{volatility}}.`,summaryWithoutCoverage:`{{activeDays}} active {{unit}} in the selected slice.`,avgModels:`Avg models/entry`,providersActive:`Providers active`,weekendShare:`Weekend share`,thinkingShare:`Thinking share`},peakWindow:{title:`Peak window`,summary:`Strongest 7-day phase from {{start}} to {{end}}.`,fallback:`No 7-day window is available, so the focus falls back to the most expensive single point.`,peakDay:`Peak day`,avgPerUnit:`Avg/{{unit}}`,peak7DayAverage:`Peak 7D avg/day`,signal:`Signal`,signalStrong:`highly concentrated`,signalModerate:`moderately concentrated`,signalWide:`broadly distributed`},quickRead:{summary:`{{provider}} accounts for {{providerShare}} of cost, while the top 3 models concentrate {{topThreeShare}}. {{requestLeader}}`,requestLeader:`{{requestModel}} leads on requests, while {{tokenModel}} leads on token volume.`,fallback:`There is not enough data in the current filter slice for a stable summary yet.`}},charts:{costOverTime:{title:`Cost over time + 7-day avg`,subtitle:`Daily cost with 7-day moving average`,summary:`Latest {{latest}} · Peak {{peak}} on {{date}}`,cost:`Cost`,movingAverage:`7-day avg`},costByModel:{title:`Cost by model`,subtitle:`Cost distribution by model`,total:`Total`},costByModelOverTime:{title:`Cost by model over time`,subtitle:`Per model over time`,topDriver:`Top driver: {{model}} · {{total}} cumulative`,movingAverageHeading:`7-day average by model`,movingAverageSuffix:`avg`},cumulativeCost:{title:`Cumulative cost`,total:`Total: {{value}}`,cumulative:`Cumulative`,projection:`Projection`},tokensOverTime:{title:`Tokens over time`,subtitle:`All token types with 7-day avg`,allTypes:`Total tokens (all types)`,totalTokens:`Total tokens`,movingAverage:`7-day avg`,cacheTokens:`Cache tokens`,inputOutputTokens:`Input / Output tokens`,thinkingTokens:`Thinking tokens`,averageSuffix:`avg`},requestsOverTime:{title:`Requests over time`,subtitle:`Requests overall, by model, and with 7-day avg`,summary:`Total {{total}} · Peak {{peak}} on {{date}}`,averagePerUnit:`Avg / {{unit}}`,trend:`Trend avg`,movingAverage:`7-day avg`,trendHeading:`Moving average by model`,movingAverageHeading:`7-day average by model`,totalMovingAverage:`Total {{label}}`,requestsByModelTotal:`Requests by model total`,requestsInRange:`Requests in the selected range`,total:`Total`,topModel:`Top model`,topShare:`Top share`,totalRequestsSeries:`Total requests`},requestCacheHitRate:{title:`Cache hit rate by model`,subtitle:`Total {{total}} · 7-day avg {{trailing}}`,totalRate:`Total`,trailing7Rate:`7-day avg`,trendRate:`Trend avg`,topModel:`Top model`,models:`Models`,total:`Total`,timelineHeading:`Cache hit rate over time / {{unit}}`,modelBreakdownHeading:`Current model snapshot`},heatmap:{costTitle:`Cost heatmap`,requestsTitle:`Request heatmap`,tokensTitle:`Token heatmap`,cellLabel:`{{date}}: {{value}}`,costEmpty:`Cost heatmap is only available in daily view`,requestsEmpty:`Request heatmap is only available in daily view`,tokensEmpty:`Token heatmap is only available in daily view`,switchToDaily:`Switch to daily view for the calendar heatmap`,less:`Less`,more:`More`},tokenTypes:{title:`Token types`,subtitle:`Distribution of token types`,total:`Total`},modelMix:{title:`Model mix`,subtitle:`Cost share by model over time`},distribution:{title:`Distributions`,requiresData:`At least 2 data points are required in the current filter for distributions.`,costPerPeriod:`Cost per {{period}}`,requestsPerPeriod:`Requests per {{period}}`,tokensPerRequest:`Tokens per request`,interval:`Interval`,dataPoints:`Data points`,buckets:`Buckets`},correlation:{title:`Correlations`,requiresData:`At least 2 data points are required in the current filter for correlations.`,points:`{{count}} points`,requestsVsCost:`Requests vs. cost`,cacheVsCostPerRequest:`Cache rate vs. $/req`,requestsAxis:`Requests`,requestsLabel:`Requests`,tokensLabel:`Tokens`,costPerRequestAxis:`$/Req`,cost:`Cost`,costPerRequest:`Cost / req`,cacheRate:`Cache rate`,strongRequestCost:`Strong relationship: more requests visibly drive cost.`,mediumRequestCost:`Moderate relationship between load and cost.`,weakRequestCost:`Weak relationship: cost is driven more by model mix and token load.`,negativeCache:`Negative relationship: higher cache rate tends to reduce cost per request.`,neutralCache:`Little linear effect: cache helps, but is not the only driver.`,positiveCache:`Positive relationship: high cache rates do not automatically coincide with lower cost per request here.`},costByWeekday:{title:`Cost by weekday`,subtitle:`Peak: {{peak}} · Low: {{low}} · Weekend {{share}}`,averageCost:`Avg cost`},tokenEfficiency:{title:`Token efficiency ($/1M)`,subtitle:`Avg {{value}}/1M tokens`,series:`$/1M tokens`,movingAverage:`7D avg`}},risk:{title:`Concentration risk`,modelDependency:`Model dependency`,providerDependency:`Provider dependency`,high:`high`,medium:`medium`,low:`low`,modelHint:`HHI {{value}} · Higher values indicate a few dominant models.`,providerHint:`HHI {{value}} · Shows dependency on individual providers.`},requestQuality:{title:`Request quality`,tokensPerRequest:`Tokens / request`,costPerRequest:`Cost / request`,cachePerRequest:`Cache / request`,thinkingPerRequest:`Thinking / request`,tokensHint:`Average token load per request`,costHint:`Direct cost per request`,cacheHint:`Read cache tokens per request`,thinkingHint:`Thinking tokens per request`,requestDensity:`Request density`,averagePerActiveUnit:`Avg per active {{unit}}`,cacheHitRate:`Cache hit rate`,cacheHitHint:`Direct cache-read relative to all tokens`,inputOutput:`Input / Output`,inputOutputHint:`Drift between incoming and generated tokens`,topRequestModel:`Top request model`,noRequestLeader:`No request leader`},forecast:{noData:`No data available`,noForecast:`No forecast available`,requiresTwoDays:`At least 2 days with data are required`,avgMonthlyCost:`Avg monthly cost`,avgYearlyCost:`Avg yearly cost`,totalOverPeriods:`Total: {{total}} over {{count}} {{unit}}`,monthEndForecast:`Month-end forecast`,low:`low`,medium:`medium`,high:`high`,soFar:`So far: {{value}}`,remainingDays:`Days remaining: {{count}}`,projectedPerDay:`Forecast {{value}}/day`,vsLastWeek:`vs last week`,chartTitle:`Current month cost forecast`,chartSubtitle:`Month-end forecast based on smoothed calendar-day cost`,lowerBound:`Lower bound`,uncertaintyBand:`Uncertainty band`,actualCost:`Actual cost`,projection:`Forecast`},cacheRoi:{title:`Cache savings (ROI)`,noData:`No data available`,heuristicFallback:`For {{count}} {{modelsLabel}} without a configured price table, the ROI estimate uses a heuristic fallback.`,model:`model`,models:`models`,withoutCache:`Without cache`,withCache:`With cache`,withCacheActual:`With cache (actual)`,savings:`Savings`,avgCostPerUnit:`Avg cost/{{unit}}`,paid:`Paid`,saved:`Saved`},comparison:{title:`Period comparison`,notEnoughData:`Not enough data for a comparison`,requiresDays:`At least 7 days required (currently: {{count}})`,thisWeek:`This week`,lastWeek:`Last week`,thisMonth:`This month`,lastMonth:`Last month`,week:`Week`,month:`Month`,metric:`Metric`,delta:`Delta`,cost:`Cost`,tokens:`Tokens`,avgPerDay:`Avg/day`,cacheRate:`Cache rate`,days:`Days`},anomaly:{title:`Unusual {{period}}`,none:`No anomalies detected`,withinStdDev:`All costs are within 2 standard deviations`,description:`{{period}} with cost >2 standard deviations from the mean ({{mean}} +/- {{stdDev}})`,critical:`critical`},tables:{modelEfficiency:{title:`Model efficiency`,count:`{{count}} models`,topModel:`Top model`,mostEfficient:`Most efficient model`,totalRequests:`Total requests`,topModelTokens:`Top model tokens`,share:`{{value}} share`,perModel:`{{value}} / model`,more:`+{{count}} more`,model:`Model`,cost:`Cost`,tokens:`Tokens`,shareShort:`Share`,req:`Req`,reqShare:`Req %`,costPerReq:`$ / Req`,tokensPerReq:`Tokens / Req`,cacheShare:`Cache %`,thinkingShare:`Think %`,avgPerUnit:`Avg/{{unit}}`},providerEfficiency:{title:`Provider efficiency`,count:`{{count}} providers`,leadProvider:`Lead provider`,mostEfficient:`Most efficient provider`,totalRequests:`Total requests`,share:`{{value}} share`,perProvider:`{{value}} / provider`,avgPerUnit:`Avg/{{unit}}`,provider:`Provider`,cost:`Cost`,shareShort:`Share`,req:`Req`,tokens:`Tokens`,costPerReq:`$ / Req`,costPerMillion:`$/1M`,cacheShare:`Cache %`},recentDays:{daysDetail:`Recent days in detail`,monthsDetail:`Months in detail`,yearsDetail:`Years in detail`,showing:`Showing {{shown}} of {{total}} {{unit}}`,showLess:`Show less`,showAll:`Show all`,totalCost:`Total cost`,totalTokens:`Total tokens`,requests:`Requests`,cacheReadShare:`Cache read share`,peak:`Peak`,previousDay:`Previous day`,avg7d:`7D avg`,reqAvg:`Req avg`,date:`Date`,cost:`Cost`,tokens:`Tokens`,models:`Models`}},helpPanel:{projectLinks:{title:`Project links`,description:`Open the published npm package for v{{version}}, the GitHub repository, or the issue tracker.`,npm:`npm`,github:`GitHub`,issues:`GitHub Issues`},chartsAndFeatures:`Charts`,dashboardSectionsTitle:`Dashboard sections`,featuresTitle:`Features`,tablesTitle:`Tables`,metricLabels:{totalCost:`Total cost`,totalTokens:`Total tokens`,activeDays:`Active days`,topModel:`Top model`,cacheHitRate:`Cache hit rate`,costPerMillion:`Cost / 1M tokens`,mostExpensiveDay:`Most expensive day`,cheapestDay:`Cheapest day`,avgCostPerDay:`Avg cost / day`,outputTokens:`Output tokens`},chartLabels:{costOverTime:`Cost over time`,costByModel:`Cost by model`,costByModelOverTime:`Cost by model over time`,cumulativeCost:`Cumulative cost`,costByWeekday:`Cost by weekday`,tokensOverTime:`Tokens over time`,requestsOverTime:`Requests over time`,requestCacheHitRate:`Cache hit rate by model`,tokenTypes:`Token types`,tokenEfficiency:`Token efficiency`,modelMix:`Model mix`,distributionAnalysis:`Distributions`,correlationAnalysis:`Correlations`,heatmap:`Cost heatmap`,requestHeatmap:`Request heatmap`,tokenHeatmap:`Token heatmap`,forecast:`Forecast`,cacheROI:`Cache ROI`,providerLimitProgress:`Provider limit usage`,providerSubscriptionMix:`Provider subscriptions vs. API cost`,providerLimitTimeline:`Provider limits over time`,periodComparison:`Period comparison`,anomalyDetection:`Anomaly detection`,cellLabel:`{{date}}: {{value}}`},sectionLabels:{insights:`Insights`,metrics:`Metrics`,today:`Today`,currentMonth:`Month`,activity:`Activity`,forecastCache:`Forecast & Cache`,costAnalysis:`Cost analysis`,tokenAnalysis:`Token analysis`,requestAnalysis:`Request analysis`,advancedAnalysis:`Distributions & Risk`,comparisons:`Comparisons & Anomalies`,tables:`Tables`,limits:`Limits & Subscriptions`},featureLabels:{requestQuality:`Request quality`,providerLimits:`Limits & Subscriptions`,concentrationRisk:`Concentration risk`,providerEfficiency:`Provider efficiency`,modelEfficiency:`Model efficiency`,recentDays:`Periods in detail`}},autoImportModal:{title:`Toktrack auto import`,description:"Automatically imports local usage data via local `toktrack`, `bunx`, or `npm exec` and stores it only on this device.",connecting:`Connecting...`,checkingTool:`Checking {{tool}}...`,toolFound:`{{tool}} found ({{method}}, v{{version}})`,toolNotFound:`{{tool}} not found`,importedDays:`{{days}} days imported ({{cost}} USD)`,checkingPrerequisites:`Checking prerequisites...`,importingData:`Importing data...`,startingLocalImport:`Starting local toktrack import...`,loadingUsageData:`Loading usage data via {{command}}...`,processingUsageData:`Processing usage data... ({{seconds}}s)`,serverConnectionLost:`Lost connection to server.`,autoImportRunning:`An auto import is already running. Please wait.`,noRunnerFound:`No local toktrack, Bun, or npm exec found.`,errorPrefix:`Error: {{message}}`,loadedDays:`{{days}} days loaded ({{cost}} USD)`,errorOccurred:`An error occurred`,close:`Close`},commandPalette:{title:`Command palette`,description:`Keyboard-driven command menu for navigation and actions in the ttdash dashboard.`,placeholder:`Search commands...`,empty:`No command found.`,groups:{actions:`Actions`,filters:`Filters & View`,navigation:`Navigation`,view:`View`,language:`Language`,help:`Help`,providers:`Providers`,models:`Models`},commands:{autoImport:{label:`Start auto import`,description:`Run local toktrack import`},openSettings:{label:`Open settings`,description:`Manage backups, app options, and provider limits`},exportCsv:{label:`Export CSV`,description:`Export currently filtered data`},generateReport:{label:`Generate PDF report`,labelLoading:`Generating PDF report`,description:`Export currently filtered data as PDF`},upload:{label:`Upload JSON`,description:`Import toktrack or legacy JSON`},delete:{label:`Delete data`,description:`Remove local dataset`},viewDaily:{label:`Switch to daily view`,description:`Show data per day`},viewMonthly:{label:`Switch to monthly view`,description:`Show data per month`},viewYearly:{label:`Switch to yearly view`,description:`Show data per year`},preset7d:{label:`Range: last 7 days`,description:`Sets the date filter to 7 days`},preset30d:{label:`Range: last 30 days`,description:`Sets the date filter to 30 days`},presetMonth:{label:`Range: current month`,description:`Sets the date filter to the current month`},presetYear:{label:`Range: current year`,description:`Sets the date filter to the current year`},presetAll:{label:`Range: all data`,description:`Clears preset date filters`},clearProviders:{label:`Reset provider filter`,description:`Remove all active provider filters`},clearModels:{label:`Reset model filter`,description:`Remove all active model filters`},clearDates:{label:`Reset date filter`,description:`Remove start and end date`},resetAll:{label:`Reset all filters`,description:`Restore the default dashboard filter state`},scrollTop:{label:`Scroll to top`,description:`Jump to the top of the page`},scrollBottom:{label:`Scroll to bottom`,description:`Jump to the bottom of the page`},filters:{label:`Go to filters`,description:`Jump to the filter bar`},goToSection:{label:`Go to {{section}}`,description:`Jump to the {{section}} section`},insights:{label:`Go to insights`,description:`Jump to the executive summary`},metrics:{label:`Go to metrics`,description:`Jump to KPI cards`},today:{label:`Go to today`,description:`Jump to the current day KPIs`},month:{label:`Go to month`,description:`Jump to the current month KPIs`},activity:{label:`Go to activity`,description:`Jump to the activity heatmap`},forecastCache:{label:`Go to forecast & cache`,description:`Jump to forecast and cache ROI`},limits:{label:`Go to Limits & Subscriptions`,description:`Jump to the limits section`},charts:{label:`Go to cost analysis`,description:`Jump to cost charts`},tokenAnalysis:{label:`Go to token analysis`,description:`Jump to token charts and distributions`},requestAnalysis:{label:`Go to request analysis`,description:`Jump to requests over time and request distribution`},comparisons:{label:`Go to comparisons & anomalies`,description:`Jump to period comparison and unusual activity`},tables:{label:`Go to tables`,description:`Jump to detailed tables`},themeLight:{label:`Enable light mode`,description:`Switch between light and dark theme`},themeDark:{label:`Enable dark mode`,description:`Switch between light and dark theme`},languageGerman:{label:`Switch to German`,description:`Change the dashboard language to German`},languageEnglish:{label:`Switch to English`,description:`Change the dashboard language to English`},help:{label:`Open help & shortcuts`,description:`Open the help overview`}}},settings:{modal:{title:`Settings`,description:`Manage app backups, stored data, and provider limits in one place.`,languageTitle:`Dashboard language`,languageDescription:`Choose the language used in the dashboard UI, dialogs, and reports.`,dataStatus:`Data status`,lastLoaded:`Last loaded`,loadedVia:`Loaded via`,cliAutoLoad:`CLI auto-load`,defaultFiltersTitle:`Default dashboard filters`,defaultFiltersDescription:`Choose the filter state that should be applied when the dashboard opens or when filters are reset.`,defaultViewMode:`Default view mode`,defaultDateRange:`Default date range`,filterProviders:`Default provider filter`,filterModels:`Default model filter`,noModels:`No models found in the loaded report.`,sectionVisibilityTitle:`Visible dashboard sections`,sectionVisibilityDescription:`Control which sections are rendered in the dashboard and adjust their order.`,sectionOrderHint:`Drag sections to reorder them. The current order is the default dashboard layout.`,positionLabel:`Position {{position}} of {{total}}`,moveSectionUp:`Move {{section}} up`,moveSectionDown:`Move {{section}} down`,settingsBackupTitle:`Back up settings`,settingsBackupDescription:`Export and import language, theme, limits, and stored load metadata as a versioned backup.`,dataBackupTitle:`Back up data`,dataBackupDescription:`Export the locally stored usage state as a backup and import backups conservatively.`,dataImportPolicy:`Data import only adds missing days. Existing days with different values stay local and are reported as conflicts.`,dataImportReplaceHint:`If you want to fully replace the dataset, keep using the regular JSON upload in the header.`,providerLimitsTitle:`Provider limits`,providerLimitsDescription:`Define subscription and monthly limit per provider. Only providers from the currently loaded report can be edited.`,noProviders:`No providers found in the loaded report.`,exportSettings:`Export settings`,importSettings:`Import settings`,exportData:`Export data`,importData:`Import data`,close:`Close`,save:`Save`,viewModes:{daily:`Daily`,monthly:`Monthly`,yearly:`Yearly`},datePresets:{all:`All data`,"7d":`Last 7 days`,"30d":`Last 30 days`,month:`Current month`,year:`Current year`},sources:{file:`File upload`,"auto-import":`Auto import`,"cli-auto-load":`CLI auto-load`,unknown:`Unknown`}}},drillDown:{description:`Detailed daily view with token distribution, model shares, requests, and thinking tokens.`,cacheRate:`Cache rate`,tokensPerRequest:`Tokens / Req`,costPerRequest:`Cost / Req`,costRank:`Cost rank`,requestRank:`Request rank`,topRequestModel:`Top by requests`,costVsAverage7d:`Cost vs. 7D avg`,requestsVsAverage7d:`Requests vs. 7D avg`,tokenDistribution:`Token distribution`,requestCountShort:`{{count}} Req`,modelRequestSummary:`{{costPerRequest}}/Req · {{tokensPerRequest}}/Req`,noRequests:`No requests`,tokenSegments:{cacheRead:`Cache Read`,cacheWrite:`Cache Write`}},chartCard:{expandedDescription:`Expanded chart view with metric summary and optional CSV export.`,exportCsv:`Export CSV`},customTooltip:{total:`Total`,delta:`Delta`,vsPrevious:`vs. previous`,vsAverage:`vs. avg`},limits:{sectionTitle:`Limits & Subscriptions`,sectionDescription:`Budget risk separated from subscription impact in the current filter context`,providersBadge:`{{count}} providers`,warningBanner:`{{count}} providers have reached or exceeded their monthly limit in the current slice.`,cards:{atLimit:`Providers at limit`,nearLimit:`Near limit`,subscriptionVolume:`Subscription volume`,subscriptionValue:`Subscription value`,nearLimitHint:`from 80% utilization`,subscriptionVolumeHint:`fixed cost / month`,subscriptionValueHint:`usage above subscription`,noMonth:`No month`},statuses:{limitExceeded:`Limit exceeded`,budgetTight:`Budget tight`,budgetStable:`Budget stable`,noLimit:`No limit set`,noSubscription:`No subscription`,subscriptionPaysOff:`Subscription pays off`,belowSubscription:`Still below subscription`},badge:{limit:`{{value}}% Limit`,subscription:`{{value}}% Sub`,open:`Open`},tracks:{budgetTitle:`Budget status by provider`,budgetSubtitle:`Each track shows the remaining distance to the limit or the already incurred overrun for each provider`,budgetNoMonth:`No month in the current slice`,subscriptionTitle:`Subscription status by provider`,subscriptionSubtitle:`Each track shows the remaining distance to break-even or the already realized value for each provider`,subscriptionNoMonth:`No month in the current slice`,portfolioTitle:`Portfolio trend`,portfolioSubtitle:`Monthly trend of usage, configured limits, and subscription impact`,usage:`Usage`,limit:`Limit`,limits:`Limits`,subscription:`Subscription`,subscriptions:`Subscriptions`,breakEven:`Break-even`,currentlyUsed:`Currently used`,remainingToLimit:`Remaining to limit`,alreadyOverLimit:`Already over`,remainingToBreakEven:`Remaining to break-even`,alreadyAboveBreakEven:`Already above`,usageFocusMonth:`Focus month cost`,limitSubscription:`Limit / Subscription`,budgetRisk:`Budget risk`,subscriptionEffect:`Subscription effect`,stillToLimit:`{{value}} remaining to limit`,alreadyAboveLimit:`{{value}} above limit`,stillToBreakEven:`{{value}} remaining to break-even`,alreadyAboveBreakEvenText:`{{value}} above break-even`,noSubscriptionSet:`No subscription set`},modal:{title:`Provider limits`,description:`Define subscription and monthly limit per provider. Only providers from the currently loaded report can be edited. A limit of 0 means no limit.`,dataStatus:`Data status`,lastLoaded:`Last loaded`,loadedVia:`Loaded via`,cliAutoLoad:`CLI auto-load`,noProviders:`No providers found in the loaded report.`,hasSubscription:`Subscription enabled`,subscriptionPerMonth:`Subscription $/month`,monthlyLimit:`Monthly limit $`,close:`Close`,save:`Save`,sources:{file:`File upload`,"auto-import":`Auto import`,"cli-auto-load":`CLI auto-load`,unknown:`Unknown`}}},report:{title:`TTDash Report`,common:{notAvailable:`n/a`},header:{eyebrow:`TTDash PDF Report`},summary:{peakPeriod:`Peak period`},sections:{overview:`Overview`,insights:`Key insights`,filters:`Filters`,modelsProviders:`Models & Providers`,recentPeriods:`Recent periods`,interpretation:`Interpretation`},fields:{dateRange:`Date range`,view:`View`,generated:`Generated`,month:`Month`,selectedProviders:`Selected providers`,selectedModels:`Selected models`,startDate:`Start date`,endDate:`End date`},filters:{all:`All`,noFilter:`No filter`,andMore:`+{{count}} more`},tables:{topModels:`Top models`,providers:`Providers`,columns:{model:`Model`,provider:`Provider`,cost:`Cost`,tokens:`Tokens`,requests:`Requests`,period:`Period`}},charts:{costTrend:`Cost trend`,topModels:`Top models by cost`,tokenTrend:`Token mix by period`,costTrendAlt:`Line chart showing report cost by period.`,costTrendSummary:`Latest {{latest}}. Peak {{peak}} on {{date}}.`,topModelsAlt:`Horizontal bar chart comparing the highest-cost models in the report.`,topModelsSummary:`{{model}} leads with {{cost}} and {{share}} of report cost.`,topModelsFullNames:`Full chart labels: {{names}}.`,tokenTrendAlt:`Stacked bar chart showing the token mix for each report period.`,tokenTrendSummary:`Total {{total}}. Peak token volume {{peak}} on {{date}}.`,noDataSummary:`Not enough data for a stable chart summary.`},interpretation:{summary:`This report covers {{days}} raw days and {{periods}} aggregated periods. Peak period: {{peak}}. Top model: {{topModel}}. Leading provider: {{topProvider}}.`,footer:`Created with TTDash v{{version}} and server-side Typst compilation.`},insights:{coverageTitle:`Data coverage`,coverageBody:`This report is based on a narrow slice of data with {{days}} raw days and {{periods}} aggregated periods. Treat trend statements cautiously.`,providerTitle:`Provider concentration`,providerBody:`{{provider}} accounts for {{share}} of total report cost.`,cacheTitle:`Cache contribution`,cacheBody:`Cache reads contribute {{share}} of token activity in the selected period.`,peakWindowTitle:`Peak 7-day window`,peakWindowBody:`The strongest rolling 7-day window ran from {{start}} to {{end}} with {{cost}} total cost.`}},api:{fetchUsageFailed:`Failed to load data`,fetchSettingsFailed:`Failed to load settings`,uploadFailed:`Upload failed`,deleteFailed:`Delete failed`,deleteSettingsFailed:`Failed to reset settings`,importUsageFailed:`Data import failed`,importSettingsFailed:`Settings import failed`,saveSettingsFailed:`Failed to save settings`,pdfFailed:`PDF generation failed`},toasts:{fileLoaded:`File {{name}} loaded successfully`,fileReadFailed:`Could not read file`,dataDeleted:`Data deleted`,csvExported:`CSV exported`,dataImported:`Data imported successfully`,settingsExported:`Settings backup exported`,dataExported:`Data backup exported`,noDataToExport:`No data available to export`,settingsImported:`Imported settings from {{name}}`,settingsReset:`Settings reset`,settingsSaved:`Settings saved`,dataBackupImported:`Backup imported: added {{added}} new days, skipped {{unchanged}} identical days`,dataBackupImportedWithConflicts:`Backup imported: added {{added}} new days, kept {{conflicts}} conflicting days local`}},Te=[`de`,`en`],Ee={de:`de-CH`,en:`en-US`};function De(e){return e===`en`?`en`:`de`}async function Oe(e=`de`){let t=De(e);K.isInitialized?K.resolvedLanguage!==t&&await K.changeLanguage(t):await K.use(p).init({resources:{de:{common:Ce},en:{common:we}},lng:t,fallbackLng:`de`,defaultNS:`common`,ns:[`common`],interpolation:{escapeValue:!1}}),typeof document<`u`&&(document.documentElement.lang=t)}K.on(`languageChanged`,e=>{typeof document<`u`&&(document.documentElement.lang=e)});function ke(){return De(K.language)}function q(){return Ee[ke()]}var J=K,Ae=r({default:()=>je,displayAliases:()=>Y,providerMatchers:()=>X}),Y,X,je,Me=n((()=>{Y=[{pattern:`(^|-)gpt-5-4$`,name:`GPT-5.4`},{pattern:`(^|-)gpt-5$`,name:`GPT-5`},{pattern:`(^|-)opus-4-6$`,name:`Opus 4.6`},{pattern:`(^|-)opus-4-5$`,name:`Opus 4.5`},{pattern:`(^|-)sonnet-4-6$`,name:`Sonnet 4.6`},{pattern:`(^|-)sonnet-4-5$`,name:`Sonnet 4.5`},{pattern:`(^|-)haiku-4-5$`,name:`Haiku 4.5`},{pattern:`(^|-)gemini-3-flash-preview$`,name:`Gemini 3 Flash Preview`},{pattern:`(^|-)opencode$`,name:`OpenCode`}],X=[{pattern:`(^|-)opencode($|-)`,provider:`OpenCode`},{pattern:`openai-codex|(^|-)codex($|-)|(^|-)gpt($|-)|(^|[^a-z0-9])o\\d(?:$|[^a-z0-9])|openai`,provider:`OpenAI`},{pattern:`claude|anthropic|opus|sonnet|haiku`,provider:`Anthropic`},{pattern:`gemini|google|vertex`,provider:`Google`},{pattern:`grok|xai`,provider:`xAI`},{pattern:`llama|meta-llama|meta/`,provider:`Meta`},{pattern:`command|cohere`,provider:`Cohere`},{pattern:`mistral`,provider:`Mistral`},{pattern:`deepseek`,provider:`DeepSeek`},{pattern:`qwen|alibaba`,provider:`Alibaba`}],je={displayAliases:Y,providerMatchers:X}})),Ne=i(((e,n)=>{var r=(Me(),t(Ae).default),i=r.displayAliases.map(e=>({...e,matcher:new RegExp(e.pattern,`i`)})),a=r.providerMatchers.map(e=>({...e,matcher:new RegExp(e.pattern,`i`)}));function o(e){return e&&(/^\d+([.-]\d+)*$/.test(e)?e.replace(/-/g,`.`):/^[a-z]{1,4}\d+$/i.test(e)?e.toUpperCase():e.charAt(0).toUpperCase()+e.slice(1))}function s(e){return e?e.charAt(0).toUpperCase()+e.slice(1):``}function c(e){return e.replace(/-/g,`.`)}function l(e){let t=String(e||``).trim().toLowerCase().replace(/^model[:/ -]*/i,``).replace(/^(anthropic|openai|google|vertex|models)[/-]/i,``).replace(/\./g,`-`).replace(/[_/]+/g,`-`).replace(/\s+/g,`-`).replace(/-{2,}/g,`-`).replace(/^-|-$/g,``),n=t.lastIndexOf(`-`);if(n>0){let e=t.slice(n+1);if(e.length===8&&e.startsWith(`20`)&&/^\d+$/.test(e))return t.slice(0,n)}return t}function u(e){let t=e.split(`-`);if(t.length<2)return`Claude ${s(e)}`;let n=s(t[0]||``),r=t[1]||``;return/^\d+$/.test(r)?[`Claude`,n,c(t.slice(1).join(`-`))].filter(Boolean).join(` `).trim():[`Claude`,n,s(r),c(t.slice(2).join(`-`))].filter(Boolean).join(` `).trim()}function d(e){let t=e.split(`-`),n=t[0]||``,r=t[1]||``;if(r&&r.length<=2&&/^\d+$/.test(r)){let e=`${n}.${r}`;if(t.length>2){let n=t.slice(2).map(s).join(` `);return`GPT-${e}${n?` ${n}`:``}`}return`GPT-${e}`}if(t.length>1){let e=t.slice(1).map(s).join(` `);return`GPT-${n}${e?` ${e}`:``}`}return`GPT-${e}`}function f(e){let t=e.split(`-`);if(t.length<2)return`Gemini ${e}`;let n=[],r=[];for(let e of t)/^\d+$/.test(e)&&r.length===0?n.push(e):r.push(s(e));let i=n.join(`.`),a=r.join(` `);return a?`Gemini ${i} ${a}`:`Gemini ${i}`}function p(e){let t=e.replace(/-latest$/i,``);return t?`Codex ${t.split(`-`).map(s).join(` `)}`:`Codex`}function m(e){let t=e.indexOf(`-`);return t===-1?e:`${e.slice(0,t)} ${s(e.slice(t+1))}`}function h(e){let t=l(e);if(t.startsWith(`claude-`))return u(t.slice(7));for(let e of i)if(e.matcher.test(t))return e.name;if(t.startsWith(`gpt-`))return d(t.slice(4));if(t.startsWith(`gemini-`))return f(t.slice(7));if(t.startsWith(`codex-`))return p(t.slice(6));if(/^o\d/i.test(t))return m(t);let n=t.match(/^(gpt|opus|sonnet|haiku|gemini|codex|o\d|oai|grok|llama|mistral|command|deepseek|qwen)(?:-([a-z0-9-]+))?$/i);if(n){let e=n[1];if(/^codex$/i.test(e))return p(n[2]||``);if(/^(o\d)$/i.test(e))return m(t);let r=n[2]?c(n[2]):``;return/^gpt$/i.test(e)&&r?`GPT-${r.toUpperCase()}`:`${o(e)}${r?` ${r}`:``}`.trim()}return t.split(`-`).filter(Boolean).map(o).join(` `)||String(e||``)}function g(e){let t=l(e);for(let e of a)if(e.matcher.test(t))return e.provider;return`Other`}function _(e,t){let n=0,r=0,i=0,a=0,o=0,s=0,c=0;for(let e of t)n+=e.cost,r+=e.inputTokens,i+=e.outputTokens,a+=e.cacheCreationTokens,o+=e.cacheReadTokens,s+=e.thinkingTokens,c+=e.requestCount;return{...e,totalCost:n,totalTokens:r+i+a+o+s,inputTokens:r,outputTokens:i,cacheCreationTokens:a,cacheReadTokens:o,thinkingTokens:s,requestCount:c,modelBreakdowns:t,modelsUsed:[...new Set(t.map(e=>h(e.modelName)))]}}function v(e,t,n){return e.filter(e=>!(t&&e.date<t||n&&e.date>n))}function y(e,t){if(!t||t.length===0)return e;let n=new Set(t);return e.map(e=>{let t=e.modelBreakdowns.filter(e=>n.has(h(e.modelName)));return t.length===0?null:_(e,t)}).filter(Boolean)}function b(e,t){if(!t||t.length===0)return e;let n=new Set(t);return e.map(e=>{let t=e.modelBreakdowns.filter(e=>n.has(g(e.modelName)));return t.length===0?null:_(e,t)}).filter(Boolean)}function x(e,t){return t?e.filter(e=>e.date.startsWith(t)):e}function S(e){return[...e].sort((e,t)=>e.date.localeCompare(t.date))}function C(e,t){if(t===`daily`)return e;let n=t===`monthly`?e=>e.slice(0,7):e=>e.slice(0,4),r=new Map;for(let t of e){let e=n(t.date),i=r.get(e),a=t._aggregatedDays||1;if(!i){r.set(e,{...t,date:e,_aggregatedDays:a});continue}i.totalCost+=t.totalCost,i.totalTokens+=t.totalTokens,i.inputTokens+=t.inputTokens,i.outputTokens+=t.outputTokens,i.cacheCreationTokens+=t.cacheCreationTokens,i.cacheReadTokens+=t.cacheReadTokens,i.thinkingTokens+=t.thinkingTokens,i.requestCount+=t.requestCount,i._aggregatedDays+=a,i.modelBreakdowns=i.modelBreakdowns.concat(t.modelBreakdowns),i.modelsUsed=Array.from(new Set(i.modelsUsed.concat(t.modelsUsed)))}return Array.from(r.values()).sort((e,t)=>e.date.localeCompare(t.date))}function w(e,t=7){let n=Array(e.length),r=0,i=0;for(let a=0;a<e.length;a+=1){let o=e[a];if(o!==void 0&&(r+=o,i+=1),a>=t){let n=e[a-t];n!==void 0&&(r-=n,--i)}n[a]=a<t-1?void 0:i>0?r/i:void 0}return n}function T(e){if(!e.length)return 0;let t=e.reduce((e,t)=>e+t,0)/e.length,n=e.reduce((e,n)=>e+(n-t)**2,0)/e.length;return Math.sqrt(n)}function E(e){let t=e.filter(e=>/^\d{4}-\d{2}-\d{2}$/.test(e.date)).sort((e,t)=>e.date.localeCompare(t.date));if(t.length<3)return null;let n=null;for(let e=0;e<t.length;e+=1){let r=t[e];if(!r)continue;let i=new Date(`${r.date}T00:00:00`),a=new Date(i);a.setDate(a.getDate()+6);let o=0,s=e;for(;s<t.length;){let e=t[s];if(!e||new Date(`${e.date}T00:00:00`)>a)break;o+=e.totalCost,s+=1}let c=t[s-1];c&&(!n||o>n.cost)&&(n={start:r.date,end:c.date,cost:o})}return n}function D(e){if(e.some(e=>!/^\d{4}-\d{2}-\d{2}$/.test(e.date))||e.length<14)return null;let t=S(e),n=t.slice(-7),r=t.slice(-14,-7),i=n.reduce((e,t)=>e+t.totalCost,0),a=r.reduce((e,t)=>e+t.totalCost,0);return a===0?null:(i-a)/a*100}function O(e){if(e.length===0)return{totalCost:0,totalTokens:0,activeDays:0,topModel:null,topRequestModel:null,topTokenModel:null,topModelShare:0,topThreeModelsShare:0,topProvider:null,providerCount:0,hasRequestData:!1,cacheHitRate:0,costPerMillion:0,avgTokensPerRequest:0,avgCostPerRequest:0,avgModelsPerEntry:0,avgDailyCost:0,avgRequestsPerDay:0,topDay:null,cheapestDay:null,busiestWeek:null,weekendCostShare:null,totalInput:0,totalOutput:0,totalCacheRead:0,totalCacheCreate:0,totalThinking:0,totalRequests:0,weekOverWeekChange:null,requestVolatility:0,modelConcentrationIndex:0,providerConcentrationIndex:0};let t=e[0],n={date:t.date,cost:t.totalCost},r={date:t.date,cost:t.totalCost},i=0,a=0,o=0,s=0,c=0,l=0,u=0,d=0,f=0,p=!1,m=0,_=0,v=0,y=new Map,b=new Map,x=new Map,S=new Map;for(let t of e){if(i+=t.totalCost,a+=t.totalTokens,o+=t.inputTokens,s+=t.outputTokens,c+=t.cacheReadTokens,l+=t.cacheCreationTokens,u+=t.thinkingTokens,d+=t.requestCount,(t.requestCount>0||t.modelBreakdowns.some(e=>e.requestCount>0))&&(p=!0),f+=t._aggregatedDays||1,m+=t.modelsUsed.length,/^\d{4}-\d{2}-\d{2}$/.test(t.date)){let e=new Date(`${t.date}T00:00:00`).getDay();(e===0||e===6)&&(_+=t.totalCost),v+=t.totalCost}t.totalCost>n.cost&&(n={date:t.date,cost:t.totalCost}),t.totalCost<r.cost&&(r={date:t.date,cost:t.totalCost});for(let e of t.modelBreakdowns){let t=h(e.modelName),n=e.inputTokens+e.outputTokens+e.cacheCreationTokens+e.cacheReadTokens+e.thinkingTokens;y.set(t,(y.get(t)||0)+e.cost),b.set(t,(b.get(t)||0)+n),x.set(t,(x.get(t)||0)+e.requestCount);let r=g(e.modelName);S.set(r,(S.get(r)||0)+e.cost)}}let C=i/f,w=p&&f>0?d/f:0,O=a>0?i/(a/1e6):0,k=p&&d>0?a/d:0,A=p&&d>0?i/d:0,ee=e.length>0?m/e.length:0,j=c+l+o+s+u,M=j>0?c/j*100:0,N=null;for(let[e,t]of y)(!N||t>N.cost)&&(N={name:e,cost:t});let P=null;for(let[e,t]of x)(!P||t>P.requests)&&(P={name:e,requests:t});let F=null;for(let[e,t]of b)(!F||t>F.tokens)&&(F={name:e,tokens:t});let te=N&&i>0?N.cost/i*100:0,ne=i>0?[...y.values()].sort((e,t)=>t-e).slice(0,3).reduce((e,t)=>e+t,0)/i*100:0,I=null;for(let[e,t]of S)(!I||t>I.cost)&&(I={name:e,cost:t,share:i>0?t/i*100:0});let L=T(e.map(e=>e.requestCount)),R=i>0?[...y.values()].reduce((e,t)=>{let n=t/i;return e+n*n},0):0,re=i>0?[...S.values()].reduce((e,t)=>{let n=t/i;return e+n*n},0):0;return{totalCost:i,totalTokens:a,activeDays:f,topModel:N,topRequestModel:P,topTokenModel:F,topModelShare:te,topThreeModelsShare:ne,topProvider:I,providerCount:S.size,hasRequestData:p,cacheHitRate:M,costPerMillion:O,avgTokensPerRequest:k,avgCostPerRequest:A,avgModelsPerEntry:ee,avgDailyCost:C,avgRequestsPerDay:w,topDay:n,cheapestDay:r,busiestWeek:E(e),weekendCostShare:v>0?_/v*100:null,totalInput:o,totalOutput:s,totalCacheRead:c,totalCacheCreate:l,totalThinking:u,totalRequests:d,weekOverWeekChange:D(e),requestVolatility:L,modelConcentrationIndex:R,providerConcentrationIndex:re}}n.exports={aggregateToDailyFormat:C,computeBusiestWeek:E,computeMetrics:O,computeMovingAverage:w,computeWeekOverWeekChange:D,filterByDateRange:v,filterByModels:y,filterByMonth:x,filterByProviders:b,getModelProvider:g,normalizeModelName:h,sortByDate:S}})),Pe=i(((e,t)=>{var n=[{pattern:/^OpenCode$/i,light:{h:192,s:76,l:40},dark:{h:192,s:82,l:58}},{pattern:/^Codex(?: .+)?$/i,light:{h:194,s:72,l:38},dark:{h:194,s:78,l:55}},{pattern:/^GPT-5\.4 Codex$/i,light:{h:194,s:76,l:42},dark:{h:194,s:82,l:60}},{pattern:/^GPT-5\.3 Codex$/i,light:{h:194,s:70,l:36},dark:{h:194,s:74,l:52}},{pattern:/^GPT-5\.4$/i,light:{h:148,s:68,l:40},dark:{h:148,s:72,l:57}},{pattern:/^GPT-5$/i,light:{h:148,s:60,l:33},dark:{h:148,s:64,l:47}},{pattern:/^GPT-(?:4o|4\.1)(?: .+)?$/i,light:{h:160,s:58,l:34},dark:{h:160,s:62,l:49}},{pattern:/^o4 Mini$/i,light:{h:166,s:64,l:33},dark:{h:166,s:68,l:48}},{pattern:/^o1$/i,light:{h:166,s:56,l:30},dark:{h:166,s:60,l:43}},{pattern:/^Gemini 3 Flash Preview(?: .+)?$/i,light:{h:48,s:100,l:42},dark:{h:52,s:98,l:61}},{pattern:/^Gemini 2\.5 Flash$/i,light:{h:44,s:92,l:39},dark:{h:46,s:94,l:56}},{pattern:/^Gemini 2\.5 Pro$/i,light:{h:38,s:86,l:34},dark:{h:40,s:88,l:49}},{pattern:/^Gemini(?: .+)?$/i,light:{h:42,s:88,l:36},dark:{h:44,s:90,l:52}},{pattern:/^(?:Claude\s+)?Opus 4\.6$/i,light:{h:274,s:68,l:44},dark:{h:274,s:74,l:66}},{pattern:/^(?:Claude\s+)?Opus 4\.5$/i,light:{h:274,s:58,l:36},dark:{h:274,s:62,l:56}},{pattern:/^(?:Claude\s+)?Opus(?: .+)?$/i,light:{h:274,s:62,l:40},dark:{h:274,s:68,l:60}},{pattern:/^(?:Claude\s+)?Sonnet 4\.6$/i,light:{h:214,s:72,l:44},dark:{h:214,s:80,l:63}},{pattern:/^(?:Claude\s+)?Sonnet 4\.5$/i,light:{h:214,s:60,l:36},dark:{h:214,s:66,l:52}},{pattern:/^(?:Claude\s+)?Sonnet 4$/i,light:{h:214,s:56,l:34},dark:{h:214,s:62,l:48}},{pattern:/^(?:Claude\s+)?Sonnet(?: .+)?$/i,light:{h:214,s:64,l:40},dark:{h:214,s:70,l:56}},{pattern:/^(?:Claude\s+)?Haiku 4\.5$/i,light:{h:28,s:90,l:43},dark:{h:28,s:92,l:61}},{pattern:/^(?:Claude\s+)?Haiku(?: .+)?$/i,light:{h:28,s:84,l:38},dark:{h:28,s:88,l:56}}],r=[148,168,190,208,226,248,272,332,18,30,44];function i(e){return e===`light`?`light`:`dark`}function a(e){return typeof e!=`number`||!Number.isFinite(e)?null:e<=0?0:e>=1?1:Math.round(e*1e3)/1e3}function o(e){let t=0,n=String(e||``).trim().toLowerCase();for(let e=0;e<n.length;e+=1)t=(t<<5)-t+n.charCodeAt(e)|0;return t}function s(e,t){return(e%t+t)%t}function c(e){return n.find(t=>t.pattern.test(String(e||``).trim()))??null}function l(e,t){let n=o(e),i=r[s(n,r.length)],a=s(i+(Math.abs(n>>4)%7-3)*4,360);return t===`light`?{h:a,s:62+Math.abs(n>>8)%10,l:34+Math.abs(n>>12)%8}:{h:a,s:68+Math.abs(n>>8)%10,l:52+Math.abs(n>>12)%8}}function u(e,t={}){let n=i(t.theme),r=c(e);return r?{...r[n]}:l(e,n)}function d(e){return`hsl(${e.h}, ${e.s}%, ${e.l}%)`}function f(e,t){return`hsla(${e.h}, ${e.s}%, ${e.l}%, ${t})`}function p(e){let t=s(e.h,360),n=Math.max(0,Math.min(100,e.s))/100,r=Math.max(0,Math.min(100,e.l))/100,i=(1-Math.abs(2*r-1))*n,a=t/60,o=i*(1-Math.abs(a%2-1)),c=0,l=0,u=0;a>=0&&a<1?(c=i,l=o):a<2?(c=o,l=i):a<3?(l=i,u=o):a<4?(l=o,u=i):a<5?(c=o,u=i):(c=i,u=o);let d=r-i/2;return{r:Math.round((c+d)*255),g:Math.round((l+d)*255),b:Math.round((u+d)*255)}}function m(e,t={}){let n=u(e,t),r=a(t.alpha);return r===null?d(n):f(n,r)}function h(e,t={}){let{r:n,g:r,b:i}=p(u(e,t)),o=a(t.alpha);return o===null?`rgb(${n}, ${r}, ${i})`:`rgba(${n}, ${r}, ${i}, ${o})`}t.exports={MODEL_COLOR_RULES:n,getModelColor:m,getModelColorRgb:h,getModelColorSpec:u,normalizeTheme:i}})),Fe=Ne(),Ie=Pe();function Le(e){return e===`light`||e===`dark`?e:typeof document>`u`||document.documentElement.classList.contains(`dark`)?`dark`:`light`}function Re(e){return(0,Fe.normalizeModelName)(e)}function ze(e){return(0,Fe.getModelProvider)(e)}function Be(e){switch(e){case`OpenAI`:return`bg-emerald-500/10 text-emerald-400 border-emerald-500/20`;case`Anthropic`:return`bg-orange-500/10 text-orange-400 border-orange-500/20`;case`Google`:return`bg-sky-500/10 text-sky-400 border-sky-500/20`;case`xAI`:return`bg-fuchsia-500/10 text-fuchsia-400 border-fuchsia-500/20`;case`Meta`:return`bg-blue-500/10 text-blue-400 border-blue-500/20`;case`Cohere`:return`bg-lime-500/10 text-lime-400 border-lime-500/20`;case`Mistral`:return`bg-amber-500/10 text-amber-300 border-amber-500/20`;case`DeepSeek`:return`bg-teal-500/10 text-teal-300 border-teal-500/20`;case`Alibaba`:return`bg-yellow-500/10 text-yellow-300 border-yellow-500/20`;case`OpenCode`:return`bg-cyan-500/10 text-cyan-400 border-cyan-500/20`;default:return`bg-muted text-muted-foreground border-border`}}function Ve(e){switch(e){case`OpenAI`:return{color:`rgb(52, 211, 153)`,backgroundColor:`rgba(16, 185, 129, 0.10)`,borderColor:`rgba(16, 185, 129, 0.20)`};case`Anthropic`:return{color:`rgb(251, 146, 60)`,backgroundColor:`rgba(249, 115, 22, 0.10)`,borderColor:`rgba(249, 115, 22, 0.20)`};case`Google`:return{color:`rgb(56, 189, 248)`,backgroundColor:`rgba(14, 165, 233, 0.10)`,borderColor:`rgba(14, 165, 233, 0.20)`};case`xAI`:return{color:`rgb(232, 121, 249)`,backgroundColor:`rgba(217, 70, 239, 0.10)`,borderColor:`rgba(217, 70, 239, 0.20)`};case`Meta`:return{color:`rgb(96, 165, 250)`,backgroundColor:`rgba(59, 130, 246, 0.10)`,borderColor:`rgba(59, 130, 246, 0.20)`};case`Cohere`:return{color:`rgb(163, 230, 53)`,backgroundColor:`rgba(132, 204, 22, 0.10)`,borderColor:`rgba(132, 204, 22, 0.20)`};case`Mistral`:return{color:`rgb(252, 211, 77)`,backgroundColor:`rgba(245, 158, 11, 0.10)`,borderColor:`rgba(245, 158, 11, 0.20)`};case`DeepSeek`:return{color:`rgb(45, 212, 191)`,backgroundColor:`rgba(20, 184, 166, 0.10)`,borderColor:`rgba(20, 184, 166, 0.20)`};case`Alibaba`:return{color:`rgb(250, 204, 21)`,backgroundColor:`rgba(234, 179, 8, 0.10)`,borderColor:`rgba(234, 179, 8, 0.20)`};case`OpenCode`:return{color:`rgb(34, 211, 238)`,backgroundColor:`rgba(6, 182, 212, 0.10)`,borderColor:`rgba(6, 182, 212, 0.20)`};default:return{color:`rgb(148, 163, 184)`,backgroundColor:`rgba(100, 116, 139, 0.10)`,borderColor:`rgba(100, 116, 139, 0.20)`}}}function He(e,t){return(0,Ie.getModelColor)(e,{theme:Le(t)})}function Ue(e,t,n){return(0,Ie.getModelColor)(e,{theme:Le(n),alpha:t})}function We(e){let t=new Set;for(let n of e)for(let e of n)t.add(Re(e));return Array.from(t).sort()}function Ge(e){let t=new Set;for(let n of e)for(let e of n)t.add(ze(e));return Array.from(t).sort()}function Ke(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`}function Z(){return Ke(new Date)}function qe(){return Z().slice(0,7)}function Je(e){if(typeof e==`number`)return Number.isFinite(e)?e:null;if(typeof e==`string`){let t=Number(e);return Number.isFinite(t)?t:null}return null}function Ye(e){return e>=1e3?`$${(e/1e3).toFixed(1)}k`:e>=100?`$${Math.round(e)}`:e>=10?`$${e.toFixed(1)}`:`$${e.toFixed(2)}`}function Xe(e){return`$${e.toLocaleString(q(),{minimumFractionDigits:2,maximumFractionDigits:2})}`}function Ze(e){return Number.isFinite(e)?e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:e>=100?e.toFixed(0):e>=10?e.toFixed(1):e>=1?e.toFixed(2):e===0?`0`:e.toFixed(3):`0`}function Q(e){return e.toLocaleString(q())}function Qe(e){return`${e.toLocaleString(q())} ${J.t(`common.tokens`)}`}function $(e,t=1){return`${e.toFixed(t)}%`}function $e(e,t=`short`){if(/^\d{4}$/.test(e))return e;if(/^\d{4}-\d{2}$/.test(e)){let[n=`0`,r=`1`]=e.split(`-`),i=new Date(parseInt(n,10),parseInt(r,10)-1);return t===`short`?i.toLocaleDateString(q(),{month:`short`,year:`2-digit`}):i.toLocaleDateString(q(),{month:`long`,year:`numeric`})}let n=new Date(e+`T00:00:00`);return t===`long`?n.toLocaleDateString(q(),{weekday:`short`,day:`2-digit`,month:`2-digit`,year:`numeric`}):t===`weekday`?n.toLocaleDateString(q(),{weekday:`short`}):n.toLocaleDateString(q(),{day:`2-digit`,month:`2-digit`})}function et(e){if(/^\d{4}$/.test(e))return e;if(/^\d{4}-\d{2}$/.test(e)){let[t=`0`,n=`1`]=e.split(`-`);return new Date(parseInt(t,10),parseInt(n,10)-1).toLocaleDateString(q(),{month:`short`,year:`2-digit`})}return new Date(e+`T00:00:00`).toLocaleDateString(q(),{day:`2-digit`,month:`2-digit`})}function tt(e,t=!1){return e===`monthly`?J.t(t?`periods.months`:`periods.month`):e===`yearly`?J.t(t?`periods.years`:`periods.year`):J.t(t?`periods.days`:`periods.day`)}function nt(e){return e===`monthly`?J.t(`periods.unitMonth`):e===`yearly`?J.t(`periods.unitYear`):J.t(`periods.unitDay`)}function rt(e){if(!/^\d{4}-\d{2}$/.test(e))return``;let[t=``,n=``]=e.split(`-`),r=Number.parseInt(t,10),i=Number.parseInt(n,10);return!Number.isInteger(r)||!Number.isInteger(i)||i<1||i>12?``:new Date(r,i-1).toLocaleDateString(q(),{month:`long`,year:`numeric`})}function it(e){let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toLocaleString(q(),{day:`2-digit`,month:`2-digit`,hour:`2-digit`,minute:`2-digit`})}function at(e){let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toLocaleString(q(),{day:`2-digit`,month:`2-digit`,year:`numeric`,hour:`2-digit`,minute:`2-digit`})}var ot={currency:e=>Ye(e),tokens:e=>Ze(e),number:e=>Q(e),percent:(e,t)=>$(e,t)},st={currency:e=>Xe(e),tokens:e=>Qe(e),number:e=>Q(e),percent:e=>$(e,4)};function ct({value:e,type:t,className:n,decimals:r,label:i,insight:a,interactive:o=!0}){let s=ot[t](e,r),c=st[t](e);if(s===c)return(0,h.jsx)(`span`,{className:n,children:s});let l=i?`${i}: ${c}`:c;return o?(0,h.jsxs)(_,{children:[(0,h.jsx)(v,{asChild:!0,children:(0,h.jsx)(`button`,{type:`button`,"aria-label":l,className:d(`inline rounded-sm border-0 bg-transparent p-0 text-inherit cursor-help decoration-dotted underline underline-offset-4 decoration-muted-foreground/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2`,n),children:s})}),(0,h.jsx)(y,{className:`max-w-[260px]`,children:(0,h.jsxs)(`div`,{className:`space-y-1`,children:[i&&(0,h.jsx)(`div`,{className:`text-[10px] uppercase tracking-[0.14em] text-muted-foreground`,children:i}),(0,h.jsx)(`div`,{className:`font-mono text-xs`,children:c}),a&&(0,h.jsx)(`div`,{className:`text-[11px] text-muted-foreground leading-relaxed`,children:a})]})})]}):(0,h.jsxs)(`span`,{className:d(`cursor-help decoration-dotted underline underline-offset-4 decoration-muted-foreground/40`,n),title:a?`${c} — ${a}`:c,children:[(0,h.jsx)(`span`,{"aria-hidden":`true`,children:s}),(0,h.jsxs)(`span`,{className:`sr-only`,children:[l,a?`. ${a}`:``]})]})}function lt({active:e,payload:t,label:n,formatter:r,pinnedEntryNames:i=[],showComputedTotal:a=!0,hideZeroValues:o=!1}){let{t:s}=f();if(!e||!t?.length)return null;let c=e=>e.name.includes(`Ø`)||e.dataKey?.toString().includes(`MA7`)||e.dataKey?.toString().includes(`_ma7`),l=e=>i.includes(e.name),u=e=>!o||Math.abs(e.value??0)>1e-4,d=t.filter(e=>!c(e)&&!l(e)&&u(e)).sort((e,t)=>(t.value??0)-(e.value??0)),p=t.filter(e=>!c(e)&&l(e)&&u(e)),m=t.filter(e=>c(e)),g=d.reduce((e,t)=>e+(t.value??0),0),_=a&&d.length>=2,v=t[0]?.payload??{},y=d.length===1?d[0]:p.length===1?p[0]:null,b=y?v[`${y.dataKey}Prev`]:void 0,x=typeof b==`number`?b:null,S=y?m.find(e=>e.dataKey===`${y.dataKey}MA7`||e.dataKey===`${y.dataKey.toString().toLowerCase()}MA7`)??(m.length===1?m[0]:null):null,C=y&&x!==null?y.value-x:null,w=y&&S?y.value-S.value:null,T=s(`customTooltip.total`),E=s(`customTooltip.delta`);return(0,h.jsxs)(`div`,{className:`max-w-[280px] bg-popover/90 backdrop-blur-xl border border-border/50 rounded-lg shadow-lg p-3 text-xs`,children:[(0,h.jsx)(`p`,{className:`font-medium text-muted-foreground mb-1.5`,children:n}),(0,h.jsxs)(`div`,{className:`space-y-1.5`,children:[d.map((e,t)=>{let n=_&&g>0?e.value/g*100:null;return(0,h.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,h.jsx)(`span`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color}}),(0,h.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.name,`:`]}),(0,h.jsx)(`span`,{className:`font-mono font-medium text-foreground ml-auto`,children:r?r(e.value,e.name):e.value}),n!==null&&(0,h.jsxs)(`span`,{className:`text-muted-foreground/60 font-mono w-10 text-right`,children:[n.toFixed(0),`%`]})]},t)}),_&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`div`,{className:`border-t border-border/40 my-1`}),(0,h.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,h.jsx)(`span`,{className:`w-2 h-2 shrink-0`}),(0,h.jsxs)(`span`,{className:`text-muted-foreground font-medium`,children:[T,`:`]}),(0,h.jsx)(`span`,{className:`font-mono font-medium text-foreground ml-auto`,children:r?r(g,T):g}),(0,h.jsx)(`span`,{className:`text-muted-foreground/60 font-mono w-10 text-right`,children:`100%`})]})]}),m.length>0&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`div`,{className:`border-t border-border/40 my-1`}),m.map((e,t)=>(0,h.jsxs)(`div`,{className:`flex items-center gap-2 opacity-70`,children:[(0,h.jsx)(`span`,{className:`w-2 h-0.5 shrink-0 border-t border-dashed`,style:{borderColor:e.color}}),(0,h.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.name,`:`]}),(0,h.jsx)(`span`,{className:`font-mono font-medium text-foreground ml-auto`,children:r?r(e.value,e.name):e.value})]},`ma-${t}`))]}),p.length>0&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`div`,{className:`border-t border-border/40 my-1`}),p.map((e,t)=>(0,h.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,h.jsx)(`span`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color}}),(0,h.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.name,`:`]}),(0,h.jsx)(`span`,{className:`font-mono font-medium text-foreground ml-auto`,children:r?r(e.value,e.name):e.value})]},`pinned-${t}`))]}),(C!==null||w!==null)&&(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`div`,{className:`border-t border-border/40 my-1`}),C!==null&&(0,h.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,h.jsx)(`span`,{className:`w-2 h-2 shrink-0`}),(0,h.jsxs)(`span`,{className:`text-muted-foreground`,children:[s(`customTooltip.vsPrevious`),`:`]}),(0,h.jsxs)(`span`,{className:`font-mono font-medium text-foreground ml-auto`,children:[C>=0?`+`:``,r?r(C,E):C]})]}),w!==null&&(0,h.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,h.jsx)(`span`,{className:`w-2 h-2 shrink-0`}),(0,h.jsxs)(`span`,{className:`text-muted-foreground`,children:[s(`customTooltip.vsAverage`),`:`]}),(0,h.jsxs)(`span`,{className:`font-mono font-medium text-foreground ml-auto`,children:[w>=0?`+`:``,r?r(w,E):w]})]})]})]})]})}export{q as A,Ve as C,Ne as D,Re as E,g as F,v as I,Oe as M,_ as N,Te as O,y as P,Be as S,Ge as T,nt as _,Xe as a,Ue as b,it as c,Q as d,$ as f,tt as g,Z as h,Ye as i,J as j,ke as k,at as l,qe as m,ct as n,$e as o,Ze as p,Je as r,et as s,lt as t,rt as u,Ke as v,We as w,ze as x,He as y};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-COnpUsM8.js";import{_ as t,b as n,g as r,i,v as a,w as o}from"./charts-vendor-CiBqdKXh.js";import{r as s}from"./motion-vendor-BXI2L__C.js";import{a as c,c as l,i as u,n as d,o as f,r as p,t as m}from"./dialog-CA-ZSHjK.js";import{E as h,S as g,f as _,i as v,n as y,o as b,p as x,t as S,x as C,y as w}from"./CustomTooltip-CdIOw3Ep.js";var T=e(o()),E=s();function D({day:e,contextData:o=[],open:s,onClose:D}){let{t:O}=f(),k=(0,T.useMemo)(()=>{if(!e)return[];let t=new Map;for(let n of e.modelBreakdowns){let e=h(n.modelName),r=t.get(e)??{cost:0,tokens:0,input:0,output:0,cacheRead:0,cacheCreate:0,thinking:0,requests:0};r.cost+=n.cost,r.tokens+=n.inputTokens+n.outputTokens+n.cacheCreationTokens+n.cacheReadTokens+n.thinkingTokens,r.input+=n.inputTokens,r.output+=n.outputTokens,r.cacheRead+=n.cacheReadTokens,r.cacheCreate+=n.cacheCreationTokens,r.thinking+=n.thinkingTokens,r.requests+=n.requestCount,t.set(e,r)}return Array.from(t.entries()).map(([e,t])=>({name:e,...t})).sort((e,t)=>t.cost-e.cost)},[e]);if(!e)return null;let A=e.cacheReadTokens+e.cacheCreationTokens+e.inputTokens+e.outputTokens+e.thinkingTokens,j=A>0,M=j?e.cacheReadTokens/A*100:0,N=k.map(e=>({name:e.name,value:e.cost})),P=e.requestCount>0?A/e.requestCount:0,F=e.requestCount>0?e.totalCost/e.requestCount:0,I=j?e.totalCost/(A/1e6):null,L=[...o].sort((e,t)=>t.totalCost-e.totalCost).findIndex(t=>t.date===e.date)+1,R=[...o].sort((e,t)=>t.requestCount-e.requestCount).findIndex(t=>t.date===e.date)+1,z=[...o].filter(t=>t.date<e.date).sort((e,t)=>e.date.localeCompare(t.date)).slice(-7),B=z.length>0?z.reduce((e,t)=>e+t.totalCost,0)/z.length:null,V=z.length>0?z.reduce((e,t)=>e+t.requestCount,0)/z.length:null,H=k.reduce((e,t)=>!e||t.requests>e.requests?t:e,null),U=e=>j?_(e/A*100):`–`,W=[{id:`cacheRead`,value:e.cacheReadTokens,color:`hsl(160, 50%, 42%)`,label:O(`drillDown.tokenSegments.cacheRead`)},{id:`cacheWrite`,value:e.cacheCreationTokens,color:`hsl(262, 60%, 55%)`,label:O(`drillDown.tokenSegments.cacheWrite`)},{id:`input`,value:e.inputTokens,color:`hsl(340, 55%, 52%)`,label:O(`common.input`)},{id:`output`,value:e.outputTokens,color:`hsl(35, 80%, 52%)`,label:O(`common.output`)},{id:`thinking`,value:e.thinkingTokens,color:`hsl(12, 78%, 56%)`,label:O(`common.thinking`)}];return(0,E.jsx)(m,{open:s,onOpenChange:e=>!e&&D(),children:(0,E.jsxs)(d,{className:`max-w-2xl`,children:[(0,E.jsxs)(u,{children:[(0,E.jsxs)(c,{children:[b(e.date,`long`),` — `,v(e.totalCost)]}),(0,E.jsx)(p,{children:O(`drillDown.description`)})]}),(0,E.jsxs)(`div`,{className:`grid grid-cols-2 sm:grid-cols-4 gap-3 text-center`,children:[(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`common.tokens`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:(0,E.jsx)(y,{value:A,type:`tokens`})})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`$/1M`}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:I===null?`–`:(0,E.jsx)(y,{value:I,type:`currency`})})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`drillDown.cacheRate`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:(0,E.jsx)(y,{value:M,type:`percent`})})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`common.models`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:k.length})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`common.requests`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:(0,E.jsx)(y,{value:e.requestCount,type:`number`})})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`common.thinking`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:(0,E.jsx)(y,{value:e.thinkingTokens,type:`tokens`})})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`drillDown.tokensPerRequest`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:(0,E.jsx)(y,{value:P,type:`tokens`})})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`drillDown.costPerRequest`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:(0,E.jsx)(y,{value:F,type:`currency`})})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`drillDown.costRank`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:L>0?`#${L}`:`–`})]}),(0,E.jsxs)(`div`,{className:`p-2 rounded-lg bg-muted/30`,children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:O(`drillDown.requestRank`)}),(0,E.jsx)(`div`,{className:`font-mono font-medium`,children:R>0?`#${R}`:`–`})]})]}),(0,E.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-3 gap-3 text-xs`,children:[(0,E.jsxs)(`div`,{className:`rounded-lg border border-border/50 bg-muted/20 px-3 py-2`,children:[(0,E.jsx)(`div`,{className:`text-muted-foreground`,children:O(`drillDown.topRequestModel`)}),(0,E.jsx)(`div`,{className:`mt-1 font-medium`,children:H?.name??`–`})]}),(0,E.jsxs)(`div`,{className:`rounded-lg border border-border/50 bg-muted/20 px-3 py-2`,children:[(0,E.jsx)(`div`,{className:`text-muted-foreground`,children:O(`drillDown.costVsAverage7d`)}),(0,E.jsx)(`div`,{className:`mt-1 font-medium`,children:B===null?`–`:`${e.totalCost>=B?`↑`:`↓`} ${v(Math.abs(e.totalCost-B))}`})]}),(0,E.jsxs)(`div`,{className:`rounded-lg border border-border/50 bg-muted/20 px-3 py-2`,children:[(0,E.jsx)(`div`,{className:`text-muted-foreground`,children:O(`drillDown.requestsVsAverage7d`)}),(0,E.jsx)(`div`,{className:`mt-1 font-medium`,children:V===null?`–`:`${e.requestCount>=V?`↑`:`↓`} ${Math.abs(e.requestCount-V).toFixed(0)}`})]})]}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground mb-1.5`,children:O(`drillDown.tokenDistribution`)}),(0,E.jsx)(`div`,{className:`flex h-3 rounded-full overflow-hidden`,children:j&&W.map(e=>(0,E.jsx)(`div`,{className:`h-full transition-all duration-500`,style:{width:`${e.value/A*100}%`,backgroundColor:e.color},title:`${e.label}: ${x(e.value)} (${(e.value/A*100).toFixed(1)}%)`},e.id))}),(0,E.jsx)(`div`,{className:`flex gap-3 mt-1.5 text-[10px] text-muted-foreground`,children:W.map(e=>(0,E.jsxs)(`span`,{className:`flex items-center gap-1`,children:[(0,E.jsx)(`span`,{className:`w-2 h-2 rounded-full`,style:{backgroundColor:e.color}}),e.label,` `,U(e.value)]},e.id))})]}),(0,E.jsxs)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 gap-4`,children:[(0,E.jsx)(`div`,{children:(0,E.jsx)(n,{width:`100%`,height:180,children:(0,E.jsxs)(i,{children:[(0,E.jsx)(r,{data:N,cx:`50%`,cy:`50%`,innerRadius:40,outerRadius:70,paddingAngle:2,dataKey:`value`,children:N.map(e=>(0,E.jsx)(t,{fill:w(e.name)},e.name))}),(0,E.jsx)(a,{content:(0,E.jsx)(S,{formatter:e=>v(e)})})]})})}),(0,E.jsx)(`div`,{className:`space-y-2`,children:k.map(t=>{let n=e.totalCost>0?t.cost/e.totalCost*100:0;return(0,E.jsxs)(`div`,{className:`flex items-center justify-between text-sm p-1.5 rounded hover:bg-muted/30`,children:[(0,E.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,E.jsx)(`span`,{className:`w-2.5 h-2.5 rounded-full`,style:{backgroundColor:w(t.name)}}),(0,E.jsx)(`span`,{children:t.name}),(0,E.jsx)(`span`,{className:l(`inline-flex items-center rounded-full border px-1.5 py-0.5 text-[10px] font-medium leading-none`,g(C(t.name))),children:C(t.name)}),(0,E.jsx)(`span`,{className:`text-[10px] text-muted-foreground`,children:_(n)})]}),(0,E.jsxs)(`div`,{className:`text-right font-mono`,children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`span`,{className:`font-medium`,children:(0,E.jsx)(y,{value:t.cost,type:`currency`})}),(0,E.jsx)(`span`,{className:`text-muted-foreground ml-2 text-xs`,children:(0,E.jsx)(y,{value:t.tokens,type:`tokens`})}),(0,E.jsx)(`span`,{className:`text-muted-foreground ml-2 text-xs`,children:O(`drillDown.requestCountShort`,{count:t.requests})})]}),(0,E.jsx)(`div`,{className:`text-[10px] text-muted-foreground mt-0.5`,children:t.requests>0?O(`drillDown.modelRequestSummary`,{costPerRequest:v(t.cost/t.requests),tokensPerRequest:x(t.tokens/t.requests)}):O(`drillDown.noRequests`)})]})]},t.name)})})]})]})})}export{D as DrillDownModal};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-COnpUsM8.js";import{S as t,w as n}from"./charts-vendor-CiBqdKXh.js";import{r}from"./motion-vendor-BXI2L__C.js";import{y as i}from"./ui-vendor-BGjRFQGY.js";import{c as a}from"./dialog-CA-ZSHjK.js";var o=e(n()),s=e=>typeof e==`boolean`?`${e}`:e===0?`0`:e,c=t,l=(e,t)=>n=>{if(t?.variants==null)return c(e,n?.class,n?.className);let{variants:r,defaultVariants:i}=t,a=Object.keys(r).map(e=>{let t=n?.[e],a=i?.[e];if(t===null)return null;let o=s(t)||s(a);return r[e][o]}),o=n&&Object.entries(n).reduce((e,t)=>{let[n,r]=t;return r===void 0||(e[n]=r),e},{});return c(e,a,t?.compoundVariants?.reduce((e,t)=>{let{class:n,className:r,...a}=t;return Object.entries(a).every(e=>{let[t,n]=e;return Array.isArray(n)?n.includes({...i,...o}[t]):{...i,...o}[t]===n})?[...e,n,r]:e},[]),n?.class,n?.className)},u=r(),d=l(`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 cursor-pointer`,{variants:{variant:{default:`bg-primary text-primary-foreground hover:bg-primary/90`,destructive:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,outline:`border border-border bg-transparent hover:bg-accent hover:text-accent-foreground`,secondary:`bg-secondary text-secondary-foreground hover:bg-secondary/80`,ghost:`hover:bg-accent hover:text-accent-foreground`,link:`text-primary underline-offset-4 hover:underline`},size:{default:`h-9 px-4 py-2`,sm:`h-8 rounded-md px-3 text-xs`,lg:`h-10 rounded-md px-8`,icon:`h-9 w-9`}},defaultVariants:{variant:`default`,size:`default`}}),f=o.forwardRef(({className:e,variant:t,size:n,asChild:r=!1,...o},s)=>(0,u.jsx)(r?i:`button`,{className:a(d({variant:t,size:n,className:e})),ref:s,...o}));f.displayName=`Button`;export{f as t};
|