diff --git a/NEWS.md b/NEWS.md index f162e5aab..fff87cc44 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,45 @@ entry gives the `old -> new` migration; the `plant-update-interface` skill (`.claude/skills/plant-update-interface/`) reads this section to migrate products using plant. +* **The density coordinate is now chosen per model, and TF24 defaults to birth + date (#516).** `Control`'s boolean flag becomes a three-valued string, so that + a model can carry a default a passed `Control` does not silently override. + Migration: + + * `control(node_density_in_birth_date = TRUE)` -> `control(node_density_coordinate = "birth_date")` + * `control(node_density_in_birth_date = FALSE)` -> `control(node_density_coordinate = "height")` + * `ctrl$node_density_in_birth_date` -> `ctrl$node_density_coordinate` (`"auto"`/`"birth_date"`/`"height"`) + * *(resolved value, per species/node)* -> `species$density_in_birth_date` / `node$density_in_birth_date` + + ⚠️ **This changes TF24 and TF24f results for identical inputs**, by several + times on offspring production, and bumps `TF24@v9 -> v10` (`TF24f@v9.1 -> + v10.1`). `"auto"` is the new default and resolves to `"birth_date"` for + TF24/TF24f and `"height"` for FF16/K93, so **FF16 and K93 are bit-identical** + — `auto` resolves to the same `false` the old default carried, and their + reference baselines are untouched. + + Why it is not merely a numerical preference: the height coordinate's density + rate carries a compression term that equals `d(growth)/d(height)` only when + growth is a function of size alone. TF24's reserve pool feeds back into + growth, so the finite-difference probe moves height at fixed *absolute* + carbon and shifts the reserve fraction, whereas a cohort actually grows at + roughly constant reserve fraction — a different derivative, not a coarser one + (#590). Refinement confirms it: the birth-date answers are converged at the + default schedule while the height ones keep climbing and the exclusion ratio + widens instead of closing. + + An unrecognised value is refused rather than read as one of the two + coordinates, since a typo would otherwise return a plausible number. The + empty string is accepted as a synonym for `"auto"`, matching how + `shading_model` already spells "let the model decide". + + ⚠️ **A `Species` built outside a `Patch` cannot use the birth-date coordinate.** + The no-argument `introduce_new_node()` leaves every node carrying the same + birth date, which spans zero width, so the competition integral collapses to + exactly `0` and `log_densities` is `NA`. A real run cannot reach this — `Patch` + checks the birth dates are distinct and errors — but bare-`Species` diagnostic + code should set `node_density_coordinate = "height"` explicitly. + * **An unknown trait name is now an error (#636).** `generate_strategy()` (and `add_strategies()` / `add_mutant()`, which route through it) refuse a trait whose name is not a parameter of the model, naming the offenders and their @@ -539,6 +578,15 @@ were not previously recorded here: the two. The depth profile itself is not exposed — a fixed-width aux slot cannot carry a per-node vector — so the second half of #625 (reporting each leaf output against crown depth) remains open. +* **TF24 sapwood can track the Huber value that maximises growth (`a_sw`, #516).** `d(log A_s departure)/dt` gains `a_sw * R_s`, an integral controller on the marginal *growth* return of sapwood area. It converges onto `R_s = 0` rather than tracking with an offset, and because integrating is averaging, a small `a_sw` makes the stem follow the long-run mean of a signal that swings with the weather — no extra tracked state. + + The objective is growth, not net production, and the distinction is the whole design: against production extra sapwood is nearly always worth building, because it raises `k_max` and nothing charges the plant for the leaf area it did not build instead. `R_s` subtracts that price, which moves the optimum from far out (production's) in to where height growth actually peaks. That optimum is **not a single number**: it rises with height (0.87x the pipe-model ratio at 5 m, 1.05x at 10 m, 1.21x at 16 m, 1.30x at 20 m, moist soil) and rises again as soil dries, so no single fixed `theta` reproduces it. Measured after #617; the levels are the hydraulics' to set. + + ⚠️ `d(profit)/d(kmax)` costs a second full leaf solve, so `a_sw > 0` roughly doubles the leaf work per rate evaluation. The envelope-theorem shortcut — re-evaluate at the collar potential already found and the indirect term vanishes — **does not apply**: `opt_root_psi_` is a root-find (supply matching demand), not a maximisation, so the derivative of profit with respect to it is not zero. Holding it fixed under-reports the sensitivity by 15–19%. The default `a_sw = 0` skips the whole block. + + **`a_sw = 0` is the default and the model is then bit-exact** — the controller block is skipped entirely, and the one expression that changed unconditionally (`theta` becomes `theta * exp(psi)` in the conductance) is `theta * 1.0` at rest. + + ⚠️ **Refused with the deep-crown shading model.** The sensitivity is measured at a single radiation and deep-crown integrates profit over crown positions, so the difference is not its derivative. `prepare_strategy()` throws rather than skipping it, because skipping leaves the controller with only its negative cost term and the stem shrinks without bound while the run looks plausible the whole way down. * **The NSC storage pool is bounded by the shape of its own flow (`TF24@v9`, `TF24f@v9.1`).** `dS/dt` was `net_flux > 0 ? net_flux : floor_gate * net_flux` diff --git a/R/RcppExports.R b/R/RcppExports.R index bfae6c847..881676500 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -1521,6 +1521,10 @@ Node___FF16__FF16_Env__growth_rate_at_birth__get <- function(obj_) { .Call('_plant_Node___FF16__FF16_Env__growth_rate_at_birth__get', PACKAGE = 'plant', obj_) } +Node___FF16__FF16_Env__density_in_birth_date__get <- function(obj_) { + .Call('_plant_Node___FF16__FF16_Env__density_in_birth_date__get', PACKAGE = 'plant', obj_) +} + Node___FF16__FF16_Env__fecundity__get <- function(obj_) { .Call('_plant_Node___FF16__FF16_Env__fecundity__get', PACKAGE = 'plant', obj_) } @@ -1585,6 +1589,10 @@ Node___TF24__TF24_Env__growth_rate_at_birth__get <- function(obj_) { .Call('_plant_Node___TF24__TF24_Env__growth_rate_at_birth__get', PACKAGE = 'plant', obj_) } +Node___TF24__TF24_Env__density_in_birth_date__get <- function(obj_) { + .Call('_plant_Node___TF24__TF24_Env__density_in_birth_date__get', PACKAGE = 'plant', obj_) +} + Node___TF24__TF24_Env__fecundity__get <- function(obj_) { .Call('_plant_Node___TF24__TF24_Env__fecundity__get', PACKAGE = 'plant', obj_) } @@ -1649,6 +1657,10 @@ Node___TF24f__TF24_Env__growth_rate_at_birth__get <- function(obj_) { .Call('_plant_Node___TF24f__TF24_Env__growth_rate_at_birth__get', PACKAGE = 'plant', obj_) } +Node___TF24f__TF24_Env__density_in_birth_date__get <- function(obj_) { + .Call('_plant_Node___TF24f__TF24_Env__density_in_birth_date__get', PACKAGE = 'plant', obj_) +} + Node___TF24f__TF24_Env__fecundity__get <- function(obj_) { .Call('_plant_Node___TF24f__TF24_Env__fecundity__get', PACKAGE = 'plant', obj_) } @@ -1713,6 +1725,10 @@ Node___K93__K93_Env__growth_rate_at_birth__get <- function(obj_) { .Call('_plant_Node___K93__K93_Env__growth_rate_at_birth__get', PACKAGE = 'plant', obj_) } +Node___K93__K93_Env__density_in_birth_date__get <- function(obj_) { + .Call('_plant_Node___K93__K93_Env__density_in_birth_date__get', PACKAGE = 'plant', obj_) +} + Node___K93__K93_Env__fecundity__get <- function(obj_) { .Call('_plant_Node___K93__K93_Env__fecundity__get', PACKAGE = 'plant', obj_) } diff --git a/R/RcppR6.R b/R/RcppR6.R index 85394f41f..290e55b92 100644 --- a/R/RcppR6.R +++ b/R/RcppR6.R @@ -1,6 +1,6 @@ ## Generated by RcppR6: do not edit by hand ## Version: 0.2.4 -## Hash: 2d29268c82e8129b38fbce4d1c832ee0 +## Hash: ece3258b408ecfd871ba1d78ada61c97 ##' @importFrom Rcpp evalCpp ##' @importFrom R6 R6Class @@ -1974,6 +1974,13 @@ Node <- function(T, E) { stop("Node$growth_rate_at_birth is read-only") } }, + density_in_birth_date = function(value) { + if (missing(value)) { + Node___FF16__FF16_Env__density_in_birth_date__get(self) + } else { + stop("Node$density_in_birth_date is read-only") + } + }, fecundity = function(value) { if (missing(value)) { Node___FF16__FF16_Env__fecundity__get(self) @@ -2072,6 +2079,13 @@ Node <- function(T, E) { stop("Node$growth_rate_at_birth is read-only") } }, + density_in_birth_date = function(value) { + if (missing(value)) { + Node___TF24__TF24_Env__density_in_birth_date__get(self) + } else { + stop("Node$density_in_birth_date is read-only") + } + }, fecundity = function(value) { if (missing(value)) { Node___TF24__TF24_Env__fecundity__get(self) @@ -2170,6 +2184,13 @@ Node <- function(T, E) { stop("Node$growth_rate_at_birth is read-only") } }, + density_in_birth_date = function(value) { + if (missing(value)) { + Node___TF24f__TF24_Env__density_in_birth_date__get(self) + } else { + stop("Node$density_in_birth_date is read-only") + } + }, fecundity = function(value) { if (missing(value)) { Node___TF24f__TF24_Env__fecundity__get(self) @@ -2268,6 +2289,13 @@ Node <- function(T, E) { stop("Node$growth_rate_at_birth is read-only") } }, + density_in_birth_date = function(value) { + if (missing(value)) { + Node___K93__K93_Env__density_in_birth_date__get(self) + } else { + stop("Node$density_in_birth_date is read-only") + } + }, fecundity = function(value) { if (missing(value)) { Node___K93__K93_Env__fecundity__get(self) diff --git a/R/scenario_eval.R b/R/scenario_eval.R index e0f4e77a1..d47efdf27 100644 --- a/R/scenario_eval.R +++ b/R/scenario_eval.R @@ -109,7 +109,7 @@ scenario_to_config <- function(row, mapping) { } ##' @return \code{scenario_control} returns the \code{Control} the gateway runs -##' under: \code{control()} with \code{node_density_in_birth_date = TRUE}. +##' under: \code{control()} with \code{node_density_coordinate = "birth_date"}. ##' ##' Every scenario here is TF24, and TF24 is the model the two density ##' coordinates genuinely disagree on (#590). The transport equation's @@ -129,7 +129,10 @@ scenario_to_config <- function(row, mapping) { ##' @rdname scenario_eval ##' @export scenario_control <- function() { - control(node_density_in_birth_date = TRUE) + ## Set explicitly rather than left on "auto" (which TF24 now resolves to the + ## same thing), so the coordinate recorded in a stored scorecard's metadata is + ## the resolved one and not a value a reader has to resolve themselves. + control(node_density_coordinate = "birth_date") } ##' @param config A config list from \code{scenario_to_config}. @@ -411,7 +414,10 @@ run_scenarios <- function(scenarios = read_scenario_table(), ## verdict -- so a stored scorecard that does not say which produced it cannot ## honestly be compared against another, and the blessed baseline is exactly ## such a stored scorecard. - meta$node_density_in_birth_date <- ctrl$node_density_in_birth_date + ## The requested coordinate. scenario_control() sets it explicitly rather than + ## leaving it on "auto", so what is stored here is the coordinate the run + ## actually used and not one the reader has to resolve against the model. + meta$node_density_coordinate <- ctrl$node_density_coordinate meta$max_patch_lifetime <- max_patch_lifetime attr(scorecard, "metadata") <- meta attr(scorecard, "max_patch_lifetime") <- max_patch_lifetime diff --git a/inst/.DS_Store b/inst/.DS_Store new file mode 100644 index 000000000..07ca829f0 Binary files /dev/null and b/inst/.DS_Store differ diff --git a/inst/RcppR6_classes.yml b/inst/RcppR6_classes.yml index e3e38a3fc..56962934d 100644 --- a/inst/RcppR6_classes.yml +++ b/inst/RcppR6_classes.yml @@ -375,7 +375,7 @@ Control: - node_gradient_direction: int - node_gradient_richardson: bool - node_gradient_richardson_depth: size_t - - node_density_in_birth_date: bool + - node_density_coordinate: std::string - ode_step_size_initial: double - ode_step_size_min: double - ode_step_size_max: double @@ -628,6 +628,11 @@ Node: ## Exact and current for the boundary node; frozen at its own birth for an ## introduced one. growth_rate_at_birth: {type: double, access: member, readonly: true} + ## Which coordinate this node's density is carried in, with Control's + ## "auto" already resolved against the model's own requirement. Read this + ## rather than restating which models prefer which coordinate: the density + ## rate and the boundary condition both differ between them. + density_in_birth_date: {type: bool, access: member, readonly: true} fecundity: {type: double, access: member} ode_size: {type: size_t, access: member} ode_state: {type: "std::vector", access: function, name_cpp: "odelia::ode::r_ode_state", name_cpp_set: "odelia::ode::r_set_ode_state"} @@ -672,8 +677,10 @@ Species: ## |dh/dtau| per node, boundary node last; the conversion between the two. height_jacobian: {type: "std::vector", access: member, readonly: true} node_times: {type: "std::vector", access: member} - ## Which coordinate this species' size distribution is carried in. Set from - ## the patch's control, not the strategy's (Patch::add_strategies). + ## Which coordinate this species' size distribution is carried in: the + ## patch's control (not the strategy's -- Patch::add_strategies), with + ## "auto" resolved against the model's own requirement. This is the resolved + ## value, so it is what a run should be reported against. density_in_birth_date: {type: bool, access: member, readonly: true} patch_densities: {type: "std::vector", access: member, name_cpp: r_patch_densities} pr_patch_survival_at_birth: {type: "std::vector", access: member, name_cpp: r_pr_patch_survival_at_birth} @@ -1343,6 +1350,12 @@ TF24_Pars: - a_st1: double - a_st2: double - a_st3: double + - a_pl0: double + - a_pl1: double + - a_pl2: double + - a_pl3: double + - a_pl4: double + - a_sw: double - k_I: double # ⚠️ The leaf traits carry phylloptim's names (#634). One name per quantity, # spelled the same on both sides of the boundary; see TF24_Pars in diff --git a/inst/include/plant/RcppR6_post.hpp b/inst/include/plant/RcppR6_post.hpp index a8de06b35..98a1ef396 100644 --- a/inst/include/plant/RcppR6_post.hpp +++ b/inst/include/plant/RcppR6_post.hpp @@ -430,7 +430,7 @@ template <> inline SEXP wrap(const plant::Control& x) { ret["node_gradient_direction"] = Rcpp::wrap(x.node_gradient_direction); ret["node_gradient_richardson"] = Rcpp::wrap(x.node_gradient_richardson); ret["node_gradient_richardson_depth"] = Rcpp::wrap(x.node_gradient_richardson_depth); - ret["node_density_in_birth_date"] = Rcpp::wrap(x.node_density_in_birth_date); + ret["node_density_coordinate"] = Rcpp::wrap(x.node_density_coordinate); ret["ode_step_size_initial"] = Rcpp::wrap(x.ode_step_size_initial); ret["ode_step_size_min"] = Rcpp::wrap(x.ode_step_size_min); ret["ode_step_size_max"] = Rcpp::wrap(x.ode_step_size_max); @@ -479,8 +479,8 @@ template <> inline plant::Control as(SEXP x) { ret.node_gradient_richardson = Rcpp::as(xl["node_gradient_richardson"]); // ret.node_gradient_richardson_depth = Rcpp::as(xl["node_gradient_richardson_depth"]); ret.node_gradient_richardson_depth = Rcpp::as(xl["node_gradient_richardson_depth"]); - // ret.node_density_in_birth_date = Rcpp::as(xl["node_density_in_birth_date"]); - ret.node_density_in_birth_date = Rcpp::as(xl["node_density_in_birth_date"]); + // ret.node_density_coordinate = Rcpp::as(xl["node_density_coordinate"]); + ret.node_density_coordinate = Rcpp::as(xl["node_density_coordinate"]); // ret.ode_step_size_initial = Rcpp::as(xl["ode_step_size_initial"]); ret.ode_step_size_initial = Rcpp::as(xl["ode_step_size_initial"]); // ret.ode_step_size_min = Rcpp::as(xl["ode_step_size_min"]); @@ -1373,6 +1373,12 @@ template <> inline SEXP wrap(const plant::TF24_Pars& x) { ret["a_st1"] = Rcpp::wrap(x.a_st1); ret["a_st2"] = Rcpp::wrap(x.a_st2); ret["a_st3"] = Rcpp::wrap(x.a_st3); + ret["a_pl0"] = Rcpp::wrap(x.a_pl0); + ret["a_pl1"] = Rcpp::wrap(x.a_pl1); + ret["a_pl2"] = Rcpp::wrap(x.a_pl2); + ret["a_pl3"] = Rcpp::wrap(x.a_pl3); + ret["a_pl4"] = Rcpp::wrap(x.a_pl4); + ret["a_sw"] = Rcpp::wrap(x.a_sw); ret["k_I"] = Rcpp::wrap(x.k_I); ret["vcmax_25"] = Rcpp::wrap(x.vcmax_25); ret["stem_P50"] = Rcpp::wrap(x.stem_P50); @@ -1483,6 +1489,18 @@ template <> inline plant::TF24_Pars as(SEXP x) { ret.a_st2 = Rcpp::as(xl["a_st2"]); // ret.a_st3 = Rcpp::as(xl["a_st3"]); ret.a_st3 = Rcpp::as(xl["a_st3"]); + // ret.a_pl0 = Rcpp::as(xl["a_pl0"]); + ret.a_pl0 = Rcpp::as(xl["a_pl0"]); + // ret.a_pl1 = Rcpp::as(xl["a_pl1"]); + ret.a_pl1 = Rcpp::as(xl["a_pl1"]); + // ret.a_pl2 = Rcpp::as(xl["a_pl2"]); + ret.a_pl2 = Rcpp::as(xl["a_pl2"]); + // ret.a_pl3 = Rcpp::as(xl["a_pl3"]); + ret.a_pl3 = Rcpp::as(xl["a_pl3"]); + // ret.a_pl4 = Rcpp::as(xl["a_pl4"]); + ret.a_pl4 = Rcpp::as(xl["a_pl4"]); + // ret.a_sw = Rcpp::as(xl["a_sw"]); + ret.a_sw = Rcpp::as(xl["a_sw"]); // ret.k_I = Rcpp::as(xl["k_I"]); ret.k_I = Rcpp::as(xl["k_I"]); // ret.vcmax_25 = Rcpp::as(xl["vcmax_25"]); diff --git a/inst/include/plant/control.h b/inst/include/plant/control.h index 37419be92..944e0a4c6 100644 --- a/inst/include/plant/control.h +++ b/inst/include/plant/control.h @@ -60,10 +60,23 @@ struct Control { bool node_gradient_richardson; size_t node_gradient_richardson_depth; - // Carry the size distribution as a density in birth date rather than in - // height. The two resource integrals then run over introduction times, and - // the density rate is mortality alone. - bool node_density_in_birth_date; + // Which coordinate the size distribution's density is carried in: + // + // "auto" let the model decide (the default) + // "birth_date" density in birth date; the two resource integrals run over + // introduction times and the density rate is mortality alone + // "height" density in height; the density rate additionally carries a + // compression term + // + // The height coordinate's compression term is the total derivative of the + // growth rate along a cohort's own trajectory, which equals the partial + // d(growth)/d(height) only when growth is a function of size alone. A model + // carrying state that feeds back into growth breaks that, so the coordinate + // is not a free numerical choice for every model -- hence "auto", resolved + // per model against Strategy::density_in_birth_date_default. An explicit + // value is an override and always wins, so both coordinates stay available + // for the comparison tests. See notes/516-flexible-allometry.md. + std::string node_density_coordinate; double ode_step_size_initial; double ode_step_size_min; @@ -95,6 +108,28 @@ struct Control { double ci_niter; }; +// Resolve Control::node_density_coordinate for a model whose own preference is +// `model_prefers_birth_date` (Strategy::density_in_birth_date_default). Only +// "auto" consults the model; an explicit setting wins. An unrecognised value is +// refused rather than silently treated as one of the two coordinates, because +// the coordinates do not agree for a model with carried state -- a typo would +// otherwise read as a real result. +inline bool density_in_birth_date(const Control& control, + bool model_prefers_birth_date) { + const std::string& coord = control.node_density_coordinate; + if (coord == "auto" || coord.empty()) { + return model_prefers_birth_date; + } + if (coord == "birth_date") { + return true; + } + if (coord == "height") { + return false; + } + util::stop("Unknown node_density_coordinate \"" + coord + + "\": expected \"auto\", \"birth_date\" or \"height\""); +} + inline odelia::ode::OdeControl make_ode_control(const Control& control) { return odelia::ode::OdeControl(control.ode_tol_abs, control.ode_tol_rel, diff --git a/inst/include/plant/models/tf24_strategy.h b/inst/include/plant/models/tf24_strategy.h index 102c92a11..0759f5965 100644 --- a/inst/include/plant/models/tf24_strategy.h +++ b/inst/include/plant/models/tf24_strategy.h @@ -69,6 +69,56 @@ struct TF24_Pars { double a_st1 = 0.10; // Storage capacity per unit sapwood mass [kg NSC / kg] double a_st2 = 0.1; // Reserve fraction at which growth is half-on [0-1] double a_st3 = 0.8; // Initial storage at birth [fraction of capacity] + // * Flexible allometry (#516) -- a plant under carbon stress declines to + // replace the leaf and sapwood its turnover destroys, so its canopy thins + // instead of its mortality spiking, and rebuilds when carbon returns. + // Settable as traits, being TF24_Pars fields; not hyperparameterised, + // there being no trade-off to encode until #512 reports one. + // a_pl0 = 0 is the fixed allometry EXACTLY, not approximately: it zeroes the + // withheld fraction, which leaves both departures resting at zero. + double a_pl0 = 0.0; // Max fraction of leaf/sapwood turnover left unreplaced [0-1] + // ⚠️ a_pl1 GATES ON THE MARGINAL LEAF'S CARBON BALANCE, NOT ON RESERVES. It is + // the dimensionless return (gain - cost)/cost at which withholding is half its + // maximum, so 0 is exactly Manzoni et al. (2015)'s optimum -- shed once a leaf + // stops covering its own upkeep. An earlier version gated on the NSC reserve + // fraction; that fires only after the pool has drained, which is the evergreen + // strategy Manzoni shows losing a long drought, and it was measured here to buy + // a factor of 1.0-1.13 on survivorship. Negative values make a plant hold its + // canopy past break-even; positive values make it shed while still in profit. + double a_pl1 = 0.0; // Marginal leaf return at which withholding is half its max + double a_pl2 = 0.2; // Log-gap scale for rebuilding, and for the canopy floor + // Smallest canopy a plant will thin to, as a fraction of what its height + // implies. Two jobs. Biologically it is the evergreen habit: Robinson's mulga + // that de-leafed severely died, so for an evergreen the floor is real rather + // than a numerical convenience. Numerically it is what keeps the state in a + // range where the arithmetic means something -- without it the canopy decays + // exponentially with no bound, reaching 2e-8 for a fast-leaved species and + // 0.000 for a suppressed cohort in an ordinary wet stand, with divisions by + // leaf area reaching 1e9 inside a solver step shared with live cohorts. + // + // Set it very small for a drought-deciduous species, which sheds to nothing and + // re-flushes. That is supported and should stay reachable, but it is not the + // habit this model is aimed at, and the departure coordinate degrades as the + // floor approaches zero (phi -> -inf). + double a_pl3 = 0.05; // Minimum canopy, as a fraction of the preferred [0-1] + // Rate at which the tracked marginal return chases the instantaneous one, /yr. + // The gate must read a RUNNING MEAN: assimilation swings with the weather, and + // a plant that shed and re-flushed on every dry week would be neither + // physical nor integrable. 1/a_pl4 is the averaging window, so the default is + // about a four-month memory -- long against weather, short against a drought. + double a_pl4 = 3.0; // Acclimation rate of the tracked marginal return [/yr] + // Rate at which sapwood per leaf area chases the ratio that maximises GROWTH, + // /yr. Zero (the default) pins it to the pipe model and leaves every result + // unchanged. + // + // The controller integrates the marginal return, and an integrator IS an + // averager: a small rate makes the stem respond to the mean of a signal that + // swings with the weather, without needing a second state to track it. + // + // ⚠️ The objective is growth, NOT net production. Priced properly, extra stem + // is paid for in forgone leaf-area growth, and the two optima differ a lot: + // production peaks near 3.3x the pipe-model ratio, growth near 1.4-1.8x. + double a_sw = 0.0; // Sapwood acclimation rate [/yr] // * Light capture double k_I = 0.5; // * Leaf hydraulic / photosynthesis traits (default Eucalyptus saligna) @@ -391,7 +441,25 @@ class TF24_Strategy: public Strategy { // the vulnerability curve from K_s, so B_Hv1 was re-anchored 0.4607063 -> // 0.36591565341924093 to stop the reparameterisation from also moving it. // Left alone it would have gone to 3.5933 MPa. - static constexpr int scientific_version = 10; + // v11: the size distribution's density is carried in birth date by default + // rather than in height (Control's node_density_coordinate = "auto" resolves + // here to "birth_date"; see density_in_birth_date_default below). Nothing in + // the equations moved -- what changed is which coordinate the transport + // equation is solved in, and the height coordinate's compression term is a + // different derivative rather than a coarser one once the reserve pool feeds + // back into growth (#590). It is a bump because identical inputs now give + // different numbers, by several times on offspring production, so a cached + // TF24 run from v10 is not comparable. + // + // v11 also frees leaf and sapwood area as ODE states (#516), so replacement + // of turned-over leaf becomes conditional on the marginal leaf's carbon + // balance and the stem can track the Huber value that maximises growth. Both + // are off at the defaults (a_pl0 = 0, a_sw = 0). + // + // ⚠️ The version is 11, not 10: #617 took v10 on develop for the hydraulics + // below, and this branch had independently claimed v10 for the coordinate + // change. A merged TF24 carries BOTH and is comparable to neither. + static constexpr int scientific_version = 11; double compute_average_light_environment(double z, double height, const TF24_Environment &environment); @@ -404,7 +472,7 @@ class TF24_Strategy: public Strategy { // Overrides ---------------------------------------------- // update this when the length of state_names changes - static size_t state_size () { return 6; } + static size_t state_size () { return 9; } // update this when the length of aux_names changes size_t aux_size () { return aux_names().size(); } @@ -415,7 +483,10 @@ class TF24_Strategy: public Strategy { "fecundity", "area_heartwood", "mass_heartwood", - "storage" + "storage", + "log_area_leaf_departure", + "log_area_sapwood_departure", + "leaf_marginal_return_tracked" }); } @@ -424,6 +495,14 @@ class TF24_Strategy: public Strategy { // and the solver rejects it and retries smaller. static std::vector non_negative_states() { return {"storage"}; } + // TF24 carries reserves that feed back into growth, so its growth rate is not + // a function of size alone and the height coordinate's compression term is a + // different derivative rather than a worse approximation of the right one + // (#590). The two coordinates' offspring production differ by several times + // here, where FF16's and K93's agree to 5e-5 and 5.6e-7, so this is a + // correctness default and not a performance one. TF24f inherits it. + static constexpr bool density_in_birth_date_default = true; + std::vector aux_names() { std::vector ret({ "competition_effect", @@ -465,7 +544,17 @@ class TF24_Strategy: public Strategy { // temperature of any single leaf, and a canopy with a hot top and a cool // base reports the mean of the two. The depth profile itself is not an // aux (a fixed-width slot cannot carry a per-quadrature-node vector). - "Tleaf" + "Tleaf", + // The marginal leaf's carbon balance, which the replacement gate reads. + // Dimensionless and zero at break-even, so its sign says whether the last + // leaf is paying for itself. + "leaf_marginal_return", + // The marginal return of SAPWOOD area, in growth rather than production + // (#516). Dimensionless, and zero at the Huber value that maximises the + // plant's growth rate, so its sign says which way the stem should move. + // Zero unless sapwood acclimation is on (a_sw > 0), because computing it + // costs a second leaf evaluation. + "sapwood_marginal_return" }); // add the associated computation to compute_rates and compute there if (collect_all_auxiliary) { @@ -491,8 +580,20 @@ class TF24_Strategy: public Strategy { // [eqn 1] mass_leaf (inverse of [eqn 2]) double mass_leaf(double area_leaf) const; - // [eqn 4] area and mass of sapwood + // Sapwood area per unit leaf area -- the Huber value, `theta` displaced by + // the sapwood departure state. ALWAYS form the ratio this way rather than as + // area_sapwood / area_leaf: the two are algebraically equal but not bitwise, + // because a multiply followed by a divide does not recover its operand, and + // that difference is enough to lose the exactness of the resting model. + double sapwood_per_leaf_area(double sapwood_departure) const { + return pars.theta * std::exp(sapwood_departure); + } + + // [eqn 4] area and mass of sapwood. The one-argument form is the resting + // allometry (used where a plant is on its trajectory by definition, e.g. the + // germination inversion); the two-argument form reads the departure state. double area_sapwood(double area_leaf) const; + double area_sapwood(double area_leaf, double sapwood_departure) const; double mass_sapwood(double area_sapwood, double height) const; // [eqn 5] area and mass of bark @@ -543,20 +644,118 @@ class TF24_Strategy: public Strategy { double respiration_root(double mass) const; // [eqn 14] Total turnover - double turnover(double mass_leaf, double mass_bark, + // Turnover the plant actually PAYS for. `replacement` is the fraction of the + // leaf and sapwood flux it chooses to rebuild; the rest is not charged, and + // the matching tissue is lost through the departure states instead. + // + // ⚠️ ONLY A POOL WHOSE SIZE IS A STATE MAY BE GATED. Bark and root turnover + // stay fully charged because neither has a state to lose, so withholding + // their cost would save carbon that no tissue paid for -- a free lunch, and a + // silent one. + double turnover(double replacement_leaf, double replacement_sapwood, + double mass_leaf, double mass_bark, double mass_sapwood, double mass_root) const; double turnover_leaf(double mass) const; double turnover_bark(double mass) const; double turnover_sapwood(double mass) const; double turnover_root(double mass) const; + // The marginal leaf's carbon balance, set by net_mass_production_dt and read + // by compute_rates. Dimensionless; zero at break-even. + double marginal_leaf_return_ = 0.0; + // The withheld shares net_mass_production_dt actually charged, kept so + // compute_rates cannot form them differently from the budget that used them. + // The carbon not spent and the tissue lost are two halves of one decision, so + // they must come from one number. + double withheld_leaf_ = 0.0; + double withheld_sapwood_ = 0.0; + // d(profit)/d(kmax) at the leaf's own operating point, umol m^-2 s^-1 per unit + // conductance. Zero unless sapwood acclimation is on. + double dprofit_dkmax_ = 0.0; + // Respiration plus turnover (kg yr^-1), the strictly-positive scale the + // sapwood controller normalises by. Set in net_mass_production_dt. + double maintenance_flux_ = 0.0; + + // The leaf-specific max hydraulic conductance actually handed to the leaf + // (kg m^-2 LA s^-1 MPa^-1), stored so the sapwood controller differentiates + // the value the model used rather than a recomputed copy of it. + double leaf_specific_conductance_max_ = 0.0; + + // Relative reserves r = S / S_max, the buffered carbon signal that growth and + // mortality read. Leaf replacement no longer reads it (see a_pl1). + double relative_reserves(const Internals& vars) const { + const double S_max = + storage_capacity(vars.aux(aux_idx_competition_effect), + vars.state(HEIGHT_INDEX), + vars.state(state_idx_log_area_sapwood_departure)); + return S_max > 0.0 ? vars.state(state_idx_storage) / S_max : 0.0; + } + + // The fraction of leaf and sapwood turnover a plant rebuilds, as a smooth + // function of its reserves: ~1 while they are ample, falling to 1 - a_pl0 as + // they empty. a_pl0 = 0 gives exactly 1 and so exactly the fixed allometry. + // + // Centred BELOW the growth gate a_st2, which orders the allocation ladder + // without any branching: reproduction and growth are cut first, canopy + // replacement next, and only then do reserves run out and mortality rise. + double replacement_fraction(double marginal_return) const { + return 1.0 - pars.a_pl0 / + (1.0 + std::exp((marginal_return - pars.a_pl1) / + plasticity_gate_width)); + } + + // How much of the withheld replacement actually happens, tapering to nothing + // at the canopy floor. Same functional form as the rebuild share, mirrored: + // rebuilding vanishes at the ceiling (phi = 0) and shedding at the floor + // (phi = ln a_pl3), so phi is confined to [ln a_pl3, 0] by the SHAPE of the + // flow rather than by any clamp -- and both bounds are therefore differentiable + // and cost the solver nothing. + double shedding_gate(double leaf_departure) const { + const double floor_departure = std::log(pars.a_pl3); + return 1.0 - std::exp((floor_departure - leaf_departure) / pars.a_pl2); + } + + // Sapwood replaces a scaled share of what its conversion to heartwood + // removes: the same carbon gate as leaves, times exp(-psi / a_pl2), so a stem + // carrying more conducting area than its canopy needs declines to renew the + // excess even when carbon is ample. + // + // This is what gives the Huber value a restoring force. Without it psi has + // only terms that push it around and none that return it, and measured, it + // drifted to leave plants hydraulically UNDER-built (#516). + // + // ⚠️ psi >= 0 IS INVARIANT, and that is the reason this form needs no bound. + // At psi = 0 the factor is 1, so the two replacement fractions coincide and + // dpsi/dt = (1 - replacement) * (k_l - k_s) >= 0, + // since k_l > k_s. The flow at the boundary points inward, so the "too little + // sapwood" branch is unreachable, the factor stays within (0, 1], and no + // over-replacement (a fraction above 1) can arise to cost unbounded carbon. + // If k_s were ever raised above k_l that argument reverses and this needs + // revisiting. + double sapwood_replacement_fraction(double replacement_leaf, + double sapwood_departure) const { + return replacement_leaf * std::exp(-sapwood_departure / pars.a_pl2); + } + + // Carbon cost of a unit of leaf area bought at UNCHANGED height: the leaf, + // the fine root, and the sapwood and bark that supply it, at the ratio the + // plant prefers rather than the one it currently has. Buying the whole + // package is what stops rebuilding a canopy from diluting the Huber value. + double mass_live_per_area_leaf_at_height(double height) const { + return pars.lma + pars.a_r1 + + pars.theta * height * eta_c * pars.rho * (1.0 + pars.a_b1); + } + // [eqn 15] Net production double net_mass_production_dt_A(double assimilation, double respiration, double turnover) const; virtual double net_mass_production_dt(const TF24_Environment& environment, double height, double area_leaf_, - double height_inverse); + double height_inverse, + double sapwood_departure, + double leaf_departure, + double tracked_marginal); // Resolve the leaf operating point on the already-set-up `leaf` (i.e. after // leaf.set_physiology(...)). Base TF24 optimises the root-collar psi via @@ -570,9 +769,13 @@ class TF24_Strategy: public Strategy { // does not need to know TF24's state/aux layout. double net_mass_production_dt(const TF24_Environment& environment, const Internals& vars) { - return net_mass_production_dt(environment, vars.state(HEIGHT_INDEX), - vars.aux(aux_idx_competition_effect), - vars.aux(aux_idx_height_inverse)); + return net_mass_production_dt( + environment, vars.state(HEIGHT_INDEX), + vars.aux(aux_idx_competition_effect), + vars.aux(aux_idx_height_inverse), + vars.state(state_idx_log_area_sapwood_departure), + vars.state(state_idx_log_area_leaf_departure), + vars.state(state_idx_leaf_marginal_tracked)); } // [eqn 16] Fraction of whole plan growth that is leaf @@ -583,15 +786,25 @@ class TF24_Strategy: public Strategy { double fraction_allocation_reproduction) const; // [eqn 18] Fraction of mass growth that is leaves - double darea_leaf_dmass_live(double area_leaf) const; + // Leaf area bought per unit live mass. Takes the sapwood departure because + // the stem that comes with a new leaf is priced at the Huber value the plant + // ACTUALLY carries, not at pars.theta. Without that a plant holding extra + // conducting area gets its hydraulic benefit free, which is most of why net + // production appeared to peak at 3.3x the pipe-model ratio. + double darea_leaf_dmass_live(double area_leaf, + double sapwood_departure) const; // change in height per change in leaf area double dheight_darea_leaf(double area_leaf) const; // Mass of leaf needed for new unit area leaf, d m_s / d a_l double dmass_leaf_darea_leaf(double area_leaf) const; // Mass of stem needed for new unit area leaf, d m_s / d a_l - double dmass_sapwood_darea_leaf(double area_leaf) const; + double dmass_sapwood_darea_leaf(double area_leaf, + double sapwood_departure) const; // Mass of bark needed for new unit area leaf, d m_b / d a_l + // Bark is pinned to LEAF area, not to sapwood, so it keeps pars.theta and + // does not move with the departure. Sharing the sapwood expression would give + // it the Huber value's excursion, which it has no business having. double dmass_bark_darea_leaf(double area_leaf) const; // Mass of root needed for new unit area leaf, d m_r / d a_l double dmass_root_darea_leaf(double area_leaf) const; @@ -600,7 +813,8 @@ class TF24_Strategy: public Strategy { // Growth rate of components per unit time: double area_leaf_dt(double area_leaf_dt) const; double area_sapwood_dt(double area_leaf_dt) const; - double area_heartwood_dt(double area_leaf) const; + double area_heartwood_dt(double area_leaf, + double sapwood_departure) const; double area_bark_dt(double area_leaf_dt) const; double area_stem_dt(double area_leaf, double area_leaf_dt) const; double diameter_stem_dt(double area_stem, double area_stem_dt) const; @@ -629,7 +843,8 @@ class TF24_Strategy: public Strategy { // reserves r = S/S_max deplete, bounded in [a_dG1*e^-a_dG2, a_dG1]. double mortality_storage_dependent_dt(double relative_reserves) const; // NSC storage capacity S_max = a_st1 * mass_sapwood [kg NSC]. - double storage_capacity(double area_leaf, double height) const; + double storage_capacity(double area_leaf, double height, + double sapwood_departure) const; // Seed the storage state for a newly germinated individual (#517). void set_initial_states(const TF24_Environment& environment, Internals& vars); // [eqn 20] Survival of seedlings during establishment, from the carbon a @@ -713,6 +928,11 @@ class TF24_Strategy: public Strategy { // step is invalid, as a fraction of capacity. A draining cohort approaches the // boundary, so this separates round-off there from a real excursion. double storage_domain_tol = 1e-8; + // Width of the replacement gate in reserve-fraction units. Narrower than + // storage_gate_width because it sits below it (a_pl1 < a_st2): growth is the + // first thing cut, leaf replacement the next, so the two gates have to be + // distinguishable rather than overlapping into one. + double plasticity_gate_width = 0.02; // Solver tolerances and other constants not currently exposed to R double newton_tol_abs = 0.001; @@ -743,10 +963,23 @@ class TF24_Strategy: public Strategy { int aux_idx_stom_cond_CO2 = -1; int aux_idx_assimilation = -1; int aux_idx_Tleaf = -1; + int aux_idx_leaf_marginal_return = -1; + int aux_idx_sapwood_marginal_return = -1; int aux_idx_area_sapwood = -1; // only present when collect_all_auxiliary int state_idx_area_heartwood = -1; int state_idx_mass_heartwood = -1; int state_idx_storage = -1; + // ln(area_leaf / area_leaf(height)): how far the canopy sits from the leaf + // area the height allometry prefers. Signed, so not a non_negative_state. + int state_idx_log_area_leaf_departure = -1; + // ln(area_sapwood / (theta * area_leaf)): how far the conducting stem sits + // from the leaf area it supports, i.e. the departure of the Huber value from + // its preferred one. Also signed. + int state_idx_log_area_sapwood_departure = -1; + // Running mean of the marginal leaf's carbon balance. The gate reads THIS, + // not the instantaneous value, so a plant does not shed and re-flush with + // every passing dry spell. + int state_idx_leaf_marginal_tracked = -1; // For integrating functions with using Gauss-Kronrod quadrature quadrature::QK function_integrator; diff --git a/inst/include/plant/node.h b/inst/include/plant/node.h index d286c97e0..17fda71fd 100644 --- a/inst/include/plant/node.h +++ b/inst/include/plant/node.h @@ -111,6 +111,13 @@ class Node { individual_type individual; + // Which coordinate this node's density is carried in. Resolves Control's + // "auto" against the strategy's own requirement; see control.h. + bool density_in_birth_date() const { + return plant::density_in_birth_date(individual.control(), + T::density_in_birth_date_default); + } + private: // This is the gradient of growth rate with respect to height: double growth_rate_gradient(const environment_type& environment) const; @@ -154,7 +161,7 @@ void Node::compute_rates(const environment_type& environment, // individual along the birth-date axis. A density in height additionally // compresses as the spacing between neighbouring sizes changes. log_density_dt = -individual.rate(MORTALITY_INDEX); - if (!individual.control().node_density_in_birth_date) { + if (!density_in_birth_date()) { log_density_dt -= growth_rate_gradient(environment); } // survival_individual: converts from the mean of the poisson process (on @@ -205,7 +212,7 @@ void Node::compute_initial_conditions(const environment_type& environment, // present-day Jacobian; see Species::height_jacobian(). const double g = individual.rate(HEIGHT_INDEX); birth_growth_rate = g; - if (individual.control().node_density_in_birth_date) { + if (density_in_birth_date()) { set_log_density(log(birth_rate * pr_estab)); } else { // NOTE: log(0.0) -> -Inf, which should behave fine. diff --git a/inst/include/plant/patch.h b/inst/include/plant/patch.h index 9bcfdf796..f3e798159 100644 --- a/inst/include/plant/patch.h +++ b/inst/include/plant/patch.h @@ -424,7 +424,7 @@ void Patch::check_birth_dates_distinct() const { "and drop out of the competition and resource integrals. Supply " "per-node introduction times (parameters$initial_node_times) " "with the initial state, or run with " - "control$node_density_in_birth_date = FALSE."); + "control$node_density_coordinate = \"height\"."); } } } diff --git a/inst/include/plant/species.h b/inst/include/plant/species.h index fc8e8d7b0..05dedee5c 100644 --- a/inst/include/plant/species.h +++ b/inst/include/plant/species.h @@ -99,7 +99,8 @@ class Species : public SpeciesBase, T, E, Node> { // Which coordinate this species' size distribution is carried in. Exposed so // Patch can check every species agrees before summing their contributions. bool density_in_birth_date() const { - return control().node_density_in_birth_date; + return plant::density_in_birth_date(control(), + T::density_in_birth_date_default); } // * ODE interface @@ -210,12 +211,12 @@ class Species : public SpeciesBase, T, E, Node> { return birth_date ? n.introduction_time() : -n.height(); } double quadrature_abscissa(const node_type& n) const { - return abscissa_of(n, control().node_density_in_birth_date); + return abscissa_of(n, density_in_birth_date()); } std::vector quadrature_abscissae() const { std::vector ret; ret.reserve(size()); - const bool birth_date = control().node_density_in_birth_date; + const bool birth_date = density_in_birth_date(); for (auto& c : nodes) { ret.push_back(abscissa_of(c, birth_date)); } @@ -356,7 +357,7 @@ double Species::compute_competition(double height) const { // Read the coordinate once: this is the hottest loop in the solver (one pass // per spline knot per Runge-Kutta stage), so the control lookup does not // belong inside it. - const bool birth_date = control().node_density_in_birth_date; + const bool birth_date = density_in_birth_date(); // The loop below uses the node list itself as the quadrature grid, and the // early exit is valid only if that grid is monotone. When it is not, the exit // fires at the first node below `height` and silently drops every node beyond @@ -533,7 +534,7 @@ double Species::consumption_rate(int i) const { if (size() == 0) { return 0.0; } - if (control().node_density_in_birth_date) { + if (density_in_birth_date()) { // Introduction times are fixed at birth and nodes are appended in that // order, so this grid is ascending however the heights behave -- there is no // inverted case to sort. new_node's birth date is the current time, which is @@ -616,7 +617,7 @@ Rcpp::NumericMatrix Species::r_get_state() const { // meaning, and the quantity actually integrated is reported alongside it as // `log_density_state`. Note export_patch_state() resumes from patch$ode_state, // not from here, so the raw state is what a resume reloads. - const size_t extra = control().node_density_in_birth_date ? 1 : 0; + const size_t extra = density_in_birth_date() ? 1 : 0; // Set output size. // +1 is seed Rcpp::NumericMatrix ret(static_cast(ode_size + aux_size + extra), n_nodes + 1); @@ -778,7 +779,7 @@ std::vector Species::r_log_densities_state() const { template std::vector Species::r_log_densities() const { std::vector ret = r_log_densities_state(); - if (!control().node_density_in_birth_date) { + if (!density_in_birth_date()) { return ret; } // N = nu / |dh/dtau|. jac carries one extra trailing entry for the boundary diff --git a/inst/include/plant/strategy.h b/inst/include/plant/strategy.h index 237727e44..bb57f9078 100644 --- a/inst/include/plant/strategy.h +++ b/inst/include/plant/strategy.h @@ -32,6 +32,13 @@ class Strategy { // check compiles to nothing. static std::vector non_negative_states() { return {}; } + // Which density coordinate this model needs when Control leaves the choice on + // "auto". The height coordinate's compression term is only valid where growth + // is a function of size alone, so a model that carries state feeding back into + // growth must say so here. Size-only models leave this false and keep the + // height coordinate they were calibrated in. + static constexpr bool density_in_birth_date_default = false; + std::vector aux_names(); // TODO(#483) : expose this so can access state_names directly diff --git a/man/scenario_eval.Rd b/man/scenario_eval.Rd index 3b9b47bf4..1773e5331 100644 --- a/man/scenario_eval.Rd +++ b/man/scenario_eval.Rd @@ -128,7 +128,7 @@ cache deliberately errs toward rerunning.} (\code{"failure"} or \code{"success"}). \code{scenario_control} returns the \code{Control} the gateway runs - under: \code{control()} with \code{node_density_in_birth_date = TRUE}. + under: \code{control()} with \code{node_density_coordinate = "birth_date"}. Every scenario here is TF24, and TF24 is the model the two density coordinates genuinely disagree on (#590). The transport equation's diff --git a/notes/.DS_Store b/notes/.DS_Store new file mode 100644 index 000000000..42e8c988c Binary files /dev/null and b/notes/.DS_Store differ diff --git a/notes/516-flexible-allometry.md b/notes/516-flexible-allometry.md new file mode 100644 index 000000000..5b389e697 --- /dev/null +++ b/notes/516-flexible-allometry.md @@ -0,0 +1,680 @@ +# Flexible allometry for TF24: leaf area and sapwood as ODE states (#516) + +Design note for the epic #516, covering tasks #513 (sketch), #514 (draft implementation) and #407 (break the fixed relationship). Written before the code so the decisions are reviewable and so a second session on this branch can see what is required rather than optional. + +Issues: #516 (epic) · #513 · #514 · #407 · #512 (empirical review, still open) · #517 (NSC, the precedent) · #609/#619 (storage bounds) · #620 (`storage_prod_eps`, open) · #590 (birth-date coordinate) + +## Problem + +TF24 inherits FF16's fixed allometry, `area_leaf(h) = (h/a_l1)^(1/a_l2)`, refreshed on every height write. This was a deliberate and productive simplification: one size dimension makes the state a scalar, makes the size-density PDE one-dimensional, and is much of why the SCM is fast. It is also what the model has been calibrated against. + +What it cannot represent is the first thing a struggling plant does — thin its canopy. Three consequences hold in the current code: + +- Leaf turnover is charged as a cost and the tissue is then restored by the allometry, so replacement is unconditional. A plant cannot economise by carrying less leaf. +- `dh/dt >= 0` is structural (`growth_flux >= 0` times two positive derivatives), so shrinking is not expressible at all. +- At the empty-reserve boundary the unmet part of the carbon deficit leaves the budget. NEWS records this and names "routing it into tissue loss" as deferred work — and that sink is a leaf-area state, which makes this change a completion of the NSC work rather than a new direction. + +## Decisions + +| Decision | Choice | +|---|---| +| Recovery | Gradual relaxation toward the preferred trajectory, not priority rebuild | +| Scope | Leaf area **and** sapwood area. Root:leaf is a separate issue | +| Gate signal | NSC relative reserves `r = S/S_max`, reusing the existing logistic | +| Density coordinate | Birth-date for TF24, via a tri-state `Control` field | +| Sapwood target | `theta * area_leaf`, written as a function. Optimality-derived targets are a separate epic | +| Delivery | One PR, numbered commits, each recording its own number movements | + +## Required, not optional + +**The birth-date coordinate is a prerequisite.** The height-coordinate density equation subtracts a compression term `∂g/∂h` obtained by a finite difference that perturbs height while holding every other state at its absolute value. That equals the true compression only when growth is a function of size alone. NEWS already records the reserve gate breaking this. A leaf-area state makes it qualitatively worse, because height's rate is defined *through* leaf area — so perturbing height at fixed leaf area changes growth only via self-shading, which is near zero in a uniform light environment, and the probe returns approximately the wrong thing by construction. Under the birth-date coordinate the density ODE is `-mortality`, which is valid for a state vector of any dimension. + +**Sapwood must be freed with leaf area, not after it.** Mortality reads only `r = S/S_max`, with `S_max = a_st1 * mass_sapwood` and `area_sapwood = theta * area_leaf`, so `S_max` is proportional to leaf area. Free leaf area alone and shedding shrinks the denominator of `r`, raising apparent reserves and dropping mortality to its floor at zero carbon cost, while pushing `r` above 1 — the hazard flagged in #609, which the storage rate's form no longer bounds. Physically a leaf's sapwood dissolving with the leaf is also wrong: sapwood leaves the pool only by becoming heartwood, at `k_s`. + +Freeing sapwood fixes all of it emergently. The canopy thins at up to `k_l = 0.457`/yr while sapwood decays only at `k_s = 0.2`/yr, so per-leaf-area maintenance cost rises as the canopy thins — the penalty that makes shedding self-limiting — and per-leaf-area hydraulic supply improves, which is real drought acclimation reaching phylloptim through `leaf_specific_conductance_max`. + +**Keep `S_max` on sapwood.** Bark does not help: `area_bark = a_b1 * theta * area_leaf`, the same proportionality, so capacity on bark has exactly the shrinking problem capacity on sapwood has. Bark helps only if bark is repinned to sapwood rather than to leaf area, and then it is equivalent. Heartwood would make capacity monotone but NSC sits in living parenchyma, so sapwood is the right tissue. Once sapwood is a state, capacity declines only at `k_s`, which is enough. + +## Mechanism + +Two new states, `state_size()` 6 -> 8. **Each is integrated as a log departure from its preferred value, not as a level:** + +- `log_area_leaf_departure` = `ln(A / A*(h))`, where `A*(h) = (h/a_l1)^(1/a_l2)` is the preferred canopy for the current height; +- `log_area_sapwood_departure` = `ln(A_s / (theta * A))`, added in the sapwood commit. + +Leaf area itself is then derived, `A = A*(h) * exp(phi)`, and cached in the `competition_effect` aux the model already reads. + +**Why the departure rather than the level.** Integrating `A` directly makes the pair `(h, A)` a *redundant* system: `A = A*(h)` is an invariant of the exact flow but Runge–Kutta preserves it only to truncation error, so height's rate would read a drifted `A` and exactness would be unreachable *by construction* rather than through any coding mistake. On the departure coordinate the allometric motion stays analytic and only the departure is integrated, so with plasticity off `dphi/dt` is exactly `0`, `phi` stays exactly `0`, and `exp(0) == 1` makes `A` bit-identical to today's `area_leaf(height)`. + +That exactness survives the solver because odelia's error control is a **max** norm over the states (`ode_control.hpp`, `rmax = std::max(r, rmax)`): a state with zero error contributes zero, so step sizes are untouched. An RMS norm would have diluted the mean and changed the steps, and the exactness claim would have been false — worth re-checking if odelia's controller ever changes. + +Three consequences worth having: + +- **Zero is the right default.** `Internals` zero-initialises states and `phi = 0` *is* "on the preferred trajectory", so a freshly constructed `Individual`, a `make_initial_state()` seeding, and an export/resume are all correct with no seeding code. Integrating levels would have started every plant at `A = 0`. +- **Neither state belongs in `non_negative_states()`** — a log ratio is signed, so there is no bound to violate and nothing to declare. +- **Scale-free by construction**, which is what keeps the plasticity parameters from repeating `storage_prod_eps`'s mistake (#620) of being an absolute constant against fluxes spanning six orders. + +`height` stays a state and stays monotone: its rate remains a product of non-negative factors, so height never decreases even while the canopy is shedding. + +**Conditional replacement of leaf turnover.** A smooth replacement fraction `f(r)`, logistic, centred below the growth threshold `a_st2`: + +- the leaf turnover charged to the budget becomes `f(r) * k_l * m_leaf`, other pools unchanged; +- leaf area declines by the remainder, `dA/dt` gaining `-(1 - f(r)) * k_l * A`. + +These are two halves of one decision and conserve carbon exactly: carbon not spent is `(1-f) * k_l * lma * A`, and leaf mass lost is `lma * (1-f) * k_l * A`. **Assert this as an identity, not a tolerance.** It also bounds thinning naturally at `k_l`, because the mechanism is declining to replace what died rather than active shedding. + +**Priority ladder.** Growth is already gated at `a_st2` by `G(r)`. Gating replacement at a lower centre gives a smooth ladder out of two logistics with no branching: reproduction and growth are cut first, leaf replacement next, then reserves empty and mortality rises. + +**Gradual rebuild.** `growth_flux = Ppos * G` splits smoothly between extension along the preferred trajectory and closing the leaf-area gap, with the split a smooth function of the gap that vanishes when it closes, so the gap closes asymptotically with no breakpoint. + +**Sapwood — and a correction to how this note first described it.** It said sapwood is *not sheddable*, so its plasticity could only enter through the allocation of new growth. That is wrong, and the implementation is better for it: sapwood is continuously lost to heartwood at `k_s`, and that loss is currently replaced *implicitly* by the allometry, exactly as leaf turnover is. So the same "decline to replace" mechanism applies, and one uniform gate covers both pools rather than two special cases. + +The asymmetry is then a consequence rather than an assumption. Because the two departures differ only by their rate constants, + + dpsi/dt = withheld * (k_l - k_s) - rebuild + +so withholding both raises sapwood per leaf area at up to `k_l - k_s` = 0.457 − 0.2 = 0.257/yr. The Huber value rises under stress because leaves turn over faster than sapwood does, not because anything says sapwood is special. Heartwood accumulation stays ungated either way: the tissue becomes heartwood whether or not it is replaced. + +## Invariants a future edit could break + +- **Height's monotonicity is by construction, and nothing can catch it if that breaks.** `dh/dt` is a product of non-negative factors, which is why height never decreases. That has to stay true structurally, because the solver cannot check it: a step is rejected either by a `DomainError` thrown from inside `compute_rates` (as the negative-storage check does) or by `ode_state_valid()` refusing the state the step landed on — and the latter is a predicate over the flattened state vector alone, so it can express "height >= 0" but cannot see the previous step and so cannot express "height is non-decreasing". `non_negative_states()` will not help here. If the product structure ever has to go, the replacement is an explicit `stop_domain` on a negative computed rate, not a state bound. +- **A new call into phylloptim must translate its exceptions.** `phylloptim::util::infeasible_error` and `odelia::util::DomainError` are siblings, both deriving from `std::runtime_error`, so odelia's handler cannot see phylloptim's throw: it escapes the step and kills the solve having taken none (#608 measured this). `src/tf24_strategy.cpp` and `src/tf24f_strategy.cpp` catch and re-throw as `stop_domain` for that reason. Any new leaf-solving path needs the same translation. +- **Every new expression must be smooth.** No `min`, `max` or `?:` in the carbon-to-growth or carbon-to-mortality map. The house pattern is at `src/tf24_strategy.cpp:201-297`: shape the flow so bounds follow from the form rather than clamping the read. `test-strategy-tf24.R:427-520` asserts a derivative-difference *convergence rate* rather than a value at one step width, precisely because a clamp passes bound assertions while leaving the rate kinked; `:522-560` asserts `|lambda|/own_rate < 10`. New gates need both. +- **The exactness anchor.** With plasticity off the model should be bit-identical to today. This is a diagnostic goal subordinate to the science — if a better formulation breaks it, take the formulation and re-bless — but it must be *checked early*, while the diff is small enough to attribute a discrepancy. Do not discover a lost exactness late and relax a tolerance to hide it. +- **`competition_effect` is load-bearing, not diagnostic.** `compute_rates` never calls `area_leaf`; it reads the cached aux written only by `update_dependent_aux`. An allometry change not routed through that function passes every test that calls `area_leaf` directly while the solver keeps the old behaviour. +- **`set_ode_state` refreshes aux per slot, in slot order.** A height-triggered write at slot 0 would read a stale leaf area still at slot 6. Do not simply add a second branch — write the aux after all states are in, or derive it from whichever state is authoritative. +- **The derivative family is hand-differentiated and must move in lockstep.** `dmass_sapwood_darea_leaf` carries an `(a_l2 + 1)` factor that is the product rule against `H(A)`; `dmass_bark_darea_leaf` inherits it; `darea_leaf_dmass_live` is their reciprocal sum. `a_l1`/`a_l2` appear on exactly four lines of TF24 code. +- **Canopy shape stays `Q(z/height)`**, so a smaller leaf area at unchanged height is a *sparser* crown of the same depth, not a shallower one. That is the intended reading of thinning, but it only becomes visible once the two decouple. +- **`set_initial_states` is non-virtual.** TF24f must keep chaining to the base or the leaf-area seed is silently dropped. +- **Height crossings become routine.** The birth-date integral is safe, but `describe_nodes_near`'s "node heights are NOT decreasing" message becomes a false accusation, `r_set_heights()` still stops, and `scale_node_densities` selects by height. +- **The version drift-guard will not catch a missing bump.** `test-model-version.R` snapshots only `pars`/`control` defaults, so adding a state without a parameter passes silently. Bumping `scientific_version` is reviewer discipline. + +## Not in this work + +- **Optimality-derived allometric targets** — own epic under #516. The criterion is stationarity of the plant's own *growth rate*, not leaf profit: against profit sapwood is always worth building, because nothing charges the plant for the carbon the sapwood consumed, whereas putting growth in the objective internalises the trade-off. The signal must be long-run, and sapwood's own inertia may supply that for free, since `dA_s/dt = k(target - A_s)` makes `A_s` an exponentially-weighted moving average of its target. Needs `∂profit/∂kmax` from phylloptim, whose gradient outputs are currently disjoint from the `profit_` plant bills. The same criterion is how preferred *leaf* area would be derived, which is the larger prize. +- **Root:leaf plasticity** — roots are sheddable like leaves, so it reuses this machinery with no new mechanism. +- **`storage_prod_eps` rescaling** (#620) — inherited, and this work is sensitive to it near the compensation point. Its own commit and its own number check; do not silently absorb it. + +### Deciding the objective by invasion analysis + +*Which* growth rate the optimality criterion maximises — `dh/dt`, `dA/dt`, or the relative `(dA/dt)/A` — should not be argued from first principles. All three are **proxies for fitness**, and a proxy is worth only what its correlation with lifetime offspring production is in the environment the plant actually experiences. plant already computes that currency, so this is an empirical question inside the model rather than a modelling preference. + +The sharper form is not "which proxy wins" but **which proxy attains the ESS**. Two separable questions, in this order: + +1. **What sapwood:leaf ratio is evolutionarily stable?** Treat `theta` as a trait and run the standard resident–mutant invasion analysis. This needs **no proximate rule at all** — evolution supplies the set-point — and it needs no new code: `theta` is already a `TF24_Pars` field and `add_strategies()` accepts it as a trait (verified, two distinct values across two strategies), and `run_mutant()` works for TF24 as of #643. + + Run this **first**, because it prices the rest of the epic. If the fitness landscape in `theta` is close to flat, an optimality-derived target is not worth building whatever it costs. If it is sharply peaked, the ESS is the number every candidate proxy then has to reproduce. + +2. **Does a plastic rule beat the best fixed ratio, and which proxy does it best?** Only here is a rule needed. The test is whether a plastic strategy invades a resident sitting at the ESS ratio from (1). If it cannot, the plasticity is not earning its keep and the fixed ratio stands. + +**The trap that would silently drain this of power.** Under constant conditions all three proxies are monotone in the same carbon surplus and will very likely agree, possibly exactly. The differences live in the *fluctuating* case, which is the whole motivation for plasticity — so the comparison has to run under drought or deep shade (the scenario gateway's regimes), not a benign constant environment. This is the same shape as the trap already recorded for shading models: a stand-alone individual sees uniform light, so every shading model agrees exactly and the test has no power. **A null result in a constant environment means the experiment was posed wrongly, not that the choice does not matter.** + +**Scope of what it establishes.** Invasion analysis answers "given TF24's physiology, which rule is evolutionarily stable". That is well posed, but the answer is a property of the model, not evidence about real plants — using the model to select its own mechanism is legitimate only if the conclusion is stated at that scope. The reality check is #512: observed Huber values and how they shift with light and water. Both are needed and they answer different questions. + +**Cost is the binding constraint.** TF24 is expensive per step and an ESS search over one trait is many resident-plus-mutant runs under a fluctuating driver. Expect this to want HPC rather than a laptop. + +**Evaluate mutants one at a time, not in a batch.** Measured on a wet one-species TF24 stand (`mpl = 20`, default traits, `theta` as the trait), comparing the resident's own R0 against the resident slot the mutant run recomputes: + +| mutants in the call | resident slot | relative shift | +|---|---|---| +| 1 (a twin of the resident) | 5.7636882085232299 | 5.5e-07 | +| 9 (spanning 0.25x to 4x) | 5.6314597794715402 | **2.3e-02** | + +In both cases the twin mutant agrees with the resident slot *exactly*, so this is not mutants leaking into the competitive environment — that part works. The likely cause is that mutants are integrated in the **same ODE system** as the resident, so their error enters the shared max-norm step-size control and changes the accepted steps, and with them the resident's own trajectory. That is a hypothesis: the batch here varied both the count and the extremeness of the mutants (some sit at R0 ~ 1e-18), and those were not separated. + +Either way the practical rule is the same, and it is not a small correction: a batched landscape carries a per-cent error that depends on **which other mutants happened to be in the batch**, which is exactly the kind of contamination an ESS search cannot tolerate, since it compares nearby strategies. One mutant per call costs one run each and buys ~1e-7. + +### What stage 1 already found + +Run on a wet (1.5 m/yr) and an arid (0.4 m/yr) constant stand, `mpl = 20`, default traits, `theta` swept over 0.25x to 4x of its default 1/4669. + +**The landscape is nowhere near flat, so the epic is worth building.** On the wet stand R0 spans about **1e20** across the sweep. Fitness is steeply asymmetric: *raising* theta above the default collapses R0 by 13 orders of magnitude and more, while lowering it toward ~0.7x is strongly favoured — the peak mutant reaches R0 ~ 200 against the resident's 5.76. Sapwood is expensive (its mass scales with theta *and* with height, so respiration and turnover scale with it) while the hydraulic benefit saturates, and the model prices that very sharply. + +**Two things it does not establish.** The peak is one step of an iteration, not an ESS: for that the resident has to be moved to the peak and the scan repeated until the peak sits at the resident, and the resident should be at demographic equilibrium (R0 = 1) rather than the 5.76 it sits at here. And the arid stand is **not an ESS analysis at all** — every strategy on it has R0 between 1e-11 and 2e-9, so nothing persists and the ranking is among strategies that all go extinct. Its apparent preference for *less* sapwood under drought is therefore not evidence of a drought response; that comparison needs a stand where something survives. + +**The extremely seasonal case does not complete**, failing on the negative-storage domain boundary at t ≈ 2.94 with the sub-step already at its minimum. That is the pre-existing #550/#609 failure mode under an extreme driver, not something this work introduced. + +**Worth its own look:** TF24's default theta is far from its own model's fitness optimum, by ~1.4x in the trait and ~35x in fitness on a wet stand. Since theta is a *calibrated* value, the more likely reading is that the model over-prices sapwood rather than that the parameter is wrong — but either way it is a finding about TF24 rather than about this epic, and it deserves separating from it. + +## Where this stands after the first behavioural validation + +The mechanism is in and exact when off (`a_pl0 = 0`), and it thins a canopy in +the intended direction. Three things measured on it say the default should +**not** be turned on yet, and each is a modelling decision rather than a bug. + +**Measured, single plant at h = 5 m with reserves held empty, `a_pl0 = 1`:** + +| departure `phi` | `dphi/dt` | `dpsi/dt` | `dh/dt` | production per leaf area | +|---|---|---|---|---| +| 0.00 | −0.422 | +0.237 | 0.632 | 1.765 | +| −0.50 | −0.290 | +0.105 | 0.383 | 1.894 | +| −1.00 | −0.272 | +0.087 | 0.242 | 1.989 | + +Thinning throughout, the Huber value rising, height still climbing but more +slowly, and production per leaf area rising 13 per cent as the canopy thins -- +the benefit the mechanism exists to deliver. + +**1. Rebuilding has to be gated on the same signal as replacement.** The first +version made the rebuild share a function of the gap alone, so a starving plant +withheld replacement and spent its growth flux rebuilding at the same time. +Measured, it rebuilt at ~1.5/yr against shedding's 0.42/yr: the canopy thinned +5 per cent and stalled, and the Huber value *fell*. Fixed by multiplying the +share by `replacement`, so a plant rebuilds only to the degree it is willing to +maintain. This one is settled and done, and is why the factor is load-bearing. + +**2. The response is far too small at the default parameters.** On a strongly +seasonal stand (mean rain 0.7 and 1.1 m/yr, amplitude 0.9 of mean) the canopy +thins by only **1.6 to 3.0 per cent** (`phi` reaching −0.030 and −0.016). That +is not "thinning out the canopy" in any meaningful sense. The cause is that the +NSC gate keeps reserves well above `a_pl1 = 0.05` except in permanent deficit, +so the replacement gate almost never opens. Either `a_pl1` has to sit much +closer to the growth gate `a_st2 = 0.10`, or the gate should read something +other than the reserve fraction. Undecided. + +**3. The sapwood departure had no restoring force. FIXED.** Its only terms were +`+withheld*(k_l - k_s)` and `−rebuild_rel`, neither of which returns it to zero, +and because rebuilding bought leaf area *without* sapwood the second dominated: +on both seasonal stands `psi` ended in [−0.10, 0], leaving plants hydraulically +**under**-built. Two changes, and neither needed the three-way flux split that +first looked unavoidable: + +- **Rebuilding buys the whole package** -- leaf, fine root, and the sapwood and + bark that supply it -- at the ratio the plant *prefers* rather than the one it + has, so closing a canopy gap no longer dilutes the Huber value. +- **Sapwood renews a scaled share**, `replacement * exp(-psi / a_pl2)`, so a + stem carrying more conducting area than its canopy needs declines to renew the + excess even when carbon is ample. That is the restoring force. + +**`psi >= 0` is now invariant, by the form rather than by a guard.** At `psi = 0` +the two replacement fractions coincide, so `dpsi/dt = (1 - replacement) * +(k_l - k_s) >= 0` because `k_l > k_s`: the boundary flow points inward, the "too +little sapwood" branch is unreachable, and the scaling factor stays in (0, 1] so +no over-replacement can arise to cost unbounded carbon. ⚠️ **If `k_s` were ever +raised above `k_l` that argument reverses.** + +Measured after the fix, on the same seasonal stands: `psi` in **[0, +0.040]** and +**[0, +0.043]** -- the right sign -- and `dpsi/dt` holds near +0.21 across the +gap range instead of decaying to +0.087. Leaf departure reaches −0.052 against +sapwood's +0.043, so leaf is the larger of the two, with the ratio set by +`k_l / (k_l - k_s)` ~ 1.8 under pure withholding: the speeds are governed by the +turnover constants, as they should be. + +**What the fix does NOT do: bound either departure under a permanent deficit.** +With reserves empty, `withheld * k_l` (0.42/yr) outruns `withheld_sapwood * k_s` +(0.2/yr) whatever `psi` is, so `psi` keeps rising -- measured at +0.22/yr even at +`psi = 6`. This is arithmetic rather than a defect: a plant thinning its canopy +at 46 per cent a year while losing conducting area at 20 per cent really does +raise its Huber value without limit. But it means a plant in *permanent* deficit +has both departures diverging linearly, `phi` toward −inf and `psi` toward +inf. +What removes such a plant is mortality, not the allometry. Whether that is +acceptable, or whether the departures need a bound, is the live question -- and +it is the same question as (4) below. + +**4. A stiffness hazard, identified and not fixed.** `rebuild_rel` is an +absolute carbon rate divided by leaf area, which is correct -- it is what turns +a carbon flux into a relative rate, and the absolute `dA/dt` stays bounded by +the carbon. But in the departure coordinate it scales as `exp(-phi)`, so it +grows without bound as the canopy empties. This is structurally the same +fast-attracting-boundary shape that #609's analysis identified for `log S`, and +the same remedy applies if it bites: a basis whose rate vanishes at the +boundary. It has not caused a failure in any run here, and a plant deep enough +in deficit to reach it is dying, but a cohort in that state is carried by the +SCM and can slow or reject steps. + +**On fitness.** Turning plasticity on lowered R0 in every stand tested: −0.07 +per cent on a wet stand where it barely engages, and factors of 0.76 and 0.83 +on the seasonal ones. All the seasonal stands have R0 far below 1, so nothing +persists on them and the ranking is among strategies that all die out -- the +same caveat as the theta scan, and the reason these numbers do not settle +whether the mechanism helps. A stand where something survives, and where the +deficit is transient rather than permanent, is what would. + +## Second exploration: why thinning does not buy survival (2026-09-08) + +Five measurements, and they move the problem out of the allometry entirely. + +### 1. The sheddable costs are large. RETRACTION. + +An earlier note here and in the demo said sapwood respiration dominates a drought +deficit, so thinning could not reach it. **That is wrong.** Leaf, fine root and +bark all scale with leaf area — only sapwood is sticky. At 10 m: + +| leaf | bark | sapwood | root | reachable by thinning | +|---|---|---|---|---| +| 49.6% | 5.4% | 23.5% | 21.5% | **76.5%** | + +(Roots follow leaf area *exactly*, `m_r = a_r1 * A`, so they shrink instantly with +the canopy rather than decaying at `k_r`. Same simplification as bark. Neither has +a state.) + +### 2. But thinning cuts income just as fast + +Assimilation scales with leaf area too. Net production per unit leaf area is flat +as the canopy falls from 100% to 1.8%, and slightly *worsens* as the stem it still +carries is spread over fewer leaves: + +| canopy fullness | 1.00 | 0.50 | 0.20 | 0.10 | 0.05 | 0.018 | +|---|---|---|---|---|---|---| +| net production per m² leaf | −3.81 | −3.69 | −3.77 | −3.92 | −4.15 | −4.68 | +| stem per leaf | 1.0 | 1.5 | 2.5 | 3.6 | 5.4 | 9.5 | + +A plant whose leaves cost more than they earn cannot fix that by having fewer +leaves. Thinning slows the burn; it never reaches balance. + +### 3. There is no drought in which it changes the outcome + +| soil water | 0.20 | 0.17 | 0.15 | 0.13 | 0.11 | +|---|---|---|---|---|---| +| survivorship, 4-yr drought | 0.93 | 0.93 | 0.93 | 4.9e-10 | 3.4e-10 | +| gate engaged? | no | no | no | yes | yes | + +A cliff, not a gradient. Above 0.15 reserves stay full and the gate never opens; +below it the plant dies whatever it does. Thinning *early* — raising `a_pl1` from +0.05 to 0.30, which was the obvious fix — was measured across this sweep and buys +a factor of **1.0 to 1.13**, while costing height. + +### 4. The root cause is the reserve pool, not the gate + +`dS/dt = charge*(1-r) - drain*r` has **no resting point**: positive production +fills the pool to capacity, negative empties it, and nothing sits between. So `r` +is close to a binary readout of the *sign* of production. Mortality then reads it +through `a_dG1 * exp(-a_dG2 * r)` with `a_dG2 = 20`, which is sharp enough to turn +a near-binary input into a near-binary output spanning eight orders. + +**A mechanism that makes a plant modestly cheaper to run has nothing to act on.** +The buffer does not buffer. That is an NSC-design property, not an allometry one. + +### 5. The departures are unbounded, and it bites in ORDINARY conditions + +Withholding gives a constant *relative* thinning rate `u * k_l`, so the canopy +decays exponentially with no floor. `k_l` is a trait, so this arrives sooner for +fast-leaved species: + +| lma | k_l /yr | max thinning /yr | canopy after 2 yr | after 4 yr | +|---|---|---|---|---| +| 0.05 | 4.80 | 4.44 | 1.4e-04 | 2.0e-08 | +| 0.0825 | 2.04 | 1.88 | 0.023 | 5.4e-04 | +| 0.1979 | 0.46 | 0.42 | 0.43 | 0.185 | +| 0.40 | 0.14 | 0.13 | 0.78 | 0.60 | + +⚠️ **And it is not confined to drought.** In a plain WET stand (rainfall 1.5 m/yr, +`lma = 0.0825`, self-thinning over 25 years) suppressed cohorts show exactly the +intended gradual decline at first — a 0.45 m seedling at 0.63 of its preferred +canopy — but the deeply shaded ones run away: at t = 20 a 10 m suppressed cohort +sits at canopy **0.000** with stem-per-leaf **1.3e9**. Mortality has already +removed them (survivorship 1e-34) so `R0` is unaffected (ratio 0.9992), but the +states are meaningless and numerically hazardous. + +**This is a NUMERICAL failure, not a biological one — the distinction matters for +the fix.** The ordering across LMA is right and is a success: a fast-leaved species +*should* shed faster and die sooner, and `u * k_l` is the correct rate law. What +fails is that the state runs far past any meaningful floor and into arithmetic that +stops meaning anything — leaf area at 1e-8 m², production per leaf area at −9.2e7, +`stem_per_leaf` at 1.3e9 — all on the same vanishing denominator, and +`rebuild_rel` scales as `1/A` too. Those divisions sit in a solver step shared with +live cohorts. + +But underneath it is a real biological gap: **nothing in the model kills a plant +for having lost its canopy.** Mortality reads reserves alone, so TF24 will carry a +plant to 2e-8 of its canopy provided its reserve fraction says otherwise. The fix +is therefore not a clamp on the departure but a mortality term that responds to +canopy state — which would also give mortality something *continuous* to read in +place of the near-binary reserve fraction. + +### What the literature says, and it contradicts the current design + +A global synthesis of 121 studies and 177 species finds **minimum NSC around 46 +per cent of the seasonal maximum**, with depletion of total NSC "rare" +(Martínez-Vilalta et al. 2016, Ecol. Monogr., doi:10.1002/ecm.1231). Soluble +sugars in particular are "kept above some critical threshold". Beech under three +years of drought *increased* NSC for two years before starch fell, and it was the +**dead** trees that were "virtually empty" — the authors conclude that +"maintaining an active C storage function at the expense of growth was certainly +key to survival" (Chuste et al. 2019, Trees, doi:10.1007/s00468-019-01923-5). + +So real plants **defend** the pool, sacrificing growth to do it, and are found +empty only when dead. TF24 does the reverse: growth is gated but storage is the +residual, so the pool drains to zero and the plant is scored dead by a fraction +that had no floor to begin with. + +Also relevant: time-to-starch-depletion predicted mortality better than any +instantaneous level (Trueba et al. 2024, Ann. For. Sci., +doi:10.1186/s13595-024-01246-7) — which is an argument for what mortality should +read. + +### Where this leaves the design + +Confirmed with Daniel: **the canopy thinning IS the tissue consumption that pays +the deficit.** That reframes the gate. Withholding should be sized to the +*shortfall* rather than to reserves — withhold what is needed to close the deficit, +up to what turnover makes available — so the pool acquires a resting point by +construction and `r` stops being binary. One change, addressing items 4 and 5 +together, since a demand-driven withholding also stops once the deficit closes. + +Open, and needing a decision: + +- **What bounds the departures** when the deficit exceeds what withholding can + close. Mortality removes the plant, but not before the states are absurd. +- **What mortality should read.** A reserve fraction cannot see a plant that has + made itself cheaper to run. Time-to-depletion at the current burn rate can, and + has empirical support. +- **Whether storage should outrank growth**, as the literature says it does. + +## The empirical case against a reserve-gated trigger (2026-09-08) + +Two sources read in full: Robinson's mulga chapter (573 *Acacia aneura*, 49 dune +sites, drone imagery 2017-2024 across a severe drought) and Manzoni et al. 2015 +(*Adv. Water Resour.* 84:37-51), an optimality model of leaf phenology. + +**They say the trigger should be the instantaneous carbon balance, not the size of +the reserve pool.** Four independent lines: + +1. **The optimal trigger is a flux, derived not assumed.** Manzoni maximises + cumulative season carbon gain over leaf area and gets `dG/dt = 0` -> `A_net = 0` + (Eq. 7, p.40): shed when the marginal leaf stops paying for its own + respiration. In water-potential units that is `psi_s ~ -2 MPa`, about day 20 of + a dry-down — *"optimal leaf loss is a later and more drastic measure of water + loss regulation than stomatal closure"* (p.48). +2. **It fires while the plant is still carbon-rich.** Manzoni's Fig. 4D has + cumulative gain at its *seasonal maximum* when shedding begins. **Waiting for + reserves to run down IS the evergreen strategy** — and that strategy runs + `A_net` to -10 umol m^-2 s^-1 and its season gain from +150 to **-50 gC m^-2**. + It is the loser at long drought. This is the sharpest contradiction of what we + built. +3. **Shedding is what healthy plants do.** 85% of Robinson's trees shed, including + the healthiest; the died and survived canopy-density distributions are + *indistinguishable* in 2018 and only separate from 2019. Shedding is not a + marker of imminent death. +4. **The size result runs backwards for a reserve rule.** Under reserve exhaustion + the biggest stores should shed last and die when they shed. Robinson finds + large trees shed *less* (*"a large canopy area apparently buffering against the + most severe drought-driven leaf loss"*) **and** survive best — canopy area is + the strongest mortality predictor (log-odds -0.03, p = 8.4e-5). The explanation + offered is water access, not carbon stores. + +### What the data require + +- **Leaf area must reach ~zero and come back, in a plant that stays alive.** + Manzoni's optimum is literally `L = 0` for all three shedding strategies; + Robinson's methods treat complete de-greening followed by re-leafing as + documented mulga behaviour, and only score a tree dead if it fails to re-green + in a later wet year. ⚠️ **This kills the idea of canopy-dependent mortality** + floated above — losing the canopy must not itself be lethal. +- **Decline is slow, recovery fast.** Robinson: 2-3 years down, one season back. +- **Recovery's cost is a discrete re-flush, not a rate.** Manzoni prices it at + `gamma = LMA * f_C / Y ~ 48 gC m^-2` per unit LAI, so a full canopy is ~95 + against a 600-800 gC m^-2 season — 12-16 per cent. We charge continuous turnover + instead and so miss the flushing cost that drives the whole result. +- **Duration matters more than intensity.** The switch is at `T_d/T ~ 0.1`; + evergreen gain crosses zero at `T_d/T ~ 0.45`. +- **Gradual and instantaneous shedding give identical carbon gain** in Manzoni, so + gradual is free in the optimality currency and is what the field data show. + +### Consequence for this work + +**The gate reads the wrong variable.** Raising `a_pl1` failed not because the +threshold was in the wrong place but because reserves are the wrong signal — they +are near-binary (see above), and they turn over *after* the decision should have +been made. Switching the gate to the instantaneous carbon balance would: + +- fire early, while the plant still has reserves, which is what the empirical + record shows and what Daniel proposed; +- leave the pool defended rather than drained, so `r` stops being binary and gains + a resting point without any change to `dS/dt`; +- make the response continuous in a quantity that is itself continuous, so there is + something for it to act on. + +⚠️ **One structural tension it creates.** If leaf area must be able to reach zero, +the log-departure coordinate cannot represent the endpoint — `phi -> -inf` — and +`rebuild_rel ~ 1/A` diverges there. The coordinate was chosen to make the resting +model exact, and it does; but it assumes the canopy stays a fixed fraction away +from nothing. A fully-shedding species breaks that assumption, and choosing between +exactness at rest and representability at zero is now an open design question. + +## When does shedding actually pay? An analytical answer (2026-09-08) + +Daniel's framing: shedding is only useful if it improves the plant's net carbon +budget, and that should be designable without stand simulations. It is. + +### The decomposition + +At fixed height, net production splits by whether a cost scales with leaf area. +Leaf, fine root and bark all do; sapwood does not: + +$$P = c\,\bar a\!\left(\tfrac{A_s}{A}\right) A \;-\; g(h)\,A \;-\; s(h, A_s)$$ + +**Verified bit-exactly** against `net_mass_production_dt` (relative error 1e-16 at +four size/soil combinations). `g(h)` is a constant per unit leaf area; `s` is the +sapwood burden and is independent of `A`. + +### The criterion + +Differentiating at **fixed sapwood** — which is what real thinning does, since +sapwood only decays at `k_s`, and which is the step my earlier probe got wrong by +letting `A_s` follow `A` down the pipe model: + +$$\frac{\partial P}{\partial A}\bigg|_{A_s} = c\,\bar a\,(1-\eta) - g(h), +\qquad \eta \equiv \frac{k_{\max}}{\bar a}\frac{\partial \bar a}{\partial k_{\max}}$$ + +because `kmax` is proportional to `1/A` at fixed sapwood. With +`kappa = g/(c*abar)` the leaf-side cost as a fraction of leaf-side gain, + +> **shedding pays iff `eta > 1 - kappa`.** + +`eta` is the elasticity of per-leaf assimilation to hydraulic supply. Reading it: + +- `eta = 0` (no hydraulic feedback) recovers `kappa > 1`, which is exactly + Manzoni's `A_net = 0`. So the criterion currently implemented is the special + case where leaf area does not affect supply. +- `eta = 1` (assimilation proportional to supply) means shedding **always** pays: + halving leaf area leaves total assimilation unchanged and halves the cost. +- In between, shedding pays *earlier* than Manzoni's rule, by exactly `eta`. + +**This closes the gap** where a tall plant died without shedding. `kmax ~ 1/h`, so +`eta` rises with height (measured 0.20 at 5 m, 0.43 at 10 m, 0.63 at 15 m, 0.84 at +20 m) — tall plants have most to gain from thinning, and the current criterion, +which sets `eta = 0`, cannot see it. + +**And it rules out gating on whole-plant solvency.** At h = 15, theta = 0.20 the +plant is solvent (`P = +3.4`) and shedding still improves the budget. Solvency and +marginal benefit are different questions, and only the second says whether +shedding pays. + +### Two cautions on the numbers + +⚠️ **The `profit` / `shadow_cost` auxes do not faithfully report the assimilation +net production used.** The decomposition reconstructs `P` exactly at a resting +state but is 2 per cent out at a departed one (5.71 against 6.09 at h = 10, +theta = 0.20, phi = −0.05). So `abar` recovered from those auxes is unreliable off +the trajectory, and every `eta` above is an estimate rather than a measurement. +The *direct* finite difference of `P` is unambiguous and is what the sign +conclusions rest on. Worth its own look — it may be the same class of issue as +the leaf's carried state. + +⚠️ **The apparent size of the benefit is an artefact of a badly-placed Huber +value.** Shedding 10 per cent of the canopy at fixed sapwood raised `P` from 3.42 +to 8.33 for a healthy 15 m plant — but `P` is a small residual between large +numbers precisely because the sapwood burden is large, so a modest absolute gain +looks dramatic. The plant is sitting far from its optimal sapwood-to-leaf ratio, +which is what gives thinning such leverage. + +### What this implies for the order of work + +The leverage above is the **optimality-derived sapwood target** asking to be built +(the epic split out earlier). If sapwood tracked its optimum, a plant would not sit +at a Huber value this wrong, and the thinning question would be posed cleanly +instead of against a misconfigured stem. + +It also depends on the height-hydraulics relation, which **#617 (epic #615)** is +replacing: it derives the height exponent from conduit widening and the Huber +profile rather than assuming resistance linear in height. TF24 currently drops +per-leaf assimilation 46-fold between 5 m and 15 m, and that number is doing most +of the work in everything above. Any `eta` measured now is measured against a +height-resistance relation that is about to change. + +**So: sapwood optimality first, then re-measure `eta`, then implement the +criterion.** Implementing `eta` against the current stem model would be fitting to +a relation that #617 replaces. + +## Sapwood tracking its optimum: the design (2026-09-08) + +Agreed direction. Four decisions, and one of them removes the cost objection. + +**1. The objective is GROWTH RATE, not net production.** Corrected by Daniel, and +it matters here in a way it does not for shedding. Growth is +`F * f_g * darea_leaf_dmass_live(A*)`, and that conversion factor is evaluated at +`A*(h)` -- the leaf area the plant's HEIGHT implies -- so at fixed height it is a +constant. Therefore `d(growth)/dA` and `dP/dA` have the same sign and **the +shedding criterion is unaffected**. For sapwood it is decisive, because extra +sapwood must be paid for in forgone leaf-area growth. + +**2. First fix an inconsistency that biases the optimum.** +`dmass_sapwood_darea_leaf` uses `pars.theta`, not the plant's actual Huber value. +So a plant carrying 3.3x the sapwood per leaf currently pays the *pipe-model* +price for new growth and gets the hydraulic benefit free. That is much of why P +peaked as far out as 3.3x. Fixing it moves the growth optimum well below the P +optimum. Its own commit, its own number check -- it changes behaviour on its own. + +**3. `psi` integrating the marginal return IS the slow, time-averaged response.** +`dpsi/dt = a_sw * R_s`, with `R_s` the dimensionless marginal growth return of +sapwood (zero at the optimum), is an integral controller: it converges exactly +onto `R_s = 0`, and a small `a_sw` makes it slow. **No extra tracked state is +needed, because integration is averaging** -- which is what the tracked marginal +for the shedding gate had to be built for, and is not needed twice. + +**4. ⚠️ RETRACTED — see "What the implementation found" below. The derivative is NOT nearly free; the envelope theorem does not apply to the collar potential, which is root-found rather than maximised. The reasoning as originally written:** + +**The derivative is nearly free, by the envelope theorem.** `R_s` needs +`d(profit)/d(kmax)`, which looked like a second leaf solve per rate evaluation -- +a doubling of the hot path. It is not. `profit_` is already *maximised* over the +collar potential, so the derivative with respect to a parameter is the partial +derivative of the objective at the optimum already found: + + d(profit*)/d(kmax) = (partial profit / partial kmax) at psi* + +the indirect term vanishing because `partial profit / partial psi = 0` there. It +holds at the KKT corner too: the active constraint is `psi <= psi_crit`, and +`psi_crit` is built from `stem_b`/`stem_c`, not from `kmax`, so the multiplier +term drops out. **One evaluation of a closed form at a known point, not a +re-optimisation.** + +This is what phylloptim's IFT gradient machinery (#4) exists for; the known gap is +that its gradient outputs are `A`, `gc`, `psi_stem` and `collar` rather than the +`profit_` plant bills -- plant #614, and the same sensitivity the optimality epic +already needed. + +### Order + +1. Construction cost reads the actual Huber value, not `theta`. Behaviour change, + own commit. +2. Re-measure the optimum against growth rate. Expect it well below 3.3x. +3. Add `d(profit)/d(kmax)` to phylloptim by the envelope theorem. +4. The integral controller, with `a_sw = 0` by default so exactness holds. + +⚠️ And #617 (epic #615) replaces the height-resistance relation this is all +measured against, so step 2's number should be re-taken after it lands. + +### What the implementation found (2026-09-08) + +Steps 1, 2 and 4 are done. Step 3 is not needed as an upstream change: `d(profit)/d(kmax)` is measured inside plant. plant #614 remains worth having for the analytic version, and is now worth MORE than it looked, for the reason below. + +**⚠️ RETRACTION: the envelope theorem does not apply, and point 4 above is wrong.** The shortcut was to re-evaluate the leaf at the collar potential already found, on the argument that the indirect term vanishes at an optimum. That holds for `opt_psi_stem_`, which is genuinely chosen to maximise profit. It does NOT hold for `opt_root_psi_`, which is found by a **root find** — the collar potential at which the soil-root network's supply matches the leaf's demand. A constraint is not an optimum, so `d(profit)/d(collar)` is not zero and the indirect term is real. + +Measured: holding the collar fixed under-reports `d(profit)/d(kmax)` by **15-19 per cent**, which put the controller's zero at 1.22x the pipe-model ratio where growth actually peaks at 1.28x. A full re-solve matches a finite difference of the model's own assimilation to **0.09 per cent** and lands the zero on the peak in all twelve height/soil cells tried. + +**Why it survived so long:** in wet soil the growth peak is extremely flat (at 16 m, `dh/dt` differs by 6e-4 relative between 1.13x and 1.22x), so a 0.025 scan grid could not resolve a 0.03 offset in psi and the zero appeared to land exactly on the peak. It only showed up in dry soil, on a 0.01 grid. **A coarse grid does not merely lose precision here; it manufactures an exact-looking agreement.** + +**Consequence:** `a_sw > 0` costs a second full leaf solve per rate evaluation (three in total: the original, the perturbed, and one to restore the leaf's members for the auxes). The default `a_sw = 0` skips the block entirely, so the hot path is untouched unless acclimation is on. An analytic `d(profit)/d(kmax)` from phylloptim would remove that cost. + +**The controller.** `dpsi/dt` gains `a_sw * R_s`, with + + R_s = availability * (dP/dpsi - P * dmass_sapwood_darea_leaf * darea_leaf_dmass_live) / maintenance + +The second term in the bracket is the price of the extra stem, paid in forgone leaf area; dropping it optimises production instead, whose optimum sits far out near 3.3x. `a_sw = 0` is the default and the model is then **bit-exact** — verified by building at HEAD and re-running the scenario gateway, which returned the same eight numbers to every digit. + +**Four things the implementation got wrong first, each worth stating because each looked right:** + +1. **⚠️ Sapwood turnover is GATED, so its `psi`-derivative is not `k_s * m_s`.** What the budget is charged is `replacement_sapwood * k_s * m_s` with `replacement_sapwood ∝ exp(-psi/a_pl2)` against `m_s ∝ exp(psi)`, so the charge falls as `exp((1 - 1/a_pl2) psi)` — steeply, `a_pl2` being well below 1. Differentiating the ungated cost drops a term worth **+6.8 kg/yr of 13.1** and moved the controller's zero from the true 1.35x down to 1.05x. This is the single largest error in the derivation and it is invisible to any sign or monotonicity check. + +2. **The denominator must be strictly positive, and `profit` is not.** `profit + shadow_cost` is net of leaf respiration and goes negative in exactly the drought where the controller most needs a sign. Normalising by it silently switched the controller off at soil 0.13. It now divides by the maintenance bill (`a_bio * a_y * respiration + turnover`), which is positive whenever the plant has tissue. + +3. **Re-proportioning must be paid for.** Nothing debits the budget for the `a_sw` drift, so without a gate a plant in carbon deficit keeps thickening its stem on carbon it does not have. **The reserve gate `G` is NOT the right switch**: at soil 0.13 reserves are still full so `G ~ 1`, and what has gone to zero is `Ppos`. The factor used is `growth_flux / (growth_flux + maintenance)` — a share of throughput, so smooth, in `[0, 1)`, vanishing with the growth flux, and strictly positive so **it cannot move the zero**, only the speed. + +4. **Deep-crown is refused, not skipped.** The sensitivity is measured at one radiation; deep-crown integrates profit over crown positions, so that difference is not its derivative. Skipping it leaves the controller with only its negative cost term, and the stem shrinks without bound while the run looks plausible the whole way down. `prepare_strategy()` now throws on `a_sw > 0` with deep-crown. + +**On the FD step.** The first diagnosis was that `dk = 1e-6 * kmax` sat in the solver's noise floor. It did not — widening it 1000x moved `R_s` by 0.3%, which also rules out a constant offset between a point value and an integral. The step is now `1e-3` relative on the reasoning that it should clear the leaf's internal tolerances, but the recorded finding is that **the step was never the problem**; the missing turnover term was. + +**Measured, at h = 10 m, soil 0.20, against the pipe-model ratio:** + +| stem/leaf | dh/dt | R_s | +|---|---|---| +| 1.00 | 1.191 | +0.264 | +| 1.22 | 1.393 | +0.089 | +| **1.35** | **1.411** | **−0.002** | +| 1.49 | 1.396 | −0.085 | +| 1.82 | 1.303 | −0.221 | + +The zero-crossing lands on the argmax of `dh/dt` — which is the defining correctness property, since a controller built on production instead is still monotone, still converges, and is still wrong. `test-strategy-tf24.R` asserts it on the grid rather than by interpolation so that the production version fails rather than passing on a tolerance. + +At soil 0.15 growth is still rising at 1.82x and `R_s` stays positive throughout; at soil 0.13 the plant has no carbon and `R_s` is ~1e-11. In an SCM run on a wet stand, `a_sw = 0.5` raises R0 from 97.3 to 154.0 (+58%), which is the size of the prize in leaving the pipe model. + +## Shedding's benefit is a steep function of SIZE — re-measured after #617 (2026-09-08) + +**The prediction below was made before #617 landed and it held.** It said the benefit band sits at the height-resistance relation's viability ceiling, and that the path integral should push the ceiling up and take the band with it. Measured after the merge: + +| | before #617 | after #617 | +|---|---|---| +| viability ceiling (P > 0 in wet soil) | between 17 and 18 m | between 30 and 36 m | +| shedding benefit first appears | ~16 m | ~20 m | +| largest benefit found | 6.1e9x (at 18 m, and both arms dead) | 84x (at 30 m, 4 yr @ soil 0.14) | +| benefit at soil 0.16 for 4 yr, any height | up to 4.4e9x | **exactly 1.00 at every height to 24 m** | + +The ceiling roughly doubled, which is what conduit widening is for. Three things follow. + +**1. TF24 is now far more drought-tolerant, and the earlier "cliff" is gone.** A 4-year drought at soil 0.16 no longer kills anything up to 24 m (survivorship ~0.92 at every height) and the canopy never thins, so shedding has nothing to do. Before #617 that same drought took a 20 m plant to 2.9e-19. + +**2. The size dependence survives, shifted.** At soil 0.14 the benefit is 1.00 at 10 m, 1.04 at 16 m, 2.4 at 20 m, 21 at 24 m and 84 at 30 m. Below ~13 m the canopy still does not thin at all: the marginal leaf keeps paying for itself, which is the gate working as designed. + +**3. Shedding still never converts death into survival.** Zero cells of the post-#617 grid (heights 16-30, soils 0.14-0.12, 4 yr) have the fixed plant dead and the shedding plant alive; the large ratios still sit between two very small numbers. And the benefit is largest at *moderate* drought (0.14), not the harshest — at soil 0.12 everything dies whatever it does, so the ratio returns to ~1. + +⚠️ **The numbers in the original section below are PRE-#617 and superseded.** They are kept because the reasoning they support — that the band tracks the viability ceiling — is what the merge then confirmed, and because the size of the shift is the clearest available statement of how much the height-resistance relation was driving this. + +## Shedding's benefit is a steep function of SIZE — the pre-#617 measurement (2026-09-08) + +Re-asking "does shedding buy survival?" against a well-configured stem, as the earlier section said had to be done. The answer is more interesting than either yes or no, and **the earlier null result was measured at one size**. + +Measured on a single plant: wet acclimation, mortality integral zeroed at the start of the drought so only the drought's own hazard is compared, then drought, then recovery. + +| height | 4 | 8 | 10 | 13 | 16 | 18 | 20 | +|---|---|---|---|---|---|---|---| +| survival ratio, shed / fixed (4 yr @ 0.16) | 1.00 | 1.00 | 1.00 | 1.03 | 9.5 | — | 4.4e9 | +| canopy retained at the end | 1.00 | 1.00 | 1.00 | 1.00 | 0.74 | — | 0.38 | + +**Below about 13 m shedding does literally nothing** — the ratio is 1.000 and the canopy never leaves 1.000. Not a weak effect: no effect. The gate reads the *marginal* leaf's balance, and a short plant's marginal leaf still pays for itself even in drought. This is why the earlier sweep, run at 10 m and below, found 1.001-1.06x and concluded thinning does not buy survival. That conclusion was right about the size it was taken at and wrong as a general statement. + +**⚠️ But the large ratios are not what they look like.** At 20 m and above the plant has `P < 0 in WET soil` (-17.9 kg/yr at 20 m, -84.2 at 24 m). Those cells are not a tree surviving a drought; they are a tree that this height-resistance relation cannot sustain at all, which shedding then rescues. A ratio of 4e9 between 3e-19 and 1e-9 is two kinds of dead. + +**The viability ceiling and the benefit band are the same thing.** `P` in wet soil crosses zero between 17 and 18 m: + +| height | 14 | 16 | 17 | 18 | 19 | 20 | +|---|---|---|---|---|---|---| +| P at soil 0.30 (kg/yr) | +9.6 | +6.6 | +3.2 | **-1.8** | -8.7 | -17.9 | +| shed/fixed survival, 1 yr @ 0.15 | 2.6 | 4.8 | 10.6 | 6.1e9 | 4.9e9 | 2.1e9 | + +So the whole of shedding's leverage lives in a narrow band straddling the height at which the model stops being able to keep a tree alive. Of a 90-cell grid (heights 8-18, soil 0.20-0.14, droughts 1-4 yr), **zero cells** had shedding take a plant from dead to comfortably alive by a strict bar; the best real rescue is 18 m, 1 yr at soil 0.15, where survivorship goes from 2.2e-11 to **0.137**. + +### What this means for the work + +1. **The demo's "thinning does not buy survival" section needs qualifying, not deleting.** It is true below 13 m and false above 16 m, and the reason is the one the analytical criterion already gives: eta grows with height because `k_max ∝ 1/h`, so tall plants are exactly the ones for which thinning pays. The criterion predicted this; the behavioural test was taken at a size where the criterion says the answer is no. + +2. **⚠️ Every number here is provisional against #617**, and more so than anything else measured on this branch. The band's location IS the height-resistance relation. #617 replaces resistance-linear-in-height with a path integral over conduit widening, and basipetal widening is precisely what stops resistance growing linearly with height in real trees — so it should move the ceiling up and take the band with it. Re-measure this table after #617, before drawing any ecological conclusion from it. + +3. **Sapwood acclimation helps more than shedding does, in the range where plants are viable.** At 10 m, `a_sw = 0.5` raised drought survivorship about 10x (7.7e-3 to 7.9e-2 at soil 0.16) where shedding gave 1.002x. Both mechanisms matter, but they matter at different sizes. + +## Open + +- Which growth rate the optimality criterion should maximise is **not** a modelling choice to be argued — see "Deciding the objective by invasion analysis" above. It is settled by experiment, and the cheap half of that experiment can run before any of this code exists. + +## Settled + +- **The new gate centres and the rebuild rate are `TF24_Pars` fields, and therefore settable as traits.** Nothing further is needed for that: plant's trait mechanism reaches nested `pars`, so a parameter that lives there can be varied through `trait_matrix()`/`add_strategies()` immediately — verified on `theta`, which takes two distinct values across two strategies with no hyperpar involvement. A **hyperpar** entry is a different thing and is *not* wanted yet: that machinery is for a parameter *derived* from another trait (as `k_l` is from `lma`), and there is no trade-off to encode until #512 says what one would look like. Defaults reproduce the current model. diff --git a/notes/atls/.DS_Store b/notes/atls/.DS_Store new file mode 100644 index 000000000..5008ddfcf Binary files /dev/null and b/notes/atls/.DS_Store differ diff --git a/notes/plan-tf24-scenario-framework.md b/notes/plan-tf24-scenario-framework.md index 8ba89802c..33ffa37fb 100644 --- a/notes/plan-tf24-scenario-framework.md +++ b/notes/plan-tf24-scenario-framework.md @@ -310,10 +310,14 @@ Read on the two axes the gateway now reports: **numerical viability 8/8**, and ### Density coordinate: the gateway runs in birth date (#590, decided 2026-08-05) -`scenario_control()` supplies `control(node_density_in_birth_date = TRUE)` and is -the default `ctrl` for `build_scenario`, `classify_scm_run`, `evaluate_scenario` -and `run_scenarios`. The package default (`FALSE`, height) is deliberately left -alone; only the gateway opts in. +`scenario_control()` supplies `control(node_density_coordinate = "birth_date")` and +is the default `ctrl` for `build_scenario`, `classify_scm_run`, `evaluate_scenario` +and `run_scenarios`. + +Since #516 the package default is `"auto"`, which TF24 resolves to `"birth_date"` +anyway, so the gateway no longer differs from the default — it still names the +coordinate explicitly so that the value recorded in a scorecard's metadata is the +resolved one rather than something a reader has to resolve against the model. Why the gateway and not the package: every scenario here is TF24, and TF24 is exactly the model #590 identifies as the one the coordinates disagree on. The diff --git a/overstorey_staging/.DS_Store b/overstorey_staging/.DS_Store new file mode 100644 index 000000000..831883218 Binary files /dev/null and b/overstorey_staging/.DS_Store differ diff --git a/overstorey_staging/TF24_flexible_allometry_demo.qmd b/overstorey_staging/TF24_flexible_allometry_demo.qmd new file mode 100644 index 000000000..bc3b914a5 --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo.qmd @@ -0,0 +1,1164 @@ +--- +title: "A canopy that thins" +subtitle: "Flexible allometry in TF24 — what it does, and why it does not yet buy survival" +format: + html: + toc: true + toc-depth: 3 + code-fold: true + fig-width: 9 + fig-height: 5 +--- + +```{r setup, message=FALSE, warning=FALSE} +# Staging demo: needs the in-tree dev build (#516), not necessarily the +# installed `plant`. +pkg_root <- if (file.exists("DESCRIPTION")) "." else ".." +if (requireNamespace("pkgload", quietly = TRUE)) { + pkgload::load_all(pkg_root, quiet = TRUE) +} else { + library(plant) +} +library(ggplot2) +library(patchwork) +library(dplyr) +library(tidyr) + +# Shared computation, kept out of this file so a test can exercise it: a chunk +# that runs is not a chunk that is checked. +source(file.path(pkg_root, "overstorey_staging", "allometry_demo_helpers.R")) + +theme_set(theme_bw(base_size = 12)) +``` + +Real plants under stress thin their canopies. TF24 could not: leaf area was pinned +to height, so a struggling plant had no way to economise and no option but to die. +It now has one. + +This page shows the new mechanism working — a plant thinning through a drought and +rebuilding afterwards, and a suppressed plant doing the same in the shade — and +then shows the problem with it. **Thinning saves the plant almost nothing.** We +have now tested two different triggers for it, and both give a survival gain of +about one per cent while costing two metres of height. That rules the trigger out +and points somewhere else, which is the useful part. + +The mechanism is off by default. Everything here runs with it switched on. + +## Principles + +These are the rules the build follows. Most of the design decisions below are +consequences of them rather than independent choices, and where a measurement +overturned one it is said so explicitly. + +1. **The old model must be recoverable exactly.** Switching the mechanism off + returns the fixed allometry bit for bit, not approximately. This is a + diagnostic, not an end in itself: it is how we know a decomposition is + algebraically right rather than merely plausible. +2. **Bounds should follow from the form, not from clamps.** Where a quantity must + stay in a range, arrange the flow so it cannot leave — a rate that vanishes at + the boundary. A clamp changes the answer silently, is a kink in every + downstream derivative, and hides the overshoot it was added to catch. +3. **Everything smooth.** No `min`, `max` or branches in the carbon-to-growth map. + Automatic differentiation is coming, and a kink propagates into every + sensitivity that passes through it. +4. **Carbon and tissue balance as an identity.** Carbon a plant declines to spend + and tissue it consequently loses are two halves of one decision, so they are + computed from one number and asserted as an identity, never as a tolerance. +5. **Only gate a pool that has a state.** Withholding the cost of tissue that + cannot shrink saves carbon no tissue paid for — a free lunch, and a silent one. +6. **Scale-free where possible.** Rates are relative, so the same parameter means + the same thing for a seedling and a mature tree. This is what keeps the + plasticity parameters from repeating `storage_prod_eps`'s mistake of being an + absolute constant against fluxes spanning six orders of magnitude. +7. **Signals that drive slow structure must be slow.** Assimilation swings with + the weather; leaf and stem take years to build. Anything reading the first to + decide the second reads a running mean. +8. **Numerically safe always.** A state that runs somewhere its arithmetic stops + meaning anything is a defect even when the biology it represents is right — + a dying plant is still integrated alongside live ones. +9. **Follow the evidence, and record what it overturns.** Two of the decisions + here reverse earlier ones after measurement, and both retractions are kept in + place rather than quietly edited away. + +## What changed + +TF24 used to pin leaf area to height through a fixed allometry, `A = A*(h)`. A +plant could not carry less leaf than its height implied, and its height could only +ever increase, so *thinning was not expressible at all*. + +Leaf area and sapwood area are now ODE states. But they are carried as **departures +from their preferred values** rather than as the areas themselves: + +| state | in words | resting value | +|---|---|---| +| `log_area_leaf_departure` | how much less canopy the plant carries than its height implies | 0 | +| `log_area_sapwood_departure` | how much more conducting stem it carries than its canopy needs | 0 | + +Leaf area is then derived rather than integrated. Writing `phi` for the first +departure, `A = A*(h) * exp(phi)`, so `phi = 0` means "exactly on the old +allometry" and `phi = -0.7` means "half a canopy". + +::: {.callout-note} +## Why the two move in opposite directions +Both departures are defined the same way — the log of what a plant *has* over what +it *should* have. What differs is the reference, because the allometry is a chain: + +$$h \;\longrightarrow\; A = A_\star(h) \;\longrightarrow\; A_s = \theta A$$ + +Each departure is measured against its own parent in that chain. `phi` asks *"how +much leaf do I carry, against what my height implies?"*; `psi` asks *"how much +conducting stem do I carry, against what my canopy needs?"*. + +Under stress they then move oppositely, and that is the physical result rather than +an inconsistency. Leaves turn over faster than sapwood, so the canopy falls below +what its height implies (`phi` negative) while the stem is left carrying more than +the now-smaller canopy needs (`psi` positive). + +Referencing both to height instead — which would be $\psi' = \psi + \phi$ — would +give them a shared sign. It would cost two things: `psi` would stop being the log +Huber value, which is the quantity the hydraulics actually reads, and the clean +`psi >= 0` invariant would become the messier $\psi' \ge \phi$. +::: + +Carrying departures rather than levels is what makes the old model recoverable +*exactly*. Integrating leaf area alongside height would make `A = A*(h)` a +redundant relationship that the ODE solver holds only to its own error tolerance, +so height would end up reading a slightly drifted leaf area. On the departure +coordinate the allometric part stays exact and only the departure is integrated — +so with the mechanism off, its rate is exactly zero and the old model comes back +bit for bit. + +**The switch is `a_pl0`**: the largest fraction of leaf and sapwood turnover a +plant may decline to replace. `a_pl0 = 0`, the default, is the old model. + +```{r versions} +s <- TF24_Strategy() +data.frame( + quantity = c("model", "number of states", "a_pl0 (default, = off)", + "a_pl1 (reserve level where withholding is half its max)", + "a_pl2 (gap scale)", + "k_l (leaf turnover, /yr)", "k_s (sapwood turnover, /yr)"), + value = c(model_id("TF24"), TF24_Individual(s)$ode_size, + s$pars$a_pl0, s$pars$a_pl1, s$pars$a_pl2, + round(s$pars$k_l, 4), s$pars$k_s)) |> + knitr::kable() +``` + +### How it works, in words + +1. **A plant sheds when its marginal leaf stops paying for itself.** Not when its + reserves run out — when the last leaf's assimilation no longer covers its own + upkeep and that of the fine root and bark that come with it. Below that point, + the plant declines to replace some of the leaf and sapwood its turnover + destroys, and *is not charged for what it does not replace*. +2. **It reads a running mean, not today's weather.** Assimilation swings daily; a + canopy takes years to build. The gate reads a filtered balance with a memory of + about four months — long against weather, short against a drought. +3. **Leaves go faster than stem.** Leaves turn over at `k_l = 0.46`/yr and sapwood + at `k_s = 0.20`/yr, so withholding both thins the canopy faster than the stem. + Conducting area per unit leaf area therefore *rises*. Nothing imposes this; it + falls out of the two rate constants. +4. **When the balance recovers, the plant rebuilds**, redirecting growth from + height into canopy, tapering off as the gap closes. +5. **Height never falls, and the canopy never empties.** A plant in deficit stops + growing, and thinning tapers to nothing at a floor. + +::: {.callout-important} +## Why the trigger is the carbon balance and not the reserve pool +The first version gated on the NSC reserve fraction: shed once reserves are nearly +gone. Two lines of evidence overturned it. + +**Theory.** Manzoni et al. (2015) maximise a season's carbon gain over leaf area +and *derive* the trigger: `dG/dL = 0`, i.e. shed once a leaf stops covering its +upkeep. That fires while the plant is still carbon-rich — their Fig. 4D has +cumulative gain at its seasonal *maximum* when shedding starts. **Waiting for +reserves to run down is precisely the evergreen strategy in that paper, and it is +the one that loses a long drought**, running its season's gain from +150 to +−50 gC m⁻². + +**Field data.** In Robinson's mulga, 85 per cent of trees shed — the healthiest +included — and the died and survived canopy distributions are indistinguishable in +the first year. Shedding is what healthy trees do, not what dying trees do last. + +Measured here, the reserve gate bought a survival factor of 1.0–1.13 even when +moved as early as it would go. The carbon-balance gate is the better model on the +evidence; it does not, as it turns out, fix survival either — see below. +::: + +## When does shedding pay? An analytical criterion + +This is the centre of the design. Thinning is only worth doing if it improves the +plant's carbon budget, and that can be settled on paper rather than by running +stands. + +### The budget splits in two + +At a given height, every cost either scales with leaf area or does not. Leaf, fine +root and bark all do — bark because it is pinned to leaf area. Sapwood does not: +it is carried whether or not any particular leaf exists. So + +$$P \;=\; \underbrace{c\,\bar a\!\left(\tfrac{A_s}{A}\right) A}_{\text{gain}} +\;-\; \underbrace{g(h)\,A}_{\substack{\text{leaf, root, bark}\\ \text{(scales with }A)}} +\;-\; \underbrace{s(h, A_s)}_{\substack{\text{sapwood}\\ \text{(does not)}}}$$ + +where $\bar a$ is assimilation per unit leaf area. It depends on $A$ only through +the Huber value $A_s/A$: fewer leaves on the same stem means better hydraulic +supply to each. + +```{r decomposition} +terms <- lapply(c(5, 10, 15, 20), allometry_carbon_terms, theta_soil = 0.20) +do.call(rbind, lapply(terms, function(z) + data.frame(height = z$height, gain = z$gain, `leaf-side cost` = z$g, + `sapwood cost` = z$s, + `gain - costs` = z$gain - z$g - z$s, `actual P` = z$P, + check.names = FALSE))) |> + knitr::kable(digits = 3) +``` + +The last two columns agree to machine precision, so this is the model's own budget +rearranged rather than an approximation of it. + +### Differentiate at fixed sapwood + +Real thinning happens at roughly constant sapwood: the stem is lost only to +heartwood, at `k_s`, while leaves go at the faster `k_l`. So the derivative that +matters holds $A_s$ fixed — and since $k_{\max}\propto A_s/A$, reducing leaf area +*raises* supply per leaf: + +$$\frac{\partial P}{\partial A}\bigg|_{A_s} = c\,\bar a\,(1-\eta) - g(h), +\qquad +\eta \;\equiv\; \frac{k_{\max}}{\bar a}\,\frac{\partial \bar a}{\partial k_{\max}}$$ + +Writing $\kappa = g/(c\bar a)$ for the leaf-side cost as a fraction of the +leaf-side gain, shedding improves the budget exactly when this is negative: + +$$\boxed{\;\text{shedding pays} \iff \eta > 1 - \kappa\;}$$ + +### Reading it + +$\eta$ is the elasticity of per-leaf assimilation to hydraulic supply, and it is +the whole content of the criterion. + +- **$\eta = 0$** — no hydraulic feedback — gives $\kappa > 1$: shed once leaf-side + costs exceed leaf-side gains. That is exactly Manzoni et al. (2015)'s + $A_\text{net} = 0$, and it is what the model implements today. +- **$\eta = 1$** — assimilation proportional to supply — means shedding *always* + pays: halving leaf area leaves total assimilation unchanged and halves the cost. +- **$\eta > 1$** means leaf area is actively counterproductive: removing leaves + *raises* total assimilation. + +```{r elasticity} +do.call(rbind, lapply(terms, function(z) + data.frame(height = z$height, kappa = z$kappa, `threshold 1-kappa` = 1 - z$kappa, + eta = z$eta, `dP/dA` = z$dPdA, + `shedding pays` = z$eta > 1 - z$kappa, check.names = FALSE))) |> + knitr::kable(digits = 3) +``` + +**$\eta$ rises steeply with height**, because $k_{\max}\propto 1/h$ — a taller +plant is more supply-limited, so relieving that limitation is worth more. Above +about 10 m it exceeds 1: TF24 says a tall plant assimilates *more* in total after +shedding leaves. Per-leaf assimilation falls 46-fold between 5 m and 15 m in this +model, which is what makes the effect so large. + +### What this settles, and what it does not + +**It closes the gap** in which a tall plant died without ever shedding. That gap +was an artefact of setting $\eta = 0$: with the hydraulic term included, tall +plants are exactly the ones for which thinning pays most. + +**Solvency is not wrong, but it is late.** Across every size and soil tried, no +state has the plant insolvent while shedding *hurts* — so gating on whole-plant +solvency would never make a plant thin pointlessly. What it would do is fire late: +there is a wide band of *solvent* plants for which thinning already pays. + +```{r solvency-vs-criterion} +grid <- expand.grid(height = c(2, 5, 10, 15, 20), + theta_soil = c(0.30, 0.20, 0.16, 0.14, 0.12)) +q <- do.call(rbind, lapply(seq_len(nrow(grid)), function(i) { + z <- allometry_carbon_terms(grid$height[i], grid$theta_soil[i]) + data.frame(height = z$height, soil = z$theta_soil, P = z$P, dPdA = z$dPdA, + quadrant = if (z$P >= 0 && z$dPdA >= 0) "solvent, keep" + else if (z$P >= 0) "solvent, SHEDDING PAYS" + else if (z$dPdA < 0) "insolvent, shedding pays" + else "insolvent, shedding hurts") +})) +table(q$quadrant) |> as.data.frame() |> + setNames(c("quadrant", "cases")) |> knitr::kable() +``` + +**And that band is an artefact of the stem being wrong, not of the criterion.** +Sweeping the sapwood departure at fixed leaf area, net production is maximised at +stem-per-leaf about **3.3 times** the value the pipe model prefers — and at *that* +sapwood, shedding no longer pays: + +| stem per leaf | 1.0 (default) | 1.35 | 2.5 | **3.3 (optimum)** | 6.0 | +|---|---|---|---|---|---| +| P at 15 m, moist | 3.42 | 17.45 | 24.91 | **29.74** | 22.92 | +| does shedding pay? | yes | yes | no | **no** | no | + +So a plant carrying its optimal stem is one for which thinning does not pay while +it is solvent, and the two criteria coincide. The discrepancy above is the model +sitting at a badly-placed Huber value, not a disagreement between the criteria. + +This also says a *single fixed* $\theta$ cannot be right, because +$k_{\max}\propto 1/h$: the ratio that suits a seedling starves a 15 m tree. It is +the strongest argument yet for the sapwood target being derived rather than fixed. + +::: {.callout-warning} +## Why this is not implemented yet +Two reasons, both about measuring $\eta$ rather than about the criterion. + +**The auxes cannot currently measure it.** `profit` and `shadow_cost` reconstruct +`P` exactly at a resting state but are about 2 per cent out at a departed one. +That is small against the level and comparable to the *difference* being taken, so +differencing $\bar a$ directly is unusable. The $\eta$ column above is therefore +recovered from the measured `dP/dA` through the exact decomposition — a valid +measurement of $\eta$, but not an independent check of the criterion. + +**And the number it depends on is about to change.** The 46-fold assimilation drop +with height comes from stem resistance assumed linear in height. #617 (epic #615) +replaces that with a path integral over conduit widening and the Huber profile, so +the height exponent is derived rather than assumed. Any $\eta$ measured now is +measured against a relation that is being replaced. + +There is also a prior question. The leverage above is large partly because the +plant sits far from a sensible sapwood-to-leaf ratio, so `P` is a small residual +between large numbers. **Sapwood should track its optimum first**; then the +shedding question is posed against a well-configured stem instead of a +misconfigured one. That part is now built, and is the next section. +::: + +## Sapwood tracks its own optimum + +The stem no longer sits where the pipe model puts it. It moves, slowly, toward +the Huber value that maximises the plant's **growth rate**: + +$$\frac{d\psi}{dt} = a_{sw}\,R_s$$ + +This is an integral controller. It has no resting point except $R_s = 0$, so it +converges on the optimum rather than tracking it with an offset — and because +**integrating is averaging**, a small $a_{sw}$ makes the stem respond to the +long-run mean of a signal that swings with the daily weather. No separate +running-mean state is needed; the one built for the shedding gate was needed +because that gate reads its signal *instantaneously*, and this one does not. + +### The objective is growth, not production + +This distinction is the whole design. Against **production**, extra sapwood is +almost always worth building: it raises $k_{\max}$, which raises assimilation, +and nothing in $P$ charges the plant for the leaf area it did not build instead. +That is why the table above puts the production optimum out at 3.3x. + +Growth internalises the trade-off, because carbon in the stem is carbon not in +the canopy: + +$$R_s \;=\; \underbrace{\text{availability}}_{\text{can it be paid for?}}\times\; +\frac{1}{\text{maintenance}}\left(\frac{\partial P}{\partial \psi} +\;-\; \underbrace{P\,\frac{\partial m_s}{\partial A}\,\frac{\partial A}{\partial m_{live}}}_{\text{price of the extra stem}}\right)$$ + +Drop the second term and you optimise production; keep it and the optimum moves +in to **1.35x** at 10 m in moist soil, where growth actually peaks. The optimum is +not one number: it depends on height and on soil water, which is the point. + +### The derivative costs a second solve, and an argument that it does not + +$\partial P/\partial\psi$ needs $d(\text{profit})/d(k_{\max})$, which is a +second leaf solve on the hottest path in the package. There is a tempting +argument that it need not be — and it is wrong, which is worth recording because +it was believed long enough to ship. + +**The argument.** Profit is already maximised, so by the envelope theorem the +derivative with respect to a parameter is the *partial* derivative at the optimum +already found: re-evaluate at the collar potential you have, and the indirect term +vanishes because $\partial\,\text{profit}/\partial\psi^\ast = 0$ there. + +**Why it fails.** That holds for `opt_psi_stem_`, which really is chosen to +maximise profit. It does not hold for `opt_root_psi_`, the *collar* potential, +which is not maximised at all — it is found by a **root find**, the potential at +which the soil-root network's supply matches the leaf's demand. A constraint, not +an optimum. So $\partial\,\text{profit}/\partial(\text{collar}) \neq 0$ and the +indirect term is real. + +**What it cost.** Holding the collar fixed under-reported the sensitivity by +15–19%, which put the controller's zero at 1.22x the pipe-model ratio where growth +actually peaks at 1.28x. It was invisible in wet soil, where the scan grid was too +coarse to resolve the gap. Re-solving properly matches a finite difference of the +model's own assimilation to 0.09% and lands the zero on the peak. + +So `a_sw > 0` roughly doubles the leaf work per rate evaluation. At the default +`a_sw = 0` the block never runs. + +### What it does + +```{r sapwood-controller, fig.height = 3.6} +ctl <- do.call(rbind, lapply(c(0.30, 0.20, 0.15), + allometry_sapwood_controller)) +ctl$soil <- factor(sprintf("soil %.2f", ctl$theta_soil)) + +par(mfrow = c(1, 2), mar = c(4, 4, 2, 1), cex = 0.8) +cols <- c("#2c7fb8", "#31a354", "#d95f0e") +plot(range(ctl$huber_ratio), range(ctl$dheight), type = "n", + xlab = "stem area per leaf area (x pipe model)", + ylab = "height growth (m/yr)", main = "growth") +for (i in seq_along(levels(ctl$soil))) { + d <- ctl[ctl$soil == levels(ctl$soil)[i], ] + lines(d$huber_ratio, d$dheight, col = cols[i], lwd = 2) + points(d$huber_ratio[which.max(d$dheight)], max(d$dheight), + pch = 19, col = cols[i]) +} +legend("bottomright", levels(ctl$soil), col = cols, lwd = 2, bty = "n") + +plot(range(ctl$huber_ratio), range(ctl$R_s), type = "n", + xlab = "stem area per leaf area (x pipe model)", + ylab = expression(R[s]), main = "the controller's signal") +abline(h = 0, col = "grey60", lty = 2) +for (i in seq_along(levels(ctl$soil))) { + d <- ctl[ctl$soil == levels(ctl$soil)[i], ] + lines(d$huber_ratio, d$R_s, col = cols[i], lwd = 2) +} +``` + +Filled circles mark where growth peaks. **The signal crosses zero where growth +peaks** — that is the property the whole derivation exists to produce, and it is +asserted in `test-strategy-tf24.R` on the grid rather than by interpolation, so +that a controller built on production instead fails rather than passing on a +tolerance. + +The optimum moves with soil water — 1.28x, 1.35x, and beyond the right-hand edge +of the sweep as the soil dries. **A drier plant wants more stem per leaf**, which +is the hydraulic acclimation a single fixed $\theta$ cannot express, and it is +why the pipe model is wrong in a way no re-tuning of $\theta$ could fix. + +One honest wart is visible at the left of the driest curve: $R_s$ is *zero* there, +not positive. A plant at the pipe-model ratio in dry soil cannot grow at all +(`dh/dt` ~ 5e-10), so the availability factor switches the controller off — it +can only start acclimating once it has some carbon to acclimate with. That is the +correct accounting, but it does mean the plant that would benefit most from more +stem is the one least able to build it. + +Turning it on is not a small effect. On a wet stand, $a_{sw} = 0.5$ raises $R_0$ +from **97.3 to 154.0**, because the default pipe-model ratio is simply not where +growth is maximised. + +::: {.callout-note} +## Three things that had to be got right, and were not at first +**Sapwood turnover is gated, so its derivative is not $k_s m_s$.** What the budget +is charged is $f_s k_s m_s$ with $f_s \propto e^{-\psi/a_{pl2}}$ against +$m_s \propto e^{\psi}$, so the charge *falls* steeply with $\psi$. +Differentiating the ungated cost drops a term worth 6.8 of 13.1 kg/yr and moves +the zero from 1.35x to 1.05x — an error invisible to any check on sign or +monotonicity. + +**The denominator has to stay positive.** Profit is net of leaf respiration and +goes negative in exactly the drought where the controller most needs a sign, so +$R_s$ divides by the maintenance bill instead. + +**Re-proportioning has to be paid for.** Nothing debits the budget for this drift, +so a plant in deficit would keep thickening its stem on carbon it does not have. +The reserve gate $G$ is *not* the right switch — at soil 0.13 reserves are still +full, and what has gone to zero is production. The availability factor +$F/(F + \text{maintenance})$ vanishes with the growth flux, and being strictly +positive it cannot move the zero, only the speed. +::: + +## What it does + +### The gate + +The gate responds to soil water — through the marginal leaf's carbon balance — +while reserves are held *full* throughout. That is the demonstration that reserves +are no longer the axis it reads. + +```{r gate, fig.height=4, fig.cap="A 5 m plant across soil water, with reserves at 0.8 of capacity throughout. The old gate could not fire anywhere on this axis."} +gate <- allometry_gate_map(a_pl0 = 1.0, height = 5) + +p_margin <- ggplot(gate, aes(theta_soil, margin)) + + geom_hline(yintercept = 0, linewidth = 0.3, colour = "grey50") + + geom_line(linewidth = 0.9) + + labs(x = "soil water content", y = "marginal leaf return", + title = "Is the last leaf paying for itself?", + subtitle = "Zero is break-even: Manzoni's criterion") + +p_rates <- gate |> + select(theta_soil, leaf = dphi, sapwood = dpsi) |> + pivot_longer(-theta_soil) |> + ggplot(aes(theta_soil, value, colour = name)) + + geom_hline(yintercept = 0, linewidth = 0.3, colour = "grey50") + + geom_line(linewidth = 0.9) + + labs(x = "soil water content", y = "departure rate (per year)", colour = NULL, + title = "What the plant does about it", + subtitle = "Canopy thins; stem-per-leaf rises") + +p_margin + p_rates +``` + +The two departure curves have **opposite signs** — that is the acclimation, and it +is `k_l > k_s` showing up. And the response is switch-like in soil water, because +the quantity it reads crosses zero sharply: between 0.15 and 0.13 the marginal +leaf goes from 88 per cent in profit to 106 per cent in loss. + +### Through a drought and out the other side + +A plant sits in wet soil, is dropped into a four-year drought, and is then returned +to wet soil. Soil water is prescribed directly here so the carbon balance can be +driven cleanly — this is *not* how the SCM drives soil water. + +```{r trajectory, message=FALSE, warning=FALSE} +history <- demo_soil_history(wet = 0.30, dry = 0.11, + years_wet = 2, years_dry = 4) +traj <- bind_rows( + allometry_trajectory(0.0, history, dt = 0.25), + allometry_trajectory(1.0, history, dt = 0.25)) |> + mutate(allometry = ifelse(a_pl0 == 0, "fixed", "flexible")) +``` + +```{r trajectory-plot, fig.height=7, fig.cap="Shaded band is the drought. Canopy fullness of 1 means the plant sits on the old allometry."} +dry_band <- annotate("rect", xmin = 2, xmax = 6, ymin = -Inf, ymax = Inf, + fill = "grey85", alpha = 0.6) + +p1 <- ggplot(traj, aes(time, canopy_fraction, colour = allometry)) + + dry_band + geom_line(linewidth = 0.9) + + labs(x = NULL, y = "canopy fullness", colour = NULL, + title = "Canopy, relative to what its height implies") + +p2 <- ggplot(traj, aes(time, huber_ratio, colour = allometry)) + + dry_band + geom_line(linewidth = 0.9) + + labs(x = NULL, y = "stem per leaf, relative", colour = NULL, + title = "Conducting area per unit leaf area") + +p3 <- ggplot(traj, aes(time, height, colour = allometry)) + + dry_band + geom_line(linewidth = 0.9) + + labs(x = "time (yr)", y = "height (m)", colour = NULL, + title = "Height") + +(p1 / p2 / p3) + plot_layout(guides = "collect") +``` + +The same trajectories seen in the plane the allometry lives in. The fixed plant is +confined to the curve; the flexible one leaves it and comes back. + +```{r allometry-plane, fig.height=4.5, fig.cap="Leaf and sapwood area against height. Dashed lines are the fixed allometry. Note the two y-axes differ by four orders of magnitude."} +s_demo <- TF24_Strategy() +ref <- allometry_reference_curve( + s_demo, seq(min(traj$height) * 0.95, max(traj$height) * 1.05, + length.out = 200)) + +p_leaf <- ggplot(traj, aes(height, area_leaf, colour = allometry)) + + geom_line(data = ref, aes(height, area_leaf), inherit.aes = FALSE, + linetype = "dashed", colour = "grey40") + + geom_path(linewidth = 0.9) + + labs(x = "height (m)", y = "leaf area (m²)", colour = NULL, + title = "Leaf area vs height", + subtitle = "Dashed: the fixed allometry") + +p_sap <- ggplot(traj, aes(height, area_sapwood, colour = allometry)) + + geom_line(data = ref, aes(height, area_sapwood), inherit.aes = FALSE, + linetype = "dashed", colour = "grey40") + + geom_path(linewidth = 0.9) + + labs(x = "height (m)", y = "sapwood area (m²)", colour = NULL, + title = "Sapwood area vs height", + subtitle = "Dashed: the pipe model, theta * A*(h)") + +(p_leaf + p_sap) + plot_layout(guides = "collect") +``` + +These two panels are the clearest statement of what the change does. The fixed +plant cannot leave the dashed curve — that was the whole constraint. The flexible +one tracks it while conditions are good, drops **below** it during the drought as +the canopy thins at constant height — a vertical fall, since height is frozen — +and then climbs back onto it as the canopy rebuilds. + +The sapwood panel shows the asymmetry — but compare the two *relative* to their +own curves rather than by eye, since the y-axes differ by four orders of magnitude. +At the worst of the drought, leaf area falls to **19 per cent** of what its height +implies while sapwood area falls only to **46 per cent**, because sapwood is lost +at `k_s` and leaf area at the faster `k_l`. That gap between the two is exactly the +rise in conducting area per unit leaf area. + +```{r trajectory-table} +traj |> + filter(allometry == "flexible", time %in% c(2, 3, 4, 5, 6, 6.5, 7.5, 8)) |> + transmute(time, soil = theta_soil, + `canopy fullness` = round(canopy_fraction, 3), + `stem per leaf` = round(huber_ratio, 3), + height = round(height, 2)) |> + knitr::kable() +``` + +All of this emerges from the two rate constants and the reserve gate. None of it is +imposed: + +- the canopy thins to about **19 per cent** of what its height implies, and can + thin no faster than `k_l`, because the mechanism is *declining to replace* rather + than actively shedding; +- conducting area per unit leaf area rises to about **2.4 times** its preferred + value, purely because `k_l > k_s`; +- **height never falls** — it stops, and resumes when the drought breaks; +- on recovery the canopy rebuilds to about **98 per cent**, smoothly, with no jump + as the gap closes. + +So the mechanism does what it was designed to do. + +### In the shade: self-thinning in a wet stand + +Shade is as much the point as drought. A plant losing the light race has the same +problem as one losing water — its leaves stop paying for themselves — and the same +lever. Here a wet stand (rainfall 1.5 m/yr) is left to self-thin for 25 years. + +```{r selfthin, message=FALSE, warning=FALSE} +thin_flex <- allometry_self_thinning(a_pl0 = 1.0) +thin_fix <- allometry_self_thinning(a_pl0 = 0.0) +``` + +```{r selfthin-plot, fig.height=4.5, fig.cap="Every cohort alive at each census, against its height. Shading is a within-stand gradient, so the canopy response is a function of position in it."} +late <- thin_flex$cohorts |> + filter(time %in% unique(time)[round(seq(0.3, 1, length.out = 4) * + length(unique(time)))]) + +p_pos <- ggplot(late, aes(height, canopy_fraction, colour = factor(round(time)))) + + geom_hline(yintercept = 1, linewidth = 0.3, colour = "grey50") + + geom_point(size = 1.1) + + labs(x = "height (m)", y = "canopy fullness", colour = "patch age", + title = "Suppressed plants thin; dominants do not") + +p_surv <- ggplot(late, aes(canopy_fraction, survivorship, + colour = factor(round(time)))) + + geom_point(size = 1.1) + scale_y_log10() + + labs(x = "canopy fullness", y = "survivorship", colour = "patch age", + title = "And a thinned canopy goes with a dying plant") + +(p_pos + p_surv) + plot_layout(guides = "collect") +``` + +```{r selfthin-table} +thin_flex$cohorts |> + filter(time == max(time)) |> + arrange(desc(height)) |> + slice(unique(round(seq(1, n(), length.out = 7)))) |> + transmute(height = round(height, 2), + `canopy fullness` = signif(canopy_fraction, 3), + `stem per leaf` = signif(huber_ratio, 3), + survivorship = signif(survivorship, 2)) |> + knitr::kable() +``` + +This is the behaviour asked for, and it emerges from competition alone: dominants +sit exactly on their allometry, suppressed plants thin progressively, and the +thinnest are the ones on their way out. Nothing in the model knows about canopy +position — the light gradient does all of it. + +```{r selfthin-r0} +data.frame(allometry = c("fixed", "flexible"), + R0 = c(thin_fix$R0, thin_flex$R0)) |> + knitr::kable() +``` + +Lifetime offspring production is essentially unchanged, because the cohorts that +thin are the ones already contributing nothing. + +## ⚠️ The problem: thinning does not buy survival + +It does not, however, do what it was *for*. The point was to stop a drop in +productivity turning straight into death. + +```{r survival, fig.height=4, fig.cap="Survivorship falls through nine orders of magnitude with or without the mechanism, and the ratio ends slightly below one."} +surv <- traj |> + select(time, theta_soil, allometry, survivorship) |> + pivot_wider(names_from = allometry, values_from = survivorship) |> + mutate(gain = flexible / fixed) + +p_s <- traj |> + ggplot(aes(time, survivorship, colour = allometry)) + + dry_band + geom_line(linewidth = 0.9) + scale_y_log10() + + labs(x = "time (yr)", y = "survivorship", colour = NULL, + title = "Survivorship is not improved") + +p_g <- ggplot(surv, aes(time, gain)) + + dry_band + geom_hline(yintercept = 1, linewidth = 0.3, colour = "grey50") + + geom_line(linewidth = 0.9) + + labs(x = "time (yr)", y = "flexible / fixed", + title = "What thinning buys") + +p_s + p_g +``` + +```{r survival-numbers} +surv |> + filter(time %in% c(2, 4, 6, 8)) |> + transmute(time, soil = theta_soil, + `survivorship, fixed` = signif(fixed, 3), + `survivorship, flexible` = signif(flexible, 3), + `ratio` = round(gain, 4)) |> + knitr::kable() +``` + +**There is no gain at all — the ratio ends slightly below one**, against a +survivorship that falls through nine orders of magnitude either way. And thinning +*costs* something real: the flexible plant finishes about **four metres shorter** +(9.5 m against 13.3 m), having spent its recovery carbon on canopy instead of +height. + +At the stand level that cost is now small, which is itself a change: lifetime +offspring production is essentially unaffected by switching the mechanism on. + +| stand | `a_pl0 = 0` | `a_pl0 = 1` | ratio | +|---|---|---|---| +| wet, rain 1.5 | 636.9 | 637.0 | 1.000 | +| seasonal, rain 0.4 | 11.16 | 11.13 | 0.997 | +| dry, rain 0.6 | 2.73e-5 | 2.52e-5 | 0.924 | + +::: {.callout-note} +## An earlier draft of this page was much harsher, and #617 is the reason +It reported that shedding *lowered* offspring production by factors of 0.55 to +0.64 on seasonal stands. Those numbers were taken before the stem path integral +landed, when resistance was linear in height and tall plants were penalised far +more heavily. The mechanism is now close to free at the stand level rather than +expensive — but it still does not buy survival, which is the claim this section +is about. +::: + +### Why — and it is not the trigger + +Three measurements rule out the obvious explanations, and a fourth rules out the +trigger itself. + +**It is not that the sheddable costs are too small.** Most of a plant's +maintenance *does* follow its canopy — leaf, fine root and bark all scale with +leaf area, and only sapwood is sticky: + +| height | leaf | bark | sapwood | root | reachable by thinning | +|---|---|---|---|---|---| +| 10 m | 49.6% | 5.4% | 23.5% | 21.5% | **76.5%** | +| 20 m | 38.5% | 8.4% | 36.4% | 16.7% | **63.6%** | + +(An earlier draft of this page claimed sapwood respiration dominated the drought +deficit. That was wrong, and this table is the retraction. Sapwood's share does +grow with height, which is why the tall row is worth showing, but even at 20 m +most of the bill still follows the canopy.) + +**It is that thinning cannot reach balance, even though it now helps.** This is +the argument that changed most with #617, and the earlier version of it was +wrong. Thinning *does* improve the per-leaf carbon balance — by 43% between a full +canopy and a tenth of one — because the remaining leaves inherit the whole stem's +hydraulic supply. But the improvement saturates, reverses, and never reaches zero: + +| canopy fullness | 1.00 | 0.50 | 0.20 | 0.10 | 0.05 | 0.018 | +|---|---|---|---|---|---|---| +| net production per m² leaf | −1.47 | −1.17 | −0.94 | **−0.84** | −0.86 | −0.99 | +| stem per leaf, relative | 1.0 | 1.3 | 1.8 | 2.2 | 2.9 | 4.1 | + +::: {.callout-warning} +## Retraction +Before #617 this table read −3.81 at a full canopy and *worsened* monotonically to +−4.68, and the argument was that "thinning cuts income just as fast" — that +shrinking the canopy shrinks both sides of the budget together. **That is no +longer true.** With resistance derived from stem anatomy the hydraulic benefit of +carrying a whole stem over fewer leaves is real and substantial, and there is an +interior optimum near a tenth of full canopy. + +The conclusion survives the argument being replaced: a plant whose leaves cost +more than they earn can now *narrow* the gap by having fewer leaves, but it still +cannot close it. Thinning slows the burn; it never reaches balance. +::: + +**The transition from fine to dead is a cliff**, and it is narrow in soil water +whatever the plant's size: + +| soil water, 4-yr drought | 0.20 | 0.17 | 0.15 | 0.14 | 0.13 | 0.11 | +|---|---|---|---|---|---|---| +| survivorship, 10 m | 0.96 | 0.96 | 0.95 | 1.0e-06 | 9.9e-10 | 4.9e-10 | +| survivorship, 20 m | 0.96 | 0.96 | 0.85 | 6.0e-08 | 1.7e-09 | 7.3e-10 | + +Everything happens between 0.15 and 0.14. Nine orders of magnitude of survivorship +are crossed in one hundredth of volumetric soil water. + +**And the two thresholds are in the wrong order in stress space.** This is the +decisive measurement. Sweeping intensity at three sizes, and reading the minimum +canopy the shedding plant reaches beside the survivorship the fixed plant gets: + +| height | soil | survivorship, fixed | survivorship, shedding | min canopy | gain | +|---|---|---|---|---|---| +| 10 m | 0.145 | 0.953 | 0.953 | **1.000** — never thins | 1.00 | +| 10 m | 0.140 | 1.0e-06 | 1.0e-06 | **1.000** — still never thins | 1.00 | +| 10 m | 0.135 | 3.8e-09 | 7.4e-09 | 0.357 | 1.95 | +| 20 m | 0.145 | 2.4e-05 | 2.4e-05 | **1.000** | 1.00 | +| 20 m | 0.140 | 6.0e-08 | 1.4e-07 | 0.674 | 2.36 | +| 20 m | 0.135 | 5.6e-09 | 1.9e-08 | 0.260 | 3.32 | +| 24 m | 0.145 | 5.0e-07 | 5.0e-07 | 0.999 | 1.00 | +| 24 m | 0.140 | 2.8e-08 | 5.6e-07 | 0.467 | **20.1** | +| 24 m | 0.135 | 5.4e-09 | 2.0e-08 | 0.212 | 3.70 | + +Read the rows where the canopy is still **1.000**. At soil 0.145 the plant is +healthy and its leaves are still profitable, so it has no reason to shed — quite +right. At 0.140 a 10 m plant is already at a survivorship of one in a million, and +its canopy *still has not moved*. **Mortality saturates at a milder drought than +shedding begins at**, so there is no intensity at which a plant is both stressed +enough to thin and alive enough to profit from it. + +The largest gain in the grid is 20-fold, and it takes survivorship from 2.8e-08 to +5.6e-07. Both of those are dead. Across a 90-cell sweep of size, intensity and +duration there is **no cell** where the fixed plant dies and the shedding plant +lives. + +No gate can fix this, because the ordering is not the gate's doing: mortality +collapses as soon as net production turns slightly negative, since the pool has no +resting point and drains completely. + +::: {.callout-note} +## The gate itself was tested, and is not the problem +Three gates have been run through the same drought. These were measured *before* +#617 and have not been re-taken, so read the levels as historical — but the +comparison between them is what matters, and the ordering above is unchanged: + +| gate | fires when | survival gain | +|---|---|---| +| reserve fraction, centred at 0.05 | reserves nearly gone | 1.010 | +| reserve fraction, moved as early as it goes | reserves at 30% | 1.0–1.13 | +| **marginal leaf balance** (current) | **leaf stops paying, reserves still full** | **1.001** | + +Firing *earlier*, on a *better-supported* signal, bought nothing. The +carbon-balance gate is still the right model — the evidence for it is independent +of survival — but survival is downstream of something else. +::: + +### The real cause is the reserve pool, and what mortality reads + +The storage pool has **no resting point**. Its rate is +$\dot S = \text{charge}\,(1-r) - \text{drain}\,r$, so positive production fills it +to capacity and negative empties it, with nothing in between. The reserve fraction +is therefore close to a binary readout of the *sign* of net production. Mortality +then reads it through $a_{dG1}e^{-a_{dG2} r}$ with $a_{dG2}=20$, sharp enough to +turn a near-binary input into a near-binary output spanning eight orders. + +So a mechanism that makes a plant modestly cheaper to run has nothing to act on, +whatever triggers it. The buffer does not buffer. + +The literature says both halves of this are wrong (see the [NSC +appendix](#appendix-what-the-nsc-literature-says)): plants hold a **minimum NSC of +about 46 per cent** of their seasonal maximum and are found empty only when dead, +and they **sacrifice growth to defend storage** — the reverse of TF24, which gates +growth and leaves storage as the residual. + +### Where the fix has to go + +1. **Give the pool a resting point.** If the part of a deficit the pool cannot + meet were paid by consuming tissue — which is what canopy thinning *is* — the + pool would stabilise instead of emptying, and the reserve fraction would sit + somewhere informative. NEWS already records that this unmet deficit currently + leaves the budget, with "routing it into tissue loss" named as deferred work. +2. **Defend storage ahead of growth.** Beech under three years of drought + *increased* NSC for two years before starch fell, and the authors conclude that + maintaining storage at the expense of growth was key to survival. TF24 does the + opposite. +3. **Change what mortality reads.** A reserve *fraction* cannot see a plant that + has made itself cheaper to run — which is exactly what thinning does. Time to + depletion at the current burn rate can, and predicted mortality better than any + instantaneous level across 12 species. + +## Also unresolved: nothing bounds the departures in permanent deficit + +If reserves never recover, withheld leaf turnover (0.42/yr) outruns withheld +sapwood turnover (0.2/yr) whatever the plant does, so both departures grow without +limit — the canopy toward nothing, the stem-per-leaf ratio toward infinity. + +This is arithmetic rather than a defect. A plant thinning at 46 per cent a year +while losing stem at 20 per cent really does have an ever-rising ratio. But what +removes such a plant is mortality, not the allometry, and a cohort model keeps +carrying it meanwhile. + +Related, and worth watching: the rebuild rate grows as the canopy empties, which is +the same fast-boundary shape that #609 identified for the storage pool. It has not +caused a failure in any run so far. + +## What is settled + +```{r settled} +data.frame( + claim = c("Switched off, the old model is recovered", + "Carbon and tissue balance when replacement is withheld", + "Stem per leaf never falls below its preferred value", + "Height never decreases", + "The canopy rebuilds after a drought"), + basis = c("bit-identical, over 288 quantities and a full SCM run", + "an exact identity: turnover not charged is mass lost", + "follows from the form, given that k_l > k_s", + "follows from the form: a product of non-negative factors", + "measured: to ~98 per cent of preferred, smoothly")) |> + knitr::kable() +``` + +The open questions are the two sections above: thinning does not yet buy survival, +and nothing bounds the departures for a plant that never recovers. + +## Future refinements + +Deliberately out of scope here, recorded so they are not rediscovered. + +**A discrete re-flush drawing on stores.** Leaf construction *is* fully paid for +in the rebuild term — leaf, fine root, sapwood and bark at the preferred ratio — +so nothing is missing from the budget. What is missing is the *shape*: rebuilding +is continuous, financed out of current flux, whereas a real plant flushes a canopy +in a burst financed from reserves. Manzoni prices such a flush at 12–16 per cent of +a season's gain, and whether one happens changes his result qualitatively at long +drought duration. This is also the natural place for a reserve term to re-enter: +modulating the *cost of recovering*, not the *onset of shedding*. + +**Acclimation of photosynthetic capacity.** `Amax` is fixed here, but it is +observed to scale back under sustained stress (Joshi et al. 2022). That is a +cheaper adjustment than shedding and a faster one, so it should sit between +stomatal closure and leaf loss in the ladder — and its absence may be part of why +the marginal balance crosses zero as abruptly as it does. + +**Leaf turnover under an optimality argument.** `k_l` is currently a trait fixed by +the LMA trade-off. Leaf lifespan is itself an optimisation — hold a leaf while its +marginal return exceeds the cost of replacing it — so `k_l` could be derived rather +than imposed, in the same currency as the shedding gate. Attractive because it +would make shedding and leaf lifespan one mechanism instead of two. + +**Optimality-derived allometric targets.** The preferred sapwood-to-leaf ratio, and +ultimately the preferred leaf area itself, could come from stationarity of the +plant's own growth rate rather than from fixed coefficients. Its own epic; the +sapwood target is written as a replaceable function so this can drop in. + +**Drought-deciduous habit.** Setting the canopy floor near zero already permits +shedding to nothing and re-flushing, and that is supported behaviour for some +species. It is not the habit this model is aimed at, and the departure coordinate +degrades as the floor approaches zero, so it stays possible rather than +prioritised. + +# Appendix: the mathematics {#appendix-the-mathematics} + +::: {.callout-tip} +## These equations are checked, not just written down +`tests/testthat/test-allometry-demo.R` reimplements this appendix in R — working +from the prose rather than from the source — and compares it against what the C++ +computes, across 81 combinations of height, both departures and reserve level. +They agree to 1e-10. So a divergence between this description and the model fails +a test, rather than quietly misleading a reader. +::: + +### Symbols + +| symbol | in the code | meaning | +|---|---|---| +| $h$ | `height` | height, a state (m) | +| $\phi$ | `log_area_leaf_departure` | leaf-area departure, a state | +| $\psi$ | `log_area_sapwood_departure` | sapwood departure, a state | +| $S$ | `storage` | NSC pool, a state (kg) | +| $A_\star(h)$ | `area_leaf(height)` | preferred leaf area (m²) | +| $A$, $A_s$, $A_b$ | — | actual leaf, sapwood, bark area (m²) | +| $\rho_\ell,\ \rho_s$ | `replacement`, `replacement_sapwood` | replaced share of leaf / sapwood turnover | +| $u_\ell,\ u_s$ | `withheld`, `withheld_sapwood` | withheld share, $1-\rho$ | +| $\sigma$ | `rebuild_share` | share of growth redirected to rebuilding | +| $b$ | `rebuild_rel` | relative rebuild rate (yr⁻¹) | +| $F$ | `growth_flux` | carbon for growth and reproduction (kg yr⁻¹) | + +### Sizes + +The allometry itself is unchanged, $A_\star(h) = (h/a_{l1})^{1/a_{l2}}$. What +changes is that a plant need not sit on it: + +$$A = A_\star(h)\,e^{\phi}, \qquad A_s = \theta A\,e^{\psi} = \theta A_\star(h)\,e^{\phi+\psi}.$$ + +So $\phi$ is log canopy fullness, and $\psi$ is the log of the Huber value relative +to its preferred value $\theta$. Masses follow as before: $m_\ell = \lambda A$ (with +$\lambda$ the leaf mass per area), $m_r = a_{r1} A$, $m_s = A_s h \eta_c \rho$ and +$m_b = A_b h \eta_c \rho$. + +::: {.callout-note} +Bark area is still pinned to *leaf* area, $A_b = a_{b1}\theta A$, rather than to +sapwood. Repinning it to sapwood is arguably more physical — bark sheathes the stem +— but it was left alone to keep this change bit-identical at rest. +::: + +Hydraulic supply per unit leaf area reads the Huber value the plant actually has, + +$$k_{\max,\text{leaf}} = \frac{K_s\,\theta e^{\psi}}{h\,\eta_c},$$ + +which is the channel through which thinning improves supply to the leaves that +remain. + +### The replacement gate + +With $r = S/S_{\max}$ and $S_{\max} = a_{st1} m_s$, the replaced share of leaf +turnover is a logistic on reserves. The sapwood share is that same quantity, scaled +down by how over-built the stem already is: + +$$\rho_\ell = 1 - \frac{a_{pl0}}{1 + \exp\!\big((r - a_{pl1})/w_{pl}\big)}, +\qquad +\rho_s = \rho_\ell\, e^{-\psi/a_{pl2}}.$$ + +$a_{pl0}$ caps how much may be withheld, so $a_{pl0}=0$ gives $\rho_\ell \equiv 1$. +Only the two pools that have states are gated; the turnover actually charged is + +$$T = \rho_\ell k_\ell m_\ell + k_b m_b + \rho_s k_s m_s + k_r m_r.$$ + +Bark and root stay fully charged because neither has a state to lose. Withholding +their cost would save carbon that no tissue ever paid for. + +### Growth, and where it goes + +Net production and the existing NSC gate are untouched: + +$$P = a_{bio}a_y(\tilde A - R) - T,\qquad +P_+ = \tfrac12\Big(P + \sqrt{P^2+\varepsilon^2}\Big),\qquad +F = P_+\,G(r).$$ + +$F$ then splits between **extension** along the allometry and **rebuilding** the +canopy, with the rebuild share gated on the same reserves as replacement: + +$$\sigma = \rho_\ell\left(1 - e^{\phi/a_{pl2}}\right).$$ + +Extension moves the plant along the curve. Its marginal costs are evaluated at +$A_\star$ — the leaf area the plant's *height* implies — because they are properties +of the curve, and a plant's place on the curve is given by its height: + +$$\dot A_\star = (1-\sigma)\,F f_g \left.\frac{\partial A}{\partial m_{\text{live}}}\right|_{A_\star}, +\qquad +\frac{dh}{dt} = \left.\frac{\partial h}{\partial A}\right|_{A_\star}\dot A_\star += a_{l1}a_{l2}A_\star^{\,a_{l2}-1}\,\dot A_\star .$$ + +Rebuilding buys leaf area at **unchanged height**, and buys the whole package — +leaf, fine root, and the sapwood and bark that supply it — at the ratio the plant +prefers rather than the one it currently has: + +$$c_{\text{reb}}(h) = \lambda + a_{r1} + \theta h \eta_c \rho\,(1+a_{b1}), +\qquad +b = \frac{\sigma F f_g}{c_{\text{reb}}(h)\,A}.$$ + +### The two departure equations + +$$\boxed{\;\frac{d\phi}{dt} = b - u_\ell k_\ell\;} +\qquad +\boxed{\;\frac{d\psi}{dt} = u_\ell k_\ell - u_s k_s + b\left(e^{-\psi}-1\right)\;}$$ + +In words: the canopy loses the turnover it declined to replace, and regains what +rebuilding buys. The Huber value moves on the **difference** between the two +losses. The final term is exact geometry rather than a parameter — rebuilding adds +leaf and sapwood in the ratio $\theta$, so it moves the two logs by $b/A$ and +$\theta b/A_s$, and their difference is $(b/A)(e^{-\psi}-1)$. + +### Properties that follow from the form + +**Thinning conserves carbon exactly.** Carbon not charged is +$u_\ell k_\ell m_\ell + u_s k_s m_s$. The withholding terms move the states by +$d(\ln A)/dt = -u_\ell k_\ell$ and, since +$d(\ln A_s)/dt = d(\ln A)/dt + d\psi/dt$, by $d(\ln A_s)/dt = -u_s k_s$. The mass +lost is therefore $\lambda u_\ell k_\ell A + h\eta_c\rho\,u_s k_s A_s$ — the same +two terms. An identity, not a tolerance. + +**$\phi \le 0$ is invariant.** At $\phi=0$, $\sigma=0$ so $b=0$, leaving +$d\phi/dt = -u_\ell k_\ell \le 0$: the flow points inward. A plant never carries +*more* leaf than its height implies. + +**$\psi \ge 0$ is invariant.** At $\psi=0$, $\rho_s = \rho_\ell$ so $u_s=u_\ell$, +and $e^{-\psi}-1 = 0$, leaving + +$$\left.\frac{d\psi}{dt}\right|_{\psi=0} = u_\ell\,(k_\ell - k_s) \;\ge\; 0 +\qquad\text{because } k_\ell > k_s .$$ + +So a stem never ends up with less conducting area than its canopy needs, the +scaling factor $e^{-\psi/a_{pl2}}$ stays within $(0,1]$, and no over-replacement +can arise to cost unbounded carbon. **⚠️ If $k_s$ were ever raised above $k_\ell$, +this argument reverses.** + +**Height never falls.** $dh/dt$ is a product of $(1-\sigma) \in (0,1]$, $F \ge 0$, +$f_g \ge 0$, and two positive derivatives. + +**$a_{pl0}=0$ is the old model exactly.** $\rho_\ell = 1$ gives $u_\ell = 0$; +$\phi=0$ gives $\sigma = 0$ and hence $b=0$; $\psi=0$ gives $\rho_s = 1$ and hence +$u_s = 0$. Both departure rates are exactly zero, $e^0 = 1$ leaves the sizes +bitwise unchanged, and odelia's **max**-norm error control ignores a zero-error +state, so the solver's step sizes are untouched as well. + +### One approximation, stated + +Extension is charged at $\partial m_{\text{live}}/\partial A$ evaluated at +$A_\star$, but a thinned plant adds only $e^{\phi}\,\dot A_\star$ of actual leaf +area for that money. A plant off its trajectory is therefore **over-charged** for +extension, by a factor $e^{-\phi}$. + +The direction is conservative — a thinned plant grows more slowly than a strict +budget would allow, never faster — and the error vanishes as the canopy recovers. +It is the price of keeping extension exactly departure-preserving, which is what +makes the resting model exact and confines all of the departure's motion to +plasticity. + +# Appendix: what the NSC literature says {#appendix-what-the-nsc-literature-says} + +Gathered because the reserve pool turned out to be the binding constraint, not the +allometry. Every point here bears on a design decision above. + +**Plants defend the pool rather than draining it.** A global synthesis of 121 +studies and 177 species found **minimum NSC around 46 per cent of the seasonal +maximum**, with depletion of total NSC "rare"; the authors propose a dual function +in which starch is the reservoir while soluble sugars "are kept above some critical +threshold" (Martínez-Vilalta et al. 2016, *Ecol. Monogr.*, +[doi:10.1002/ecm.1231](https://doi.org/10.1002/ecm.1231)). TF24 lets the reserve +fraction run to ~1e-10. + +**Storage outranks growth — the reverse of what we do.** Beech under three years of +drought *increased* NSC through years 1–2; starch fell only in year 3, and it was +the **dead** trees that were "virtually empty", with 87 per cent surviving. The +conclusion is explicit: *"maintaining an active C storage function at the expense +of growth was certainly key to survival"* (Chuste et al. 2019, *Trees*, +[doi:10.1007/s00468-019-01923-5](https://doi.org/10.1007/s00468-019-01923-5)). +After release from darkness, "NSC reformation occurs preferentially over growth" +(Weber et al. 2018, *New Phytol.*, +[doi:10.1111/nph.14987](https://doi.org/10.1111/nph.14987)). + +**Under moderate stress the pool is actively regulated back up.** Across 47 studies +and 52 species, prolonged slight-to-moderate drought brought NSC back *toward* +control values — *"trees activated physiological regulation processes to increase +carbon storage and reduce the risks of carbon starvation"* — with net loss only +under long, severe drought (He et al. 2020, *Glob. Change Biol.*, +[doi:10.1111/gcb.15078](https://doi.org/10.1111/gcb.15078)). + +**Depletion at death is partial.** Foliar NSC in *Pinus edulis* fell 30 per cent +through mortality, but "carbohydrates were not completely exhausted at mortality" +(Adams et al. 2013, *New Phytol.*, +[doi:10.1111/nph.12102](https://doi.org/10.1111/nph.12102)). Seedlings survive +weeks at starch of 0.4–0.8 per cent dry matter (Weber et al. 2018). + +**What predicts death is a rate, not a level.** Across 12 species, total NSC and +soluble sugars did not decline at all; starch did, and *"the time leading to starch +depletion emerged as a strong mortality predictor"* (Trueba et al. 2024, *Ann. For. +Sci.*, [doi:10.1186/s13595-024-01246-7](https://doi.org/10.1186/s13595-024-01246-7)). +This is the direct argument for changing what mortality reads: a time-to-depletion +responds to a plant that has made itself cheaper to run, and an instantaneous +fraction cannot. + +**Shade depletes reserves as drought does**, so the self-thinning case above is a +carbon problem and not only a light one (Maguire & Kobe 2015, *Ecol. Evol.*, +[doi:10.1002/ece3.1819](https://doi.org/10.1002/ece3.1819)); shade-induced depletion +also raises embolism vulnerability and blocks hydraulic recovery (Tomasella et al. +2021, *New Phytol.*, [doi:10.1111/nph.17384](https://doi.org/10.1111/nph.17384)). + +**Life stage matters**, which our single size-scaled pool does not capture: mature +trees stayed homeostatic under throughfall exclusion while understorey seedlings +lost about 15 per cent of total NSC (Zhang et al. 2020, *For. Ecol. Manage.*, +[doi:10.1016/j.foreco.2020.118159](https://doi.org/10.1016/j.foreco.2020.118159)). + +## And on leaf shedding itself + +**The optimal trigger is a flux, and it fires early.** Manzoni et al. (2015, +*Adv. Water Resour.* 84:37–51) maximise a season's carbon gain over leaf area and +derive `dG/dL = 0` — shed when a leaf stops covering its upkeep — at about +−2 MPa soil water potential, *"a later and more drastic measure of water loss +regulation than stomatal closure"*. Gradual and instantaneous shedding give +*identical* carbon gain, so gradual is free in the optimality currency and is what +the field data show. + +**Shedding is what healthy plants do.** In Robinson's mulga (573 trees, 49 sites, +2017–2024), 85 per cent shed, including the healthiest; the died and survived +canopy-density distributions are indistinguishable in the first year and only +separate later. Decline took 2–3 years; recovery took one season. Larger trees shed +*less* and survived better (canopy area the strongest mortality predictor), which +that work attributes to deep-water access rather than to carbon stores. + +⚠️ **One correction to an earlier reading.** Severe de-leafing in that dataset went +with death: the trajectory groups that fell to near-zero canopy density all died. +Complete de-greening followed by re-leafing is documented for mulga but is rare, +and whether a plant can do it depends on its strategy. So a canopy floor is not +merely a numerical convenience for an evergreen — it is the observed behaviour. diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-917079515d91bccb85b543faf8aa8bb6.min.css b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-917079515d91bccb85b543faf8aa8bb6.min.css new file mode 100644 index 000000000..cba42bf6c --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-917079515d91bccb85b543faf8aa8bb6.min.css @@ -0,0 +1,12 @@ +/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root,[data-bs-theme=light]{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-black: #000;--bs-white: #ffffff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #343a40;--bs-gray-900: #212529;--bs-default: #dee2e6;--bs-primary: #0d6efd;--bs-secondary: #6c757d;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #f8f9fa;--bs-dark: #212529;--bs-default-rgb: 222, 226, 230;--bs-primary-rgb: 13, 110, 253;--bs-secondary-rgb: 108, 117, 125;--bs-success-rgb: 25, 135, 84;--bs-info-rgb: 13, 202, 240;--bs-warning-rgb: 255, 193, 7;--bs-danger-rgb: 220, 53, 69;--bs-light-rgb: 248, 249, 250;--bs-dark-rgb: 33, 37, 41;--bs-primary-text-emphasis: rgb(5.2, 44, 101.2);--bs-secondary-text-emphasis: rgb(43.2, 46.8, 50);--bs-success-text-emphasis: rgb(10, 54, 33.6);--bs-info-text-emphasis: rgb(5.2, 80.8, 96);--bs-warning-text-emphasis: rgb(102, 77.2, 2.8);--bs-danger-text-emphasis: rgb(88, 21.2, 27.6);--bs-light-text-emphasis: #495057;--bs-dark-text-emphasis: #495057;--bs-primary-bg-subtle: rgb(206.6, 226, 254.6);--bs-secondary-bg-subtle: rgb(225.6, 227.4, 229);--bs-success-bg-subtle: rgb(209, 231, 220.8);--bs-info-bg-subtle: rgb(206.6, 244.4, 252);--bs-warning-bg-subtle: rgb(255, 242.6, 205.4);--bs-danger-bg-subtle: rgb(248, 214.6, 217.8);--bs-light-bg-subtle: rgb(251.5, 252, 252.5);--bs-dark-bg-subtle: #ced4da;--bs-primary-border-subtle: rgb(158.2, 197, 254.2);--bs-secondary-border-subtle: rgb(196.2, 199.8, 203);--bs-success-border-subtle: rgb(163, 207, 186.6);--bs-info-border-subtle: rgb(158.2, 233.8, 249);--bs-warning-border-subtle: rgb(255, 230.2, 155.8);--bs-danger-border-subtle: rgb(241, 174.2, 180.6);--bs-light-border-subtle: #e9ecef;--bs-dark-border-subtle: #adb5bd;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-root-font-size: 17px;--bs-body-font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-body-font-size:1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #212529;--bs-body-color-rgb: 33, 37, 41;--bs-body-bg: #ffffff;--bs-body-bg-rgb: 255, 255, 255;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0, 0, 0;--bs-secondary-color: rgba(33, 37, 41, 0.75);--bs-secondary-color-rgb: 33, 37, 41;--bs-secondary-bg: #e9ecef;--bs-secondary-bg-rgb: 233, 236, 239;--bs-tertiary-color: rgba(33, 37, 41, 0.5);--bs-tertiary-color-rgb: 33, 37, 41;--bs-tertiary-bg: #f8f9fa;--bs-tertiary-bg-rgb: 248, 249, 250;--bs-heading-color: inherit;--bs-link-color: #0d6efd;--bs-link-color-rgb: 13, 110, 253;--bs-link-decoration: underline;--bs-link-hover-color: rgb(10.4, 88, 202.4);--bs-link-hover-color-rgb: 10, 88, 202;--bs-code-color: #7d12ba;--bs-highlight-bg: rgb(255, 242.6, 205.4);--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: rgb(221.7, 222.3, 222.9);--bs-border-color-translucent: rgba(0, 0, 0, 0.175);--bs-border-radius: 0.375rem;--bs-border-radius-sm: 0.25rem;--bs-border-radius-lg: 0.5rem;--bs-border-radius-xl: 1rem;--bs-border-radius-xxl: 2rem;--bs-border-radius-2xl: var(--bs-border-radius-xxl);--bs-border-radius-pill: 50rem;--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width: 0.25rem;--bs-focus-ring-opacity: 0.25;--bs-focus-ring-color: rgba(13, 110, 253, 0.25);--bs-form-valid-color: #198754;--bs-form-valid-border-color: #198754;--bs-form-invalid-color: #dc3545;--bs-form-invalid-border-color: #dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222, 226, 230;--bs-body-bg: #212529;--bs-body-bg-rgb: 33, 37, 41;--bs-emphasis-color: #ffffff;--bs-emphasis-color-rgb: 255, 255, 255;--bs-secondary-color: rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb: 222, 226, 230;--bs-secondary-bg: #343a40;--bs-secondary-bg-rgb: 52, 58, 64;--bs-tertiary-color: rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb: 222, 226, 230;--bs-tertiary-bg: rgb(42.5, 47.5, 52.5);--bs-tertiary-bg-rgb: 43, 48, 53;--bs-primary-text-emphasis: rgb(109.8, 168, 253.8);--bs-secondary-text-emphasis: rgb(166.8, 172.2, 177);--bs-success-text-emphasis: rgb(117, 183, 152.4);--bs-info-text-emphasis: rgb(109.8, 223.2, 246);--bs-warning-text-emphasis: rgb(255, 217.8, 106.2);--bs-danger-text-emphasis: rgb(234, 133.8, 143.4);--bs-light-text-emphasis: #f8f9fa;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: rgb(2.6, 22, 50.6);--bs-secondary-bg-subtle: rgb(21.6, 23.4, 25);--bs-success-bg-subtle: rgb(5, 27, 16.8);--bs-info-bg-subtle: rgb(2.6, 40.4, 48);--bs-warning-bg-subtle: rgb(51, 38.6, 1.4);--bs-danger-bg-subtle: rgb(44, 10.6, 13.8);--bs-light-bg-subtle: #343a40;--bs-dark-bg-subtle: #1a1d20;--bs-primary-border-subtle: rgb(7.8, 66, 151.8);--bs-secondary-border-subtle: rgb(64.8, 70.2, 75);--bs-success-border-subtle: rgb(15, 81, 50.4);--bs-info-border-subtle: rgb(7.8, 121.2, 144);--bs-warning-border-subtle: rgb(153, 115.8, 4.2);--bs-danger-border-subtle: rgb(132, 31.8, 41.4);--bs-light-border-subtle: #495057;--bs-dark-border-subtle: #343a40;--bs-heading-color: inherit;--bs-link-color: rgb(109.8, 168, 253.8);--bs-link-hover-color: rgb(138.84, 185.4, 254.04);--bs-link-color-rgb: 110, 168, 254;--bs-link-hover-color-rgb: 139, 185, 254;--bs-code-color: white;--bs-border-color: #495057;--bs-border-color-translucent: rgba(255, 255, 255, 0.15);--bs-form-valid-color: rgb(117, 183, 152.4);--bs-form-valid-border-color: rgb(117, 183, 152.4);--bs-form-invalid-color: rgb(234, 133.8, 143.4);--bs-form-invalid-border-color: rgb(234, 133.8, 143.4)}*,*::before,*::after{box-sizing:border-box}:root{font-size:var(--bs-root-font-size)}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;border:0;border-top:1px solid;opacity:.25}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}h1,.h1{font-size:calc(1.325rem + 0.9vw)}@media(min-width: 1200px){h1,.h1{font-size:2rem}}h2,.h2{font-size:calc(1.29rem + 0.48vw)}@media(min-width: 1200px){h2,.h2{font-size:1.65rem}}h3,.h3{font-size:calc(1.27rem + 0.24vw)}@media(min-width: 1200px){h3,.h3{font-size:1.45rem}}h4,.h4{font-size:1.25rem}h5,.h5{font-size:1.1rem}h6,.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{text-decoration:underline dotted;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;-ms-text-decoration:underline dotted;-o-text-decoration:underline dotted;cursor:help;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem;padding:.625rem 1.25rem;border-left:.25rem solid #e9ecef}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}b,strong{font-weight:bolder}small,.small{font-size:0.875em}mark,.mark{padding:.1875em;background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:0.75em;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}a{color:rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}a:hover{--bs-link-color-rgb: var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:0.875em;color:#000;background-color:#f8f9fa;line-height:1.5;padding:.5rem;border:1px solid var(--bs-border-color, rgb(221.7, 222.3, 222.9));border-radius:.375rem}pre code{background-color:rgba(0,0,0,0);font-size:inherit;color:inherit;word-break:normal}code{font-size:0.875em;color:var(--bs-code-color);background-color:#f8f9fa;border-radius:.375rem;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.4rem .4rem;font-size:0.875em;color:#fff;background-color:#212529;border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:rgba(33,37,41,.75);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}thead,tbody,tfoot,tr,td,th{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none !important}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + 0.3vw)}@media(min-width: 1200px){legend{font-size:1.5rem}}legend{line-height:inherit}legend+*{clear:left}::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-text,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none !important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:calc(1.625rem + 4.5vw)}@media(min-width: 1200px){.display-1{font-size:5rem}}.display-1{font-weight:300;line-height:1.2}.display-2{font-size:calc(1.575rem + 3.9vw)}@media(min-width: 1200px){.display-2{font-size:4.5rem}}.display-2{font-weight:300;line-height:1.2}.display-3{font-size:calc(1.525rem + 3.3vw)}@media(min-width: 1200px){.display-3{font-size:4rem}}.display-3{font-weight:300;line-height:1.2}.display-4{font-size:calc(1.475rem + 2.7vw)}@media(min-width: 1200px){.display-4{font-size:3.5rem}}.display-4{font-weight:300;line-height:1.2}.display-5{font-size:calc(1.425rem + 2.1vw)}@media(min-width: 1200px){.display-5{font-size:3rem}}.display-5{font-weight:300;line-height:1.2}.display-6{font-size:calc(1.375rem + 1.5vw)}@media(min-width: 1200px){.display-6{font-size:2.5rem}}.display-6{font-weight:300;line-height:1.2}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:0.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:0.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid rgb(221.7,222.3,222.9);border-radius:.375rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:0.875em;color:rgba(33,37,41,.75)}.container,.container-fluid,.container-xxl,.container-xl,.container-lg,.container-md,.container-sm{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;width:100%;padding-right:calc(var(--bs-gutter-x)*.5);padding-left:calc(var(--bs-gutter-x)*.5);margin-right:auto;margin-left:auto}@media(min-width: 576px){.container-sm,.container{max-width:540px}}@media(min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media(min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media(min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}@media(min-width: 1400px){.container-xxl,.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1320px}}:root{--bs-breakpoint-xs: 0;--bs-breakpoint-sm: 576px;--bs-breakpoint-md: 768px;--bs-breakpoint-lg: 992px;--bs-breakpoint-xl: 1200px;--bs-breakpoint-xxl: 1400px}.grid{display:grid;grid-template-rows:repeat(var(--bs-rows, 1), 1fr);grid-template-columns:repeat(var(--bs-columns, 12), 1fr);gap:var(--bs-gap, 1.5rem)}.grid .g-col-1{grid-column:auto/span 1}.grid .g-col-2{grid-column:auto/span 2}.grid .g-col-3{grid-column:auto/span 3}.grid .g-col-4{grid-column:auto/span 4}.grid .g-col-5{grid-column:auto/span 5}.grid .g-col-6{grid-column:auto/span 6}.grid .g-col-7{grid-column:auto/span 7}.grid .g-col-8{grid-column:auto/span 8}.grid .g-col-9{grid-column:auto/span 9}.grid .g-col-10{grid-column:auto/span 10}.grid .g-col-11{grid-column:auto/span 11}.grid .g-col-12{grid-column:auto/span 12}.grid .g-start-1{grid-column-start:1}.grid .g-start-2{grid-column-start:2}.grid .g-start-3{grid-column-start:3}.grid .g-start-4{grid-column-start:4}.grid .g-start-5{grid-column-start:5}.grid .g-start-6{grid-column-start:6}.grid .g-start-7{grid-column-start:7}.grid .g-start-8{grid-column-start:8}.grid .g-start-9{grid-column-start:9}.grid .g-start-10{grid-column-start:10}.grid .g-start-11{grid-column-start:11}@media(min-width: 576px){.grid .g-col-sm-1{grid-column:auto/span 1}.grid .g-col-sm-2{grid-column:auto/span 2}.grid .g-col-sm-3{grid-column:auto/span 3}.grid .g-col-sm-4{grid-column:auto/span 4}.grid .g-col-sm-5{grid-column:auto/span 5}.grid .g-col-sm-6{grid-column:auto/span 6}.grid .g-col-sm-7{grid-column:auto/span 7}.grid .g-col-sm-8{grid-column:auto/span 8}.grid .g-col-sm-9{grid-column:auto/span 9}.grid .g-col-sm-10{grid-column:auto/span 10}.grid .g-col-sm-11{grid-column:auto/span 11}.grid .g-col-sm-12{grid-column:auto/span 12}.grid .g-start-sm-1{grid-column-start:1}.grid .g-start-sm-2{grid-column-start:2}.grid .g-start-sm-3{grid-column-start:3}.grid .g-start-sm-4{grid-column-start:4}.grid .g-start-sm-5{grid-column-start:5}.grid .g-start-sm-6{grid-column-start:6}.grid .g-start-sm-7{grid-column-start:7}.grid .g-start-sm-8{grid-column-start:8}.grid .g-start-sm-9{grid-column-start:9}.grid .g-start-sm-10{grid-column-start:10}.grid .g-start-sm-11{grid-column-start:11}}@media(min-width: 768px){.grid .g-col-md-1{grid-column:auto/span 1}.grid .g-col-md-2{grid-column:auto/span 2}.grid .g-col-md-3{grid-column:auto/span 3}.grid .g-col-md-4{grid-column:auto/span 4}.grid .g-col-md-5{grid-column:auto/span 5}.grid .g-col-md-6{grid-column:auto/span 6}.grid .g-col-md-7{grid-column:auto/span 7}.grid .g-col-md-8{grid-column:auto/span 8}.grid .g-col-md-9{grid-column:auto/span 9}.grid .g-col-md-10{grid-column:auto/span 10}.grid .g-col-md-11{grid-column:auto/span 11}.grid .g-col-md-12{grid-column:auto/span 12}.grid .g-start-md-1{grid-column-start:1}.grid .g-start-md-2{grid-column-start:2}.grid .g-start-md-3{grid-column-start:3}.grid .g-start-md-4{grid-column-start:4}.grid .g-start-md-5{grid-column-start:5}.grid .g-start-md-6{grid-column-start:6}.grid .g-start-md-7{grid-column-start:7}.grid .g-start-md-8{grid-column-start:8}.grid .g-start-md-9{grid-column-start:9}.grid .g-start-md-10{grid-column-start:10}.grid .g-start-md-11{grid-column-start:11}}@media(min-width: 992px){.grid .g-col-lg-1{grid-column:auto/span 1}.grid .g-col-lg-2{grid-column:auto/span 2}.grid .g-col-lg-3{grid-column:auto/span 3}.grid .g-col-lg-4{grid-column:auto/span 4}.grid .g-col-lg-5{grid-column:auto/span 5}.grid .g-col-lg-6{grid-column:auto/span 6}.grid .g-col-lg-7{grid-column:auto/span 7}.grid .g-col-lg-8{grid-column:auto/span 8}.grid .g-col-lg-9{grid-column:auto/span 9}.grid .g-col-lg-10{grid-column:auto/span 10}.grid .g-col-lg-11{grid-column:auto/span 11}.grid .g-col-lg-12{grid-column:auto/span 12}.grid .g-start-lg-1{grid-column-start:1}.grid .g-start-lg-2{grid-column-start:2}.grid .g-start-lg-3{grid-column-start:3}.grid .g-start-lg-4{grid-column-start:4}.grid .g-start-lg-5{grid-column-start:5}.grid .g-start-lg-6{grid-column-start:6}.grid .g-start-lg-7{grid-column-start:7}.grid .g-start-lg-8{grid-column-start:8}.grid .g-start-lg-9{grid-column-start:9}.grid .g-start-lg-10{grid-column-start:10}.grid .g-start-lg-11{grid-column-start:11}}@media(min-width: 1200px){.grid .g-col-xl-1{grid-column:auto/span 1}.grid .g-col-xl-2{grid-column:auto/span 2}.grid .g-col-xl-3{grid-column:auto/span 3}.grid .g-col-xl-4{grid-column:auto/span 4}.grid .g-col-xl-5{grid-column:auto/span 5}.grid .g-col-xl-6{grid-column:auto/span 6}.grid .g-col-xl-7{grid-column:auto/span 7}.grid .g-col-xl-8{grid-column:auto/span 8}.grid .g-col-xl-9{grid-column:auto/span 9}.grid .g-col-xl-10{grid-column:auto/span 10}.grid .g-col-xl-11{grid-column:auto/span 11}.grid .g-col-xl-12{grid-column:auto/span 12}.grid .g-start-xl-1{grid-column-start:1}.grid .g-start-xl-2{grid-column-start:2}.grid .g-start-xl-3{grid-column-start:3}.grid .g-start-xl-4{grid-column-start:4}.grid .g-start-xl-5{grid-column-start:5}.grid .g-start-xl-6{grid-column-start:6}.grid .g-start-xl-7{grid-column-start:7}.grid .g-start-xl-8{grid-column-start:8}.grid .g-start-xl-9{grid-column-start:9}.grid .g-start-xl-10{grid-column-start:10}.grid .g-start-xl-11{grid-column-start:11}}@media(min-width: 1400px){.grid .g-col-xxl-1{grid-column:auto/span 1}.grid .g-col-xxl-2{grid-column:auto/span 2}.grid .g-col-xxl-3{grid-column:auto/span 3}.grid .g-col-xxl-4{grid-column:auto/span 4}.grid .g-col-xxl-5{grid-column:auto/span 5}.grid .g-col-xxl-6{grid-column:auto/span 6}.grid .g-col-xxl-7{grid-column:auto/span 7}.grid .g-col-xxl-8{grid-column:auto/span 8}.grid .g-col-xxl-9{grid-column:auto/span 9}.grid .g-col-xxl-10{grid-column:auto/span 10}.grid .g-col-xxl-11{grid-column:auto/span 11}.grid .g-col-xxl-12{grid-column:auto/span 12}.grid .g-start-xxl-1{grid-column-start:1}.grid .g-start-xxl-2{grid-column-start:2}.grid .g-start-xxl-3{grid-column-start:3}.grid .g-start-xxl-4{grid-column-start:4}.grid .g-start-xxl-5{grid-column-start:5}.grid .g-start-xxl-6{grid-column-start:6}.grid .g-start-xxl-7{grid-column-start:7}.grid .g-start-xxl-8{grid-column-start:8}.grid .g-start-xxl-9{grid-column-start:9}.grid .g-start-xxl-10{grid-column-start:10}.grid .g-start-xxl-11{grid-column-start:11}}.table{--bs-table-color-type: initial;--bs-table-bg-type: initial;--bs-table-color-state: initial;--bs-table-bg-state: initial;--bs-table-color: #212529;--bs-table-bg: #ffffff;--bs-table-border-color: rgb(221.7, 222.3, 222.9);--bs-table-accent-bg: transparent;--bs-table-striped-color: #212529;--bs-table-striped-bg: rgba(0, 0, 0, 0.05);--bs-table-active-color: #212529;--bs-table-active-bg: rgba(0, 0, 0, 0.1);--bs-table-hover-color: #212529;--bs-table-hover-bg: rgba(0, 0, 0, 0.075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;color:var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:1px;box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(1px*2) solid #909294}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:1px 0}.table-bordered>:not(caption)>*>*{border-width:0 1px}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type: var(--bs-table-striped-color);--bs-table-bg-type: var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(even){--bs-table-color-type: var(--bs-table-striped-color);--bs-table-bg-type: var(--bs-table-striped-bg)}.table-active{--bs-table-color-state: var(--bs-table-active-color);--bs-table-bg-state: var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state: var(--bs-table-hover-color);--bs-table-bg-state: var(--bs-table-hover-bg)}.table-primary{--bs-table-color: #000;--bs-table-bg: rgb(206.6, 226, 254.6);--bs-table-border-color: rgb(185.94, 203.4, 229.14);--bs-table-striped-bg: rgb(196.27, 214.7, 241.87);--bs-table-striped-color: #000;--bs-table-active-bg: rgb(185.94, 203.4, 229.14);--bs-table-active-color: #000;--bs-table-hover-bg: rgb(191.105, 209.05, 235.505);--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color: #000;--bs-table-bg: rgb(225.6, 227.4, 229);--bs-table-border-color: rgb(203.04, 204.66, 206.1);--bs-table-striped-bg: rgb(214.32, 216.03, 217.55);--bs-table-striped-color: #000;--bs-table-active-bg: rgb(203.04, 204.66, 206.1);--bs-table-active-color: #000;--bs-table-hover-bg: rgb(208.68, 210.345, 211.825);--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color: #000;--bs-table-bg: rgb(209, 231, 220.8);--bs-table-border-color: rgb(188.1, 207.9, 198.72);--bs-table-striped-bg: rgb(198.55, 219.45, 209.76);--bs-table-striped-color: #000;--bs-table-active-bg: rgb(188.1, 207.9, 198.72);--bs-table-active-color: #000;--bs-table-hover-bg: rgb(193.325, 213.675, 204.24);--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color: #000;--bs-table-bg: rgb(206.6, 244.4, 252);--bs-table-border-color: rgb(185.94, 219.96, 226.8);--bs-table-striped-bg: rgb(196.27, 232.18, 239.4);--bs-table-striped-color: #000;--bs-table-active-bg: rgb(185.94, 219.96, 226.8);--bs-table-active-color: #000;--bs-table-hover-bg: rgb(191.105, 226.07, 233.1);--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color: #000;--bs-table-bg: rgb(255, 242.6, 205.4);--bs-table-border-color: rgb(229.5, 218.34, 184.86);--bs-table-striped-bg: rgb(242.25, 230.47, 195.13);--bs-table-striped-color: #000;--bs-table-active-bg: rgb(229.5, 218.34, 184.86);--bs-table-active-color: #000;--bs-table-hover-bg: rgb(235.875, 224.405, 189.995);--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color: #000;--bs-table-bg: rgb(248, 214.6, 217.8);--bs-table-border-color: rgb(223.2, 193.14, 196.02);--bs-table-striped-bg: rgb(235.6, 203.87, 206.91);--bs-table-striped-color: #000;--bs-table-active-bg: rgb(223.2, 193.14, 196.02);--bs-table-active-color: #000;--bs-table-hover-bg: rgb(229.4, 198.505, 201.465);--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color: #000;--bs-table-bg: #f8f9fa;--bs-table-border-color: rgb(223.2, 224.1, 225);--bs-table-striped-bg: rgb(235.6, 236.55, 237.5);--bs-table-striped-color: #000;--bs-table-active-bg: rgb(223.2, 224.1, 225);--bs-table-active-color: #000;--bs-table-hover-bg: rgb(229.4, 230.325, 231.25);--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color: #ffffff;--bs-table-bg: #212529;--bs-table-border-color: rgb(55.2, 58.8, 62.4);--bs-table-striped-bg: rgb(44.1, 47.9, 51.7);--bs-table-striped-color: #ffffff;--bs-table-active-bg: rgb(55.2, 58.8, 62.4);--bs-table-active-color: #ffffff;--bs-table-hover-bg: rgb(49.65, 53.35, 57.05);--bs-table-hover-color: #ffffff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width: 575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media(max-width: 1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label,.shiny-input-container .control-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.875rem}.form-text{margin-top:.25rem;font-size:0.875em;color:rgba(33,37,41,.75)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#fff;background-clip:padding-box;border:1px solid rgb(221.7,222.3,222.9);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:#212529;background-color:#fff;border-color:rgb(134,182.5,254);outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:rgba(33,37,41,.75);opacity:1}.form-control:disabled{background-color:#e9ecef;opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-0.375rem -0.75rem;margin-inline-end:.75rem;color:#212529;background-color:#f8f9fa;pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:1px;border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:#e9ecef}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:#212529;background-color:rgba(0,0,0,0);border:solid rgba(0,0,0,0);border-width:1px 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + 0.5rem + calc(1px * 2));padding:.25rem .5rem;font-size:0.875rem;border-radius:.25rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-0.25rem -0.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(1px * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-0.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + 0.75rem + calc(1px * 2))}textarea.form-control-sm{min-height:calc(1.5em + 0.5rem + calc(1px * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(1px * 2))}.form-control-color{width:3rem;height:calc(1.5em + 0.75rem + calc(1px * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0 !important;border-radius:.375rem}.form-control-color::-webkit-color-swatch{border:0 !important;border-radius:.375rem}.form-control-color.form-control-sm{height:calc(1.5em + 0.5rem + calc(1px * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(1px * 2))}.form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#fff;background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:1px solid rgb(221.7,222.3,222.9);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-select{transition:none}}.form-select:focus{border-color:rgb(134,182.5,254);outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:#e9ecef}.form-select:-moz-focusring{color:rgba(0,0,0,0);text-shadow:0 0 0 #212529}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:0.875rem;border-radius:.25rem}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:.5rem}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check,.shiny-input-container .checkbox,.shiny-input-container .radio{display:block;min-height:1.5rem;padding-left:0;margin-bottom:.125rem}.form-check .form-check-input,.form-check .shiny-input-container .checkbox input,.form-check .shiny-input-container .radio input,.shiny-input-container .checkbox .form-check-input,.shiny-input-container .checkbox .shiny-input-container .checkbox input,.shiny-input-container .checkbox .shiny-input-container .radio input,.shiny-input-container .radio .form-check-input,.shiny-input-container .radio .shiny-input-container .checkbox input,.shiny-input-container .radio .shiny-input-container .radio input{float:left;margin-left:0}.form-check-reverse{padding-right:0;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:0;margin-left:0}.form-check-input,.shiny-input-container .checkbox input,.shiny-input-container .checkbox-inline input,.shiny-input-container .radio input,.shiny-input-container .radio-inline input{--bs-form-check-bg: #ffffff;width:1em;height:1em;margin-top:.25em;vertical-align:top;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:1px solid rgb(221.7,222.3,222.9);print-color-adjust:exact}.form-check-input[type=checkbox],.shiny-input-container .checkbox input[type=checkbox],.shiny-input-container .checkbox-inline input[type=checkbox],.shiny-input-container .radio input[type=checkbox],.shiny-input-container .radio-inline input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio],.shiny-input-container .checkbox input[type=radio],.shiny-input-container .checkbox-inline input[type=radio],.shiny-input-container .radio input[type=radio],.shiny-input-container .radio-inline input[type=radio]{border-radius:50%}.form-check-input:active,.shiny-input-container .checkbox input:active,.shiny-input-container .checkbox-inline input:active,.shiny-input-container .radio input:active,.shiny-input-container .radio-inline input:active{filter:brightness(90%)}.form-check-input:focus,.shiny-input-container .checkbox input:focus,.shiny-input-container .checkbox-inline input:focus,.shiny-input-container .radio input:focus,.shiny-input-container .radio-inline input:focus{border-color:rgb(134,182.5,254);outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked,.shiny-input-container .checkbox input:checked,.shiny-input-container .checkbox-inline input:checked,.shiny-input-container .radio input:checked,.shiny-input-container .radio-inline input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox],.shiny-input-container .checkbox input:checked[type=checkbox],.shiny-input-container .checkbox-inline input:checked[type=checkbox],.shiny-input-container .radio input:checked[type=checkbox],.shiny-input-container .radio-inline input:checked[type=checkbox]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio],.shiny-input-container .checkbox input:checked[type=radio],.shiny-input-container .checkbox-inline input:checked[type=radio],.shiny-input-container .radio input:checked[type=radio],.shiny-input-container .radio-inline input:checked[type=radio]{--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23ffffff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate,.shiny-input-container .checkbox input[type=checkbox]:indeterminate,.shiny-input-container .checkbox-inline input[type=checkbox]:indeterminate,.shiny-input-container .radio input[type=checkbox]:indeterminate,.shiny-input-container .radio-inline input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled,.shiny-input-container .checkbox input:disabled,.shiny-input-container .checkbox-inline input:disabled,.shiny-input-container .radio input:disabled,.shiny-input-container .radio-inline input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input[disabled]~span,.form-check-input:disabled~.form-check-label,.form-check-input:disabled~span,.shiny-input-container .checkbox input[disabled]~.form-check-label,.shiny-input-container .checkbox input[disabled]~span,.shiny-input-container .checkbox input:disabled~.form-check-label,.shiny-input-container .checkbox input:disabled~span,.shiny-input-container .checkbox-inline input[disabled]~.form-check-label,.shiny-input-container .checkbox-inline input[disabled]~span,.shiny-input-container .checkbox-inline input:disabled~.form-check-label,.shiny-input-container .checkbox-inline input:disabled~span,.shiny-input-container .radio input[disabled]~.form-check-label,.shiny-input-container .radio input[disabled]~span,.shiny-input-container .radio input:disabled~.form-check-label,.shiny-input-container .radio input:disabled~span,.shiny-input-container .radio-inline input[disabled]~.form-check-label,.shiny-input-container .radio-inline input[disabled]~span,.shiny-input-container .radio-inline input:disabled~.form-check-label,.shiny-input-container .radio-inline input:disabled~span{cursor:default;opacity:.5}.form-check-label,.shiny-input-container .checkbox label,.shiny-input-container .checkbox-inline label,.shiny-input-container .radio label,.shiny-input-container .radio-inline label{cursor:pointer}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgb%28134, 182.5, 254%29'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.btn-check[disabled]+.btn,.btn-check:disabled+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:rgba(0,0,0,0)}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-0.25rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:rgb(182.4,211.5,254.4)}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#f8f9fa;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:rgb(182.4,211.5,254.4)}.form-range::-moz-range-track{width:100%;height:.5rem;color:rgba(0,0,0,0);cursor:pointer;background-color:#f8f9fa;border-color:rgba(0,0,0,0);border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:rgba(33,37,41,.75)}.form-range:disabled::-moz-range-thumb{background-color:rgba(33,37,41,.75)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(1px * 2));min-height:calc(3.5rem + calc(1px * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;height:100%;padding:1rem .75rem;overflow:hidden;text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:1px solid rgba(0,0,0,0);transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media(prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control::placeholder,.form-floating>.form-control-plaintext::placeholder{color:rgba(0,0,0,0)}.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown),.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:-webkit-autofill,.form-floating>.form-control-plaintext:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-control-plaintext~label,.form-floating>.form-select~label{color:rgba(var(--bs-body-color-rgb), 0.65);transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control:focus~label::after,.form-floating>.form-control:not(:placeholder-shown)~label::after,.form-floating>.form-control-plaintext~label::after,.form-floating>.form-select~label::after{position:absolute;inset:1rem .375rem;z-index:-1;height:1.5em;content:"";background-color:#fff;border-radius:.375rem}.form-floating>.form-control:-webkit-autofill~label{color:rgba(var(--bs-body-color-rgb), 0.65);transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control-plaintext~label{border-width:1px 0}.form-floating>:disabled~label,.form-floating>.form-control:disabled~label{color:#6c757d}.form-floating>:disabled~label::after,.form-floating>.form-control:disabled~label::after{background-color:#e9ecef}.input-group{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:stretch;-webkit-align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-floating{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-select:focus,.input-group>.form-floating:focus-within{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:center;white-space:nowrap;background-color:#f8f9fa;border:1px solid rgb(221.7,222.3,222.9);border-radius:.375rem}.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text,.input-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;border-radius:.5rem}.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text,.input-group-sm>.btn{padding:.25rem .5rem;font-size:0.875rem;border-radius:.25rem}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(1px*-1);border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#198754}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:#198754;border-radius:.375rem}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#198754;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:#198754}.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"],.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:#198754;box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:calc(3rem + calc(1.5em + 0.75rem))}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:#198754}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:#198754}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(25,135,84,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#198754}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):valid,.input-group>.form-control:not(:focus).is-valid,.was-validated .input-group>.form-select:not(:focus):valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.input-group>.form-floating:not(:focus-within).is-valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:0.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.875rem;color:#fff;background-color:#dc3545;border-radius:.375rem}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#dc3545;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:#dc3545}.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"],.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid{width:calc(3rem + calc(1.5em + 0.75rem))}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:#dc3545}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:#dc3545}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(220,53,69,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#dc3545}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.was-validated .input-group>.form-control:not(:focus):invalid,.input-group>.form-control:not(:focus).is-invalid,.was-validated .input-group>.form-select:not(:focus):invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.input-group>.form-floating:not(:focus-within).is-invalid{z-index:4}.btn{--bs-btn-padding-x: 0.75rem;--bs-btn-padding-y: 0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: #212529;--bs-btn-bg: transparent;--bs-btn-border-width: 1px;--bs-btn-border-color: transparent;--bs-btn-border-radius: 0.375rem;--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity: 0.65;--bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;vertical-align:middle;cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,:not(.btn-check)+.btn:active,.btn:first-child:active,.btn.active,.btn.show{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,:not(.btn-check)+.btn:active:focus-visible,.btn:first-child:active:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn:disabled,.btn.disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-default{--bs-btn-color: #000;--bs-btn-bg: #dee2e6;--bs-btn-border-color: #dee2e6;--bs-btn-hover-color: #000;--bs-btn-hover-bg: rgb(226.95, 230.35, 233.75);--bs-btn-hover-border-color: rgb(225.3, 228.9, 232.5);--bs-btn-focus-shadow-rgb: 189, 192, 196;--bs-btn-active-color: #000;--bs-btn-active-bg: rgb(228.6, 231.8, 235);--bs-btn-active-border-color: rgb(225.3, 228.9, 232.5);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #dee2e6;--bs-btn-disabled-border-color: #dee2e6}.btn-primary{--bs-btn-color: #ffffff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: rgb(11.05, 93.5, 215.05);--bs-btn-hover-border-color: rgb(10.4, 88, 202.4);--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: rgb(10.4, 88, 202.4);--bs-btn-active-border-color: rgb(9.75, 82.5, 189.75);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-secondary{--bs-btn-color: #ffffff;--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: rgb(91.8, 99.45, 106.25);--bs-btn-hover-border-color: rgb(86.4, 93.6, 100);--bs-btn-focus-shadow-rgb: 130, 138, 145;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: rgb(86.4, 93.6, 100);--bs-btn-active-border-color: rgb(81, 87.75, 93.75);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}.btn-success{--bs-btn-color: #ffffff;--bs-btn-bg: #198754;--bs-btn-border-color: #198754;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: rgb(21.25, 114.75, 71.4);--bs-btn-hover-border-color: rgb(20, 108, 67.2);--bs-btn-focus-shadow-rgb: 60, 153, 110;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: rgb(20, 108, 67.2);--bs-btn-active-border-color: rgb(18.75, 101.25, 63);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #198754;--bs-btn-disabled-border-color: #198754}.btn-info{--bs-btn-color: #000;--bs-btn-bg: #0dcaf0;--bs-btn-border-color: #0dcaf0;--bs-btn-hover-color: #000;--bs-btn-hover-bg: rgb(49.3, 209.95, 242.25);--bs-btn-hover-border-color: rgb(37.2, 207.3, 241.5);--bs-btn-focus-shadow-rgb: 11, 172, 204;--bs-btn-active-color: #000;--bs-btn-active-bg: rgb(61.4, 212.6, 243);--bs-btn-active-border-color: rgb(37.2, 207.3, 241.5);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #0dcaf0;--bs-btn-disabled-border-color: #0dcaf0}.btn-warning{--bs-btn-color: #000;--bs-btn-bg: #ffc107;--bs-btn-border-color: #ffc107;--bs-btn-hover-color: #000;--bs-btn-hover-bg: rgb(255, 202.3, 44.2);--bs-btn-hover-border-color: rgb(255, 199.2, 31.8);--bs-btn-focus-shadow-rgb: 217, 164, 6;--bs-btn-active-color: #000;--bs-btn-active-bg: rgb(255, 205.4, 56.6);--bs-btn-active-border-color: rgb(255, 199.2, 31.8);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #ffc107;--bs-btn-disabled-border-color: #ffc107}.btn-danger{--bs-btn-color: #ffffff;--bs-btn-bg: #dc3545;--bs-btn-border-color: #dc3545;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: rgb(187, 45.05, 58.65);--bs-btn-hover-border-color: rgb(176, 42.4, 55.2);--bs-btn-focus-shadow-rgb: 225, 83, 97;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: rgb(176, 42.4, 55.2);--bs-btn-active-border-color: rgb(165, 39.75, 51.75);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #dc3545;--bs-btn-disabled-border-color: #dc3545}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: rgb(210.8, 211.65, 212.5);--bs-btn-hover-border-color: rgb(198.4, 199.2, 200);--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: rgb(198.4, 199.2, 200);--bs-btn-active-border-color: rgb(186, 186.75, 187.5);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.btn-dark{--bs-btn-color: #ffffff;--bs-btn-bg: #212529;--bs-btn-border-color: #212529;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: rgb(66.3, 69.7, 73.1);--bs-btn-hover-border-color: rgb(55.2, 58.8, 62.4);--bs-btn-focus-shadow-rgb: 66, 70, 73;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: rgb(77.4, 80.6, 83.8);--bs-btn-active-border-color: rgb(55.2, 58.8, 62.4);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #212529;--bs-btn-disabled-border-color: #212529}.btn-outline-default{--bs-btn-color: #dee2e6;--bs-btn-border-color: #dee2e6;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #dee2e6;--bs-btn-hover-border-color: #dee2e6;--bs-btn-focus-shadow-rgb: 222, 226, 230;--bs-btn-active-color: #000;--bs-btn-active-bg: #dee2e6;--bs-btn-active-border-color: #dee2e6;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #dee2e6;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #dee2e6;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-primary{--bs-btn-color: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #0d6efd;--bs-btn-hover-border-color: #0d6efd;--bs-btn-focus-shadow-rgb: 13, 110, 253;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #0d6efd;--bs-btn-active-border-color: #0d6efd;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #0d6efd;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #0d6efd;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-secondary{--bs-btn-color: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #6c757d;--bs-btn-hover-border-color: #6c757d;--bs-btn-focus-shadow-rgb: 108, 117, 125;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #6c757d;--bs-btn-active-border-color: #6c757d;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #6c757d;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-success{--bs-btn-color: #198754;--bs-btn-border-color: #198754;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #198754;--bs-btn-hover-border-color: #198754;--bs-btn-focus-shadow-rgb: 25, 135, 84;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #198754;--bs-btn-active-border-color: #198754;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #198754;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #198754;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-info{--bs-btn-color: #0dcaf0;--bs-btn-border-color: #0dcaf0;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #0dcaf0;--bs-btn-hover-border-color: #0dcaf0;--bs-btn-focus-shadow-rgb: 13, 202, 240;--bs-btn-active-color: #000;--bs-btn-active-bg: #0dcaf0;--bs-btn-active-border-color: #0dcaf0;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #0dcaf0;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #0dcaf0;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-warning{--bs-btn-color: #ffc107;--bs-btn-border-color: #ffc107;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #ffc107;--bs-btn-hover-border-color: #ffc107;--bs-btn-focus-shadow-rgb: 255, 193, 7;--bs-btn-active-color: #000;--bs-btn-active-bg: #ffc107;--bs-btn-active-border-color: #ffc107;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffc107;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #ffc107;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-danger{--bs-btn-color: #dc3545;--bs-btn-border-color: #dc3545;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #dc3545;--bs-btn-hover-border-color: #dc3545;--bs-btn-focus-shadow-rgb: 220, 53, 69;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #dc3545;--bs-btn-active-border-color: #dc3545;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #dc3545;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #dc3545;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-light{--bs-btn-color: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #f8f9fa;--bs-btn-hover-border-color: #f8f9fa;--bs-btn-focus-shadow-rgb: 248, 249, 250;--bs-btn-active-color: #000;--bs-btn-active-bg: #f8f9fa;--bs-btn-active-border-color: #f8f9fa;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #f8f9fa;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #f8f9fa;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-dark{--bs-btn-color: #212529;--bs-btn-border-color: #212529;--bs-btn-hover-color: #ffffff;--bs-btn-hover-bg: #212529;--bs-btn-hover-border-color: #212529;--bs-btn-focus-shadow-rgb: 33, 37, 41;--bs-btn-active-color: #ffffff;--bs-btn-active-bg: #212529;--bs-btn-active-border-color: #212529;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #212529;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #212529;--bs-btn-bg: transparent;--bs-gradient: none}.btn-link{--bs-btn-font-weight: 400;--bs-btn-color: #0d6efd;--bs-btn-bg: transparent;--bs-btn-border-color: transparent;--bs-btn-hover-color: rgb(10.4, 88, 202.4);--bs-btn-hover-border-color: transparent;--bs-btn-active-color: rgb(10.4, 88, 202.4);--bs-btn-active-border-color: transparent;--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-border-color: transparent;--bs-btn-box-shadow: 0 0 0 #000;--bs-btn-focus-shadow-rgb: 49, 132, 253;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-lg,.btn-group-lg>.btn{--bs-btn-padding-y: 0.5rem;--bs-btn-padding-x: 1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius: 0.5rem}.btn-sm,.btn-group-sm>.btn{--bs-btn-padding-y: 0.25rem;--bs-btn-padding-x: 0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius: 0.25rem}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .2s ease}@media(prefers-reduced-motion: reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media(prefers-reduced-motion: reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart,.dropup-center,.dropdown-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid rgba(0,0,0,0);border-bottom:0;border-left:.3em solid rgba(0,0,0,0)}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex: 1000;--bs-dropdown-min-width: 10rem;--bs-dropdown-padding-x: 0;--bs-dropdown-padding-y: 0.5rem;--bs-dropdown-spacer: 0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color: #212529;--bs-dropdown-bg: #ffffff;--bs-dropdown-border-color: rgba(0, 0, 0, 0.175);--bs-dropdown-border-radius: 0.375rem;--bs-dropdown-border-width: 1px;--bs-dropdown-inner-border-radius: calc(0.375rem - 1px);--bs-dropdown-divider-bg: rgba(0, 0, 0, 0.175);--bs-dropdown-divider-margin-y: 0.5rem;--bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-dropdown-link-color: #212529;--bs-dropdown-link-hover-color: #212529;--bs-dropdown-link-hover-bg: #f8f9fa;--bs-dropdown-link-active-color: #ffffff;--bs-dropdown-link-active-bg: #0d6efd;--bs-dropdown-link-disabled-color: rgba(33, 37, 41, 0.5);--bs-dropdown-item-padding-x: 1rem;--bs-dropdown-item-padding-y: 0.25rem;--bs-dropdown-header-color: #6c757d;--bs-dropdown-header-padding-x: 1rem;--bs-dropdown-header-padding-y: 0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position: start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position: end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media(min-width: 576px){.dropdown-menu-sm-start{--bs-position: start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position: end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 768px){.dropdown-menu-md-start{--bs-position: start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position: end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 992px){.dropdown-menu-lg-start{--bs-position: start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position: end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1200px){.dropdown-menu-xl-start{--bs-position: start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position: end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media(min-width: 1400px){.dropdown-menu-xxl-start{--bs-position: start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position: end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid rgba(0,0,0,0);border-bottom:.3em solid;border-left:.3em solid rgba(0,0,0,0)}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:0;border-bottom:.3em solid rgba(0,0,0,0);border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid rgba(0,0,0,0);border-right:.3em solid;border-bottom:.3em solid rgba(0,0,0,0)}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap;background-color:rgba(0,0,0,0);border:0;border-radius:var(--bs-dropdown-item-border-radius, 0)}.dropdown-item:hover,.dropdown-item:focus{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:rgba(0,0,0,0)}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:0.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color: #dee2e6;--bs-dropdown-bg: #343a40;--bs-dropdown-border-color: rgba(0, 0, 0, 0.175);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color: #dee2e6;--bs-dropdown-link-hover-color: #ffffff;--bs-dropdown-divider-bg: rgba(0, 0, 0, 0.175);--bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color: #ffffff;--bs-dropdown-link-active-bg: #0d6efd;--bs-dropdown-link-disabled-color: #adb5bd;--bs-dropdown-header-color: #adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto}.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn:hover,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;justify-content:flex-start;-webkit-justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:.375rem}.btn-group>:not(.btn-check:first-child)+.btn,.btn-group>.btn-group:not(:first-child){margin-left:calc(1px*-1)}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn,.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;-webkit-flex-direction:column;align-items:flex-start;-webkit-align-items:flex-start;justify-content:center;-webkit-justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:calc(1px*-1)}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn~.btn,.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x: 1rem;--bs-nav-link-padding-y: 0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color: #0d6efd;--bs-nav-link-hover-color: rgb(10.4, 88, 202.4);--bs-nav-link-disabled-color: rgba(33, 37, 41, 0.75);display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background:none;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media(prefers-reduced-motion: reduce){.nav-link{transition:none}}.nav-link:hover,.nav-link:focus{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width: 1px;--bs-nav-tabs-border-color: rgb(221.7, 222.3, 222.9);--bs-nav-tabs-border-radius: 0.375rem;--bs-nav-tabs-link-hover-border-color: #e9ecef #e9ecef rgb(221.7, 222.3, 222.9);--bs-nav-tabs-link-active-color: #000;--bs-nav-tabs-link-active-bg: #ffffff;--bs-nav-tabs-link-active-border-color: rgb(221.7, 222.3, 222.9) rgb(221.7, 222.3, 222.9) #ffffff;border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1*var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid rgba(0,0,0,0);border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1*var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius: 0.375rem;--bs-nav-pills-link-active-color: #ffffff;--bs-nav-pills-link-active-bg: #0d6efd}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap: 1rem;--bs-nav-underline-border-width: 0.125rem;--bs-nav-underline-link-active-color: #000;gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid rgba(0,0,0,0)}.nav-underline .nav-link:hover,.nav-underline .nav-link:focus{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x: 0;--bs-navbar-padding-y: 0.5rem;--bs-navbar-color: rgb(253.26, 253.63, 253.98);--bs-navbar-hover-color: rgba(252.58, 253.55, 254.98, 0.8);--bs-navbar-disabled-color: rgba(253.26, 253.63, 253.98, 0.75);--bs-navbar-active-color: rgb(252.58, 253.55, 254.98);--bs-navbar-brand-padding-y: 0.3125rem;--bs-navbar-brand-margin-end: 1rem;--bs-navbar-brand-font-size: 1.25rem;--bs-navbar-brand-color: rgb(253.26, 253.63, 253.98);--bs-navbar-brand-hover-color: rgb(252.58, 253.55, 254.98);--bs-navbar-nav-link-padding-x: 0.5rem;--bs-navbar-toggler-padding-y: 0.25;--bs-navbar-toggler-padding-x: 0;--bs-navbar-toggler-font-size: 1.25rem;--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgb%28253.26, 253.63, 253.98%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color: rgba(253.26, 253.63, 253.98, 0);--bs-navbar-toggler-border-radius: 0.375rem;--bs-navbar-toggler-focus-width: 0.25rem;--bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out;position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-sm,.navbar>.container-md,.navbar>.container-lg,.navbar>.container-xl,.navbar>.container-xxl{display:flex;display:-webkit-flex;flex-wrap:inherit;-webkit-flex-wrap:inherit;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x: 0;--bs-nav-link-padding-y: 0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color: var(--bs-navbar-color);--bs-nav-link-hover-color: var(--bs-navbar-hover-color);--bs-nav-link-disabled-color: var(--bs-navbar-disabled-color);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:hover,.navbar-text a:focus{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;-webkit-flex-basis:100%;flex-grow:1;-webkit-flex-grow:1;align-items:center;-webkit-align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:rgba(0,0,0,0);border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media(prefers-reduced-motion: reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media(min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}@media(min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;-webkit-flex-grow:1;width:auto !important;height:auto !important;visibility:visible !important;background-color:rgba(0,0,0,0) !important;border:0 !important;transform:none !important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color: rgb(253.26, 253.63, 253.98);--bs-navbar-hover-color: rgba(252.58, 253.55, 254.98, 0.8);--bs-navbar-disabled-color: rgba(253.26, 253.63, 253.98, 0.75);--bs-navbar-active-color: rgb(252.58, 253.55, 254.98);--bs-navbar-brand-color: rgb(253.26, 253.63, 253.98);--bs-navbar-brand-hover-color: rgb(252.58, 253.55, 254.98);--bs-navbar-toggler-border-color: rgba(253.26, 253.63, 253.98, 0);--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgb%28253.26, 253.63, 253.98%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgb%28253.26, 253.63, 253.98%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y: 1rem;--bs-card-spacer-x: 1rem;--bs-card-title-spacer-y: 0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width: 1px;--bs-card-border-color: rgba(0, 0, 0, 0.175);--bs-card-border-radius: 0.375rem;--bs-card-box-shadow: ;--bs-card-inner-border-radius: calc(0.375rem - 1px);--bs-card-cap-padding-y: 0.5rem;--bs-card-cap-padding-x: 1rem;--bs-card-cap-bg: rgba(33, 37, 41, 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg: #ffffff;--bs-card-img-overlay-padding: 1rem;--bs-card-group-margin: 0.75rem;position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;-webkit-flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-0.5*var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-0.5*var(--bs-card-cap-padding-x));margin-bottom:calc(-1*var(--bs-card-cap-padding-y));margin-left:calc(-0.5*var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-0.5*var(--bs-card-cap-padding-x));margin-left:calc(-0.5*var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-top,.card-img-bottom{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media(min-width: 576px){.card-group{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap}.card-group>.card{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion{--bs-accordion-color: #212529;--bs-accordion-bg: #ffffff;--bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease;--bs-accordion-border-color: rgb(221.7, 222.3, 222.9);--bs-accordion-border-width: 1px;--bs-accordion-border-radius: 0.375rem;--bs-accordion-inner-border-radius: calc(0.375rem - 1px);--bs-accordion-btn-padding-x: 1.25rem;--bs-accordion-btn-padding-y: 1rem;--bs-accordion-btn-color: #212529;--bs-accordion-btn-bg: #ffffff;--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width: 1.25rem;--bs-accordion-btn-icon-transform: rotate(-180deg);--bs-accordion-btn-icon-transition: transform 0.2s ease-in-out;--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%285.2, 44, 101.2%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-focus-border-color: rgb(134, 182.5, 254);--bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-accordion-body-padding-x: 1.25rem;--bs-accordion-body-padding-y: 1rem;--bs-accordion-active-color: rgb(5.2, 44, 101.2);--bs-accordion-active-bg: rgb(206.6, 226, 254.6)}.accordion-button{position:relative;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media(prefers-reduced-motion: reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1*var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;-webkit-flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media(prefers-reduced-motion: reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;border-color:var(--bs-accordion-btn-focus-border-color);outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type .accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush .accordion-collapse{border-width:0}.accordion-flush .accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush .accordion-item:first-child{border-top:0}.accordion-flush .accordion-item:last-child{border-bottom:0}.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button::after{--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28109.8, 168, 253.8%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='rgb%28109.8, 168, 253.8%29'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x: 0;--bs-breadcrumb-padding-y: 0;--bs-breadcrumb-margin-bottom: 1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color: rgba(33, 37, 41, 0.75);--bs-breadcrumb-item-padding-x: 0.5rem;--bs-breadcrumb-item-active-color: rgba(33, 37, 41, 0.75);display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, ">") /* rtl: var(--bs-breadcrumb-divider, ">") */}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x: 0.75rem;--bs-pagination-padding-y: 0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color: #0d6efd;--bs-pagination-bg: #ffffff;--bs-pagination-border-width: 1px;--bs-pagination-border-color: rgb(221.7, 222.3, 222.9);--bs-pagination-border-radius: 0.375rem;--bs-pagination-hover-color: rgb(10.4, 88, 202.4);--bs-pagination-hover-bg: #f8f9fa;--bs-pagination-hover-border-color: rgb(221.7, 222.3, 222.9);--bs-pagination-focus-color: rgb(10.4, 88, 202.4);--bs-pagination-focus-bg: #e9ecef;--bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-pagination-active-color: #ffffff;--bs-pagination-active-bg: #0d6efd;--bs-pagination-active-border-color: #0d6efd;--bs-pagination-disabled-color: rgba(33, 37, 41, 0.75);--bs-pagination-disabled-bg: #e9ecef;--bs-pagination-disabled-border-color: rgb(221.7, 222.3, 222.9);display:flex;display:-webkit-flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.page-link.active,.active>.page-link{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.page-link.disabled,.disabled>.page-link{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(1px*-1)}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x: 1.5rem;--bs-pagination-padding-y: 0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius: 0.5rem}.pagination-sm{--bs-pagination-padding-x: 0.5rem;--bs-pagination-padding-y: 0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius: 0.25rem}.badge{--bs-badge-padding-x: 0.65em;--bs-badge-padding-y: 0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight: 700;--bs-badge-color: #ffffff;--bs-badge-border-radius: 0.375rem;display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg: transparent;--bs-alert-padding-x: 1rem;--bs-alert-padding-y: 1rem;--bs-alert-margin-bottom: 1rem;--bs-alert-color: inherit;--bs-alert-border-color: transparent;--bs-alert-border: 1px solid var(--bs-alert-border-color);--bs-alert-border-radius: 0.375rem;--bs-alert-link-color: inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-default{--bs-alert-color: var(--bs-default-text-emphasis);--bs-alert-bg: var(--bs-default-bg-subtle);--bs-alert-border-color: var(--bs-default-border-subtle);--bs-alert-link-color: var(--bs-default-text-emphasis)}.alert-primary{--bs-alert-color: var(--bs-primary-text-emphasis);--bs-alert-bg: var(--bs-primary-bg-subtle);--bs-alert-border-color: var(--bs-primary-border-subtle);--bs-alert-link-color: var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color: var(--bs-secondary-text-emphasis);--bs-alert-bg: var(--bs-secondary-bg-subtle);--bs-alert-border-color: var(--bs-secondary-border-subtle);--bs-alert-link-color: var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color: var(--bs-success-text-emphasis);--bs-alert-bg: var(--bs-success-bg-subtle);--bs-alert-border-color: var(--bs-success-border-subtle);--bs-alert-link-color: var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color: var(--bs-info-text-emphasis);--bs-alert-bg: var(--bs-info-bg-subtle);--bs-alert-border-color: var(--bs-info-border-subtle);--bs-alert-link-color: var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color: var(--bs-warning-text-emphasis);--bs-alert-bg: var(--bs-warning-bg-subtle);--bs-alert-border-color: var(--bs-warning-border-subtle);--bs-alert-link-color: var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color: var(--bs-danger-text-emphasis);--bs-alert-bg: var(--bs-danger-bg-subtle);--bs-alert-border-color: var(--bs-danger-border-subtle);--bs-alert-link-color: var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color: var(--bs-light-text-emphasis);--bs-alert-bg: var(--bs-light-bg-subtle);--bs-alert-border-color: var(--bs-light-border-subtle);--bs-alert-link-color: var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color: var(--bs-dark-text-emphasis);--bs-alert-bg: var(--bs-dark-bg-subtle);--bs-alert-border-color: var(--bs-dark-border-subtle);--bs-alert-link-color: var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:1rem}}.progress,.progress-stacked{--bs-progress-height: 1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg: #e9ecef;--bs-progress-border-radius: 0.375rem;--bs-progress-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-progress-bar-color: #ffffff;--bs-progress-bar-bg: #0d6efd;--bs-progress-bar-transition: width 0.6s ease;display:flex;display:-webkit-flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media(prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media(prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color: #212529;--bs-list-group-bg: #ffffff;--bs-list-group-border-color: rgb(221.7, 222.3, 222.9);--bs-list-group-border-width: 1px;--bs-list-group-border-radius: 0.375rem;--bs-list-group-item-padding-x: 1rem;--bs-list-group-item-padding-y: 0.5rem;--bs-list-group-action-color: rgba(33, 37, 41, 0.75);--bs-list-group-action-hover-color: #000;--bs-list-group-action-hover-bg: #f8f9fa;--bs-list-group-action-active-color: #212529;--bs-list-group-action-active-bg: #e9ecef;--bs-list-group-disabled-color: rgba(33, 37, 41, 0.75);--bs-list-group-disabled-bg: #ffffff;--bs-list-group-active-color: #ffffff;--bs-list-group-active-bg: #0d6efd;--bs-list-group-active-border-color: #0d6efd;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1*var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-horizontal{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media(min-width: 576px){.list-group-horizontal-sm{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 768px){.list-group-horizontal-md{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 992px){.list-group-horizontal-lg{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 1200px){.list-group-horizontal-xl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media(min-width: 1400px){.list-group-horizontal-xxl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1*var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-default{--bs-list-group-color: var(--bs-default-text-emphasis);--bs-list-group-bg: var(--bs-default-bg-subtle);--bs-list-group-border-color: var(--bs-default-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-default-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-default-border-subtle);--bs-list-group-active-color: var(--bs-default-bg-subtle);--bs-list-group-active-bg: var(--bs-default-text-emphasis);--bs-list-group-active-border-color: var(--bs-default-text-emphasis)}.list-group-item-primary{--bs-list-group-color: var(--bs-primary-text-emphasis);--bs-list-group-bg: var(--bs-primary-bg-subtle);--bs-list-group-border-color: var(--bs-primary-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-primary-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-primary-border-subtle);--bs-list-group-active-color: var(--bs-primary-bg-subtle);--bs-list-group-active-bg: var(--bs-primary-text-emphasis);--bs-list-group-active-border-color: var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color: var(--bs-secondary-text-emphasis);--bs-list-group-bg: var(--bs-secondary-bg-subtle);--bs-list-group-border-color: var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-secondary-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-secondary-border-subtle);--bs-list-group-active-color: var(--bs-secondary-bg-subtle);--bs-list-group-active-bg: var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color: var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color: var(--bs-success-text-emphasis);--bs-list-group-bg: var(--bs-success-bg-subtle);--bs-list-group-border-color: var(--bs-success-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-success-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-success-border-subtle);--bs-list-group-active-color: var(--bs-success-bg-subtle);--bs-list-group-active-bg: var(--bs-success-text-emphasis);--bs-list-group-active-border-color: var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color: var(--bs-info-text-emphasis);--bs-list-group-bg: var(--bs-info-bg-subtle);--bs-list-group-border-color: var(--bs-info-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-info-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-info-border-subtle);--bs-list-group-active-color: var(--bs-info-bg-subtle);--bs-list-group-active-bg: var(--bs-info-text-emphasis);--bs-list-group-active-border-color: var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color: var(--bs-warning-text-emphasis);--bs-list-group-bg: var(--bs-warning-bg-subtle);--bs-list-group-border-color: var(--bs-warning-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-warning-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-warning-border-subtle);--bs-list-group-active-color: var(--bs-warning-bg-subtle);--bs-list-group-active-bg: var(--bs-warning-text-emphasis);--bs-list-group-active-border-color: var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color: var(--bs-danger-text-emphasis);--bs-list-group-bg: var(--bs-danger-bg-subtle);--bs-list-group-border-color: var(--bs-danger-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-danger-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-danger-border-subtle);--bs-list-group-active-color: var(--bs-danger-bg-subtle);--bs-list-group-active-bg: var(--bs-danger-text-emphasis);--bs-list-group-active-border-color: var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color: var(--bs-light-text-emphasis);--bs-list-group-bg: var(--bs-light-bg-subtle);--bs-list-group-border-color: var(--bs-light-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-light-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-light-border-subtle);--bs-list-group-active-color: var(--bs-light-bg-subtle);--bs-list-group-active-bg: var(--bs-light-text-emphasis);--bs-list-group-active-border-color: var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color: var(--bs-dark-text-emphasis);--bs-list-group-bg: var(--bs-dark-bg-subtle);--bs-list-group-border-color: var(--bs-dark-border-subtle);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-dark-border-subtle);--bs-list-group-action-active-color: var(--bs-emphasis-color);--bs-list-group-action-active-bg: var(--bs-dark-border-subtle);--bs-list-group-active-color: var(--bs-dark-bg-subtle);--bs-list-group-active-bg: var(--bs-dark-text-emphasis);--bs-list-group-active-border-color: var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color: #000;--bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e");--bs-btn-close-opacity: 0.5;--bs-btn-close-hover-opacity: 0.75;--bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-btn-close-focus-opacity: 1;--bs-btn-close-disabled-opacity: 0.25;--bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%);box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:var(--bs-btn-close-color);background:rgba(0,0,0,0) var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close:disabled,.btn-close.disabled{pointer-events:none;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{filter:var(--bs-btn-close-white-filter)}[data-bs-theme=dark] .btn-close{filter:var(--bs-btn-close-white-filter)}.toast{--bs-toast-zindex: 1090;--bs-toast-padding-x: 0.75rem;--bs-toast-padding-y: 0.5rem;--bs-toast-spacing: 1.5rem;--bs-toast-max-width: 350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg: rgba(255, 255, 255, 0.85);--bs-toast-border-width: 1px;--bs-toast-border-color: rgba(0, 0, 0, 0.175);--bs-toast-border-radius: 0.375rem;--bs-toast-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-toast-header-color: rgba(33, 37, 41, 0.75);--bs-toast-header-bg: rgba(255, 255, 255, 0.85);--bs-toast-header-border-color: rgba(0, 0, 0, 0.175);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex: 1090;position:absolute;z-index:var(--bs-toast-zindex);width:max-content;width:-webkit-max-content;width:-moz-max-content;width:-ms-max-content;width:-o-max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-0.5*var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex: 1055;--bs-modal-width: 500px;--bs-modal-padding: 1rem;--bs-modal-margin: 0.5rem;--bs-modal-color: ;--bs-modal-bg: #ffffff;--bs-modal-border-color: rgba(0, 0, 0, 0.175);--bs-modal-border-width: 1px;--bs-modal-border-radius: 0.5rem;--bs-modal-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-modal-inner-border-radius: calc(0.5rem - 1px);--bs-modal-header-padding-x: 1rem;--bs-modal-header-padding-y: 1rem;--bs-modal-header-padding: 1rem 1rem;--bs-modal-header-border-color: rgb(221.7, 222.3, 222.9);--bs-modal-header-border-width: 1px;--bs-modal-title-line-height: 1.5;--bs-modal-footer-gap: 0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color: rgb(221.7, 222.3, 222.9);--bs-modal-footer-border-width: 1px;position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out}@media(prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.fade .modal-dialog{transform:translate(0, -50px)}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin)*2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;min-height:calc(100% - var(--bs-modal-margin)*2)}.modal-content{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex: 1050;--bs-backdrop-bg: #000;--bs-backdrop-opacity: 0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y)*.5) calc(var(--bs-modal-header-padding-x)*.5);margin:calc(-0.5*var(--bs-modal-header-padding-y)) calc(-0.5*var(--bs-modal-header-padding-x)) calc(-0.5*var(--bs-modal-header-padding-y)) auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;display:-webkit-flex;flex-shrink:0;-webkit-flex-shrink:0;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:flex-end;-webkit-justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap)*.5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap)*.5)}@media(min-width: 576px){.modal{--bs-modal-margin: 1.75rem;--bs-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width: 300px}}@media(min-width: 992px){.modal-lg,.modal-xl{--bs-modal-width: 800px}}@media(min-width: 1200px){.modal-xl{--bs-modal-width: 1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media(max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header,.modal-fullscreen-sm-down .modal-footer{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media(max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header,.modal-fullscreen-md-down .modal-footer{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media(max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header,.modal-fullscreen-lg-down .modal-footer{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media(max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header,.modal-fullscreen-xl-down .modal-footer{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media(max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header,.modal-fullscreen-xxl-down .modal-footer{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex: 1080;--bs-tooltip-max-width: 200px;--bs-tooltip-padding-x: 0.5rem;--bs-tooltip-padding-y: 0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color: #ffffff;--bs-tooltip-bg: #000;--bs-tooltip-border-radius: 0.375rem;--bs-tooltip-opacity: 0.9;--bs-tooltip-arrow-width: 0.8rem;--bs-tooltip-arrow-height: 0.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:rgba(0,0,0,0);border-style:solid}.bs-tooltip-top .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow{bottom:calc(-1*var(--bs-tooltip-arrow-height))}.bs-tooltip-top .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width)*.5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-end .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow{left:calc(-1*var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-end .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width)*.5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-bottom .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow{top:calc(-1*var(--bs-tooltip-arrow-height))}.bs-tooltip-bottom .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-start .tooltip-arrow,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow{right:calc(-1*var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-start .tooltip-arrow::before,.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width)*.5) 0 calc(var(--bs-tooltip-arrow-width)*.5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex: 1070;--bs-popover-max-width: 276px;--bs-popover-font-size:0.875rem;--bs-popover-bg: #ffffff;--bs-popover-border-width: 1px;--bs-popover-border-color: rgba(0, 0, 0, 0.175);--bs-popover-border-radius: 0.5rem;--bs-popover-inner-border-radius: calc(0.5rem - 1px);--bs-popover-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-popover-header-padding-x: 1rem;--bs-popover-header-padding-y: 0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color: inherit;--bs-popover-header-bg: #e9ecef;--bs-popover-body-padding-x: 1rem;--bs-popover-body-padding-y: 1rem;--bs-popover-body-color: #212529;--bs-popover-arrow-width: 1rem;--bs-popover-arrow-height: 0.5rem;--bs-popover-arrow-border: var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::before,.popover .popover-arrow::after{position:absolute;display:block;content:"";border-color:rgba(0,0,0,0);border-style:solid;border-width:0}.bs-popover-top>.popover-arrow,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow{bottom:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width)*.5) 0}.bs-popover-top>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-top>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-end>.popover-arrow,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow{left:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width)*.5) 0}.bs-popover-end>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-end>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-bottom>.popover-arrow,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow{top:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{border-width:0 calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height)}.bs-popover-bottom>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-bottom>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-bottom .popover-header::before,.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-0.5*var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-start>.popover-arrow,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow{right:calc(-1*(var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{border-width:calc(var(--bs-popover-arrow-width)*.5) 0 calc(var(--bs-popover-arrow-width)*.5) var(--bs-popover-arrow-height)}.bs-popover-start>.popover-arrow::before,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-start>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y;-webkit-touch-action:pan-y;-moz-touch-action:pan-y;-ms-touch-action:pan-y;-o-touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden;transition:transform .6s ease-in-out}@media(prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-start),.active.carousel-item-end{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end{z-index:1;opacity:1}.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{z-index:0;opacity:0;transition:opacity 0s .6s}@media(prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-start,.carousel-fade .active.carousel-item-end{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media(prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ffffff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ffffff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;display:-webkit-flex;justify-content:center;-webkit-justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;-webkit-flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border:0;border-top:10px solid rgba(0,0,0,0);border-bottom:10px solid rgba(0,0,0,0);opacity:.5;transition:opacity .6s ease}@media(prefers-reduced-motion: reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:#fff;text-align:center}.carousel-dark .carousel-control-prev-icon,.carousel-dark .carousel-control-next-icon{filter:invert(1) grayscale(100)}.carousel-dark .carousel-indicators [data-bs-target]{background-color:#000}.carousel-dark .carousel-caption{color:#000}[data-bs-theme=dark] .carousel .carousel-control-prev-icon,[data-bs-theme=dark] .carousel .carousel-control-next-icon,[data-bs-theme=dark].carousel .carousel-control-prev-icon,[data-bs-theme=dark].carousel .carousel-control-next-icon{filter:invert(1) grayscale(100)}[data-bs-theme=dark] .carousel .carousel-indicators [data-bs-target],[data-bs-theme=dark].carousel .carousel-indicators [data-bs-target]{background-color:#000}[data-bs-theme=dark] .carousel .carousel-caption,[data-bs-theme=dark].carousel .carousel-caption{color:#000}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg) /* rtl:ignore */}}.spinner-border{--bs-spinner-width: 2rem;--bs-spinner-height: 2rem;--bs-spinner-vertical-align: -0.125em;--bs-spinner-border-width: 0.25em;--bs-spinner-animation-speed: 0.75s;--bs-spinner-animation-name: spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:rgba(0,0,0,0)}.spinner-border-sm{--bs-spinner-width: 1rem;--bs-spinner-height: 1rem;--bs-spinner-border-width: 0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width: 2rem;--bs-spinner-height: 2rem;--bs-spinner-vertical-align: -0.125em;--bs-spinner-animation-speed: 0.75s;--bs-spinner-animation-name: spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width: 1rem;--bs-spinner-height: 1rem}@media(prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed: 1.5s}}.offcanvas,.offcanvas-xxl,.offcanvas-xl,.offcanvas-lg,.offcanvas-md,.offcanvas-sm{--bs-offcanvas-zindex: 1045;--bs-offcanvas-width: 400px;--bs-offcanvas-height: 30vh;--bs-offcanvas-padding-x: 1rem;--bs-offcanvas-padding-y: 1rem;--bs-offcanvas-color: #212529;--bs-offcanvas-bg: #ffffff;--bs-offcanvas-border-width: 1px;--bs-offcanvas-border-color: rgba(0, 0, 0, 0.175);--bs-offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-offcanvas-transition: transform 0.3s ease-in-out;--bs-offcanvas-title-line-height: 1.5}@media(max-width: 575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 575.98px)and (prefers-reduced-motion: reduce){.offcanvas-sm{transition:none}}@media(max-width: 575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.showing,.offcanvas-sm.show:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show{visibility:visible}}@media(min-width: 576px){.offcanvas-sm{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 767.98px)and (prefers-reduced-motion: reduce){.offcanvas-md{transition:none}}@media(max-width: 767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.showing,.offcanvas-md.show:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show{visibility:visible}}@media(min-width: 768px){.offcanvas-md{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 991.98px)and (prefers-reduced-motion: reduce){.offcanvas-lg{transition:none}}@media(max-width: 991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.showing,.offcanvas-lg.show:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show{visibility:visible}}@media(min-width: 992px){.offcanvas-lg{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 1199.98px)and (prefers-reduced-motion: reduce){.offcanvas-xl{transition:none}}@media(max-width: 1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.showing,.offcanvas-xl.show:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show{visibility:visible}}@media(min-width: 1200px){.offcanvas-xl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}@media(max-width: 1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media(max-width: 1399.98px)and (prefers-reduced-motion: reduce){.offcanvas-xxl{transition:none}}@media(max-width: 1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.showing,.offcanvas-xxl.show:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show{visibility:visible}}@media(min-width: 1400px){.offcanvas-xxl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:rgba(0,0,0,0) !important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;display:-webkit-flex;flex-grow:0;-webkit-flex-grow:0;padding:0;overflow-y:visible;background-color:rgba(0,0,0,0) !important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}@media(prefers-reduced-motion: reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.showing,.offcanvas.show:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y)*.5) calc(var(--bs-offcanvas-padding-x)*.5);margin-top:calc(-0.5*var(--bs-offcanvas-padding-y));margin-right:calc(-0.5*var(--bs-offcanvas-padding-x));margin-bottom:calc(-0.5*var(--bs-offcanvas-padding-y))}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;-webkit-flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);-webkit-mask-image:linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%);mask-size:200% 100%;-webkit-mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{mask-position:-200% 0%;-webkit-mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-default{color:#000 !important;background-color:RGBA(var(--bs-default-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-primary{color:#fff !important;background-color:RGBA(var(--bs-primary-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-secondary{color:#fff !important;background-color:RGBA(var(--bs-secondary-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-success{color:#fff !important;background-color:RGBA(var(--bs-success-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-info{color:#000 !important;background-color:RGBA(var(--bs-info-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-warning{color:#000 !important;background-color:RGBA(var(--bs-warning-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-danger{color:#fff !important;background-color:RGBA(var(--bs-danger-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-light{color:#000 !important;background-color:RGBA(var(--bs-light-rgb), var(--bs-bg-opacity, 1)) !important}.text-bg-dark{color:#fff !important;background-color:RGBA(var(--bs-dark-rgb), var(--bs-bg-opacity, 1)) !important}.link-default{color:RGBA(var(--bs-default-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-default-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-default:hover,.link-default:focus{color:RGBA(229, 232, 235, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(229, 232, 235, var(--bs-link-underline-opacity, 1)) !important}.link-primary{color:RGBA(var(--bs-primary-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-primary-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-primary:hover,.link-primary:focus{color:RGBA(10, 88, 202, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(10, 88, 202, var(--bs-link-underline-opacity, 1)) !important}.link-secondary{color:RGBA(var(--bs-secondary-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-secondary-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-secondary:hover,.link-secondary:focus{color:RGBA(86, 94, 100, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(86, 94, 100, var(--bs-link-underline-opacity, 1)) !important}.link-success{color:RGBA(var(--bs-success-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-success-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-success:hover,.link-success:focus{color:RGBA(20, 108, 67, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(20, 108, 67, var(--bs-link-underline-opacity, 1)) !important}.link-info{color:RGBA(var(--bs-info-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-info-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-info:hover,.link-info:focus{color:RGBA(61, 213, 243, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(61, 213, 243, var(--bs-link-underline-opacity, 1)) !important}.link-warning{color:RGBA(var(--bs-warning-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-warning-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-warning:hover,.link-warning:focus{color:RGBA(255, 205, 57, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(255, 205, 57, var(--bs-link-underline-opacity, 1)) !important}.link-danger{color:RGBA(var(--bs-danger-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-danger-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-danger:hover,.link-danger:focus{color:RGBA(176, 42, 55, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(176, 42, 55, var(--bs-link-underline-opacity, 1)) !important}.link-light{color:RGBA(var(--bs-light-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-light-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-light:hover,.link-light:focus{color:RGBA(249, 250, 251, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(249, 250, 251, var(--bs-link-underline-opacity, 1)) !important}.link-dark{color:RGBA(var(--bs-dark-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-dark-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-dark:hover,.link-dark:focus{color:RGBA(26, 30, 33, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(26, 30, 33, var(--bs-link-underline-opacity, 1)) !important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-body-emphasis:hover,.link-body-emphasis:focus{color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-opacity, 0.75)) !important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb), var(--bs-link-underline-opacity, 0.75)) !important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0) var(--bs-focus-ring-blur, 0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;-webkit-align-items:center;text-decoration-color:rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 0.5));text-underline-offset:.25em;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;-webkit-flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media(prefers-reduced-motion: reduce){.icon-link>.bi{transition:none}}.icon-link-hover:hover>.bi,.icon-link-hover:focus-visible>.bi{transform:var(--bs-icon-link-transform, translate3d(0.25em, 0, 0))}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media(min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media(min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;display:-webkit-flex;flex-direction:row;-webkit-flex-direction:row;align-items:center;-webkit-align-items:center;align-self:stretch;-webkit-align-self:stretch}.vstack{display:flex;display:-webkit-flex;flex:1 1 auto;-webkit-flex:1 1 auto;flex-direction:column;-webkit-flex-direction:column;align-self:stretch;-webkit-align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.visually-hidden:not(caption),.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption){position:absolute !important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;-webkit-align-self:stretch;width:1px;min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.float-start{float:left !important}.float-end{float:right !important}.float-none{float:none !important}.object-fit-contain{object-fit:contain !important}.object-fit-cover{object-fit:cover !important}.object-fit-fill{object-fit:fill !important}.object-fit-scale{object-fit:scale-down !important}.object-fit-none{object-fit:none !important}.opacity-0{opacity:0 !important}.opacity-25{opacity:.25 !important}.opacity-50{opacity:.5 !important}.opacity-75{opacity:.75 !important}.opacity-100{opacity:1 !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.overflow-visible{overflow:visible !important}.overflow-scroll{overflow:scroll !important}.overflow-x-auto{overflow-x:auto !important}.overflow-x-hidden{overflow-x:hidden !important}.overflow-x-visible{overflow-x:visible !important}.overflow-x-scroll{overflow-x:scroll !important}.overflow-y-auto{overflow-y:auto !important}.overflow-y-hidden{overflow-y:hidden !important}.overflow-y-visible{overflow-y:visible !important}.overflow-y-scroll{overflow-y:scroll !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-grid{display:grid !important}.d-inline-grid{display:inline-grid !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15) !important}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175) !important}.shadow-none{box-shadow:none !important}.focus-ring-default{--bs-focus-ring-color: rgba(var(--bs-default-rgb), var(--bs-focus-ring-opacity))}.focus-ring-primary{--bs-focus-ring-color: rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color: rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color: rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color: rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color: rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color: rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color: rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color: rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.top-0{top:0 !important}.top-50{top:50% !important}.top-100{top:100% !important}.bottom-0{bottom:0 !important}.bottom-50{bottom:50% !important}.bottom-100{bottom:100% !important}.start-0{left:0 !important}.start-50{left:50% !important}.start-100{left:100% !important}.end-0{right:0 !important}.end-50{right:50% !important}.end-100{right:100% !important}.translate-middle{transform:translate(-50%, -50%) !important}.translate-middle-x{transform:translateX(-50%) !important}.translate-middle-y{transform:translateY(-50%) !important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-0{border:0 !important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-top-0{border-top:0 !important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-end-0{border-right:0 !important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-bottom-0{border-bottom:0 !important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important}.border-start-0{border-left:0 !important}.border-default{--bs-border-opacity: 1;border-color:rgba(var(--bs-default-rgb), var(--bs-border-opacity)) !important}.border-primary{--bs-border-opacity: 1;border-color:rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important}.border-secondary{--bs-border-opacity: 1;border-color:rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important}.border-success{--bs-border-opacity: 1;border-color:rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important}.border-info{--bs-border-opacity: 1;border-color:rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important}.border-warning{--bs-border-opacity: 1;border-color:rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important}.border-danger{--bs-border-opacity: 1;border-color:rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important}.border-light{--bs-border-opacity: 1;border-color:rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important}.border-dark{--bs-border-opacity: 1;border-color:rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important}.border-black{--bs-border-opacity: 1;border-color:rgba(var(--bs-black-rgb), var(--bs-border-opacity)) !important}.border-white{--bs-border-opacity: 1;border-color:rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle) !important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle) !important}.border-success-subtle{border-color:var(--bs-success-border-subtle) !important}.border-info-subtle{border-color:var(--bs-info-border-subtle) !important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle) !important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle) !important}.border-light-subtle{border-color:var(--bs-light-border-subtle) !important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle) !important}.border-1{border-width:1px !important}.border-2{border-width:2px !important}.border-3{border-width:3px !important}.border-4{border-width:4px !important}.border-5{border-width:5px !important}.border-opacity-10{--bs-border-opacity: 0.1}.border-opacity-25{--bs-border-opacity: 0.25}.border-opacity-50{--bs-border-opacity: 0.5}.border-opacity-75{--bs-border-opacity: 0.75}.border-opacity-100{--bs-border-opacity: 1}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.mw-100{max-width:100% !important}.vw-100{width:100vw !important}.min-vw-100{min-width:100vw !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mh-100{max-height:100% !important}.vh-100{height:100vh !important}.min-vh-100{min-height:100vh !important}.flex-fill{flex:1 1 auto !important}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.justify-content-evenly{justify-content:space-evenly !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}.order-first{order:-1 !important}.order-0{order:0 !important}.order-1{order:1 !important}.order-2{order:2 !important}.order-3{order:3 !important}.order-4{order:4 !important}.order-5{order:5 !important}.order-last{order:6 !important}.m-0{margin:0 !important}.m-1{margin:.25rem !important}.m-2{margin:.5rem !important}.m-3{margin:1rem !important}.m-4{margin:1.5rem !important}.m-5{margin:3rem !important}.m-auto{margin:auto !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.mx-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-3{margin-right:1rem !important;margin-left:1rem !important}.mx-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-5{margin-right:3rem !important;margin-left:3rem !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.my-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-0{margin-top:0 !important}.mt-1{margin-top:.25rem !important}.mt-2{margin-top:.5rem !important}.mt-3{margin-top:1rem !important}.mt-4{margin-top:1.5rem !important}.mt-5{margin-top:3rem !important}.mt-auto{margin-top:auto !important}.me-0{margin-right:0 !important}.me-1{margin-right:.25rem !important}.me-2{margin-right:.5rem !important}.me-3{margin-right:1rem !important}.me-4{margin-right:1.5rem !important}.me-5{margin-right:3rem !important}.me-auto{margin-right:auto !important}.mb-0{margin-bottom:0 !important}.mb-1{margin-bottom:.25rem !important}.mb-2{margin-bottom:.5rem !important}.mb-3{margin-bottom:1rem !important}.mb-4{margin-bottom:1.5rem !important}.mb-5{margin-bottom:3rem !important}.mb-auto{margin-bottom:auto !important}.ms-0{margin-left:0 !important}.ms-1{margin-left:.25rem !important}.ms-2{margin-left:.5rem !important}.ms-3{margin-left:1rem !important}.ms-4{margin-left:1.5rem !important}.ms-5{margin-left:3rem !important}.ms-auto{margin-left:auto !important}.p-0{padding:0 !important}.p-1{padding:.25rem !important}.p-2{padding:.5rem !important}.p-3{padding:1rem !important}.p-4{padding:1.5rem !important}.p-5{padding:3rem !important}.px-0{padding-right:0 !important;padding-left:0 !important}.px-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-3{padding-right:1rem !important;padding-left:1rem !important}.px-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-5{padding-right:3rem !important;padding-left:3rem !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.py-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-0{padding-top:0 !important}.pt-1{padding-top:.25rem !important}.pt-2{padding-top:.5rem !important}.pt-3{padding-top:1rem !important}.pt-4{padding-top:1.5rem !important}.pt-5{padding-top:3rem !important}.pe-0{padding-right:0 !important}.pe-1{padding-right:.25rem !important}.pe-2{padding-right:.5rem !important}.pe-3{padding-right:1rem !important}.pe-4{padding-right:1.5rem !important}.pe-5{padding-right:3rem !important}.pb-0{padding-bottom:0 !important}.pb-1{padding-bottom:.25rem !important}.pb-2{padding-bottom:.5rem !important}.pb-3{padding-bottom:1rem !important}.pb-4{padding-bottom:1.5rem !important}.pb-5{padding-bottom:3rem !important}.ps-0{padding-left:0 !important}.ps-1{padding-left:.25rem !important}.ps-2{padding-left:.5rem !important}.ps-3{padding-left:1rem !important}.ps-4{padding-left:1.5rem !important}.ps-5{padding-left:3rem !important}.gap-0{gap:0 !important}.gap-1{gap:.25rem !important}.gap-2{gap:.5rem !important}.gap-3{gap:1rem !important}.gap-4{gap:1.5rem !important}.gap-5{gap:3rem !important}.row-gap-0{row-gap:0 !important}.row-gap-1{row-gap:.25rem !important}.row-gap-2{row-gap:.5rem !important}.row-gap-3{row-gap:1rem !important}.row-gap-4{row-gap:1.5rem !important}.row-gap-5{row-gap:3rem !important}.column-gap-0{column-gap:0 !important}.column-gap-1{column-gap:.25rem !important}.column-gap-2{column-gap:.5rem !important}.column-gap-3{column-gap:1rem !important}.column-gap-4{column-gap:1.5rem !important}.column-gap-5{column-gap:3rem !important}.font-monospace{font-family:var(--bs-font-monospace) !important}.fs-1{font-size:calc(1.325rem + 0.9vw) !important}.fs-2{font-size:calc(1.29rem + 0.48vw) !important}.fs-3{font-size:calc(1.27rem + 0.24vw) !important}.fs-4{font-size:1.25rem !important}.fs-5{font-size:1.1rem !important}.fs-6{font-size:1rem !important}.fst-italic{font-style:italic !important}.fst-normal{font-style:normal !important}.fw-lighter{font-weight:lighter !important}.fw-light{font-weight:300 !important}.fw-normal{font-weight:400 !important}.fw-medium{font-weight:500 !important}.fw-semibold{font-weight:600 !important}.fw-bold{font-weight:700 !important}.fw-bolder{font-weight:bolder !important}.lh-1{line-height:1 !important}.lh-sm{line-height:1.25 !important}.lh-base{line-height:1.5 !important}.lh-lg{line-height:2 !important}.text-start{text-align:left !important}.text-end{text-align:right !important}.text-center{text-align:center !important}.text-decoration-none{text-decoration:none !important}.text-decoration-underline{text-decoration:underline !important}.text-decoration-line-through{text-decoration:line-through !important}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-break{word-wrap:break-word !important;word-break:break-word !important}.text-default{--bs-text-opacity: 1;color:rgba(var(--bs-default-rgb), var(--bs-text-opacity)) !important}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important}.text-secondary{--bs-text-opacity: 1;color:rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important}.text-success{--bs-text-opacity: 1;color:rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important}.text-info{--bs-text-opacity: 1;color:rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important}.text-warning{--bs-text-opacity: 1;color:rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important}.text-danger{--bs-text-opacity: 1;color:rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important}.text-light{--bs-text-opacity: 1;color:rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important}.text-dark{--bs-text-opacity: 1;color:rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important}.text-black{--bs-text-opacity: 1;color:rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important}.text-white{--bs-text-opacity: 1;color:rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important}.text-body{--bs-text-opacity: 1;color:rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color) !important}.text-black-50{--bs-text-opacity: 1;color:rgba(0,0,0,.5) !important}.text-white-50{--bs-text-opacity: 1;color:hsla(0,0%,100%,.5) !important}.text-body-secondary{--bs-text-opacity: 1;color:var(--bs-secondary-color) !important}.text-body-tertiary{--bs-text-opacity: 1;color:var(--bs-tertiary-color) !important}.text-body-emphasis{--bs-text-opacity: 1;color:var(--bs-emphasis-color) !important}.text-reset{--bs-text-opacity: 1;color:inherit !important}.text-opacity-25{--bs-text-opacity: 0.25}.text-opacity-50{--bs-text-opacity: 0.5}.text-opacity-75{--bs-text-opacity: 0.75}.text-opacity-100{--bs-text-opacity: 1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis) !important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis) !important}.text-success-emphasis{color:var(--bs-success-text-emphasis) !important}.text-info-emphasis{color:var(--bs-info-text-emphasis) !important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis) !important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis) !important}.text-light-emphasis{color:var(--bs-light-text-emphasis) !important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis) !important}.link-opacity-10{--bs-link-opacity: 0.1}.link-opacity-10-hover:hover{--bs-link-opacity: 0.1}.link-opacity-25{--bs-link-opacity: 0.25}.link-opacity-25-hover:hover{--bs-link-opacity: 0.25}.link-opacity-50{--bs-link-opacity: 0.5}.link-opacity-50-hover:hover{--bs-link-opacity: 0.5}.link-opacity-75{--bs-link-opacity: 0.75}.link-opacity-75-hover:hover{--bs-link-opacity: 0.75}.link-opacity-100{--bs-link-opacity: 1}.link-opacity-100-hover:hover{--bs-link-opacity: 1}.link-offset-1{text-underline-offset:.125em !important}.link-offset-1-hover:hover{text-underline-offset:.125em !important}.link-offset-2{text-underline-offset:.25em !important}.link-offset-2-hover:hover{text-underline-offset:.25em !important}.link-offset-3{text-underline-offset:.375em !important}.link-offset-3-hover:hover{text-underline-offset:.375em !important}.link-underline-default{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-default-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-primary{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-primary-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-secondary{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-secondary-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-success{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-success-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-info{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-info-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-warning{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-warning-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-danger{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-danger-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-light{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-light-rgb), var(--bs-link-underline-opacity)) !important}.link-underline-dark{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-dark-rgb), var(--bs-link-underline-opacity)) !important}.link-underline{--bs-link-underline-opacity: 1;text-decoration-color:rgba(var(--bs-link-color-rgb), var(--bs-link-underline-opacity, 1)) !important}.link-underline-opacity-0{--bs-link-underline-opacity: 0}.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity: 0}.link-underline-opacity-10{--bs-link-underline-opacity: 0.1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity: 0.1}.link-underline-opacity-25{--bs-link-underline-opacity: 0.25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity: 0.25}.link-underline-opacity-50{--bs-link-underline-opacity: 0.5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity: 0.5}.link-underline-opacity-75{--bs-link-underline-opacity: 0.75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity: 0.75}.link-underline-opacity-100{--bs-link-underline-opacity: 1}.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity: 1}.bg-default{--bs-bg-opacity: 1;background-color:rgba(var(--bs-default-rgb), var(--bs-bg-opacity)) !important}.bg-primary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important}.bg-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important}.bg-success{--bs-bg-opacity: 1;background-color:rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important}.bg-info{--bs-bg-opacity: 1;background-color:rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important}.bg-warning{--bs-bg-opacity: 1;background-color:rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important}.bg-danger{--bs-bg-opacity: 1;background-color:rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important}.bg-light{--bs-bg-opacity: 1;background-color:rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important}.bg-dark{--bs-bg-opacity: 1;background-color:rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important}.bg-black{--bs-bg-opacity: 1;background-color:rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important}.bg-white{--bs-bg-opacity: 1;background-color:rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important}.bg-body{--bs-bg-opacity: 1;background-color:rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important}.bg-transparent{--bs-bg-opacity: 1;background-color:rgba(0,0,0,0) !important}.bg-body-secondary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-secondary-bg-rgb), var(--bs-bg-opacity)) !important}.bg-body-tertiary{--bs-bg-opacity: 1;background-color:rgba(var(--bs-tertiary-bg-rgb), var(--bs-bg-opacity)) !important}.bg-opacity-10{--bs-bg-opacity: 0.1}.bg-opacity-25{--bs-bg-opacity: 0.25}.bg-opacity-50{--bs-bg-opacity: 0.5}.bg-opacity-75{--bs-bg-opacity: 0.75}.bg-opacity-100{--bs-bg-opacity: 1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle) !important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle) !important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle) !important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle) !important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle) !important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle) !important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle) !important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle) !important}.bg-gradient{background-image:var(--bs-gradient) !important}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.pe-none{pointer-events:none !important}.pe-auto{pointer-events:auto !important}.rounded{border-radius:var(--bs-border-radius) !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:var(--bs-border-radius-sm) !important}.rounded-2{border-radius:var(--bs-border-radius) !important}.rounded-3{border-radius:var(--bs-border-radius-lg) !important}.rounded-4{border-radius:var(--bs-border-radius-xl) !important}.rounded-5{border-radius:var(--bs-border-radius-xxl) !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:var(--bs-border-radius-pill) !important}.rounded-top{border-top-left-radius:var(--bs-border-radius) !important;border-top-right-radius:var(--bs-border-radius) !important}.rounded-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm) !important;border-top-right-radius:var(--bs-border-radius-sm) !important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius) !important;border-top-right-radius:var(--bs-border-radius) !important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg) !important;border-top-right-radius:var(--bs-border-radius-lg) !important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl) !important;border-top-right-radius:var(--bs-border-radius-xl) !important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl) !important;border-top-right-radius:var(--bs-border-radius-xxl) !important}.rounded-top-circle{border-top-left-radius:50% !important;border-top-right-radius:50% !important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill) !important;border-top-right-radius:var(--bs-border-radius-pill) !important}.rounded-end{border-top-right-radius:var(--bs-border-radius) !important;border-bottom-right-radius:var(--bs-border-radius) !important}.rounded-end-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm) !important;border-bottom-right-radius:var(--bs-border-radius-sm) !important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius) !important;border-bottom-right-radius:var(--bs-border-radius) !important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg) !important;border-bottom-right-radius:var(--bs-border-radius-lg) !important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl) !important;border-bottom-right-radius:var(--bs-border-radius-xl) !important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl) !important;border-bottom-right-radius:var(--bs-border-radius-xxl) !important}.rounded-end-circle{border-top-right-radius:50% !important;border-bottom-right-radius:50% !important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill) !important;border-bottom-right-radius:var(--bs-border-radius-pill) !important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius) !important;border-bottom-left-radius:var(--bs-border-radius) !important}.rounded-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm) !important;border-bottom-left-radius:var(--bs-border-radius-sm) !important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius) !important;border-bottom-left-radius:var(--bs-border-radius) !important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg) !important;border-bottom-left-radius:var(--bs-border-radius-lg) !important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl) !important;border-bottom-left-radius:var(--bs-border-radius-xl) !important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl) !important;border-bottom-left-radius:var(--bs-border-radius-xxl) !important}.rounded-bottom-circle{border-bottom-right-radius:50% !important;border-bottom-left-radius:50% !important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill) !important;border-bottom-left-radius:var(--bs-border-radius-pill) !important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius) !important;border-top-left-radius:var(--bs-border-radius) !important}.rounded-start-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm) !important;border-top-left-radius:var(--bs-border-radius-sm) !important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius) !important;border-top-left-radius:var(--bs-border-radius) !important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg) !important;border-top-left-radius:var(--bs-border-radius-lg) !important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl) !important;border-top-left-radius:var(--bs-border-radius-xl) !important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl) !important;border-top-left-radius:var(--bs-border-radius-xxl) !important}.rounded-start-circle{border-bottom-left-radius:50% !important;border-top-left-radius:50% !important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill) !important;border-top-left-radius:var(--bs-border-radius-pill) !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}.z-n1{z-index:-1 !important}.z-0{z-index:0 !important}.z-1{z-index:1 !important}.z-2{z-index:2 !important}.z-3{z-index:3 !important}@media(min-width: 576px){.float-sm-start{float:left !important}.float-sm-end{float:right !important}.float-sm-none{float:none !important}.object-fit-sm-contain{object-fit:contain !important}.object-fit-sm-cover{object-fit:cover !important}.object-fit-sm-fill{object-fit:fill !important}.object-fit-sm-scale{object-fit:scale-down !important}.object-fit-sm-none{object-fit:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-grid{display:grid !important}.d-sm-inline-grid{display:inline-grid !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.justify-content-sm-evenly{justify-content:space-evenly !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}.order-sm-first{order:-1 !important}.order-sm-0{order:0 !important}.order-sm-1{order:1 !important}.order-sm-2{order:2 !important}.order-sm-3{order:3 !important}.order-sm-4{order:4 !important}.order-sm-5{order:5 !important}.order-sm-last{order:6 !important}.m-sm-0{margin:0 !important}.m-sm-1{margin:.25rem !important}.m-sm-2{margin:.5rem !important}.m-sm-3{margin:1rem !important}.m-sm-4{margin:1.5rem !important}.m-sm-5{margin:3rem !important}.m-sm-auto{margin:auto !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.mx-sm-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-sm-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-sm-3{margin-right:1rem !important;margin-left:1rem !important}.mx-sm-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-sm-5{margin-right:3rem !important;margin-left:3rem !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.my-sm-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-sm-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-sm-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-sm-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-sm-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-sm-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-sm-0{margin-top:0 !important}.mt-sm-1{margin-top:.25rem !important}.mt-sm-2{margin-top:.5rem !important}.mt-sm-3{margin-top:1rem !important}.mt-sm-4{margin-top:1.5rem !important}.mt-sm-5{margin-top:3rem !important}.mt-sm-auto{margin-top:auto !important}.me-sm-0{margin-right:0 !important}.me-sm-1{margin-right:.25rem !important}.me-sm-2{margin-right:.5rem !important}.me-sm-3{margin-right:1rem !important}.me-sm-4{margin-right:1.5rem !important}.me-sm-5{margin-right:3rem !important}.me-sm-auto{margin-right:auto !important}.mb-sm-0{margin-bottom:0 !important}.mb-sm-1{margin-bottom:.25rem !important}.mb-sm-2{margin-bottom:.5rem !important}.mb-sm-3{margin-bottom:1rem !important}.mb-sm-4{margin-bottom:1.5rem !important}.mb-sm-5{margin-bottom:3rem !important}.mb-sm-auto{margin-bottom:auto !important}.ms-sm-0{margin-left:0 !important}.ms-sm-1{margin-left:.25rem !important}.ms-sm-2{margin-left:.5rem !important}.ms-sm-3{margin-left:1rem !important}.ms-sm-4{margin-left:1.5rem !important}.ms-sm-5{margin-left:3rem !important}.ms-sm-auto{margin-left:auto !important}.p-sm-0{padding:0 !important}.p-sm-1{padding:.25rem !important}.p-sm-2{padding:.5rem !important}.p-sm-3{padding:1rem !important}.p-sm-4{padding:1.5rem !important}.p-sm-5{padding:3rem !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.px-sm-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-sm-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-sm-3{padding-right:1rem !important;padding-left:1rem !important}.px-sm-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-sm-5{padding-right:3rem !important;padding-left:3rem !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.py-sm-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-sm-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-sm-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-sm-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-sm-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-sm-0{padding-top:0 !important}.pt-sm-1{padding-top:.25rem !important}.pt-sm-2{padding-top:.5rem !important}.pt-sm-3{padding-top:1rem !important}.pt-sm-4{padding-top:1.5rem !important}.pt-sm-5{padding-top:3rem !important}.pe-sm-0{padding-right:0 !important}.pe-sm-1{padding-right:.25rem !important}.pe-sm-2{padding-right:.5rem !important}.pe-sm-3{padding-right:1rem !important}.pe-sm-4{padding-right:1.5rem !important}.pe-sm-5{padding-right:3rem !important}.pb-sm-0{padding-bottom:0 !important}.pb-sm-1{padding-bottom:.25rem !important}.pb-sm-2{padding-bottom:.5rem !important}.pb-sm-3{padding-bottom:1rem !important}.pb-sm-4{padding-bottom:1.5rem !important}.pb-sm-5{padding-bottom:3rem !important}.ps-sm-0{padding-left:0 !important}.ps-sm-1{padding-left:.25rem !important}.ps-sm-2{padding-left:.5rem !important}.ps-sm-3{padding-left:1rem !important}.ps-sm-4{padding-left:1.5rem !important}.ps-sm-5{padding-left:3rem !important}.gap-sm-0{gap:0 !important}.gap-sm-1{gap:.25rem !important}.gap-sm-2{gap:.5rem !important}.gap-sm-3{gap:1rem !important}.gap-sm-4{gap:1.5rem !important}.gap-sm-5{gap:3rem !important}.row-gap-sm-0{row-gap:0 !important}.row-gap-sm-1{row-gap:.25rem !important}.row-gap-sm-2{row-gap:.5rem !important}.row-gap-sm-3{row-gap:1rem !important}.row-gap-sm-4{row-gap:1.5rem !important}.row-gap-sm-5{row-gap:3rem !important}.column-gap-sm-0{column-gap:0 !important}.column-gap-sm-1{column-gap:.25rem !important}.column-gap-sm-2{column-gap:.5rem !important}.column-gap-sm-3{column-gap:1rem !important}.column-gap-sm-4{column-gap:1.5rem !important}.column-gap-sm-5{column-gap:3rem !important}.text-sm-start{text-align:left !important}.text-sm-end{text-align:right !important}.text-sm-center{text-align:center !important}}@media(min-width: 768px){.float-md-start{float:left !important}.float-md-end{float:right !important}.float-md-none{float:none !important}.object-fit-md-contain{object-fit:contain !important}.object-fit-md-cover{object-fit:cover !important}.object-fit-md-fill{object-fit:fill !important}.object-fit-md-scale{object-fit:scale-down !important}.object-fit-md-none{object-fit:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-grid{display:grid !important}.d-md-inline-grid{display:inline-grid !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.justify-content-md-evenly{justify-content:space-evenly !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}.order-md-first{order:-1 !important}.order-md-0{order:0 !important}.order-md-1{order:1 !important}.order-md-2{order:2 !important}.order-md-3{order:3 !important}.order-md-4{order:4 !important}.order-md-5{order:5 !important}.order-md-last{order:6 !important}.m-md-0{margin:0 !important}.m-md-1{margin:.25rem !important}.m-md-2{margin:.5rem !important}.m-md-3{margin:1rem !important}.m-md-4{margin:1.5rem !important}.m-md-5{margin:3rem !important}.m-md-auto{margin:auto !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.mx-md-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-md-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-md-3{margin-right:1rem !important;margin-left:1rem !important}.mx-md-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-md-5{margin-right:3rem !important;margin-left:3rem !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.my-md-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-md-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-md-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-md-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-md-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-md-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-md-0{margin-top:0 !important}.mt-md-1{margin-top:.25rem !important}.mt-md-2{margin-top:.5rem !important}.mt-md-3{margin-top:1rem !important}.mt-md-4{margin-top:1.5rem !important}.mt-md-5{margin-top:3rem !important}.mt-md-auto{margin-top:auto !important}.me-md-0{margin-right:0 !important}.me-md-1{margin-right:.25rem !important}.me-md-2{margin-right:.5rem !important}.me-md-3{margin-right:1rem !important}.me-md-4{margin-right:1.5rem !important}.me-md-5{margin-right:3rem !important}.me-md-auto{margin-right:auto !important}.mb-md-0{margin-bottom:0 !important}.mb-md-1{margin-bottom:.25rem !important}.mb-md-2{margin-bottom:.5rem !important}.mb-md-3{margin-bottom:1rem !important}.mb-md-4{margin-bottom:1.5rem !important}.mb-md-5{margin-bottom:3rem !important}.mb-md-auto{margin-bottom:auto !important}.ms-md-0{margin-left:0 !important}.ms-md-1{margin-left:.25rem !important}.ms-md-2{margin-left:.5rem !important}.ms-md-3{margin-left:1rem !important}.ms-md-4{margin-left:1.5rem !important}.ms-md-5{margin-left:3rem !important}.ms-md-auto{margin-left:auto !important}.p-md-0{padding:0 !important}.p-md-1{padding:.25rem !important}.p-md-2{padding:.5rem !important}.p-md-3{padding:1rem !important}.p-md-4{padding:1.5rem !important}.p-md-5{padding:3rem !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.px-md-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-md-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-md-3{padding-right:1rem !important;padding-left:1rem !important}.px-md-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-md-5{padding-right:3rem !important;padding-left:3rem !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.py-md-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-md-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-md-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-md-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-md-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-md-0{padding-top:0 !important}.pt-md-1{padding-top:.25rem !important}.pt-md-2{padding-top:.5rem !important}.pt-md-3{padding-top:1rem !important}.pt-md-4{padding-top:1.5rem !important}.pt-md-5{padding-top:3rem !important}.pe-md-0{padding-right:0 !important}.pe-md-1{padding-right:.25rem !important}.pe-md-2{padding-right:.5rem !important}.pe-md-3{padding-right:1rem !important}.pe-md-4{padding-right:1.5rem !important}.pe-md-5{padding-right:3rem !important}.pb-md-0{padding-bottom:0 !important}.pb-md-1{padding-bottom:.25rem !important}.pb-md-2{padding-bottom:.5rem !important}.pb-md-3{padding-bottom:1rem !important}.pb-md-4{padding-bottom:1.5rem !important}.pb-md-5{padding-bottom:3rem !important}.ps-md-0{padding-left:0 !important}.ps-md-1{padding-left:.25rem !important}.ps-md-2{padding-left:.5rem !important}.ps-md-3{padding-left:1rem !important}.ps-md-4{padding-left:1.5rem !important}.ps-md-5{padding-left:3rem !important}.gap-md-0{gap:0 !important}.gap-md-1{gap:.25rem !important}.gap-md-2{gap:.5rem !important}.gap-md-3{gap:1rem !important}.gap-md-4{gap:1.5rem !important}.gap-md-5{gap:3rem !important}.row-gap-md-0{row-gap:0 !important}.row-gap-md-1{row-gap:.25rem !important}.row-gap-md-2{row-gap:.5rem !important}.row-gap-md-3{row-gap:1rem !important}.row-gap-md-4{row-gap:1.5rem !important}.row-gap-md-5{row-gap:3rem !important}.column-gap-md-0{column-gap:0 !important}.column-gap-md-1{column-gap:.25rem !important}.column-gap-md-2{column-gap:.5rem !important}.column-gap-md-3{column-gap:1rem !important}.column-gap-md-4{column-gap:1.5rem !important}.column-gap-md-5{column-gap:3rem !important}.text-md-start{text-align:left !important}.text-md-end{text-align:right !important}.text-md-center{text-align:center !important}}@media(min-width: 992px){.float-lg-start{float:left !important}.float-lg-end{float:right !important}.float-lg-none{float:none !important}.object-fit-lg-contain{object-fit:contain !important}.object-fit-lg-cover{object-fit:cover !important}.object-fit-lg-fill{object-fit:fill !important}.object-fit-lg-scale{object-fit:scale-down !important}.object-fit-lg-none{object-fit:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-grid{display:grid !important}.d-lg-inline-grid{display:inline-grid !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.justify-content-lg-evenly{justify-content:space-evenly !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}.order-lg-first{order:-1 !important}.order-lg-0{order:0 !important}.order-lg-1{order:1 !important}.order-lg-2{order:2 !important}.order-lg-3{order:3 !important}.order-lg-4{order:4 !important}.order-lg-5{order:5 !important}.order-lg-last{order:6 !important}.m-lg-0{margin:0 !important}.m-lg-1{margin:.25rem !important}.m-lg-2{margin:.5rem !important}.m-lg-3{margin:1rem !important}.m-lg-4{margin:1.5rem !important}.m-lg-5{margin:3rem !important}.m-lg-auto{margin:auto !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.mx-lg-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-lg-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-lg-3{margin-right:1rem !important;margin-left:1rem !important}.mx-lg-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-lg-5{margin-right:3rem !important;margin-left:3rem !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.my-lg-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-lg-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-lg-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-lg-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-lg-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-lg-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-lg-0{margin-top:0 !important}.mt-lg-1{margin-top:.25rem !important}.mt-lg-2{margin-top:.5rem !important}.mt-lg-3{margin-top:1rem !important}.mt-lg-4{margin-top:1.5rem !important}.mt-lg-5{margin-top:3rem !important}.mt-lg-auto{margin-top:auto !important}.me-lg-0{margin-right:0 !important}.me-lg-1{margin-right:.25rem !important}.me-lg-2{margin-right:.5rem !important}.me-lg-3{margin-right:1rem !important}.me-lg-4{margin-right:1.5rem !important}.me-lg-5{margin-right:3rem !important}.me-lg-auto{margin-right:auto !important}.mb-lg-0{margin-bottom:0 !important}.mb-lg-1{margin-bottom:.25rem !important}.mb-lg-2{margin-bottom:.5rem !important}.mb-lg-3{margin-bottom:1rem !important}.mb-lg-4{margin-bottom:1.5rem !important}.mb-lg-5{margin-bottom:3rem !important}.mb-lg-auto{margin-bottom:auto !important}.ms-lg-0{margin-left:0 !important}.ms-lg-1{margin-left:.25rem !important}.ms-lg-2{margin-left:.5rem !important}.ms-lg-3{margin-left:1rem !important}.ms-lg-4{margin-left:1.5rem !important}.ms-lg-5{margin-left:3rem !important}.ms-lg-auto{margin-left:auto !important}.p-lg-0{padding:0 !important}.p-lg-1{padding:.25rem !important}.p-lg-2{padding:.5rem !important}.p-lg-3{padding:1rem !important}.p-lg-4{padding:1.5rem !important}.p-lg-5{padding:3rem !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.px-lg-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-lg-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-lg-3{padding-right:1rem !important;padding-left:1rem !important}.px-lg-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-lg-5{padding-right:3rem !important;padding-left:3rem !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.py-lg-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-lg-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-lg-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-lg-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-lg-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-lg-0{padding-top:0 !important}.pt-lg-1{padding-top:.25rem !important}.pt-lg-2{padding-top:.5rem !important}.pt-lg-3{padding-top:1rem !important}.pt-lg-4{padding-top:1.5rem !important}.pt-lg-5{padding-top:3rem !important}.pe-lg-0{padding-right:0 !important}.pe-lg-1{padding-right:.25rem !important}.pe-lg-2{padding-right:.5rem !important}.pe-lg-3{padding-right:1rem !important}.pe-lg-4{padding-right:1.5rem !important}.pe-lg-5{padding-right:3rem !important}.pb-lg-0{padding-bottom:0 !important}.pb-lg-1{padding-bottom:.25rem !important}.pb-lg-2{padding-bottom:.5rem !important}.pb-lg-3{padding-bottom:1rem !important}.pb-lg-4{padding-bottom:1.5rem !important}.pb-lg-5{padding-bottom:3rem !important}.ps-lg-0{padding-left:0 !important}.ps-lg-1{padding-left:.25rem !important}.ps-lg-2{padding-left:.5rem !important}.ps-lg-3{padding-left:1rem !important}.ps-lg-4{padding-left:1.5rem !important}.ps-lg-5{padding-left:3rem !important}.gap-lg-0{gap:0 !important}.gap-lg-1{gap:.25rem !important}.gap-lg-2{gap:.5rem !important}.gap-lg-3{gap:1rem !important}.gap-lg-4{gap:1.5rem !important}.gap-lg-5{gap:3rem !important}.row-gap-lg-0{row-gap:0 !important}.row-gap-lg-1{row-gap:.25rem !important}.row-gap-lg-2{row-gap:.5rem !important}.row-gap-lg-3{row-gap:1rem !important}.row-gap-lg-4{row-gap:1.5rem !important}.row-gap-lg-5{row-gap:3rem !important}.column-gap-lg-0{column-gap:0 !important}.column-gap-lg-1{column-gap:.25rem !important}.column-gap-lg-2{column-gap:.5rem !important}.column-gap-lg-3{column-gap:1rem !important}.column-gap-lg-4{column-gap:1.5rem !important}.column-gap-lg-5{column-gap:3rem !important}.text-lg-start{text-align:left !important}.text-lg-end{text-align:right !important}.text-lg-center{text-align:center !important}}@media(min-width: 1200px){.float-xl-start{float:left !important}.float-xl-end{float:right !important}.float-xl-none{float:none !important}.object-fit-xl-contain{object-fit:contain !important}.object-fit-xl-cover{object-fit:cover !important}.object-fit-xl-fill{object-fit:fill !important}.object-fit-xl-scale{object-fit:scale-down !important}.object-fit-xl-none{object-fit:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-grid{display:grid !important}.d-xl-inline-grid{display:inline-grid !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.justify-content-xl-evenly{justify-content:space-evenly !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}.order-xl-first{order:-1 !important}.order-xl-0{order:0 !important}.order-xl-1{order:1 !important}.order-xl-2{order:2 !important}.order-xl-3{order:3 !important}.order-xl-4{order:4 !important}.order-xl-5{order:5 !important}.order-xl-last{order:6 !important}.m-xl-0{margin:0 !important}.m-xl-1{margin:.25rem !important}.m-xl-2{margin:.5rem !important}.m-xl-3{margin:1rem !important}.m-xl-4{margin:1.5rem !important}.m-xl-5{margin:3rem !important}.m-xl-auto{margin:auto !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.mx-xl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xl-0{margin-top:0 !important}.mt-xl-1{margin-top:.25rem !important}.mt-xl-2{margin-top:.5rem !important}.mt-xl-3{margin-top:1rem !important}.mt-xl-4{margin-top:1.5rem !important}.mt-xl-5{margin-top:3rem !important}.mt-xl-auto{margin-top:auto !important}.me-xl-0{margin-right:0 !important}.me-xl-1{margin-right:.25rem !important}.me-xl-2{margin-right:.5rem !important}.me-xl-3{margin-right:1rem !important}.me-xl-4{margin-right:1.5rem !important}.me-xl-5{margin-right:3rem !important}.me-xl-auto{margin-right:auto !important}.mb-xl-0{margin-bottom:0 !important}.mb-xl-1{margin-bottom:.25rem !important}.mb-xl-2{margin-bottom:.5rem !important}.mb-xl-3{margin-bottom:1rem !important}.mb-xl-4{margin-bottom:1.5rem !important}.mb-xl-5{margin-bottom:3rem !important}.mb-xl-auto{margin-bottom:auto !important}.ms-xl-0{margin-left:0 !important}.ms-xl-1{margin-left:.25rem !important}.ms-xl-2{margin-left:.5rem !important}.ms-xl-3{margin-left:1rem !important}.ms-xl-4{margin-left:1.5rem !important}.ms-xl-5{margin-left:3rem !important}.ms-xl-auto{margin-left:auto !important}.p-xl-0{padding:0 !important}.p-xl-1{padding:.25rem !important}.p-xl-2{padding:.5rem !important}.p-xl-3{padding:1rem !important}.p-xl-4{padding:1.5rem !important}.p-xl-5{padding:3rem !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.px-xl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xl-0{padding-top:0 !important}.pt-xl-1{padding-top:.25rem !important}.pt-xl-2{padding-top:.5rem !important}.pt-xl-3{padding-top:1rem !important}.pt-xl-4{padding-top:1.5rem !important}.pt-xl-5{padding-top:3rem !important}.pe-xl-0{padding-right:0 !important}.pe-xl-1{padding-right:.25rem !important}.pe-xl-2{padding-right:.5rem !important}.pe-xl-3{padding-right:1rem !important}.pe-xl-4{padding-right:1.5rem !important}.pe-xl-5{padding-right:3rem !important}.pb-xl-0{padding-bottom:0 !important}.pb-xl-1{padding-bottom:.25rem !important}.pb-xl-2{padding-bottom:.5rem !important}.pb-xl-3{padding-bottom:1rem !important}.pb-xl-4{padding-bottom:1.5rem !important}.pb-xl-5{padding-bottom:3rem !important}.ps-xl-0{padding-left:0 !important}.ps-xl-1{padding-left:.25rem !important}.ps-xl-2{padding-left:.5rem !important}.ps-xl-3{padding-left:1rem !important}.ps-xl-4{padding-left:1.5rem !important}.ps-xl-5{padding-left:3rem !important}.gap-xl-0{gap:0 !important}.gap-xl-1{gap:.25rem !important}.gap-xl-2{gap:.5rem !important}.gap-xl-3{gap:1rem !important}.gap-xl-4{gap:1.5rem !important}.gap-xl-5{gap:3rem !important}.row-gap-xl-0{row-gap:0 !important}.row-gap-xl-1{row-gap:.25rem !important}.row-gap-xl-2{row-gap:.5rem !important}.row-gap-xl-3{row-gap:1rem !important}.row-gap-xl-4{row-gap:1.5rem !important}.row-gap-xl-5{row-gap:3rem !important}.column-gap-xl-0{column-gap:0 !important}.column-gap-xl-1{column-gap:.25rem !important}.column-gap-xl-2{column-gap:.5rem !important}.column-gap-xl-3{column-gap:1rem !important}.column-gap-xl-4{column-gap:1.5rem !important}.column-gap-xl-5{column-gap:3rem !important}.text-xl-start{text-align:left !important}.text-xl-end{text-align:right !important}.text-xl-center{text-align:center !important}}@media(min-width: 1400px){.float-xxl-start{float:left !important}.float-xxl-end{float:right !important}.float-xxl-none{float:none !important}.object-fit-xxl-contain{object-fit:contain !important}.object-fit-xxl-cover{object-fit:cover !important}.object-fit-xxl-fill{object-fit:fill !important}.object-fit-xxl-scale{object-fit:scale-down !important}.object-fit-xxl-none{object-fit:none !important}.d-xxl-inline{display:inline !important}.d-xxl-inline-block{display:inline-block !important}.d-xxl-block{display:block !important}.d-xxl-grid{display:grid !important}.d-xxl-inline-grid{display:inline-grid !important}.d-xxl-table{display:table !important}.d-xxl-table-row{display:table-row !important}.d-xxl-table-cell{display:table-cell !important}.d-xxl-flex{display:flex !important}.d-xxl-inline-flex{display:inline-flex !important}.d-xxl-none{display:none !important}.flex-xxl-fill{flex:1 1 auto !important}.flex-xxl-row{flex-direction:row !important}.flex-xxl-column{flex-direction:column !important}.flex-xxl-row-reverse{flex-direction:row-reverse !important}.flex-xxl-column-reverse{flex-direction:column-reverse !important}.flex-xxl-grow-0{flex-grow:0 !important}.flex-xxl-grow-1{flex-grow:1 !important}.flex-xxl-shrink-0{flex-shrink:0 !important}.flex-xxl-shrink-1{flex-shrink:1 !important}.flex-xxl-wrap{flex-wrap:wrap !important}.flex-xxl-nowrap{flex-wrap:nowrap !important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse !important}.justify-content-xxl-start{justify-content:flex-start !important}.justify-content-xxl-end{justify-content:flex-end !important}.justify-content-xxl-center{justify-content:center !important}.justify-content-xxl-between{justify-content:space-between !important}.justify-content-xxl-around{justify-content:space-around !important}.justify-content-xxl-evenly{justify-content:space-evenly !important}.align-items-xxl-start{align-items:flex-start !important}.align-items-xxl-end{align-items:flex-end !important}.align-items-xxl-center{align-items:center !important}.align-items-xxl-baseline{align-items:baseline !important}.align-items-xxl-stretch{align-items:stretch !important}.align-content-xxl-start{align-content:flex-start !important}.align-content-xxl-end{align-content:flex-end !important}.align-content-xxl-center{align-content:center !important}.align-content-xxl-between{align-content:space-between !important}.align-content-xxl-around{align-content:space-around !important}.align-content-xxl-stretch{align-content:stretch !important}.align-self-xxl-auto{align-self:auto !important}.align-self-xxl-start{align-self:flex-start !important}.align-self-xxl-end{align-self:flex-end !important}.align-self-xxl-center{align-self:center !important}.align-self-xxl-baseline{align-self:baseline !important}.align-self-xxl-stretch{align-self:stretch !important}.order-xxl-first{order:-1 !important}.order-xxl-0{order:0 !important}.order-xxl-1{order:1 !important}.order-xxl-2{order:2 !important}.order-xxl-3{order:3 !important}.order-xxl-4{order:4 !important}.order-xxl-5{order:5 !important}.order-xxl-last{order:6 !important}.m-xxl-0{margin:0 !important}.m-xxl-1{margin:.25rem !important}.m-xxl-2{margin:.5rem !important}.m-xxl-3{margin:1rem !important}.m-xxl-4{margin:1.5rem !important}.m-xxl-5{margin:3rem !important}.m-xxl-auto{margin:auto !important}.mx-xxl-0{margin-right:0 !important;margin-left:0 !important}.mx-xxl-1{margin-right:.25rem !important;margin-left:.25rem !important}.mx-xxl-2{margin-right:.5rem !important;margin-left:.5rem !important}.mx-xxl-3{margin-right:1rem !important;margin-left:1rem !important}.mx-xxl-4{margin-right:1.5rem !important;margin-left:1.5rem !important}.mx-xxl-5{margin-right:3rem !important;margin-left:3rem !important}.mx-xxl-auto{margin-right:auto !important;margin-left:auto !important}.my-xxl-0{margin-top:0 !important;margin-bottom:0 !important}.my-xxl-1{margin-top:.25rem !important;margin-bottom:.25rem !important}.my-xxl-2{margin-top:.5rem !important;margin-bottom:.5rem !important}.my-xxl-3{margin-top:1rem !important;margin-bottom:1rem !important}.my-xxl-4{margin-top:1.5rem !important;margin-bottom:1.5rem !important}.my-xxl-5{margin-top:3rem !important;margin-bottom:3rem !important}.my-xxl-auto{margin-top:auto !important;margin-bottom:auto !important}.mt-xxl-0{margin-top:0 !important}.mt-xxl-1{margin-top:.25rem !important}.mt-xxl-2{margin-top:.5rem !important}.mt-xxl-3{margin-top:1rem !important}.mt-xxl-4{margin-top:1.5rem !important}.mt-xxl-5{margin-top:3rem !important}.mt-xxl-auto{margin-top:auto !important}.me-xxl-0{margin-right:0 !important}.me-xxl-1{margin-right:.25rem !important}.me-xxl-2{margin-right:.5rem !important}.me-xxl-3{margin-right:1rem !important}.me-xxl-4{margin-right:1.5rem !important}.me-xxl-5{margin-right:3rem !important}.me-xxl-auto{margin-right:auto !important}.mb-xxl-0{margin-bottom:0 !important}.mb-xxl-1{margin-bottom:.25rem !important}.mb-xxl-2{margin-bottom:.5rem !important}.mb-xxl-3{margin-bottom:1rem !important}.mb-xxl-4{margin-bottom:1.5rem !important}.mb-xxl-5{margin-bottom:3rem !important}.mb-xxl-auto{margin-bottom:auto !important}.ms-xxl-0{margin-left:0 !important}.ms-xxl-1{margin-left:.25rem !important}.ms-xxl-2{margin-left:.5rem !important}.ms-xxl-3{margin-left:1rem !important}.ms-xxl-4{margin-left:1.5rem !important}.ms-xxl-5{margin-left:3rem !important}.ms-xxl-auto{margin-left:auto !important}.p-xxl-0{padding:0 !important}.p-xxl-1{padding:.25rem !important}.p-xxl-2{padding:.5rem !important}.p-xxl-3{padding:1rem !important}.p-xxl-4{padding:1.5rem !important}.p-xxl-5{padding:3rem !important}.px-xxl-0{padding-right:0 !important;padding-left:0 !important}.px-xxl-1{padding-right:.25rem !important;padding-left:.25rem !important}.px-xxl-2{padding-right:.5rem !important;padding-left:.5rem !important}.px-xxl-3{padding-right:1rem !important;padding-left:1rem !important}.px-xxl-4{padding-right:1.5rem !important;padding-left:1.5rem !important}.px-xxl-5{padding-right:3rem !important;padding-left:3rem !important}.py-xxl-0{padding-top:0 !important;padding-bottom:0 !important}.py-xxl-1{padding-top:.25rem !important;padding-bottom:.25rem !important}.py-xxl-2{padding-top:.5rem !important;padding-bottom:.5rem !important}.py-xxl-3{padding-top:1rem !important;padding-bottom:1rem !important}.py-xxl-4{padding-top:1.5rem !important;padding-bottom:1.5rem !important}.py-xxl-5{padding-top:3rem !important;padding-bottom:3rem !important}.pt-xxl-0{padding-top:0 !important}.pt-xxl-1{padding-top:.25rem !important}.pt-xxl-2{padding-top:.5rem !important}.pt-xxl-3{padding-top:1rem !important}.pt-xxl-4{padding-top:1.5rem !important}.pt-xxl-5{padding-top:3rem !important}.pe-xxl-0{padding-right:0 !important}.pe-xxl-1{padding-right:.25rem !important}.pe-xxl-2{padding-right:.5rem !important}.pe-xxl-3{padding-right:1rem !important}.pe-xxl-4{padding-right:1.5rem !important}.pe-xxl-5{padding-right:3rem !important}.pb-xxl-0{padding-bottom:0 !important}.pb-xxl-1{padding-bottom:.25rem !important}.pb-xxl-2{padding-bottom:.5rem !important}.pb-xxl-3{padding-bottom:1rem !important}.pb-xxl-4{padding-bottom:1.5rem !important}.pb-xxl-5{padding-bottom:3rem !important}.ps-xxl-0{padding-left:0 !important}.ps-xxl-1{padding-left:.25rem !important}.ps-xxl-2{padding-left:.5rem !important}.ps-xxl-3{padding-left:1rem !important}.ps-xxl-4{padding-left:1.5rem !important}.ps-xxl-5{padding-left:3rem !important}.gap-xxl-0{gap:0 !important}.gap-xxl-1{gap:.25rem !important}.gap-xxl-2{gap:.5rem !important}.gap-xxl-3{gap:1rem !important}.gap-xxl-4{gap:1.5rem !important}.gap-xxl-5{gap:3rem !important}.row-gap-xxl-0{row-gap:0 !important}.row-gap-xxl-1{row-gap:.25rem !important}.row-gap-xxl-2{row-gap:.5rem !important}.row-gap-xxl-3{row-gap:1rem !important}.row-gap-xxl-4{row-gap:1.5rem !important}.row-gap-xxl-5{row-gap:3rem !important}.column-gap-xxl-0{column-gap:0 !important}.column-gap-xxl-1{column-gap:.25rem !important}.column-gap-xxl-2{column-gap:.5rem !important}.column-gap-xxl-3{column-gap:1rem !important}.column-gap-xxl-4{column-gap:1.5rem !important}.column-gap-xxl-5{column-gap:3rem !important}.text-xxl-start{text-align:left !important}.text-xxl-end{text-align:right !important}.text-xxl-center{text-align:center !important}}.bg-default{color:#000}.bg-primary{color:#fff}.bg-secondary{color:#fff}.bg-success{color:#fff}.bg-info{color:#000}.bg-warning{color:#000}.bg-danger{color:#fff}.bg-light{color:#000}.bg-dark{color:#fff}@media(min-width: 1200px){.fs-1{font-size:2rem !important}.fs-2{font-size:1.65rem !important}.fs-3{font-size:1.45rem !important}}@media print{.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-grid{display:grid !important}.d-print-inline-grid{display:inline-grid !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}.d-print-none{display:none !important}}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0}.bg-blue{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-blue{--bslib-color-fg: #0d6efd;color:var(--bslib-color-fg)}.bg-indigo{--bslib-color-bg: #6610f2;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-indigo{--bslib-color-fg: #6610f2;color:var(--bslib-color-fg)}.bg-purple{--bslib-color-bg: #6f42c1;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-purple{--bslib-color-fg: #6f42c1;color:var(--bslib-color-fg)}.bg-pink{--bslib-color-bg: #d63384;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-pink{--bslib-color-fg: #d63384;color:var(--bslib-color-fg)}.bg-red{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-red{--bslib-color-fg: #dc3545;color:var(--bslib-color-fg)}.bg-orange{--bslib-color-bg: #fd7e14;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-orange{--bslib-color-fg: #fd7e14;color:var(--bslib-color-fg)}.bg-yellow{--bslib-color-bg: #ffc107;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-yellow{--bslib-color-fg: #ffc107;color:var(--bslib-color-fg)}.bg-green{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-green{--bslib-color-fg: #198754;color:var(--bslib-color-fg)}.bg-teal{--bslib-color-bg: #20c997;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-teal{--bslib-color-fg: #20c997;color:var(--bslib-color-fg)}.bg-cyan{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-cyan{--bslib-color-fg: #0dcaf0;color:var(--bslib-color-fg)}.text-default{--bslib-color-fg: #dee2e6}.bg-default{--bslib-color-bg: #dee2e6;--bslib-color-fg: #000}.text-primary{--bslib-color-fg: #0d6efd}.bg-primary{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff}.text-secondary{--bslib-color-fg: #6c757d}.bg-secondary{--bslib-color-bg: #6c757d;--bslib-color-fg: #ffffff}.text-success{--bslib-color-fg: #198754}.bg-success{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff}.text-info{--bslib-color-fg: #0dcaf0}.bg-info{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000}.text-warning{--bslib-color-fg: #ffc107}.bg-warning{--bslib-color-bg: #ffc107;--bslib-color-fg: #000}.text-danger{--bslib-color-fg: #dc3545}.bg-danger{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff}.text-light{--bslib-color-fg: #f8f9fa}.bg-light{--bslib-color-bg: #f8f9fa;--bslib-color-fg: #000}.text-dark{--bslib-color-fg: #212529}.bg-dark{--bslib-color-bg: #212529;--bslib-color-fg: #ffffff}.bg-gradient-blue-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(48.6, 72.4, 248.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(48.6,72.4,248.6);color:#fff}.bg-gradient-blue-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(52.2, 92.4, 229);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(52.2,92.4,229);color:#fff}.bg-gradient-blue-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(93.4, 86.4, 204.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(93.4,86.4,204.6);color:#fff}.bg-gradient-blue-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(95.8, 87.2, 179.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(95.8,87.2,179.4);color:#fff}.bg-gradient-blue-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(109, 116.4, 159.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(109,116.4,159.8);color:#fff}.bg-gradient-blue-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(109.8, 143.2, 154.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(109.8,143.2,154.6);color:#000}.bg-gradient-blue-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(17.8, 120, 185.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(17.8,120,185.4);color:#fff}.bg-gradient-blue-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(20.6, 146.4, 212.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(20.6,146.4,212.2);color:#000}.bg-gradient-blue-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(13, 146.8, 247.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(13,146.8,247.8);color:#000}.bg-gradient-indigo-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(66.4, 53.6, 246.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(66.4,53.6,246.4);color:#fff}.bg-gradient-indigo-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(105.6, 36, 222.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(105.6,36,222.4);color:#fff}.bg-gradient-indigo-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(146.8, 30, 198);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(146.8,30,198);color:#fff}.bg-gradient-indigo-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(149.2, 30.8, 172.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(149.2,30.8,172.8);color:#fff}.bg-gradient-indigo-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(162.4, 60, 153.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(162.4,60,153.2);color:#fff}.bg-gradient-indigo-yellow{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(163.2, 86.8, 148);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(163.2,86.8,148);color:#fff}.bg-gradient-indigo-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(71.2, 63.6, 178.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(71.2,63.6,178.8);color:#fff}.bg-gradient-indigo-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(74, 90, 205.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(74,90,205.6);color:#fff}.bg-gradient-indigo-cyan{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(66.4, 90.4, 241.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(66.4,90.4,241.2);color:#fff}.bg-gradient-purple-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(71.8, 83.6, 217);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(71.8,83.6,217);color:#fff}.bg-gradient-purple-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(107.4, 46, 212.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(107.4,46,212.6);color:#fff}.bg-gradient-purple-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(152.2, 60, 168.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(152.2,60,168.6);color:#fff}.bg-gradient-purple-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(154.6, 60.8, 143.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(154.6,60.8,143.4);color:#fff}.bg-gradient-purple-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(167.8, 90, 123.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(167.8,90,123.8);color:#fff}.bg-gradient-purple-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(168.6, 116.8, 118.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(168.6,116.8,118.6);color:#000}.bg-gradient-purple-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(76.6, 93.6, 149.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(76.6,93.6,149.4);color:#fff}.bg-gradient-purple-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(79.4, 120, 176.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(79.4,120,176.2);color:#fff}.bg-gradient-purple-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(71.8, 120.4, 211.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(71.8,120.4,211.8);color:#000}.bg-gradient-pink-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(133.6, 74.6, 180.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(133.6,74.6,180.4);color:#fff}.bg-gradient-pink-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(169.2, 37, 176);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(169.2,37,176);color:#fff}.bg-gradient-pink-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(172.8, 57, 156.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(172.8,57,156.4);color:#fff}.bg-gradient-pink-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(216.4, 51.8, 106.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(216.4,51.8,106.8);color:#fff}.bg-gradient-pink-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(229.6, 81, 87.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(229.6,81,87.2);color:#000}.bg-gradient-pink-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(230.4, 107.8, 82);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(230.4,107.8,82);color:#000}.bg-gradient-pink-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(138.4, 84.6, 112.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(138.4,84.6,112.8);color:#fff}.bg-gradient-pink-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(141.2, 111, 139.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(141.2,111,139.6);color:#000}.bg-gradient-pink-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(133.6, 111.4, 175.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(133.6,111.4,175.2);color:#000}.bg-gradient-red-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(137.2, 75.8, 142.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(137.2,75.8,142.6);color:#fff}.bg-gradient-red-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(172.8, 38.2, 138.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(172.8,38.2,138.2);color:#fff}.bg-gradient-red-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(176.4, 58.2, 118.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(176.4,58.2,118.6);color:#fff}.bg-gradient-red-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(217.6, 52.2, 94.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(217.6,52.2,94.2);color:#fff}.bg-gradient-red-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(233.2, 82.2, 49.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(233.2,82.2,49.4);color:#000}.bg-gradient-red-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(234, 109, 44.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(234,109,44.2);color:#000}.bg-gradient-red-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(142, 85.8, 75);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(142,85.8,75);color:#fff}.bg-gradient-red-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(144.8, 112.2, 101.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(144.8,112.2,101.8);color:#000}.bg-gradient-red-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(137.2, 112.6, 137.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(137.2,112.6,137.4);color:#000}.bg-gradient-orange-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(157, 119.6, 113.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(157,119.6,113.2);color:#000}.bg-gradient-orange-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(192.6, 82, 108.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(192.6,82,108.8);color:#000}.bg-gradient-orange-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(196.2, 102, 89.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(196.2,102,89.2);color:#000}.bg-gradient-orange-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(237.4, 96, 64.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(237.4,96,64.8);color:#000}.bg-gradient-orange-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(239.8, 96.8, 39.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(239.8,96.8,39.6);color:#000}.bg-gradient-orange-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(253.8, 152.8, 14.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(253.8,152.8,14.8);color:#000}.bg-gradient-orange-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(161.8, 129.6, 45.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(161.8,129.6,45.6);color:#000}.bg-gradient-orange-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(164.6, 156, 72.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(164.6,156,72.4);color:#000}.bg-gradient-orange-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(157, 156.4, 108);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(157,156.4,108);color:#000}.bg-gradient-yellow-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(158.2, 159.8, 105.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(158.2,159.8,105.4);color:#000}.bg-gradient-yellow-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(193.8, 122.2, 101);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(193.8,122.2,101);color:#000}.bg-gradient-yellow-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(197.4, 142.2, 81.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(197.4,142.2,81.4);color:#000}.bg-gradient-yellow-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(238.6, 136.2, 57);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(238.6,136.2,57);color:#000}.bg-gradient-yellow-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(241, 137, 31.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(241,137,31.8);color:#000}.bg-gradient-yellow-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(254.2, 166.2, 12.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(254.2,166.2,12.2);color:#000}.bg-gradient-yellow-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(163, 169.8, 37.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(163,169.8,37.8);color:#000}.bg-gradient-yellow-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(165.8, 196.2, 64.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(165.8,196.2,64.6);color:#000}.bg-gradient-yellow-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(158.2, 196.6, 100.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(158.2,196.6,100.2);color:#000}.bg-gradient-green-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(20.2, 125, 151.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(20.2,125,151.6);color:#fff}.bg-gradient-green-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(55.8, 87.4, 147.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(55.8,87.4,147.2);color:#fff}.bg-gradient-green-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(59.4, 107.4, 127.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(59.4,107.4,127.6);color:#fff}.bg-gradient-green-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(100.6, 101.4, 103.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(100.6,101.4,103.2);color:#fff}.bg-gradient-green-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(103, 102.2, 78);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(103,102.2,78);color:#fff}.bg-gradient-green-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(116.2, 131.4, 58.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(116.2,131.4,58.4);color:#000}.bg-gradient-green-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(117, 158.2, 53.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(117,158.2,53.2);color:#000}.bg-gradient-green-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(27.8, 161.4, 110.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(27.8,161.4,110.8);color:#000}.bg-gradient-green-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(20.2, 161.8, 146.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(20.2,161.8,146.4);color:#000}.bg-gradient-teal-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(24.4, 164.6, 191.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(24.4,164.6,191.8);color:#000}.bg-gradient-teal-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(60, 127, 187.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(60,127,187.4);color:#000}.bg-gradient-teal-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(63.6, 147, 167.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(63.6,147,167.8);color:#000}.bg-gradient-teal-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(104.8, 141, 143.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(104.8,141,143.4);color:#000}.bg-gradient-teal-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(107.2, 141.8, 118.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(107.2,141.8,118.2);color:#000}.bg-gradient-teal-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(120.4, 171, 98.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(120.4,171,98.6);color:#000}.bg-gradient-teal-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(121.2, 197.8, 93.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(121.2,197.8,93.4);color:#000}.bg-gradient-teal-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(29.2, 174.6, 124.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(29.2,174.6,124.2);color:#000}.bg-gradient-teal-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(24.4, 201.4, 186.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(24.4,201.4,186.6);color:#000}.bg-gradient-cyan-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(13, 165.2, 245.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(13,165.2,245.2);color:#000}.bg-gradient-cyan-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(48.6, 127.6, 240.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(48.6,127.6,240.8);color:#000}.bg-gradient-cyan-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(52.2, 147.6, 221.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(52.2,147.6,221.2);color:#000}.bg-gradient-cyan-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(93.4, 141.6, 196.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(93.4,141.6,196.8);color:#000}.bg-gradient-cyan-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(95.8, 142.4, 171.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(95.8,142.4,171.6);color:#000}.bg-gradient-cyan-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(109, 171.6, 152);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(109,171.6,152);color:#000}.bg-gradient-cyan-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(109.8, 198.4, 146.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(109.8,198.4,146.8);color:#000}.bg-gradient-cyan-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(17.8, 175.2, 177.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(17.8,175.2,177.6);color:#000}.bg-gradient-cyan-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(20.6, 201.6, 204.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(20.6,201.6,204.4);color:#000}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.bg-blue{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-blue{--bslib-color-fg: #0d6efd;color:var(--bslib-color-fg)}.bg-indigo{--bslib-color-bg: #6610f2;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-indigo{--bslib-color-fg: #6610f2;color:var(--bslib-color-fg)}.bg-purple{--bslib-color-bg: #6f42c1;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-purple{--bslib-color-fg: #6f42c1;color:var(--bslib-color-fg)}.bg-pink{--bslib-color-bg: #d63384;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-pink{--bslib-color-fg: #d63384;color:var(--bslib-color-fg)}.bg-red{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-red{--bslib-color-fg: #dc3545;color:var(--bslib-color-fg)}.bg-orange{--bslib-color-bg: #fd7e14;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-orange{--bslib-color-fg: #fd7e14;color:var(--bslib-color-fg)}.bg-yellow{--bslib-color-bg: #ffc107;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-yellow{--bslib-color-fg: #ffc107;color:var(--bslib-color-fg)}.bg-green{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-green{--bslib-color-fg: #198754;color:var(--bslib-color-fg)}.bg-teal{--bslib-color-bg: #20c997;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-teal{--bslib-color-fg: #20c997;color:var(--bslib-color-fg)}.bg-cyan{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-cyan{--bslib-color-fg: #0dcaf0;color:var(--bslib-color-fg)}.text-default{--bslib-color-fg: #dee2e6}.bg-default{--bslib-color-bg: #dee2e6;--bslib-color-fg: #000}.text-primary{--bslib-color-fg: #0d6efd}.bg-primary{--bslib-color-bg: #0d6efd;--bslib-color-fg: #ffffff}.text-secondary{--bslib-color-fg: #6c757d}.bg-secondary{--bslib-color-bg: #6c757d;--bslib-color-fg: #ffffff}.text-success{--bslib-color-fg: #198754}.bg-success{--bslib-color-bg: #198754;--bslib-color-fg: #ffffff}.text-info{--bslib-color-fg: #0dcaf0}.bg-info{--bslib-color-bg: #0dcaf0;--bslib-color-fg: #000}.text-warning{--bslib-color-fg: #ffc107}.bg-warning{--bslib-color-bg: #ffc107;--bslib-color-fg: #000}.text-danger{--bslib-color-fg: #dc3545}.bg-danger{--bslib-color-bg: #dc3545;--bslib-color-fg: #ffffff}.text-light{--bslib-color-fg: #f8f9fa}.bg-light{--bslib-color-bg: #f8f9fa;--bslib-color-fg: #000}.text-dark{--bslib-color-fg: #212529}.bg-dark{--bslib-color-bg: #212529;--bslib-color-fg: #ffffff}.bg-gradient-blue-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(48.6, 72.4, 248.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(48.6,72.4,248.6);color:#fff}.bg-gradient-blue-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(52.2, 92.4, 229);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(52.2,92.4,229);color:#fff}.bg-gradient-blue-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(93.4, 86.4, 204.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(93.4,86.4,204.6);color:#fff}.bg-gradient-blue-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(95.8, 87.2, 179.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(95.8,87.2,179.4);color:#fff}.bg-gradient-blue-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(109, 116.4, 159.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(109,116.4,159.8);color:#fff}.bg-gradient-blue-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(109.8, 143.2, 154.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(109.8,143.2,154.6);color:#000}.bg-gradient-blue-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(17.8, 120, 185.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(17.8,120,185.4);color:#fff}.bg-gradient-blue-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(20.6, 146.4, 212.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(20.6,146.4,212.2);color:#000}.bg-gradient-blue-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(13, 146.8, 247.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0d6efd var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(13,146.8,247.8);color:#000}.bg-gradient-indigo-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(66.4, 53.6, 246.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(66.4,53.6,246.4);color:#fff}.bg-gradient-indigo-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(105.6, 36, 222.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(105.6,36,222.4);color:#fff}.bg-gradient-indigo-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(146.8, 30, 198);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(146.8,30,198);color:#fff}.bg-gradient-indigo-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(149.2, 30.8, 172.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(149.2,30.8,172.8);color:#fff}.bg-gradient-indigo-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(162.4, 60, 153.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(162.4,60,153.2);color:#fff}.bg-gradient-indigo-yellow{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(163.2, 86.8, 148);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(163.2,86.8,148);color:#fff}.bg-gradient-indigo-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(71.2, 63.6, 178.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(71.2,63.6,178.8);color:#fff}.bg-gradient-indigo-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(74, 90, 205.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(74,90,205.6);color:#fff}.bg-gradient-indigo-cyan{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(66.4, 90.4, 241.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6610f2 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(66.4,90.4,241.2);color:#fff}.bg-gradient-purple-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(71.8, 83.6, 217);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(71.8,83.6,217);color:#fff}.bg-gradient-purple-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(107.4, 46, 212.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(107.4,46,212.6);color:#fff}.bg-gradient-purple-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(152.2, 60, 168.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(152.2,60,168.6);color:#fff}.bg-gradient-purple-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(154.6, 60.8, 143.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(154.6,60.8,143.4);color:#fff}.bg-gradient-purple-orange{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(167.8, 90, 123.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(167.8,90,123.8);color:#fff}.bg-gradient-purple-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(168.6, 116.8, 118.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(168.6,116.8,118.6);color:#000}.bg-gradient-purple-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(76.6, 93.6, 149.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(76.6,93.6,149.4);color:#fff}.bg-gradient-purple-teal{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(79.4, 120, 176.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(79.4,120,176.2);color:#fff}.bg-gradient-purple-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(71.8, 120.4, 211.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #6f42c1 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(71.8,120.4,211.8);color:#000}.bg-gradient-pink-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(133.6, 74.6, 180.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(133.6,74.6,180.4);color:#fff}.bg-gradient-pink-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(169.2, 37, 176);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(169.2,37,176);color:#fff}.bg-gradient-pink-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(172.8, 57, 156.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(172.8,57,156.4);color:#fff}.bg-gradient-pink-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(216.4, 51.8, 106.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(216.4,51.8,106.8);color:#fff}.bg-gradient-pink-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(229.6, 81, 87.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(229.6,81,87.2);color:#000}.bg-gradient-pink-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(230.4, 107.8, 82);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(230.4,107.8,82);color:#000}.bg-gradient-pink-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(138.4, 84.6, 112.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(138.4,84.6,112.8);color:#fff}.bg-gradient-pink-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(141.2, 111, 139.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(141.2,111,139.6);color:#000}.bg-gradient-pink-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(133.6, 111.4, 175.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #d63384 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(133.6,111.4,175.2);color:#000}.bg-gradient-red-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(137.2, 75.8, 142.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(137.2,75.8,142.6);color:#fff}.bg-gradient-red-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(172.8, 38.2, 138.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(172.8,38.2,138.2);color:#fff}.bg-gradient-red-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(176.4, 58.2, 118.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(176.4,58.2,118.6);color:#fff}.bg-gradient-red-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(217.6, 52.2, 94.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(217.6,52.2,94.2);color:#fff}.bg-gradient-red-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(233.2, 82.2, 49.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(233.2,82.2,49.4);color:#000}.bg-gradient-red-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(234, 109, 44.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(234,109,44.2);color:#000}.bg-gradient-red-green{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(142, 85.8, 75);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(142,85.8,75);color:#fff}.bg-gradient-red-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(144.8, 112.2, 101.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(144.8,112.2,101.8);color:#000}.bg-gradient-red-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(137.2, 112.6, 137.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #dc3545 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(137.2,112.6,137.4);color:#000}.bg-gradient-orange-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(157, 119.6, 113.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(157,119.6,113.2);color:#000}.bg-gradient-orange-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(192.6, 82, 108.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(192.6,82,108.8);color:#000}.bg-gradient-orange-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(196.2, 102, 89.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(196.2,102,89.2);color:#000}.bg-gradient-orange-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(237.4, 96, 64.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(237.4,96,64.8);color:#000}.bg-gradient-orange-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(239.8, 96.8, 39.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(239.8,96.8,39.6);color:#000}.bg-gradient-orange-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(253.8, 152.8, 14.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(253.8,152.8,14.8);color:#000}.bg-gradient-orange-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(161.8, 129.6, 45.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(161.8,129.6,45.6);color:#000}.bg-gradient-orange-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(164.6, 156, 72.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(164.6,156,72.4);color:#000}.bg-gradient-orange-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(157, 156.4, 108);background:linear-gradient(var(--bg-gradient-deg, 140deg), #fd7e14 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(157,156.4,108);color:#000}.bg-gradient-yellow-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(158.2, 159.8, 105.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(158.2,159.8,105.4);color:#000}.bg-gradient-yellow-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(193.8, 122.2, 101);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(193.8,122.2,101);color:#000}.bg-gradient-yellow-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(197.4, 142.2, 81.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(197.4,142.2,81.4);color:#000}.bg-gradient-yellow-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(238.6, 136.2, 57);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(238.6,136.2,57);color:#000}.bg-gradient-yellow-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(241, 137, 31.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(241,137,31.8);color:#000}.bg-gradient-yellow-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(254.2, 166.2, 12.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(254.2,166.2,12.2);color:#000}.bg-gradient-yellow-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(163, 169.8, 37.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(163,169.8,37.8);color:#000}.bg-gradient-yellow-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(165.8, 196.2, 64.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(165.8,196.2,64.6);color:#000}.bg-gradient-yellow-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(158.2, 196.6, 100.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #ffc107 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(158.2,196.6,100.2);color:#000}.bg-gradient-green-blue{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(20.2, 125, 151.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(20.2,125,151.6);color:#fff}.bg-gradient-green-indigo{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(55.8, 87.4, 147.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(55.8,87.4,147.2);color:#fff}.bg-gradient-green-purple{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(59.4, 107.4, 127.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(59.4,107.4,127.6);color:#fff}.bg-gradient-green-pink{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(100.6, 101.4, 103.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(100.6,101.4,103.2);color:#fff}.bg-gradient-green-red{--bslib-color-fg: #ffffff;--bslib-color-bg: rgb(103, 102.2, 78);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(103,102.2,78);color:#fff}.bg-gradient-green-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(116.2, 131.4, 58.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(116.2,131.4,58.4);color:#000}.bg-gradient-green-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(117, 158.2, 53.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(117,158.2,53.2);color:#000}.bg-gradient-green-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(27.8, 161.4, 110.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(27.8,161.4,110.8);color:#000}.bg-gradient-green-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(20.2, 161.8, 146.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #198754 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(20.2,161.8,146.4);color:#000}.bg-gradient-teal-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(24.4, 164.6, 191.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(24.4,164.6,191.8);color:#000}.bg-gradient-teal-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(60, 127, 187.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(60,127,187.4);color:#000}.bg-gradient-teal-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(63.6, 147, 167.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(63.6,147,167.8);color:#000}.bg-gradient-teal-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(104.8, 141, 143.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(104.8,141,143.4);color:#000}.bg-gradient-teal-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(107.2, 141.8, 118.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(107.2,141.8,118.2);color:#000}.bg-gradient-teal-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(120.4, 171, 98.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(120.4,171,98.6);color:#000}.bg-gradient-teal-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(121.2, 197.8, 93.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(121.2,197.8,93.4);color:#000}.bg-gradient-teal-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(29.2, 174.6, 124.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(29.2,174.6,124.2);color:#000}.bg-gradient-teal-cyan{--bslib-color-fg: #000;--bslib-color-bg: rgb(24.4, 201.4, 186.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #20c997 var(--bg-gradient-start, 36%), #0dcaf0 var(--bg-gradient-end, 180%)) rgb(24.4,201.4,186.6);color:#000}.bg-gradient-cyan-blue{--bslib-color-fg: #000;--bslib-color-bg: rgb(13, 165.2, 245.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #0d6efd var(--bg-gradient-end, 180%)) rgb(13,165.2,245.2);color:#000}.bg-gradient-cyan-indigo{--bslib-color-fg: #000;--bslib-color-bg: rgb(48.6, 127.6, 240.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6610f2 var(--bg-gradient-end, 180%)) rgb(48.6,127.6,240.8);color:#000}.bg-gradient-cyan-purple{--bslib-color-fg: #000;--bslib-color-bg: rgb(52.2, 147.6, 221.2);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #6f42c1 var(--bg-gradient-end, 180%)) rgb(52.2,147.6,221.2);color:#000}.bg-gradient-cyan-pink{--bslib-color-fg: #000;--bslib-color-bg: rgb(93.4, 141.6, 196.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #d63384 var(--bg-gradient-end, 180%)) rgb(93.4,141.6,196.8);color:#000}.bg-gradient-cyan-red{--bslib-color-fg: #000;--bslib-color-bg: rgb(95.8, 142.4, 171.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #dc3545 var(--bg-gradient-end, 180%)) rgb(95.8,142.4,171.6);color:#000}.bg-gradient-cyan-orange{--bslib-color-fg: #000;--bslib-color-bg: rgb(109, 171.6, 152);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #fd7e14 var(--bg-gradient-end, 180%)) rgb(109,171.6,152);color:#000}.bg-gradient-cyan-yellow{--bslib-color-fg: #000;--bslib-color-bg: rgb(109.8, 198.4, 146.8);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #ffc107 var(--bg-gradient-end, 180%)) rgb(109.8,198.4,146.8);color:#000}.bg-gradient-cyan-green{--bslib-color-fg: #000;--bslib-color-bg: rgb(17.8, 175.2, 177.6);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #198754 var(--bg-gradient-end, 180%)) rgb(17.8,175.2,177.6);color:#000}.bg-gradient-cyan-teal{--bslib-color-fg: #000;--bslib-color-bg: rgb(20.6, 201.6, 204.4);background:linear-gradient(var(--bg-gradient-deg, 140deg), #0dcaf0 var(--bg-gradient-start, 36%), #20c997 var(--bg-gradient-end, 180%)) rgb(20.6,201.6,204.4);color:#000}:root{--bslib-value-box-shadow: none;--bslib-value-box-border-width-auto-yes: var(--bslib-value-box-border-width-baseline);--bslib-value-box-border-width-auto-no: 0;--bslib-value-box-border-width-baseline: 1px}.bslib-value-box.card{box-shadow:var(--bslib-value-box-shadow)}.bslib-value-box{border-width:var(--bslib-value-box-border-width-auto-no, var(--bslib-value-box-border-width-baseline))}.bslib-value-box.border-auto{border-width:var(--bslib-value-box-border-width-auto-yes, var(--bslib-value-box-border-width-baseline))}.bslib-value-box.default{--bslib-value-box-bg-default: var(--bs-card-bg, #ffffff);--bslib-value-box-border-color-default: var(--bs-card-border-color, rgba(0, 0, 0, 0.175));color:var(--bslib-value-box-color);background-color:var(--bslib-value-box-bg, var(--bslib-value-box-bg-default));border-color:var(--bslib-value-box-border-color, var(--bslib-value-box-border-color-default))}.bslib-value-box{container-name:bslib-value-box;container-type:inline-size}.bslib-value-box .value-box-grid{display:grid;grid-template-areas:"left right";align-items:center;overflow:hidden}.bslib-value-box .value-box-showcase{height:100%;max-height:var(---bslib-value-box-showcase-max-h, 100%)}.bslib-value-box .value-box-showcase,.bslib-value-box .value-box-showcase>.html-fill-item{width:100%}.bslib-value-box[data-full-screen=true] .value-box-showcase{max-height:var(---bslib-value-box-showcase-max-h-fs, 100%)}@media screen and (min-width: 575.98px){@container bslib-value-box (max-width: 300px){.bslib-value-box:not(.showcase-bottom) .value-box-grid{grid-template-columns:1fr !important;grid-template-rows:auto auto;grid-template-areas:"top" "bottom"}.bslib-value-box:not(.showcase-bottom) .value-box-grid .value-box-showcase{grid-area:top !important}.bslib-value-box:not(.showcase-bottom) .value-box-grid .value-box-area{grid-area:bottom !important;justify-content:end}}}.bslib-value-box .value-box-area{justify-content:center;padding:1.5rem 1rem;font-size:.9rem;font-weight:500}.bslib-value-box .value-box-area *{margin-bottom:0;margin-top:0}.bslib-value-box .value-box-title{font-size:1rem;margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.bslib-value-box .value-box-title:empty::after{content:" "}.bslib-value-box .value-box-value{font-size:calc(1.29rem + 0.48vw)}@media(min-width: 1200px){.bslib-value-box .value-box-value{font-size:1.65rem}}.bslib-value-box .value-box-value{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.bslib-value-box .value-box-value:empty::after{content:" "}.bslib-value-box .value-box-showcase{align-items:center;justify-content:center;margin-top:auto;margin-bottom:auto;padding:1rem}.bslib-value-box .value-box-showcase .bi,.bslib-value-box .value-box-showcase .fa,.bslib-value-box .value-box-showcase .fab,.bslib-value-box .value-box-showcase .fas,.bslib-value-box .value-box-showcase .far{opacity:.85;min-width:50px;max-width:125%}.bslib-value-box .value-box-showcase .bi,.bslib-value-box .value-box-showcase .fa,.bslib-value-box .value-box-showcase .fab,.bslib-value-box .value-box-showcase .fas,.bslib-value-box .value-box-showcase .far{font-size:4rem}.bslib-value-box.showcase-top-right .value-box-grid{grid-template-columns:1fr var(---bslib-value-box-showcase-w, 50%)}.bslib-value-box.showcase-top-right .value-box-grid .value-box-showcase{grid-area:right;margin-left:auto;align-self:start;align-items:end;padding-left:0;padding-bottom:0}.bslib-value-box.showcase-top-right .value-box-grid .value-box-area{grid-area:left;align-self:end}.bslib-value-box.showcase-top-right[data-full-screen=true] .value-box-grid{grid-template-columns:auto var(---bslib-value-box-showcase-w-fs, 1fr)}.bslib-value-box.showcase-top-right[data-full-screen=true] .value-box-grid>div{align-self:center}.bslib-value-box.showcase-top-right:not([data-full-screen=true]) .value-box-showcase{margin-top:0}@container bslib-value-box (max-width: 300px){.bslib-value-box.showcase-top-right:not([data-full-screen=true]) .value-box-grid .value-box-showcase{padding-left:1rem}}.bslib-value-box.showcase-left-center .value-box-grid{grid-template-columns:var(---bslib-value-box-showcase-w, 30%) auto}.bslib-value-box.showcase-left-center[data-full-screen=true] .value-box-grid{grid-template-columns:var(---bslib-value-box-showcase-w-fs, 1fr) auto}.bslib-value-box.showcase-left-center:not([data-fill-screen=true]) .value-box-grid .value-box-showcase{grid-area:left}.bslib-value-box.showcase-left-center:not([data-fill-screen=true]) .value-box-grid .value-box-area{grid-area:right}.bslib-value-box.showcase-bottom .value-box-grid{grid-template-columns:1fr;grid-template-rows:1fr var(---bslib-value-box-showcase-h, auto);grid-template-areas:"top" "bottom";overflow:hidden}.bslib-value-box.showcase-bottom .value-box-grid .value-box-showcase{grid-area:bottom;padding:0;margin:0}.bslib-value-box.showcase-bottom .value-box-grid .value-box-area{grid-area:top}.bslib-value-box.showcase-bottom[data-full-screen=true] .value-box-grid{grid-template-rows:1fr var(---bslib-value-box-showcase-h-fs, 2fr)}.bslib-value-box.showcase-bottom[data-full-screen=true] .value-box-grid .value-box-showcase{padding:1rem}[data-bs-theme=dark] .bslib-value-box{--bslib-value-box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 50%)}@media(min-width: 576px){.nav:not(.nav-hidden){display:flex !important;display:-webkit-flex !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column){float:none !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column)>.bslib-nav-spacer{margin-left:auto !important}.nav:not(.nav-hidden):not(.nav-stacked):not(.flex-column)>.form-inline{margin-top:auto;margin-bottom:auto}.nav:not(.nav-hidden).nav-stacked{flex-direction:column;-webkit-flex-direction:column;height:100%}.nav:not(.nav-hidden).nav-stacked>.bslib-nav-spacer{margin-top:auto !important}}.bslib-card{overflow:auto}.bslib-card .card-body+.card-body{padding-top:0}.bslib-card .card-body{overflow:auto}.bslib-card .card-body p{margin-top:0}.bslib-card .card-body p:last-child{margin-bottom:0}.bslib-card .card-body{max-height:var(--bslib-card-body-max-height, none)}.bslib-card[data-full-screen=true]>.card-body{max-height:var(--bslib-card-body-max-height-full-screen, none)}.bslib-card .card-header .form-group{margin-bottom:0}.bslib-card .card-header .selectize-control{margin-bottom:0}.bslib-card .card-header .selectize-control .item{margin-right:1.15rem}.bslib-card .card-footer{margin-top:auto}.bslib-card .bslib-navs-card-title{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}.bslib-card .bslib-navs-card-title .nav{margin-left:auto}.bslib-card .bslib-sidebar-layout:not([data-bslib-sidebar-border=true]){border:none}.bslib-card .bslib-sidebar-layout:not([data-bslib-sidebar-border-radius=true]){border-top-left-radius:0;border-top-right-radius:0}[data-full-screen=true]{position:fixed;inset:3.5rem 1rem 1rem;height:auto !important;max-height:none !important;width:auto !important;z-index:1070}.bslib-full-screen-enter{display:none;position:absolute;bottom:var(--bslib-full-screen-enter-bottom, 0.2rem);right:var(--bslib-full-screen-enter-right, 0);top:var(--bslib-full-screen-enter-top);left:var(--bslib-full-screen-enter-left);color:var(--bslib-color-fg, var(--bs-card-color));background-color:var(--bslib-color-bg, var(--bs-card-bg, var(--bs-body-bg)));border:var(--bs-card-border-width) solid var(--bslib-color-fg, var(--bs-card-border-color));box-shadow:0 2px 4px rgba(0,0,0,.15);margin:.2rem .4rem;padding:.55rem !important;font-size:.8rem;cursor:pointer;opacity:.7}.bslib-full-screen-enter:hover{opacity:1}.bslib-full-screen-enter{z-index:1070}.card[data-full-screen=false]:hover>*>.bslib-full-screen-enter{display:block}.bslib-has-full-screen .card:hover>*>.bslib-full-screen-enter{display:none}@media(max-width: 575.98px){.bslib-full-screen-enter{display:none !important}}.bslib-full-screen-exit{position:relative;top:1.35rem;font-size:.9rem;cursor:pointer;text-decoration:none;display:flex;float:right;margin-right:2.15rem;align-items:center;color:rgba(var(--bs-body-bg-rgb), 0.8)}.bslib-full-screen-exit:hover{color:rgba(var(--bs-body-bg-rgb), 1)}.bslib-full-screen-exit svg{margin-left:.5rem;font-size:1.5rem}#bslib-full-screen-overlay{position:fixed;inset:0;background-color:rgba(var(--bs-body-color-rgb), 0.6);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:1069;animation:bslib-full-screen-overlay-enter 400ms cubic-bezier(0.6, 0.02, 0.65, 1) forwards}@keyframes bslib-full-screen-overlay-enter{0%{opacity:0}100%{opacity:1}}.bslib-grid{display:grid !important;gap:var(--bslib-spacer, 1rem);height:var(--bslib-grid-height)}.bslib-grid.grid{grid-template-columns:repeat(var(--bs-columns, 12), minmax(0, 1fr));grid-template-rows:unset;grid-auto-rows:var(--bslib-grid--row-heights);--bslib-grid--row-heights--xs: unset}.bslib-grid.grid.bslib-grid--row-heights--xs{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xs)}.bslib-grid.grid{--bslib-grid--row-heights--sm: unset}@media(min-width: 576px){.bslib-grid.grid.bslib-grid--row-heights--sm{--bslib-grid--row-heights: var(--bslib-grid--row-heights--sm)}}.bslib-grid.grid{--bslib-grid--row-heights--md: unset}@media(min-width: 768px){.bslib-grid.grid.bslib-grid--row-heights--md{--bslib-grid--row-heights: var(--bslib-grid--row-heights--md)}}.bslib-grid.grid{--bslib-grid--row-heights--lg: unset}@media(min-width: 992px){.bslib-grid.grid.bslib-grid--row-heights--lg{--bslib-grid--row-heights: var(--bslib-grid--row-heights--lg)}}.bslib-grid.grid{--bslib-grid--row-heights--xl: unset}@media(min-width: 1200px){.bslib-grid.grid.bslib-grid--row-heights--xl{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xl)}}.bslib-grid.grid{--bslib-grid--row-heights--xxl: unset}@media(min-width: 1400px){.bslib-grid.grid.bslib-grid--row-heights--xxl{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xxl)}}.bslib-grid>*>.shiny-input-container{width:100%}.bslib-grid-item{grid-column:auto/span 1}@media(max-width: 767.98px){.bslib-grid-item{grid-column:1/-1}}@media(max-width: 575.98px){.bslib-grid{grid-template-columns:1fr !important;height:var(--bslib-grid-height-mobile)}.bslib-grid.grid{height:unset !important;grid-auto-rows:var(--bslib-grid--row-heights--xs, auto)}}.accordion .accordion-header{font-size:calc(1.29rem + 0.48vw)}@media(min-width: 1200px){.accordion .accordion-header{font-size:1.65rem}}.accordion .accordion-header{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color);margin-bottom:0}.accordion .accordion-icon:not(:empty){margin-right:.75rem;display:flex}.accordion .accordion-button:not(.collapsed){box-shadow:none}.accordion .accordion-button:not(.collapsed):focus{box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.navbar+.container-fluid:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-sm:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-md:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-lg:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-xl:has(>.tab-content>.tab-pane.active.html-fill-container),.navbar+.container-xxl:has(>.tab-content>.tab-pane.active.html-fill-container){padding-left:0;padding-right:0}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container,.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container{padding:var(--bslib-spacer, 1rem);gap:var(--bslib-spacer, 1rem)}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container:has(>.bslib-sidebar-layout:only-child){padding:0}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border=true]){border-left:none;border-right:none;border-bottom:none}.navbar+.container-fluid>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-sm>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-md>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-lg>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-xl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]),.navbar+.container-xxl>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout:only-child:not([data-bslib-sidebar-border-radius=true]){border-radius:0}.navbar+div>.bslib-sidebar-layout{border-top:var(--bslib-sidebar-border)}html{height:100%}.bslib-page-fill{width:100%;height:100%;margin:0;padding:var(--bslib-spacer, 1rem);gap:var(--bslib-spacer, 1rem)}@media(max-width: 575.98px){.bslib-page-fill{height:var(--bslib-page-fill-mobile-height, auto)}}:root{--bslib-page-sidebar-title-bg: #517699;--bslib-page-sidebar-title-color: #ffffff}.bslib-page-title{background-color:var(--bslib-page-sidebar-title-bg);color:var(--bslib-page-sidebar-title-color);font-size:1.25rem;font-weight:300;padding:var(--bslib-spacer, 1rem);padding-left:1.5rem;margin-bottom:0;border-bottom:1px solid rgb(221.7,222.3,222.9)}.bslib-sidebar-layout{--bslib-sidebar-transition-duration: 500ms;--bslib-sidebar-transition-easing-x: cubic-bezier(0.8, 0.78, 0.22, 1.07);--bslib-sidebar-border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0, 0, 0, 0.175));--bslib-sidebar-border-radius: var(--bs-border-radius);--bslib-sidebar-vert-border: var(--bs-card-border-width, 1px) solid var(--bs-card-border-color, rgba(0, 0, 0, 0.175));--bslib-sidebar-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.05);--bslib-sidebar-fg: var(--bs-emphasis-color, black);--bslib-sidebar-main-fg: var(--bs-card-color, var(--bs-body-color));--bslib-sidebar-main-bg: var(--bs-card-bg, var(--bs-body-bg));--bslib-sidebar-toggle-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.1);--bslib-sidebar-padding: calc(var(--bslib-spacer) * 1.5);--bslib-sidebar-icon-size: var(--bslib-spacer, 1rem);--bslib-sidebar-icon-button-size: calc(var(--bslib-sidebar-icon-size, 1rem) * 2);--bslib-sidebar-padding-icon: calc(var(--bslib-sidebar-icon-button-size, 2rem) * 1.5);--bslib-collapse-toggle-border-radius: var(--bs-border-radius, 0.375rem);--bslib-collapse-toggle-transform: 0deg;--bslib-sidebar-toggle-transition-easing: cubic-bezier(1, 0, 0, 1);--bslib-collapse-toggle-right-transform: 180deg;--bslib-sidebar-column-main: minmax(0, 1fr);display:grid !important;grid-template-columns:min(100% - var(--bslib-sidebar-icon-size),var(--bslib-sidebar-width, 250px)) var(--bslib-sidebar-column-main);position:relative;transition:grid-template-columns ease-in-out var(--bslib-sidebar-transition-duration)}@media(prefers-reduced-motion: reduce){.bslib-sidebar-layout{transition:none}}.bslib-sidebar-layout{border:var(--bslib-sidebar-border);border-radius:var(--bslib-sidebar-border-radius)}.bslib-sidebar-layout[data-bslib-sidebar-border=false]{border:none}.bslib-sidebar-layout[data-bslib-sidebar-border-radius=false]{border-radius:initial}.bslib-sidebar-layout>.main,.bslib-sidebar-layout>.sidebar{grid-row:1/2;border-radius:inherit;overflow:auto}.bslib-sidebar-layout>.main{grid-column:2/3;border-top-left-radius:0;border-bottom-left-radius:0;padding:var(--bslib-sidebar-padding);transition:padding var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration);color:var(--bslib-sidebar-main-fg);background-color:var(--bslib-sidebar-main-bg)}.bslib-sidebar-layout>.sidebar{grid-column:1/2;width:100%;height:100%;border-right:var(--bslib-sidebar-vert-border);border-top-right-radius:0;border-bottom-right-radius:0;color:var(--bslib-sidebar-fg);background-color:var(--bslib-sidebar-bg);backdrop-filter:blur(5px)}.bslib-sidebar-layout>.sidebar>.sidebar-content{display:flex;flex-direction:column;gap:var(--bslib-spacer, 1rem);padding:var(--bslib-sidebar-padding);padding-top:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout>.sidebar>.sidebar-content>:last-child:not(.sidebar-title){margin-bottom:0}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion{margin-left:calc(-1*var(--bslib-sidebar-padding));margin-right:calc(-1*var(--bslib-sidebar-padding))}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:last-child{margin-bottom:calc(-1*var(--bslib-sidebar-padding))}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:last-child){margin-bottom:1rem}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion .accordion-body{display:flex;flex-direction:column}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:first-child) .accordion-item:first-child{border-top:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:not(:last-child) .accordion-item:last-child{border-bottom:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.bslib-sidebar-layout>.sidebar>.sidebar-content.has-accordion>.sidebar-title{border-bottom:none;padding-bottom:0}.bslib-sidebar-layout>.sidebar .shiny-input-container{width:100%}.bslib-sidebar-layout[data-bslib-sidebar-open=always]>.sidebar>.sidebar-content{padding-top:var(--bslib-sidebar-padding)}.bslib-sidebar-layout>.collapse-toggle{grid-row:1/2;grid-column:1/2;display:inline-flex;align-items:center;position:absolute;right:calc(var(--bslib-sidebar-icon-size));top:calc(var(--bslib-sidebar-icon-size, 1rem)/2);border:none;border-radius:var(--bslib-collapse-toggle-border-radius);height:var(--bslib-sidebar-icon-button-size, 2rem);width:var(--bslib-sidebar-icon-button-size, 2rem);display:flex;align-items:center;justify-content:center;padding:0;color:var(--bslib-sidebar-fg);background-color:unset;transition:color var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),top var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),right var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration),left var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout>.collapse-toggle:hover{background-color:var(--bslib-sidebar-toggle-bg)}.bslib-sidebar-layout>.collapse-toggle>.collapse-icon{opacity:.8;width:var(--bslib-sidebar-icon-size);height:var(--bslib-sidebar-icon-size);transform:rotateY(var(--bslib-collapse-toggle-transform));transition:transform var(--bslib-sidebar-toggle-transition-easing) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout>.collapse-toggle:hover>.collapse-icon{opacity:1}.bslib-sidebar-layout .sidebar-title{font-size:1.25rem;line-height:1.25;margin-top:0;margin-bottom:1rem;padding-bottom:1rem;border-bottom:var(--bslib-sidebar-border)}.bslib-sidebar-layout.sidebar-right{grid-template-columns:var(--bslib-sidebar-column-main) min(100% - var(--bslib-sidebar-icon-size),var(--bslib-sidebar-width, 250px))}.bslib-sidebar-layout.sidebar-right>.main{grid-column:1/2;border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:inherit;border-bottom-left-radius:inherit}.bslib-sidebar-layout.sidebar-right>.sidebar{grid-column:2/3;border-right:none;border-left:var(--bslib-sidebar-vert-border);border-top-left-radius:0;border-bottom-left-radius:0}.bslib-sidebar-layout.sidebar-right>.collapse-toggle{grid-column:2/3;left:var(--bslib-sidebar-icon-size);right:unset;border:var(--bslib-collapse-toggle-border)}.bslib-sidebar-layout.sidebar-right>.collapse-toggle>.collapse-icon{transform:rotateY(var(--bslib-collapse-toggle-right-transform))}.bslib-sidebar-layout.sidebar-collapsed{--bslib-collapse-toggle-transform: 180deg;--bslib-collapse-toggle-right-transform: 0deg;--bslib-sidebar-vert-border: none;grid-template-columns:0 minmax(0, 1fr)}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right{grid-template-columns:minmax(0, 1fr) 0}.bslib-sidebar-layout.sidebar-collapsed:not(.transitioning)>.sidebar>*{display:none}.bslib-sidebar-layout.sidebar-collapsed>.main{border-radius:inherit}.bslib-sidebar-layout.sidebar-collapsed:not(.sidebar-right)>.main{padding-left:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.main{padding-right:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout.sidebar-collapsed>.collapse-toggle{color:var(--bslib-sidebar-main-fg);top:calc(var(--bslib-sidebar-overlap-counter, 0)*(var(--bslib-sidebar-icon-size) + var(--bslib-sidebar-padding)) + var(--bslib-sidebar-icon-size, 1rem)/2);right:calc(-2.5*var(--bslib-sidebar-icon-size) - var(--bs-card-border-width, 1px))}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.collapse-toggle{left:calc(-2.5*var(--bslib-sidebar-icon-size) - var(--bs-card-border-width, 1px));right:unset}@media(min-width: 576px){.bslib-sidebar-layout.transitioning>.sidebar>.sidebar-content{display:none}}@media(max-width: 575.98px){.bslib-sidebar-layout[data-bslib-sidebar-open=desktop]{--bslib-sidebar-js-init-collapsed: true}.bslib-sidebar-layout>.sidebar,.bslib-sidebar-layout.sidebar-right>.sidebar{border:none}.bslib-sidebar-layout>.main,.bslib-sidebar-layout.sidebar-right>.main{grid-column:1/3}.bslib-sidebar-layout[data-bslib-sidebar-open=always]{display:block !important}.bslib-sidebar-layout[data-bslib-sidebar-open=always]>.sidebar{max-height:var(--bslib-sidebar-max-height-mobile);overflow-y:auto;border-top:var(--bslib-sidebar-vert-border)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-collapsed)>.sidebar{z-index:1}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-collapsed)>.collapse-toggle{z-index:1}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]){grid-template-columns:100% 0}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-right{grid-template-columns:0 100%}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed{grid-template-columns:0 100%}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed.sidebar-right{grid-template-columns:100% 0}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]):not(.sidebar-right)>.main{padding-left:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-right>.main{padding-right:var(--bslib-sidebar-padding-icon)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always])>.main{opacity:0;transition:opacity var(--bslib-sidebar-transition-easing-x) var(--bslib-sidebar-transition-duration)}.bslib-sidebar-layout:not([data-bslib-sidebar-open=always]).sidebar-collapsed>.main{opacity:1}}.html-fill-container{display:flex;flex-direction:column;min-height:0;min-width:0}.html-fill-container>.html-fill-item{flex:1 1 auto;min-height:0;min-width:0}.html-fill-container>:not(.html-fill-item){flex:0 0 auto}.tippy-box[data-theme~=quarto]{background-color:#fff;border:solid 1px rgb(221.7,222.3,222.9);border-radius:.375rem;color:#212529;font-size:.875rem}.tippy-box[data-theme~=quarto]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=quarto]>.tippy-arrow:after,.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{content:"";position:absolute;z-index:-1}.tippy-box[data-theme~=quarto]>.tippy-arrow:after{border-color:rgba(0,0,0,0);border-style:solid}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-6px}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-6px}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-6px}.tippy-box[data-placement^=left]>.tippy-arrow:before{right:-6px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-arrow:after{border-top-color:rgb(221.7,222.3,222.9);border-width:7px 7px 0;top:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow>svg{top:16px}.tippy-box[data-theme~=quarto][data-placement^=top]>.tippy-svg-arrow:after{top:17px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff;bottom:16px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-arrow:after{border-bottom-color:rgb(221.7,222.3,222.9);border-width:0 7px 7px;bottom:17px;left:1px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow>svg{bottom:15px}.tippy-box[data-theme~=quarto][data-placement^=bottom]>.tippy-svg-arrow:after{bottom:17px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-arrow:after{border-left-color:rgb(221.7,222.3,222.9);border-width:7px 0 7px 7px;left:17px;top:1px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow>svg{left:11px}.tippy-box[data-theme~=quarto][data-placement^=left]>.tippy-svg-arrow:after{left:12px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff;right:16px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-arrow:after{border-width:7px 7px 7px 0;right:17px;top:1px;border-right-color:rgb(221.7,222.3,222.9)}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow>svg{right:11px}.tippy-box[data-theme~=quarto][data-placement^=right]>.tippy-svg-arrow:after{right:12px}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow{fill:#212529}.tippy-box[data-theme~=quarto]>.tippy-svg-arrow:after{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCA2czEuNzk2LS4wMTMgNC42Ny0zLjYxNUM1Ljg1MS45IDYuOTMuMDA2IDggMGMxLjA3LS4wMDYgMi4xNDguODg3IDMuMzQzIDIuMzg1QzE0LjIzMyA2LjAwNSAxNiA2IDE2IDZIMHoiIGZpbGw9InJnYmEoMCwgOCwgMTYsIDAuMikiLz48L3N2Zz4=);background-size:16px 6px;width:16px;height:6px}.top-right{position:absolute;top:1em;right:1em}.visually-hidden{border:0;clip:rect(0 0 0 0);height:auto;margin:0;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.hidden{display:none !important}.zindex-bottom{z-index:-1 !important}figure.figure{display:block}.quarto-layout-panel{margin-bottom:1em}.quarto-layout-panel>figure{width:100%}.quarto-layout-panel>figure>figcaption,.quarto-layout-panel>.panel-caption{margin-top:10pt}.quarto-layout-panel>.table-caption{margin-top:0px}.table-caption p{margin-bottom:.5em}.quarto-layout-row{display:flex;flex-direction:row;align-items:flex-start}.quarto-layout-valign-top{align-items:flex-start}.quarto-layout-valign-bottom{align-items:flex-end}.quarto-layout-valign-center{align-items:center}.quarto-layout-cell{position:relative;margin-right:20px}.quarto-layout-cell:last-child{margin-right:0}.quarto-layout-cell figure,.quarto-layout-cell>p{margin:.2em}.quarto-layout-cell img{max-width:100%}.quarto-layout-cell .html-widget{width:100% !important}.quarto-layout-cell div figure p{margin:0}.quarto-layout-cell figure{display:block;margin-inline-start:0;margin-inline-end:0}.quarto-layout-cell table{display:inline-table}.quarto-layout-cell-subref figcaption,figure .quarto-layout-row figure figcaption{text-align:center;font-style:italic}.quarto-figure{position:relative;margin-bottom:1em}.quarto-figure>figure{width:100%;margin-bottom:0}.quarto-figure-left>figure>p,.quarto-figure-left>figure>div{text-align:left}.quarto-figure-center>figure>p,.quarto-figure-center>figure>div{text-align:center}.quarto-figure-right>figure>p,.quarto-figure-right>figure>div{text-align:right}.quarto-figure>figure>div.cell-annotation,.quarto-figure>figure>div code{text-align:left}figure>p:empty{display:none}figure>p:first-child{margin-top:0;margin-bottom:0}figure>figcaption.quarto-float-caption-bottom{margin-bottom:.5em}figure>figcaption.quarto-float-caption-top{margin-top:.5em}div[id^=tbl-]{position:relative}.quarto-figure>.anchorjs-link{position:absolute;top:.6em;right:.5em}div[id^=tbl-]>.anchorjs-link{position:absolute;top:.7em;right:.3em}.quarto-figure:hover>.anchorjs-link,div[id^=tbl-]:hover>.anchorjs-link,h2:hover>.anchorjs-link,.h2:hover>.anchorjs-link,h3:hover>.anchorjs-link,.h3:hover>.anchorjs-link,h4:hover>.anchorjs-link,.h4:hover>.anchorjs-link,h5:hover>.anchorjs-link,.h5:hover>.anchorjs-link,h6:hover>.anchorjs-link,.h6:hover>.anchorjs-link,.reveal-anchorjs-link>.anchorjs-link{opacity:1}#title-block-header{margin-block-end:1rem;position:relative;margin-top:-1px}#title-block-header .abstract{margin-block-start:1rem}#title-block-header .abstract .abstract-title{font-weight:600}#title-block-header a{text-decoration:none}#title-block-header .author,#title-block-header .date,#title-block-header .doi{margin-block-end:.2rem}#title-block-header .quarto-title-block>div{display:flex}#title-block-header .quarto-title-block>div>h1,#title-block-header .quarto-title-block>div>.h1{flex-grow:1}#title-block-header .quarto-title-block>div>button{flex-shrink:0;height:2.25rem;margin-top:0}@media(min-width: 992px){#title-block-header .quarto-title-block>div>button{margin-top:5px}}tr.header>th>p:last-of-type{margin-bottom:0px}table,table.table{margin-top:.5rem;margin-bottom:.5rem}caption,.table-caption{padding-top:.5rem;padding-bottom:.5rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-top{margin-top:.5rem;margin-bottom:.25rem;text-align:center}figure.quarto-float-tbl figcaption.quarto-float-caption-bottom{padding-top:.25rem;margin-bottom:.5rem;text-align:center}.utterances{max-width:none;margin-left:-8px}iframe{margin-bottom:1em}details{margin-bottom:1em}details[show]{margin-bottom:0}details>summary{color:rgba(33,37,41,.75)}details>summary>p:only-child{display:inline}div.code-copy-outer-scaffold{position:relative}dd code:not(.sourceCode),p code:not(.sourceCode){white-space:pre-wrap}code{white-space:pre}@media print{code{white-space:pre-wrap}}pre>code{display:block}pre>code.sourceCode{white-space:pre}pre>code.sourceCode>span>a:first-child::before{text-decoration:none}pre.code-overflow-wrap>code.sourceCode{white-space:pre-wrap}pre.code-overflow-scroll>code.sourceCode{white-space:pre}code a:any-link{color:inherit;text-decoration:none}code a:hover{color:inherit;text-decoration:underline}ul.task-list{padding-left:1em}[data-tippy-root]{display:inline-block}.tippy-content .footnote-back{display:none}.footnote-back{margin-left:.2em}.tippy-content{overflow-x:auto}.quarto-embedded-source-code{display:none}.quarto-unresolved-ref{font-weight:600}.quarto-cover-image{max-width:35%;float:right;margin-left:30px}.cell-output-display .widget-subarea{margin-bottom:1em}.cell-output-display:not(.no-overflow-x),.knitsql-table:not(.no-overflow-x){overflow-x:auto}.panel-input{margin-bottom:1em}.panel-input>div,.panel-input>div>div{display:inline-block;vertical-align:top;padding-right:12px}.panel-input>p:last-child{margin-bottom:0}.layout-sidebar{margin-bottom:1em}.layout-sidebar .tab-content{border:none}.tab-content>.page-columns.active{display:grid}div.sourceCode>iframe{width:100%;height:300px;margin-bottom:-0.5em}a{text-underline-offset:3px}.callout pre.sourceCode{padding-left:0}div.ansi-escaped-output{font-family:monospace;display:block}/*! +* +* ansi colors from IPython notebook's +* +* we also add `bright-[color]-` synonyms for the `-[color]-intense` classes since +* that seems to be what ansi_up emits +* +*/.ansi-black-fg{color:#3e424d}.ansi-black-bg{background-color:#3e424d}.ansi-black-intense-black,.ansi-bright-black-fg{color:#282c36}.ansi-black-intense-black,.ansi-bright-black-bg{background-color:#282c36}.ansi-red-fg{color:#e75c58}.ansi-red-bg{background-color:#e75c58}.ansi-red-intense-red,.ansi-bright-red-fg{color:#b22b31}.ansi-red-intense-red,.ansi-bright-red-bg{background-color:#b22b31}.ansi-green-fg{color:#00a250}.ansi-green-bg{background-color:#00a250}.ansi-green-intense-green,.ansi-bright-green-fg{color:#007427}.ansi-green-intense-green,.ansi-bright-green-bg{background-color:#007427}.ansi-yellow-fg{color:#ddb62b}.ansi-yellow-bg{background-color:#ddb62b}.ansi-yellow-intense-yellow,.ansi-bright-yellow-fg{color:#b27d12}.ansi-yellow-intense-yellow,.ansi-bright-yellow-bg{background-color:#b27d12}.ansi-blue-fg{color:#208ffb}.ansi-blue-bg{background-color:#208ffb}.ansi-blue-intense-blue,.ansi-bright-blue-fg{color:#0065ca}.ansi-blue-intense-blue,.ansi-bright-blue-bg{background-color:#0065ca}.ansi-magenta-fg{color:#d160c4}.ansi-magenta-bg{background-color:#d160c4}.ansi-magenta-intense-magenta,.ansi-bright-magenta-fg{color:#a03196}.ansi-magenta-intense-magenta,.ansi-bright-magenta-bg{background-color:#a03196}.ansi-cyan-fg{color:#60c6c8}.ansi-cyan-bg{background-color:#60c6c8}.ansi-cyan-intense-cyan,.ansi-bright-cyan-fg{color:#258f8f}.ansi-cyan-intense-cyan,.ansi-bright-cyan-bg{background-color:#258f8f}.ansi-white-fg{color:#c5c1b4}.ansi-white-bg{background-color:#c5c1b4}.ansi-white-intense-white,.ansi-bright-white-fg{color:#a1a6b2}.ansi-white-intense-white,.ansi-bright-white-bg{background-color:#a1a6b2}.ansi-default-inverse-fg{color:#fff}.ansi-default-inverse-bg{background-color:#000}.ansi-bold{font-weight:bold}.ansi-underline{text-decoration:underline}:root{--quarto-body-bg: #ffffff;--quarto-body-color: #212529;--quarto-text-muted: rgba(33, 37, 41, 0.75);--quarto-border-color: rgb(221.7, 222.3, 222.9);--quarto-border-width: 1px;--quarto-border-radius: 0.375rem}table.gt_table{color:var(--quarto-body-color);font-size:1em;width:100%;background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_column_spanner_outer{color:var(--quarto-body-color);background-color:rgba(0,0,0,0);border-top-width:inherit;border-bottom-width:inherit;border-color:var(--quarto-border-color)}table.gt_table th.gt_col_heading{color:var(--quarto-body-color);font-weight:bold;background-color:rgba(0,0,0,0)}table.gt_table thead.gt_col_headings{border-bottom:1px solid currentColor;border-top-width:inherit;border-top-color:var(--quarto-border-color)}table.gt_table thead.gt_col_headings:not(:first-child){border-top-width:1px;border-top-color:var(--quarto-border-color)}table.gt_table td.gt_row{border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-width:0px}table.gt_table tbody.gt_table_body{border-top-width:1px;border-bottom-width:1px;border-bottom-color:var(--quarto-border-color);border-top-color:currentColor}div.columns{display:initial;gap:initial}div.column{display:inline-block;overflow-x:initial;vertical-align:top;width:50%}.code-annotation-tip-content{word-wrap:break-word}.code-annotation-container-hidden{display:none !important}dl.code-annotation-container-grid{display:grid;grid-template-columns:min-content auto}dl.code-annotation-container-grid dt{grid-column:1}dl.code-annotation-container-grid dd{grid-column:2}pre.sourceCode.code-annotation-code{padding-right:0}code.sourceCode .code-annotation-anchor{z-index:100;position:relative;float:right;background-color:rgba(0,0,0,0)}input[type=checkbox]{margin-right:.5ch}:root{--mermaid-bg-color: #ffffff;--mermaid-edge-color: #6c757d;--mermaid-node-fg-color: #212529;--mermaid-fg-color: #212529;--mermaid-fg-color--lighter: rgb(55.7432432432, 62.5, 69.2567567568);--mermaid-fg-color--lightest: rgb(78.4864864865, 88, 97.5135135135);--mermaid-font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Noto Sans, Liberation Sans, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;--mermaid-label-bg-color: #ffffff;--mermaid-label-fg-color: #0d6efd;--mermaid-node-bg-color: rgba(13, 110, 253, 0.1);--mermaid-node-fg-color: #212529}@media print{:root{font-size:11pt}#quarto-sidebar,#TOC,.nav-page{display:none}.page-columns .content{grid-column-start:page-start}.fixed-top{position:relative}.panel-caption,.figure-caption,figcaption{color:#666}}body.quarto-light .dark-content{display:none !important}body.quarto-dark .light-content{display:none !important}.code-copy-button{position:absolute;top:0;right:0;border:0;margin-top:5px;margin-right:5px;background-color:rgba(0,0,0,0);z-index:3}.code-copy-button-tooltip{font-size:.75em}div.code-copy-outer-scaffold:hover>.code-copy-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}div.code-copy-outer-scaffold:hover>.code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}div.code-copy-outer-scaffold:hover>.code-copy-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}div.code-copy-outer-scaffold:hover>.code-copy-button-checked:hover>.bi::before{background-image:url('data:image/svg+xml,')}main ol ol,main ul ul,main ol ul,main ul ol{margin-bottom:1em}ul>li:not(:has(>p))>ul,ol>li:not(:has(>p))>ul,ul>li:not(:has(>p))>ol,ol>li:not(:has(>p))>ol{margin-bottom:0}ul>li:not(:has(>p))>ul>li:has(>p),ol>li:not(:has(>p))>ul>li:has(>p),ul>li:not(:has(>p))>ol>li:has(>p),ol>li:not(:has(>p))>ol>li:has(>p){margin-top:1rem}body{margin:0}main.page-columns>header>h1.title,main.page-columns>header>.title.h1{margin-bottom:0}@media(min-width: 992px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] 35px [page-end-inset page-end] 5fr [screen-end-inset] 1.5em}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset] 35px [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(850px - 3em)) [body-content-end] 3em [body-end] 50px [body-end-outset] minmax(0px, 250px) [page-end-inset] minmax(50px, 100px) [page-end] 1fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 175px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 175px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(25px, 50px) [page-start-inset] minmax(50px, 150px) [body-start-outset] minmax(25px, 50px) [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 100px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 50px [page-start-inset] minmax(50px, 150px) [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(450px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start] minmax(50px, 100px) [page-start-inset] 50px [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(0px, 200px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 50px [page-start-inset] minmax(50px, 150px) [body-start-outset] 50px [body-start] 1.5em [body-content-start] minmax(450px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(50px, 150px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] minmax(25px, 50px) [page-start-inset] minmax(50px, 150px) [body-start-outset] minmax(25px, 50px) [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] minmax(25px, 50px) [body-end-outset] minmax(50px, 150px) [page-end-inset] minmax(25px, 50px) [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 991.98px){body .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.fullcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.slimcontent:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.listing:not(.floating):not(.docked) .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset] 5fr [body-start] 1.5em [body-content-start] minmax(500px, calc(1250px - 3em)) [body-content-end body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 145px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start] 35px [page-start-inset] minmax(0px, 145px) [body-start-outset] 35px [body-start] 1.5em [body-content-start] minmax(450px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1.5em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(1000px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(800px - 3em)) [body-content-end] 1.5em [body-end body-end-outset page-end-inset page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.docked.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.docked.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(25px, 50px) [page-end-inset] 50px [page-end] 5fr [screen-end-inset] 1.5em [screen-end]}body.floating.slimcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 35px [body-end-outset] minmax(75px, 145px) [page-end-inset] 35px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}body.floating.listing .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset] 5fr [page-start page-start-inset body-start-outset body-start] 1em [body-content-start] minmax(500px, calc(750px - 3em)) [body-content-end] 1.5em [body-end] 50px [body-end-outset] minmax(75px, 150px) [page-end-inset] 25px [page-end] 4fr [screen-end-inset] 1.5em [screen-end]}}@media(max-width: 767.98px){body .page-columns,body.fullcontent:not(.floating):not(.docked) .page-columns,body.slimcontent:not(.floating):not(.docked) .page-columns,body.docked .page-columns,body.docked.slimcontent .page-columns,body.docked.fullcontent .page-columns,body.floating .page-columns,body.floating.slimcontent .page-columns,body.floating.fullcontent .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}body:not(.floating):not(.docked) .page-columns.toc-left .page-columns{display:grid;gap:0;grid-template-columns:[screen-start] 1.5em [screen-start-inset page-start page-start-inset body-start-outset body-start body-content-start] minmax(0px, 1fr) [body-content-end body-end body-end-outset page-end-inset page-end screen-end-inset] 1.5em [screen-end]}nav[role=doc-toc]{display:none}}body,.page-row-navigation{grid-template-rows:[page-top] max-content [contents-top] max-content [contents-bottom] max-content [page-bottom]}.page-rows-contents{grid-template-rows:[content-top] minmax(max-content, 1fr) [content-bottom] minmax(60px, max-content) [page-bottom]}.page-full{grid-column:screen-start/screen-end !important}.page-columns>*{grid-column:body-content-start/body-content-end}.page-columns.column-page>*{grid-column:page-start/page-end}.page-columns.column-page-left .page-columns.page-full>*,.page-columns.column-page-left>*{grid-column:page-start/body-content-end}.page-columns.column-page-right .page-columns.page-full>*,.page-columns.column-page-right>*{grid-column:body-content-start/page-end}.page-rows{grid-auto-rows:auto}.header{grid-column:screen-start/screen-end;grid-row:page-top/contents-top}#quarto-content{padding:0;grid-column:screen-start/screen-end;grid-row:contents-top/contents-bottom}body.floating .sidebar.sidebar-navigation{grid-column:page-start/body-start;grid-row:content-top/page-bottom}body.docked .sidebar.sidebar-navigation{grid-column:screen-start/body-start;grid-row:content-top/page-bottom}.sidebar.toc-left{grid-column:page-start/body-start;grid-row:content-top/page-bottom}.sidebar.margin-sidebar{grid-column:body-end/page-end;grid-row:content-top/page-bottom}.page-columns .content{grid-column:body-content-start/body-content-end;grid-row:content-top/content-bottom;align-content:flex-start}.page-columns .page-navigation{grid-column:body-content-start/body-content-end;grid-row:content-bottom/page-bottom}.page-columns .footer{grid-column:screen-start/screen-end;grid-row:contents-bottom/page-bottom}.page-columns .column-body{grid-column:body-content-start/body-content-end}.page-columns .column-body-fullbleed{grid-column:body-start/body-end}.page-columns .column-body-outset{grid-column:body-start-outset/body-end-outset;z-index:998;opacity:.999}.page-columns .column-body-outset table{background:#fff}.page-columns .column-body-outset-left{grid-column:body-start-outset/body-content-end;z-index:998;opacity:.999}.page-columns .column-body-outset-left table{background:#fff}.page-columns .column-body-outset-right{grid-column:body-content-start/body-end-outset;z-index:998;opacity:.999}.page-columns .column-body-outset-right table{background:#fff}.page-columns .column-page{grid-column:page-start/page-end;z-index:998;opacity:.999}.page-columns .column-page table{background:#fff}.page-columns .column-page-inset{grid-column:page-start-inset/page-end-inset;z-index:998;opacity:.999}.page-columns .column-page-inset table{background:#fff}.page-columns .column-page-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-page-inset-left table{background:#fff}.page-columns .column-page-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;opacity:.999}.page-columns .column-page-inset-right figcaption table{background:#fff}.page-columns .column-page-left{grid-column:page-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-page-left table{background:#fff}.page-columns .column-page-right{grid-column:body-content-start/page-end;z-index:998;opacity:.999}.page-columns .column-page-right figcaption table{background:#fff}#quarto-content.page-columns #quarto-margin-sidebar,#quarto-content.page-columns #quarto-sidebar{z-index:1}@media(max-width: 991.98px){#quarto-content.page-columns #quarto-margin-sidebar.collapse,#quarto-content.page-columns #quarto-sidebar.collapse,#quarto-content.page-columns #quarto-margin-sidebar.collapsing,#quarto-content.page-columns #quarto-sidebar.collapsing{z-index:1055}}#quarto-content.page-columns main.column-page,#quarto-content.page-columns main.column-page-right,#quarto-content.page-columns main.column-page-left{z-index:0}.page-columns .column-screen-inset{grid-column:screen-start-inset/screen-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:screen-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/screen-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:screen-start/screen-end;z-index:998;opacity:.999}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:screen-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/screen-end;z-index:998;opacity:.999}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:screen-start/screen-end;padding:1em;background:#f8f9fa;z-index:998;opacity:.999;margin-bottom:1em}.zindex-content{z-index:998;opacity:.999}.zindex-modal{z-index:1055;opacity:.999}.zindex-over-content{z-index:999;opacity:.999}img.img-fluid.column-screen,img.img-fluid.column-screen-inset-shaded,img.img-fluid.column-screen-inset,img.img-fluid.column-screen-inset-left,img.img-fluid.column-screen-inset-right,img.img-fluid.column-screen-left,img.img-fluid.column-screen-right{width:100%}@media(min-width: 992px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-end/page-end !important;z-index:998}.column-sidebar{grid-column:page-start/body-start !important;z-index:998}.column-leftmargin{grid-column:screen-start-inset/body-start !important;z-index:998}.no-row-height{height:1em;overflow:visible}}@media(max-width: 991.98px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-end/page-end !important;z-index:998}.no-row-height{height:1em;overflow:visible}.page-columns.page-full{overflow:visible}.page-columns.toc-left .margin-caption,.page-columns.toc-left div.aside,.page-columns.toc-left aside:not(.footnotes):not(.sidebar),.page-columns.toc-left .column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;opacity:.999}.page-columns.toc-left .no-row-height{height:initial;overflow:initial}}@media(max-width: 767.98px){.margin-caption,div.aside,aside:not(.footnotes):not(.sidebar),.column-margin{grid-column:body-content-start/body-content-end !important;z-index:998;opacity:.999}.no-row-height{height:initial;overflow:initial}#quarto-margin-sidebar{display:none}#quarto-sidebar-toc-left{display:none}.hidden-sm{display:none}}.panel-grid{display:grid;grid-template-rows:repeat(1, 1fr);grid-template-columns:repeat(24, 1fr);gap:1em}.panel-grid .g-col-1{grid-column:auto/span 1}.panel-grid .g-col-2{grid-column:auto/span 2}.panel-grid .g-col-3{grid-column:auto/span 3}.panel-grid .g-col-4{grid-column:auto/span 4}.panel-grid .g-col-5{grid-column:auto/span 5}.panel-grid .g-col-6{grid-column:auto/span 6}.panel-grid .g-col-7{grid-column:auto/span 7}.panel-grid .g-col-8{grid-column:auto/span 8}.panel-grid .g-col-9{grid-column:auto/span 9}.panel-grid .g-col-10{grid-column:auto/span 10}.panel-grid .g-col-11{grid-column:auto/span 11}.panel-grid .g-col-12{grid-column:auto/span 12}.panel-grid .g-col-13{grid-column:auto/span 13}.panel-grid .g-col-14{grid-column:auto/span 14}.panel-grid .g-col-15{grid-column:auto/span 15}.panel-grid .g-col-16{grid-column:auto/span 16}.panel-grid .g-col-17{grid-column:auto/span 17}.panel-grid .g-col-18{grid-column:auto/span 18}.panel-grid .g-col-19{grid-column:auto/span 19}.panel-grid .g-col-20{grid-column:auto/span 20}.panel-grid .g-col-21{grid-column:auto/span 21}.panel-grid .g-col-22{grid-column:auto/span 22}.panel-grid .g-col-23{grid-column:auto/span 23}.panel-grid .g-col-24{grid-column:auto/span 24}.panel-grid .g-start-1{grid-column-start:1}.panel-grid .g-start-2{grid-column-start:2}.panel-grid .g-start-3{grid-column-start:3}.panel-grid .g-start-4{grid-column-start:4}.panel-grid .g-start-5{grid-column-start:5}.panel-grid .g-start-6{grid-column-start:6}.panel-grid .g-start-7{grid-column-start:7}.panel-grid .g-start-8{grid-column-start:8}.panel-grid .g-start-9{grid-column-start:9}.panel-grid .g-start-10{grid-column-start:10}.panel-grid .g-start-11{grid-column-start:11}.panel-grid .g-start-12{grid-column-start:12}.panel-grid .g-start-13{grid-column-start:13}.panel-grid .g-start-14{grid-column-start:14}.panel-grid .g-start-15{grid-column-start:15}.panel-grid .g-start-16{grid-column-start:16}.panel-grid .g-start-17{grid-column-start:17}.panel-grid .g-start-18{grid-column-start:18}.panel-grid .g-start-19{grid-column-start:19}.panel-grid .g-start-20{grid-column-start:20}.panel-grid .g-start-21{grid-column-start:21}.panel-grid .g-start-22{grid-column-start:22}.panel-grid .g-start-23{grid-column-start:23}@media(min-width: 576px){.panel-grid .g-col-sm-1{grid-column:auto/span 1}.panel-grid .g-col-sm-2{grid-column:auto/span 2}.panel-grid .g-col-sm-3{grid-column:auto/span 3}.panel-grid .g-col-sm-4{grid-column:auto/span 4}.panel-grid .g-col-sm-5{grid-column:auto/span 5}.panel-grid .g-col-sm-6{grid-column:auto/span 6}.panel-grid .g-col-sm-7{grid-column:auto/span 7}.panel-grid .g-col-sm-8{grid-column:auto/span 8}.panel-grid .g-col-sm-9{grid-column:auto/span 9}.panel-grid .g-col-sm-10{grid-column:auto/span 10}.panel-grid .g-col-sm-11{grid-column:auto/span 11}.panel-grid .g-col-sm-12{grid-column:auto/span 12}.panel-grid .g-col-sm-13{grid-column:auto/span 13}.panel-grid .g-col-sm-14{grid-column:auto/span 14}.panel-grid .g-col-sm-15{grid-column:auto/span 15}.panel-grid .g-col-sm-16{grid-column:auto/span 16}.panel-grid .g-col-sm-17{grid-column:auto/span 17}.panel-grid .g-col-sm-18{grid-column:auto/span 18}.panel-grid .g-col-sm-19{grid-column:auto/span 19}.panel-grid .g-col-sm-20{grid-column:auto/span 20}.panel-grid .g-col-sm-21{grid-column:auto/span 21}.panel-grid .g-col-sm-22{grid-column:auto/span 22}.panel-grid .g-col-sm-23{grid-column:auto/span 23}.panel-grid .g-col-sm-24{grid-column:auto/span 24}.panel-grid .g-start-sm-1{grid-column-start:1}.panel-grid .g-start-sm-2{grid-column-start:2}.panel-grid .g-start-sm-3{grid-column-start:3}.panel-grid .g-start-sm-4{grid-column-start:4}.panel-grid .g-start-sm-5{grid-column-start:5}.panel-grid .g-start-sm-6{grid-column-start:6}.panel-grid .g-start-sm-7{grid-column-start:7}.panel-grid .g-start-sm-8{grid-column-start:8}.panel-grid .g-start-sm-9{grid-column-start:9}.panel-grid .g-start-sm-10{grid-column-start:10}.panel-grid .g-start-sm-11{grid-column-start:11}.panel-grid .g-start-sm-12{grid-column-start:12}.panel-grid .g-start-sm-13{grid-column-start:13}.panel-grid .g-start-sm-14{grid-column-start:14}.panel-grid .g-start-sm-15{grid-column-start:15}.panel-grid .g-start-sm-16{grid-column-start:16}.panel-grid .g-start-sm-17{grid-column-start:17}.panel-grid .g-start-sm-18{grid-column-start:18}.panel-grid .g-start-sm-19{grid-column-start:19}.panel-grid .g-start-sm-20{grid-column-start:20}.panel-grid .g-start-sm-21{grid-column-start:21}.panel-grid .g-start-sm-22{grid-column-start:22}.panel-grid .g-start-sm-23{grid-column-start:23}}@media(min-width: 768px){.panel-grid .g-col-md-1{grid-column:auto/span 1}.panel-grid .g-col-md-2{grid-column:auto/span 2}.panel-grid .g-col-md-3{grid-column:auto/span 3}.panel-grid .g-col-md-4{grid-column:auto/span 4}.panel-grid .g-col-md-5{grid-column:auto/span 5}.panel-grid .g-col-md-6{grid-column:auto/span 6}.panel-grid .g-col-md-7{grid-column:auto/span 7}.panel-grid .g-col-md-8{grid-column:auto/span 8}.panel-grid .g-col-md-9{grid-column:auto/span 9}.panel-grid .g-col-md-10{grid-column:auto/span 10}.panel-grid .g-col-md-11{grid-column:auto/span 11}.panel-grid .g-col-md-12{grid-column:auto/span 12}.panel-grid .g-col-md-13{grid-column:auto/span 13}.panel-grid .g-col-md-14{grid-column:auto/span 14}.panel-grid .g-col-md-15{grid-column:auto/span 15}.panel-grid .g-col-md-16{grid-column:auto/span 16}.panel-grid .g-col-md-17{grid-column:auto/span 17}.panel-grid .g-col-md-18{grid-column:auto/span 18}.panel-grid .g-col-md-19{grid-column:auto/span 19}.panel-grid .g-col-md-20{grid-column:auto/span 20}.panel-grid .g-col-md-21{grid-column:auto/span 21}.panel-grid .g-col-md-22{grid-column:auto/span 22}.panel-grid .g-col-md-23{grid-column:auto/span 23}.panel-grid .g-col-md-24{grid-column:auto/span 24}.panel-grid .g-start-md-1{grid-column-start:1}.panel-grid .g-start-md-2{grid-column-start:2}.panel-grid .g-start-md-3{grid-column-start:3}.panel-grid .g-start-md-4{grid-column-start:4}.panel-grid .g-start-md-5{grid-column-start:5}.panel-grid .g-start-md-6{grid-column-start:6}.panel-grid .g-start-md-7{grid-column-start:7}.panel-grid .g-start-md-8{grid-column-start:8}.panel-grid .g-start-md-9{grid-column-start:9}.panel-grid .g-start-md-10{grid-column-start:10}.panel-grid .g-start-md-11{grid-column-start:11}.panel-grid .g-start-md-12{grid-column-start:12}.panel-grid .g-start-md-13{grid-column-start:13}.panel-grid .g-start-md-14{grid-column-start:14}.panel-grid .g-start-md-15{grid-column-start:15}.panel-grid .g-start-md-16{grid-column-start:16}.panel-grid .g-start-md-17{grid-column-start:17}.panel-grid .g-start-md-18{grid-column-start:18}.panel-grid .g-start-md-19{grid-column-start:19}.panel-grid .g-start-md-20{grid-column-start:20}.panel-grid .g-start-md-21{grid-column-start:21}.panel-grid .g-start-md-22{grid-column-start:22}.panel-grid .g-start-md-23{grid-column-start:23}}@media(min-width: 992px){.panel-grid .g-col-lg-1{grid-column:auto/span 1}.panel-grid .g-col-lg-2{grid-column:auto/span 2}.panel-grid .g-col-lg-3{grid-column:auto/span 3}.panel-grid .g-col-lg-4{grid-column:auto/span 4}.panel-grid .g-col-lg-5{grid-column:auto/span 5}.panel-grid .g-col-lg-6{grid-column:auto/span 6}.panel-grid .g-col-lg-7{grid-column:auto/span 7}.panel-grid .g-col-lg-8{grid-column:auto/span 8}.panel-grid .g-col-lg-9{grid-column:auto/span 9}.panel-grid .g-col-lg-10{grid-column:auto/span 10}.panel-grid .g-col-lg-11{grid-column:auto/span 11}.panel-grid .g-col-lg-12{grid-column:auto/span 12}.panel-grid .g-col-lg-13{grid-column:auto/span 13}.panel-grid .g-col-lg-14{grid-column:auto/span 14}.panel-grid .g-col-lg-15{grid-column:auto/span 15}.panel-grid .g-col-lg-16{grid-column:auto/span 16}.panel-grid .g-col-lg-17{grid-column:auto/span 17}.panel-grid .g-col-lg-18{grid-column:auto/span 18}.panel-grid .g-col-lg-19{grid-column:auto/span 19}.panel-grid .g-col-lg-20{grid-column:auto/span 20}.panel-grid .g-col-lg-21{grid-column:auto/span 21}.panel-grid .g-col-lg-22{grid-column:auto/span 22}.panel-grid .g-col-lg-23{grid-column:auto/span 23}.panel-grid .g-col-lg-24{grid-column:auto/span 24}.panel-grid .g-start-lg-1{grid-column-start:1}.panel-grid .g-start-lg-2{grid-column-start:2}.panel-grid .g-start-lg-3{grid-column-start:3}.panel-grid .g-start-lg-4{grid-column-start:4}.panel-grid .g-start-lg-5{grid-column-start:5}.panel-grid .g-start-lg-6{grid-column-start:6}.panel-grid .g-start-lg-7{grid-column-start:7}.panel-grid .g-start-lg-8{grid-column-start:8}.panel-grid .g-start-lg-9{grid-column-start:9}.panel-grid .g-start-lg-10{grid-column-start:10}.panel-grid .g-start-lg-11{grid-column-start:11}.panel-grid .g-start-lg-12{grid-column-start:12}.panel-grid .g-start-lg-13{grid-column-start:13}.panel-grid .g-start-lg-14{grid-column-start:14}.panel-grid .g-start-lg-15{grid-column-start:15}.panel-grid .g-start-lg-16{grid-column-start:16}.panel-grid .g-start-lg-17{grid-column-start:17}.panel-grid .g-start-lg-18{grid-column-start:18}.panel-grid .g-start-lg-19{grid-column-start:19}.panel-grid .g-start-lg-20{grid-column-start:20}.panel-grid .g-start-lg-21{grid-column-start:21}.panel-grid .g-start-lg-22{grid-column-start:22}.panel-grid .g-start-lg-23{grid-column-start:23}}@media(min-width: 1200px){.panel-grid .g-col-xl-1{grid-column:auto/span 1}.panel-grid .g-col-xl-2{grid-column:auto/span 2}.panel-grid .g-col-xl-3{grid-column:auto/span 3}.panel-grid .g-col-xl-4{grid-column:auto/span 4}.panel-grid .g-col-xl-5{grid-column:auto/span 5}.panel-grid .g-col-xl-6{grid-column:auto/span 6}.panel-grid .g-col-xl-7{grid-column:auto/span 7}.panel-grid .g-col-xl-8{grid-column:auto/span 8}.panel-grid .g-col-xl-9{grid-column:auto/span 9}.panel-grid .g-col-xl-10{grid-column:auto/span 10}.panel-grid .g-col-xl-11{grid-column:auto/span 11}.panel-grid .g-col-xl-12{grid-column:auto/span 12}.panel-grid .g-col-xl-13{grid-column:auto/span 13}.panel-grid .g-col-xl-14{grid-column:auto/span 14}.panel-grid .g-col-xl-15{grid-column:auto/span 15}.panel-grid .g-col-xl-16{grid-column:auto/span 16}.panel-grid .g-col-xl-17{grid-column:auto/span 17}.panel-grid .g-col-xl-18{grid-column:auto/span 18}.panel-grid .g-col-xl-19{grid-column:auto/span 19}.panel-grid .g-col-xl-20{grid-column:auto/span 20}.panel-grid .g-col-xl-21{grid-column:auto/span 21}.panel-grid .g-col-xl-22{grid-column:auto/span 22}.panel-grid .g-col-xl-23{grid-column:auto/span 23}.panel-grid .g-col-xl-24{grid-column:auto/span 24}.panel-grid .g-start-xl-1{grid-column-start:1}.panel-grid .g-start-xl-2{grid-column-start:2}.panel-grid .g-start-xl-3{grid-column-start:3}.panel-grid .g-start-xl-4{grid-column-start:4}.panel-grid .g-start-xl-5{grid-column-start:5}.panel-grid .g-start-xl-6{grid-column-start:6}.panel-grid .g-start-xl-7{grid-column-start:7}.panel-grid .g-start-xl-8{grid-column-start:8}.panel-grid .g-start-xl-9{grid-column-start:9}.panel-grid .g-start-xl-10{grid-column-start:10}.panel-grid .g-start-xl-11{grid-column-start:11}.panel-grid .g-start-xl-12{grid-column-start:12}.panel-grid .g-start-xl-13{grid-column-start:13}.panel-grid .g-start-xl-14{grid-column-start:14}.panel-grid .g-start-xl-15{grid-column-start:15}.panel-grid .g-start-xl-16{grid-column-start:16}.panel-grid .g-start-xl-17{grid-column-start:17}.panel-grid .g-start-xl-18{grid-column-start:18}.panel-grid .g-start-xl-19{grid-column-start:19}.panel-grid .g-start-xl-20{grid-column-start:20}.panel-grid .g-start-xl-21{grid-column-start:21}.panel-grid .g-start-xl-22{grid-column-start:22}.panel-grid .g-start-xl-23{grid-column-start:23}}@media(min-width: 1400px){.panel-grid .g-col-xxl-1{grid-column:auto/span 1}.panel-grid .g-col-xxl-2{grid-column:auto/span 2}.panel-grid .g-col-xxl-3{grid-column:auto/span 3}.panel-grid .g-col-xxl-4{grid-column:auto/span 4}.panel-grid .g-col-xxl-5{grid-column:auto/span 5}.panel-grid .g-col-xxl-6{grid-column:auto/span 6}.panel-grid .g-col-xxl-7{grid-column:auto/span 7}.panel-grid .g-col-xxl-8{grid-column:auto/span 8}.panel-grid .g-col-xxl-9{grid-column:auto/span 9}.panel-grid .g-col-xxl-10{grid-column:auto/span 10}.panel-grid .g-col-xxl-11{grid-column:auto/span 11}.panel-grid .g-col-xxl-12{grid-column:auto/span 12}.panel-grid .g-col-xxl-13{grid-column:auto/span 13}.panel-grid .g-col-xxl-14{grid-column:auto/span 14}.panel-grid .g-col-xxl-15{grid-column:auto/span 15}.panel-grid .g-col-xxl-16{grid-column:auto/span 16}.panel-grid .g-col-xxl-17{grid-column:auto/span 17}.panel-grid .g-col-xxl-18{grid-column:auto/span 18}.panel-grid .g-col-xxl-19{grid-column:auto/span 19}.panel-grid .g-col-xxl-20{grid-column:auto/span 20}.panel-grid .g-col-xxl-21{grid-column:auto/span 21}.panel-grid .g-col-xxl-22{grid-column:auto/span 22}.panel-grid .g-col-xxl-23{grid-column:auto/span 23}.panel-grid .g-col-xxl-24{grid-column:auto/span 24}.panel-grid .g-start-xxl-1{grid-column-start:1}.panel-grid .g-start-xxl-2{grid-column-start:2}.panel-grid .g-start-xxl-3{grid-column-start:3}.panel-grid .g-start-xxl-4{grid-column-start:4}.panel-grid .g-start-xxl-5{grid-column-start:5}.panel-grid .g-start-xxl-6{grid-column-start:6}.panel-grid .g-start-xxl-7{grid-column-start:7}.panel-grid .g-start-xxl-8{grid-column-start:8}.panel-grid .g-start-xxl-9{grid-column-start:9}.panel-grid .g-start-xxl-10{grid-column-start:10}.panel-grid .g-start-xxl-11{grid-column-start:11}.panel-grid .g-start-xxl-12{grid-column-start:12}.panel-grid .g-start-xxl-13{grid-column-start:13}.panel-grid .g-start-xxl-14{grid-column-start:14}.panel-grid .g-start-xxl-15{grid-column-start:15}.panel-grid .g-start-xxl-16{grid-column-start:16}.panel-grid .g-start-xxl-17{grid-column-start:17}.panel-grid .g-start-xxl-18{grid-column-start:18}.panel-grid .g-start-xxl-19{grid-column-start:19}.panel-grid .g-start-xxl-20{grid-column-start:20}.panel-grid .g-start-xxl-21{grid-column-start:21}.panel-grid .g-start-xxl-22{grid-column-start:22}.panel-grid .g-start-xxl-23{grid-column-start:23}}main{margin-top:1em;margin-bottom:1em}h1,.h1,h2,.h2{color:inherit;margin-top:2rem;margin-bottom:1rem;font-weight:600}h1.title,.title.h1{margin-top:0}main.content>p:has(+section){margin-bottom:2rem}main.content>section:first-of-type>h2:nth-child(1),main.content>section:first-of-type>.h2:nth-child(1){margin-top:0}h2,.h2{border-bottom:1px solid rgb(221.7,222.3,222.9);padding-bottom:.5rem}h3,.h3{font-weight:600}h3,.h3,h4,.h4{opacity:.9;margin-top:1.5rem}h5,.h5,h6,.h6{opacity:.9}.header-section-number{color:hsl(210,10.8108108108%,39.5098039216%)}.nav-link.active .header-section-number{color:inherit}mark,.mark{padding:0em}.panel-caption,.figure-caption,.subfigure-caption,.table-caption,figcaption,caption{font-size:.9rem;color:hsl(210,10.8108108108%,39.5098039216%)}.quarto-layout-cell[data-ref-parent] caption{color:hsl(210,10.8108108108%,39.5098039216%)}.column-margin figcaption,.margin-caption,div.aside,aside,.column-margin{color:hsl(210,10.8108108108%,39.5098039216%);font-size:.825rem}.panel-caption.margin-caption{text-align:inherit}.column-margin.column-container p{margin-bottom:0}.column-margin.column-container>*:not(.collapse):first-child{padding-bottom:.5em;display:block}.column-margin.column-container>*:not(.collapse):not(:first-child){padding-top:.5em;padding-bottom:.5em;display:block}body.quarto-dark .column-margin.column-container>.light-content+.dark-content{padding-top:0}.column-margin.column-container>*.collapse:not(.show){display:none}@media(min-width: 768px){.column-margin.column-container .callout-margin-content:first-child{margin-top:4.5em}.column-margin.column-container .callout-margin-content-simple:first-child{margin-top:3.5em}}.margin-caption>*{padding-top:.5em;padding-bottom:.5em}@media(max-width: 767.98px){.quarto-layout-row{flex-direction:column}}.nav-tabs .nav-item{margin-top:1px;cursor:pointer}.tab-content{margin-top:0px;border-left:rgb(221.7,222.3,222.9) 1px solid;border-right:rgb(221.7,222.3,222.9) 1px solid;border-bottom:rgb(221.7,222.3,222.9) 1px solid;margin-left:0;padding:1em;margin-bottom:1em}@media(max-width: 767.98px){.layout-sidebar{margin-left:0;margin-right:0}}.panel-sidebar,.panel-sidebar .form-control,.panel-input,.panel-input .form-control,.selectize-dropdown{font-size:.9rem}.panel-sidebar .form-control,.panel-input .form-control{padding-top:.1rem}.tab-pane div.sourceCode{margin-top:0px}.tab-pane>p{padding-top:0}.tab-pane>p:nth-child(1){padding-top:0}.tab-pane>p:last-child{margin-bottom:0}.tab-pane>pre:last-child{margin-bottom:0}.tab-content>.tab-pane:not(.active){display:none !important}div.sourceCode{background-color:rgba(233,236,239,.65);border:1px solid rgba(233,236,239,.65);border-radius:.375rem}pre.sourceCode{background-color:rgba(0,0,0,0)}pre.sourceCode{border:none;font-size:.875em;overflow-y:visible !important;padding:.4em}div.sourceCode{overflow-y:hidden}.callout div.sourceCode{margin-left:initial}.blockquote{font-size:inherit;padding-left:1rem;padding-right:1.5rem;color:hsl(210,10.8108108108%,39.5098039216%)}.blockquote h1:first-child,.blockquote .h1:first-child,.blockquote h2:first-child,.blockquote .h2:first-child,.blockquote h3:first-child,.blockquote .h3:first-child,.blockquote h4:first-child,.blockquote .h4:first-child,.blockquote h5:first-child,.blockquote .h5:first-child{margin-top:0}pre{background-color:initial;padding:initial;border:initial}p code.sourceCode,li code.sourceCode,td code.sourceCode{background-color:rgba(233,236,239,.65)}p pre code:not(.sourceCode),li pre code:not(.sourceCode),pre code:not(.sourceCode){background-color:initial}p code:not(.sourceCode),li code:not(.sourceCode),td code:not(.sourceCode){background-color:rgba(233,236,239,.65);padding:.2em}nav p code:not(.sourceCode),nav li code:not(.sourceCode),nav td code:not(.sourceCode){background-color:rgba(0,0,0,0);padding:0}td code:not(.sourceCode){white-space:pre-wrap}#quarto-embedded-source-code-modal>.modal-dialog{max-width:1000px;padding-left:1.75rem;padding-right:1.75rem}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body{padding:0}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-body div.sourceCode{margin:0;padding:.2rem .2rem;border-radius:0px;border:none}#quarto-embedded-source-code-modal>.modal-dialog>.modal-content>.modal-header{padding:.7rem}.code-tools-button{font-size:1rem;padding:.15rem .15rem;margin-left:5px;color:rgba(33,37,41,.75);background-color:rgba(0,0,0,0);transition:initial;cursor:pointer}.code-tools-button>.bi::before{display:inline-block;height:1rem;width:1rem;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:1rem 1rem}.code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button>.bi::before{background-image:url('data:image/svg+xml,')}#quarto-embedded-source-code-modal .code-copy-button-checked>.bi::before{background-image:url('data:image/svg+xml,')}.sidebar{will-change:top;transition:top 200ms linear;position:sticky;overflow-y:auto;padding-top:1.2em;max-height:100vh}.sidebar.toc-left,.sidebar.margin-sidebar{top:0px;padding-top:1em}.sidebar.quarto-banner-title-block-sidebar>*{padding-top:1.65em}figure .quarto-notebook-link{margin-top:.5em}.quarto-notebook-link{font-size:.75em;color:rgba(33,37,41,.75);margin-bottom:1em;text-decoration:none;display:block}.quarto-notebook-link:hover{text-decoration:underline;color:#0d6efd}.quarto-notebook-link::before{display:inline-block;height:.75rem;width:.75rem;margin-bottom:0em;margin-right:.25em;content:"";vertical-align:-0.125em;background-image:url('data:image/svg+xml,');background-repeat:no-repeat;background-size:.75rem .75rem}.toc-actions i.bi,.quarto-code-links i.bi,.quarto-other-links i.bi,.quarto-alternate-notebooks i.bi,.quarto-alternate-formats i.bi{margin-right:.4em;font-size:.8rem}.quarto-other-links-text-target .quarto-code-links i.bi,.quarto-other-links-text-target .quarto-other-links i.bi{margin-right:.2em}.quarto-other-formats-text-target .quarto-alternate-formats i.bi{margin-right:.1em}.toc-actions i.bi.empty,.quarto-code-links i.bi.empty,.quarto-other-links i.bi.empty,.quarto-alternate-notebooks i.bi.empty,.quarto-alternate-formats i.bi.empty{padding-left:1em}.quarto-notebook h2,.quarto-notebook .h2{border-bottom:none}.quarto-notebook .cell-container{display:flex}.quarto-notebook .cell-container .cell{flex-grow:4}.quarto-notebook .cell-container .cell-decorator{padding-top:1.5em;padding-right:1em;text-align:right}.quarto-notebook .cell-container.code-fold .cell-decorator{padding-top:3em}.quarto-notebook .cell-code code{white-space:pre-wrap}.quarto-notebook .cell .cell-output-stderr pre code,.quarto-notebook .cell .cell-output-stdout pre code{white-space:pre-wrap;overflow-wrap:anywhere}.toc-actions,.quarto-alternate-formats,.quarto-other-links,.quarto-code-links,.quarto-alternate-notebooks{padding-left:0em}.sidebar .toc-actions a,.sidebar .quarto-alternate-formats a,.sidebar .quarto-other-links a,.sidebar .quarto-code-links a,.sidebar .quarto-alternate-notebooks a,.sidebar nav[role=doc-toc] a{text-decoration:none}.sidebar .toc-actions a:hover,.sidebar .quarto-other-links a:hover,.sidebar .quarto-code-links a:hover,.sidebar .quarto-alternate-formats a:hover,.sidebar .quarto-alternate-notebooks a:hover{color:#0d6efd}.sidebar .toc-actions h2,.sidebar .toc-actions .h2,.sidebar .quarto-code-links h2,.sidebar .quarto-code-links .h2,.sidebar .quarto-other-links h2,.sidebar .quarto-other-links .h2,.sidebar .quarto-alternate-notebooks h2,.sidebar .quarto-alternate-notebooks .h2,.sidebar .quarto-alternate-formats h2,.sidebar .quarto-alternate-formats .h2,.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-weight:500;margin-bottom:.2rem;margin-top:.3rem;font-family:inherit;border-bottom:0;padding-bottom:0;padding-top:0px}.sidebar .toc-actions>h2,.sidebar .toc-actions>.h2,.sidebar .quarto-code-links>h2,.sidebar .quarto-code-links>.h2,.sidebar .quarto-other-links>h2,.sidebar .quarto-other-links>.h2,.sidebar .quarto-alternate-notebooks>h2,.sidebar .quarto-alternate-notebooks>.h2,.sidebar .quarto-alternate-formats>h2,.sidebar .quarto-alternate-formats>.h2{font-size:.8rem}.sidebar nav[role=doc-toc]>h2,.sidebar nav[role=doc-toc]>.h2{font-size:.875rem}.sidebar nav[role=doc-toc]>ul a{border-left:1px solid #e9ecef;padding-left:.6rem}.sidebar .toc-actions h2>ul a,.sidebar .toc-actions .h2>ul a,.sidebar .quarto-code-links h2>ul a,.sidebar .quarto-code-links .h2>ul a,.sidebar .quarto-other-links h2>ul a,.sidebar .quarto-other-links .h2>ul a,.sidebar .quarto-alternate-notebooks h2>ul a,.sidebar .quarto-alternate-notebooks .h2>ul a,.sidebar .quarto-alternate-formats h2>ul a,.sidebar .quarto-alternate-formats .h2>ul a{border-left:none;padding-left:.6rem}.sidebar .toc-actions ul a:empty,.sidebar .quarto-code-links ul a:empty,.sidebar .quarto-other-links ul a:empty,.sidebar .quarto-alternate-notebooks ul a:empty,.sidebar .quarto-alternate-formats ul a:empty,.sidebar nav[role=doc-toc]>ul a:empty{display:none}.sidebar .toc-actions ul,.sidebar .quarto-code-links ul,.sidebar .quarto-other-links ul,.sidebar .quarto-alternate-notebooks ul,.sidebar .quarto-alternate-formats ul{padding-left:0;list-style:none}.sidebar nav[role=doc-toc] ul{list-style:none;padding-left:0;list-style:none}.sidebar nav[role=doc-toc]>ul{margin-left:.45em}.quarto-margin-sidebar nav[role=doc-toc]{padding-left:.5em}.sidebar .toc-actions>ul,.sidebar .quarto-code-links>ul,.sidebar .quarto-other-links>ul,.sidebar .quarto-alternate-notebooks>ul,.sidebar .quarto-alternate-formats>ul{font-size:.8rem}.sidebar nav[role=doc-toc]>ul{font-size:.875rem}.sidebar .toc-actions ul li a,.sidebar .quarto-code-links ul li a,.sidebar .quarto-other-links ul li a,.sidebar .quarto-alternate-notebooks ul li a,.sidebar .quarto-alternate-formats ul li a,.sidebar nav[role=doc-toc]>ul li a{line-height:1.1rem;padding-bottom:.2rem;padding-top:.2rem;color:inherit}.sidebar nav[role=doc-toc] ul>li>ul>li>a{padding-left:1.2em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>a{padding-left:2.4em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>a{padding-left:3.6em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:4.8em}.sidebar nav[role=doc-toc] ul>li>ul>li>ul>li>ul>li>ul>li>ul>li>a{padding-left:6em}.sidebar nav[role=doc-toc] ul>li>a.active,.sidebar nav[role=doc-toc] ul>li>ul>li>a.active{border-left:1px solid #0d6efd;color:#0d6efd !important}.sidebar nav[role=doc-toc] ul>li>a:hover,.sidebar nav[role=doc-toc] ul>li>ul>li>a:hover{color:#0d6efd !important}kbd,.kbd{color:#212529;background-color:#f8f9fa;border:1px solid;border-radius:5px;border-color:rgb(221.7,222.3,222.9)}.quarto-appendix-contents div.hanging-indent{margin-left:0em}.quarto-appendix-contents div.hanging-indent div.csl-entry{margin-left:1em;text-indent:-1em}.citation a,.footnote-ref{text-decoration:none}.footnotes ol{padding-left:1em}.tippy-content>*{margin-bottom:.7em}.tippy-content>*:last-child{margin-bottom:0}.callout{margin-top:1.25rem;margin-bottom:1.25rem;border-radius:.375rem;overflow-wrap:break-word}.callout .callout-title-container{overflow-wrap:anywhere}.callout.callout-style-simple{padding:.4em .7em;border-left:5px solid;border-right:1px solid rgb(221.7,222.3,222.9);border-top:1px solid rgb(221.7,222.3,222.9);border-bottom:1px solid rgb(221.7,222.3,222.9)}.callout.callout-style-default{border-left:5px solid;border-right:1px solid rgb(221.7,222.3,222.9);border-top:1px solid rgb(221.7,222.3,222.9);border-bottom:1px solid rgb(221.7,222.3,222.9)}.callout .callout-body-container{flex-grow:1}.callout.callout-style-simple .callout-body{font-size:.9rem;font-weight:400;margin-bottom:-0.4em;margin-top:.5em}.callout.callout-style-default .callout-body{font-size:.9rem;font-weight:400}.callout:not(.no-icon).callout-titled.callout-style-simple .callout-body{padding-left:1.6em}.callout.callout-titled>.callout-header{padding-top:.2em;margin-bottom:-0.2em}.callout.callout-empty-content>.callout-header{margin-bottom:0em;border-bottom-right-radius:calc(0.375rem + -1px)}.callout>.callout-header.collapsed{border-bottom-right-radius:calc(0.375rem + -1px)}.callout.callout-style-simple>div.callout-header{border-bottom:none;font-size:.9rem;font-weight:600;opacity:75%}.callout.callout-style-default>div.callout-header{border-bottom:none;font-weight:600;opacity:85%;font-size:.9rem;padding-left:.5em;padding-right:.5em;border-top-right-radius:calc(0.375rem + -1px)}.callout.callout-style-default .callout-body{padding-left:.5em;padding-right:.5em}.callout.callout-style-default .callout-body>:first-child{padding-top:.5rem;margin-top:0}.callout>div.callout-header[data-bs-toggle=collapse]{cursor:pointer}.callout.callout-style-default .callout-header[aria-expanded=false],.callout.callout-style-default .callout-header[aria-expanded=true]{padding-top:0px;margin-bottom:0px;align-items:center}.callout.callout-titled .callout-body>:last-child:not(.sourceCode),.callout.callout-titled .callout-body>div>:last-child:not(.sourceCode){padding-bottom:.5rem;margin-bottom:0}.callout:not(.callout-titled) .callout-body>:first-child,.callout:not(.callout-titled) .callout-body>div>:first-child{margin-top:.25rem}.callout:not(.callout-titled) .callout-body>:last-child,.callout:not(.callout-titled) .callout-body>div>:last-child{margin-bottom:.2rem}.callout.callout-style-simple:not(.callout-titled) .callout-body>:last-child,.callout.callout-style-simple:not(.callout-titled) .callout-body>div>:last-child{margin-bottom:.5em}.callout.callout-style-simple .callout-icon::before,.callout.callout-style-simple .callout-toggle::before{height:1rem;width:1rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.callout.callout-style-default .callout-icon::before,.callout.callout-style-default .callout-toggle::before{height:.9rem;width:.9rem;display:inline-block;content:"";background-repeat:no-repeat;background-size:.9rem .9rem}.callout.callout-style-default .callout-toggle::before{margin-top:5px}.callout .callout-btn-toggle .callout-toggle::before{transition:transform .2s linear}.callout .callout-header[aria-expanded=false] .callout-toggle::before{transform:rotate(-90deg)}.callout .callout-header[aria-expanded=true] .callout-toggle::before{transform:none}.callout.callout-style-simple:not(.no-icon) div.callout-icon-container{padding-top:.2em;padding-right:.55em}.callout.callout-style-default:not(.no-icon) div.callout-icon-container{padding-top:.1em;padding-right:.35em}.callout.callout-style-default:not(.no-icon) div.callout-title-container{margin-top:-1px}.callout.callout-style-default.callout-caution:not(.no-icon) div.callout-icon-container{padding-top:.3em;padding-right:.35em}.callout>.callout-body>.callout-icon-container>.no-icon,.callout>.callout-header>.callout-icon-container>.no-icon{display:none}div.callout.callout{border-left-color:rgba(33,37,41,.75)}div.callout.callout-style-default>.callout-header{background-color:rgba(33,37,41,.75)}div.callout-note.callout{border-left-color:#0d6efd}div.callout-note.callout-style-default>.callout-header{background-color:rgb(230.8,240.5,254.8)}div.callout-note:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-note .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-tip.callout{border-left-color:#198754}div.callout-tip.callout-style-default>.callout-header{background-color:rgb(232,243,237.9)}div.callout-tip:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-tip .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-warning.callout{border-left-color:#ffc107}div.callout-warning.callout-style-default>.callout-header{background-color:rgb(255,248.8,230.2)}div.callout-warning:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-warning .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-caution.callout{border-left-color:#fd7e14}div.callout-caution.callout-style-default>.callout-header{background-color:rgb(254.8,242.1,231.5)}div.callout-caution:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-caution .callout-toggle::before{background-image:url('data:image/svg+xml,')}div.callout-important.callout{border-left-color:#dc3545}div.callout-important.callout-style-default>.callout-header{background-color:rgb(251.5,234.8,236.4)}div.callout-important:not(.callout-titled) .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important.callout-titled .callout-icon::before{background-image:url('data:image/svg+xml,');}div.callout-important .callout-toggle::before{background-image:url('data:image/svg+xml,')}.quarto-toggle-container{display:flex;align-items:center}.quarto-reader-toggle .bi::before,.quarto-color-scheme-toggle .bi::before{display:inline-block;height:1rem;width:1rem;content:"";background-repeat:no-repeat;background-size:1rem 1rem}.sidebar-navigation{padding-left:20px}.navbar{background-color:#517699;color:rgb(253.26,253.63,253.98)}.navbar .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.navbar .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle:not(.alternate) .bi::before{background-image:url('data:image/svg+xml,')}.sidebar-navigation .quarto-color-scheme-toggle.alternate .bi::before{background-image:url('data:image/svg+xml,')}.quarto-sidebar-toggle{border-color:rgb(221.7,222.3,222.9);border-bottom-left-radius:.375rem;border-bottom-right-radius:.375rem;border-style:solid;border-width:1px;overflow:hidden;border-top-width:0px;padding-top:0px !important}.quarto-sidebar-toggle-title{cursor:pointer;padding-bottom:2px;margin-left:.25em;text-align:center;font-weight:400;font-size:.775em}#quarto-content .quarto-sidebar-toggle{background:hsl(0,0%,98%)}#quarto-content .quarto-sidebar-toggle-title{color:#212529}.quarto-sidebar-toggle-icon{color:rgb(221.7,222.3,222.9);margin-right:.5em;float:right;transition:transform .2s ease}.quarto-sidebar-toggle-icon::before{padding-top:5px}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-icon{transform:rotate(-180deg)}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-title{border-bottom:solid rgb(221.7,222.3,222.9) 1px}.quarto-sidebar-toggle-contents{background-color:#fff;padding-right:10px;padding-left:10px;margin-top:0px !important;transition:max-height .5s ease}.quarto-sidebar-toggle.expanded .quarto-sidebar-toggle-contents{padding-top:1em;padding-bottom:10px}@media(max-width: 767.98px){.sidebar-menu-container{padding-bottom:5em}}.quarto-sidebar-toggle:not(.expanded) .quarto-sidebar-toggle-contents{padding-top:0px !important;padding-bottom:0px}nav[role=doc-toc]{z-index:1020}#quarto-sidebar>*,nav[role=doc-toc]>*{transition:opacity .1s ease,border .1s ease}#quarto-sidebar.slow>*,nav[role=doc-toc].slow>*{transition:opacity .4s ease,border .4s ease}.quarto-color-scheme-toggle:not(.alternate).top-right .bi::before{background-image:url('data:image/svg+xml,')}.quarto-color-scheme-toggle.alternate.top-right .bi::before{background-image:url('data:image/svg+xml,')}#quarto-appendix.default{border-top:1px solid rgb(221.7,222.3,222.9)}#quarto-appendix.default{background-color:#fff;padding-top:1.5em;margin-top:2em;z-index:998}#quarto-appendix.default .quarto-appendix-heading{margin-top:0;line-height:1.4em;font-weight:600;opacity:.9;border-bottom:none;margin-bottom:0}#quarto-appendix.default .footnotes ol,#quarto-appendix.default .footnotes ol li>p:last-of-type,#quarto-appendix.default .quarto-appendix-contents>p:last-of-type{margin-bottom:0}#quarto-appendix.default .footnotes ol{margin-left:.5em}#quarto-appendix.default .quarto-appendix-secondary-label{margin-bottom:.4em}#quarto-appendix.default .quarto-appendix-bibtex{font-size:.7em;padding:1em;border:solid 1px rgb(221.7,222.3,222.9);margin-bottom:1em}#quarto-appendix.default .quarto-appendix-bibtex code.sourceCode{white-space:pre-wrap}#quarto-appendix.default .quarto-appendix-citeas{font-size:.9em;padding:1em;border:solid 1px rgb(221.7,222.3,222.9);margin-bottom:1em}#quarto-appendix.default .quarto-appendix-heading{font-size:1em !important}#quarto-appendix.default *[role=doc-endnotes]>ol,#quarto-appendix.default .quarto-appendix-contents>*:not(h2):not(.h2){font-size:.9em}#quarto-appendix.default section{padding-bottom:1.5em}#quarto-appendix.default section *[role=doc-endnotes],#quarto-appendix.default section>*:not(a){opacity:.9;word-wrap:break-word}.btn.btn-quarto,div.cell-output-display .btn-quarto{--bs-btn-color: rgb(253.53, 253.62, 253.7);--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: rgb(253.53, 253.62, 253.7);--bs-btn-hover-bg: rgb(130.05, 137.7, 144.5);--bs-btn-hover-border-color: rgb(122.7, 130.8, 138);--bs-btn-focus-shadow-rgb: 130, 137, 144;--bs-btn-active-color: #000;--bs-btn-active-bg: rgb(137.4, 144.6, 151);--bs-btn-active-border-color: rgb(122.7, 130.8, 138);--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color: #ffffff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}nav.quarto-secondary-nav.color-navbar{background-color:#517699;color:rgb(253.26,253.63,253.98)}nav.quarto-secondary-nav.color-navbar h1,nav.quarto-secondary-nav.color-navbar .h1,nav.quarto-secondary-nav.color-navbar .quarto-btn-toggle{color:rgb(253.26,253.63,253.98)}@media(max-width: 991.98px){body.nav-sidebar .quarto-title-banner{margin-bottom:0;padding-bottom:1em}body.nav-sidebar #title-block-header{margin-block-end:0}}p.subtitle{margin-top:.25em;margin-bottom:.5em}code a:any-link{color:inherit;text-decoration-color:#6c757d}/*! light */div.observablehq table thead tr th{background-color:var(--bs-body-bg)}input,button,select,optgroup,textarea{background-color:var(--bs-body-bg)}.code-annotated .code-copy-button{margin-right:1.25em;margin-top:0;padding-bottom:0;padding-top:3px}.code-annotation-gutter-bg{background-color:#fff}.code-annotation-gutter{background-color:rgba(233,236,239,.65)}.code-annotation-gutter,.code-annotation-gutter-bg{height:100%;width:calc(20px + .5em);position:absolute;top:0;right:0}dl.code-annotation-container-grid dt{margin-right:1em;margin-top:.25rem}dl.code-annotation-container-grid dt{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;color:rgb(55.7432432432,62.5,69.2567567568);border:solid rgb(55.7432432432,62.5,69.2567567568) 1px;border-radius:50%;height:22px;width:22px;line-height:22px;font-size:11px;text-align:center;vertical-align:middle;text-decoration:none}dl.code-annotation-container-grid dt[data-target-cell]{cursor:pointer}dl.code-annotation-container-grid dt[data-target-cell].code-annotation-active{color:#fff;border:solid #aaa 1px;background-color:#aaa}pre.code-annotation-code{padding-top:0;padding-bottom:0}pre.code-annotation-code code{z-index:3}#code-annotation-line-highlight-gutter{width:100%;border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}#code-annotation-line-highlight{margin-left:-4em;width:calc(100% + 4em);border-top:solid rgba(170,170,170,.2666666667) 1px;border-bottom:solid rgba(170,170,170,.2666666667) 1px;z-index:2;background-color:rgba(170,170,170,.1333333333)}code.sourceCode .code-annotation-anchor.code-annotation-active{background-color:var(--quarto-hl-normal-color, #aaaaaa);border:solid var(--quarto-hl-normal-color, #aaaaaa) 1px;color:#e9ecef;font-weight:bolder}code.sourceCode .code-annotation-anchor{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;color:var(--quarto-hl-co-color);border:solid var(--quarto-hl-co-color) 1px;border-radius:50%;height:18px;width:18px;font-size:9px;margin-top:2px}code.sourceCode button.code-annotation-anchor{padding:2px;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none}code.sourceCode a.code-annotation-anchor{line-height:18px;text-align:center;vertical-align:middle;cursor:default;text-decoration:none}@media print{.page-columns .column-screen-inset{grid-column:page-start-inset/page-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset table{background:#fff}.page-columns .column-screen-inset-left{grid-column:page-start-inset/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-inset-left table{background:#fff}.page-columns .column-screen-inset-right{grid-column:body-content-start/page-end-inset;z-index:998;opacity:.999}.page-columns .column-screen-inset-right table{background:#fff}.page-columns .column-screen{grid-column:page-start/page-end;z-index:998;opacity:.999}.page-columns .column-screen table{background:#fff}.page-columns .column-screen-left{grid-column:page-start/body-content-end;z-index:998;opacity:.999}.page-columns .column-screen-left table{background:#fff}.page-columns .column-screen-right{grid-column:body-content-start/page-end;z-index:998;opacity:.999}.page-columns .column-screen-right table{background:#fff}.page-columns .column-screen-inset-shaded{grid-column:page-start-inset/page-end-inset;padding:1em;background:#f8f9fa;z-index:998;opacity:.999;margin-bottom:1em}}.quarto-video{margin-bottom:1em}.table{border-top:1px solid rgb(210.6,211.4,212.2);border-bottom:1px solid rgb(210.6,211.4,212.2)}.table>thead{border-top-width:0;border-bottom:1px solid #909294}.table a{word-break:break-word}.table>:not(caption)>*>*{background-color:unset;color:unset}#quarto-document-content .crosstalk-input .checkbox input[type=checkbox],#quarto-document-content .crosstalk-input .checkbox-inline input[type=checkbox]{position:unset;margin-top:unset;margin-left:unset}#quarto-document-content .row{margin-left:unset;margin-right:unset}.quarto-xref{white-space:nowrap}#quarto-draft-alert{margin-top:0px;margin-bottom:0px;padding:.3em;text-align:center;font-size:.9em}#quarto-draft-alert i{margin-right:.3em}#quarto-back-to-top{z-index:1000}pre{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:0.875em;font-weight:400}pre code{font-family:inherit;font-size:inherit;font-weight:inherit}code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:0.875em;font-weight:400}a{background-color:rgba(0,0,0,0);font-weight:400;text-decoration:underline}.screen-reader-only{position:absolute;clip:rect(0 0 0 0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;width:1px}a.external:after{content:"";background-image:url('data:image/svg+xml,');background-size:contain;background-repeat:no-repeat;background-position:center center;margin-left:.2em;padding-right:.75em}div.sourceCode code a.external:after{content:none}a.external:after:hover{cursor:pointer}.quarto-ext-icon{display:inline-block;font-size:.75em;padding-left:.3em}.code-with-filename .code-with-filename-file{margin-bottom:0;padding-bottom:2px;padding-top:2px;padding-left:.7em;border:var(--quarto-border-width) solid var(--quarto-border-color);border-radius:var(--quarto-border-radius);border-bottom:0;border-bottom-left-radius:0%;border-bottom-right-radius:0%}.code-with-filename div.sourceCode,.reveal .code-with-filename div.sourceCode{margin-top:0;border-top-left-radius:0%;border-top-right-radius:0%}.code-with-filename .code-with-filename-file pre{margin-bottom:0}.code-with-filename .code-with-filename-file{background-color:rgba(219,219,219,.8)}.quarto-dark .code-with-filename .code-with-filename-file{background-color:#555}.code-with-filename .code-with-filename-file strong{font-weight:400}.quarto-title-banner{margin-bottom:1em;color:rgb(253.26,253.63,253.98);background:#517699}.quarto-title-banner a{color:rgb(253.26,253.63,253.98)}.quarto-title-banner h1,.quarto-title-banner .h1,.quarto-title-banner h2,.quarto-title-banner .h2{color:rgb(253.26,253.63,253.98)}.quarto-title-banner .code-tools-button{color:rgb(188.9556521739,202.9995652174,216.2843478261)}.quarto-title-banner .code-tools-button:hover{color:rgb(253.26,253.63,253.98)}.quarto-title-banner .code-tools-button>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .code-tools-button:hover>.bi::before{background-image:url('data:image/svg+xml,')}.quarto-title-banner .quarto-title .title{font-weight:600}.quarto-title-banner .quarto-categories{margin-top:.75em}@media(min-width: 992px){.quarto-title-banner{padding-top:2.5em;padding-bottom:2.5em}}@media(max-width: 991.98px){.quarto-title-banner{padding-top:1em;padding-bottom:1em}}@media(max-width: 767.98px){body.hypothesis-enabled #title-block-header>*{padding-right:20px}}main.quarto-banner-title-block>section:first-child>h2,main.quarto-banner-title-block>section:first-child>.h2,main.quarto-banner-title-block>section:first-child>h3,main.quarto-banner-title-block>section:first-child>.h3,main.quarto-banner-title-block>section:first-child>h4,main.quarto-banner-title-block>section:first-child>.h4{margin-top:0}.quarto-title .quarto-categories{display:flex;flex-wrap:wrap;row-gap:.5em;column-gap:.4em;padding-bottom:.5em;margin-top:.75em}.quarto-title .quarto-categories .quarto-category{padding:.25em .75em;font-size:.65em;text-transform:uppercase;border:solid 1px;border-radius:.375rem;opacity:.6}.quarto-title .quarto-categories .quarto-category a{color:inherit}.quarto-title-meta-container{display:grid;grid-template-columns:1fr auto}.quarto-title-meta-column-end{display:flex;flex-direction:column;padding-left:1em}.quarto-title-meta-column-end a .bi{margin-right:.3em}#title-block-header.quarto-title-block.default .quarto-title-meta{display:grid;grid-template-columns:repeat(2, 1fr);grid-column-gap:1em}#title-block-header.quarto-title-block.default .quarto-title .title{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-author-orcid img{margin-top:-0.2em;height:.8em;width:.8em}#title-block-header.quarto-title-block.default .quarto-title-author-email{opacity:.7}#title-block-header.quarto-title-block.default .quarto-description p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p,#title-block-header.quarto-title-block.default .quarto-title-authors p,#title-block-header.quarto-title-block.default .quarto-title-affiliations p{margin-bottom:.1em}#title-block-header.quarto-title-block.default .quarto-title-meta-heading{text-transform:uppercase;margin-top:1em;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-contents{font-size:.9em}#title-block-header.quarto-title-block.default .quarto-title-meta-contents p.affiliation:last-of-type{margin-bottom:.1em}#title-block-header.quarto-title-block.default p.affiliation{margin-bottom:.1em}#title-block-header.quarto-title-block.default .keywords,#title-block-header.quarto-title-block.default .description,#title-block-header.quarto-title-block.default .abstract{margin-top:0}#title-block-header.quarto-title-block.default .keywords>p,#title-block-header.quarto-title-block.default .description>p,#title-block-header.quarto-title-block.default .abstract>p{font-size:.9em}#title-block-header.quarto-title-block.default .keywords>p:last-of-type,#title-block-header.quarto-title-block.default .description>p:last-of-type,#title-block-header.quarto-title-block.default .abstract>p:last-of-type{margin-bottom:0}#title-block-header.quarto-title-block.default .keywords .block-title,#title-block-header.quarto-title-block.default .description .block-title,#title-block-header.quarto-title-block.default .abstract .block-title{margin-top:1em;text-transform:uppercase;font-size:.8em;opacity:.8;font-weight:400}#title-block-header.quarto-title-block.default .quarto-title-meta-author{display:grid;grid-template-columns:minmax(max-content, 1fr) 1fr;grid-column-gap:1em}.quarto-title-tools-only{display:flex;justify-content:right}:root{--quarto-scss-export-title-banner-color: ;--quarto-scss-export-title-banner-bg: ;--quarto-scss-export-btn-code-copy-color: #5E5E5E;--quarto-scss-export-btn-code-copy-color-active: #4758AB;--quarto-scss-export-sidebar-bg: #fff;--quarto-scss-export-blue: #0d6efd;--quarto-scss-export-primary: #0d6efd;--quarto-scss-export-white: #ffffff;--quarto-scss-export-gray-200: #e9ecef;--quarto-scss-export-gray-100: #f8f9fa;--quarto-scss-export-gray-900: #212529;--quarto-scss-export-link-color: #0d6efd;--quarto-scss-export-link-color-bg: transparent;--quarto-scss-export-code-color: #7d12ba;--quarto-scss-export-code-bg: #f8f9fa;--quarto-scss-export-toc-color: #0d6efd;--quarto-scss-export-toc-active-border: #0d6efd;--quarto-scss-export-toc-inactive-border: #e9ecef;--quarto-scss-export-navbar-default: #517699;--quarto-scss-export-navbar-hl-override: false;--quarto-scss-export-navbar-bg: #517699;--quarto-scss-export-btn-bg: #6c757d;--quarto-scss-export-btn-fg: rgb(253.53, 253.62, 253.7);--quarto-scss-export-body-contrast-bg: #ffffff;--quarto-scss-export-body-contrast-color: #212529;--quarto-scss-export-navbar-fg: rgb(253.26, 253.63, 253.98);--quarto-scss-export-navbar-hl: rgb(252.58, 253.55, 254.98);--quarto-scss-export-navbar-brand: rgb(253.26, 253.63, 253.98);--quarto-scss-export-navbar-brand-hl: rgb(252.58, 253.55, 254.98);--quarto-scss-export-navbar-toggler-border-color: rgba(253.26, 253.63, 253.98, 0);--quarto-scss-export-navbar-hover-color: rgba(252.58, 253.55, 254.98, 0.8);--quarto-scss-export-navbar-disabled-color: rgba(253.26, 253.63, 253.98, 0.75);--quarto-scss-export-sidebar-fg: rgb(89.25, 89.25, 89.25);--quarto-scss-export-sidebar-hl: ;--quarto-scss-export-title-block-color: #212529;--quarto-scss-export-title-block-contast-color: #ffffff;--quarto-scss-export-footer-bg: #fff;--quarto-scss-export-footer-fg: rgb(117.3, 117.3, 117.3);--quarto-scss-export-popover-bg: #ffffff;--quarto-scss-export-input-bg: #ffffff;--quarto-scss-export-input-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-code-annotation-higlight-color: rgba(170, 170, 170, 0.2666666667);--quarto-scss-export-code-annotation-higlight-bg: rgba(170, 170, 170, 0.1333333333);--quarto-scss-export-table-group-separator-color: #909294;--quarto-scss-export-table-group-separator-color-lighter: rgb(210.6, 211.4, 212.2);--quarto-scss-export-link-decoration: underline;--quarto-scss-export-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-table-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-gray-300: #dee2e6;--quarto-scss-export-gray-400: #ced4da;--quarto-scss-export-gray-500: #adb5bd;--quarto-scss-export-gray-600: #6c757d;--quarto-scss-export-gray-700: #495057;--quarto-scss-export-gray-800: #343a40;--quarto-scss-export-black: #000;--quarto-scss-export-indigo: #6610f2;--quarto-scss-export-purple: #6f42c1;--quarto-scss-export-pink: #d63384;--quarto-scss-export-red: #dc3545;--quarto-scss-export-orange: #fd7e14;--quarto-scss-export-yellow: #ffc107;--quarto-scss-export-green: #198754;--quarto-scss-export-teal: #20c997;--quarto-scss-export-cyan: #0dcaf0;--quarto-scss-export-color-contrast-dark: #000;--quarto-scss-export-color-contrast-light: #ffffff;--quarto-scss-export-blue-100: rgb(206.6, 226, 254.6);--quarto-scss-export-blue-200: rgb(158.2, 197, 254.2);--quarto-scss-export-blue-300: rgb(109.8, 168, 253.8);--quarto-scss-export-blue-400: rgb(61.4, 139, 253.4);--quarto-scss-export-blue-500: #0d6efd;--quarto-scss-export-blue-600: rgb(10.4, 88, 202.4);--quarto-scss-export-blue-700: rgb(7.8, 66, 151.8);--quarto-scss-export-blue-800: rgb(5.2, 44, 101.2);--quarto-scss-export-blue-900: rgb(2.6, 22, 50.6);--quarto-scss-export-indigo-100: rgb(224.4, 207.2, 252.4);--quarto-scss-export-indigo-200: rgb(193.8, 159.4, 249.8);--quarto-scss-export-indigo-300: rgb(163.2, 111.6, 247.2);--quarto-scss-export-indigo-400: rgb(132.6, 63.8, 244.6);--quarto-scss-export-indigo-500: #6610f2;--quarto-scss-export-indigo-600: rgb(81.6, 12.8, 193.6);--quarto-scss-export-indigo-700: rgb(61.2, 9.6, 145.2);--quarto-scss-export-indigo-800: rgb(40.8, 6.4, 96.8);--quarto-scss-export-indigo-900: rgb(20.4, 3.2, 48.4);--quarto-scss-export-purple-100: rgb(226.2, 217.2, 242.6);--quarto-scss-export-purple-200: rgb(197.4, 179.4, 230.2);--quarto-scss-export-purple-300: rgb(168.6, 141.6, 217.8);--quarto-scss-export-purple-400: rgb(139.8, 103.8, 205.4);--quarto-scss-export-purple-500: #6f42c1;--quarto-scss-export-purple-600: rgb(88.8, 52.8, 154.4);--quarto-scss-export-purple-700: rgb(66.6, 39.6, 115.8);--quarto-scss-export-purple-800: rgb(44.4, 26.4, 77.2);--quarto-scss-export-purple-900: rgb(22.2, 13.2, 38.6);--quarto-scss-export-pink-100: rgb(246.8, 214.2, 230.4);--quarto-scss-export-pink-200: rgb(238.6, 173.4, 205.8);--quarto-scss-export-pink-300: rgb(230.4, 132.6, 181.2);--quarto-scss-export-pink-400: rgb(222.2, 91.8, 156.6);--quarto-scss-export-pink-500: #d63384;--quarto-scss-export-pink-600: rgb(171.2, 40.8, 105.6);--quarto-scss-export-pink-700: rgb(128.4, 30.6, 79.2);--quarto-scss-export-pink-800: rgb(85.6, 20.4, 52.8);--quarto-scss-export-pink-900: rgb(42.8, 10.2, 26.4);--quarto-scss-export-red-100: rgb(248, 214.6, 217.8);--quarto-scss-export-red-200: rgb(241, 174.2, 180.6);--quarto-scss-export-red-300: rgb(234, 133.8, 143.4);--quarto-scss-export-red-400: rgb(227, 93.4, 106.2);--quarto-scss-export-red-500: #dc3545;--quarto-scss-export-red-600: rgb(176, 42.4, 55.2);--quarto-scss-export-red-700: rgb(132, 31.8, 41.4);--quarto-scss-export-red-800: rgb(88, 21.2, 27.6);--quarto-scss-export-red-900: rgb(44, 10.6, 13.8);--quarto-scss-export-orange-100: rgb(254.6, 229.2, 208);--quarto-scss-export-orange-200: rgb(254.2, 203.4, 161);--quarto-scss-export-orange-300: rgb(253.8, 177.6, 114);--quarto-scss-export-orange-400: rgb(253.4, 151.8, 67);--quarto-scss-export-orange-500: #fd7e14;--quarto-scss-export-orange-600: rgb(202.4, 100.8, 16);--quarto-scss-export-orange-700: rgb(151.8, 75.6, 12);--quarto-scss-export-orange-800: rgb(101.2, 50.4, 8);--quarto-scss-export-orange-900: rgb(50.6, 25.2, 4);--quarto-scss-export-yellow-100: rgb(255, 242.6, 205.4);--quarto-scss-export-yellow-200: rgb(255, 230.2, 155.8);--quarto-scss-export-yellow-300: rgb(255, 217.8, 106.2);--quarto-scss-export-yellow-400: rgb(255, 205.4, 56.6);--quarto-scss-export-yellow-500: #ffc107;--quarto-scss-export-yellow-600: rgb(204, 154.4, 5.6);--quarto-scss-export-yellow-700: rgb(153, 115.8, 4.2);--quarto-scss-export-yellow-800: rgb(102, 77.2, 2.8);--quarto-scss-export-yellow-900: rgb(51, 38.6, 1.4);--quarto-scss-export-green-100: rgb(209, 231, 220.8);--quarto-scss-export-green-200: rgb(163, 207, 186.6);--quarto-scss-export-green-300: rgb(117, 183, 152.4);--quarto-scss-export-green-400: rgb(71, 159, 118.2);--quarto-scss-export-green-500: #198754;--quarto-scss-export-green-600: rgb(20, 108, 67.2);--quarto-scss-export-green-700: rgb(15, 81, 50.4);--quarto-scss-export-green-800: rgb(10, 54, 33.6);--quarto-scss-export-green-900: rgb(5, 27, 16.8);--quarto-scss-export-teal-100: rgb(210.4, 244.2, 234.2);--quarto-scss-export-teal-200: rgb(165.8, 233.4, 213.4);--quarto-scss-export-teal-300: rgb(121.2, 222.6, 192.6);--quarto-scss-export-teal-400: rgb(76.6, 211.8, 171.8);--quarto-scss-export-teal-500: #20c997;--quarto-scss-export-teal-600: rgb(25.6, 160.8, 120.8);--quarto-scss-export-teal-700: rgb(19.2, 120.6, 90.6);--quarto-scss-export-teal-800: rgb(12.8, 80.4, 60.4);--quarto-scss-export-teal-900: rgb(6.4, 40.2, 30.2);--quarto-scss-export-cyan-100: rgb(206.6, 244.4, 252);--quarto-scss-export-cyan-200: rgb(158.2, 233.8, 249);--quarto-scss-export-cyan-300: rgb(109.8, 223.2, 246);--quarto-scss-export-cyan-400: rgb(61.4, 212.6, 243);--quarto-scss-export-cyan-500: #0dcaf0;--quarto-scss-export-cyan-600: rgb(10.4, 161.6, 192);--quarto-scss-export-cyan-700: rgb(7.8, 121.2, 144);--quarto-scss-export-cyan-800: rgb(5.2, 80.8, 96);--quarto-scss-export-cyan-900: rgb(2.6, 40.4, 48);--quarto-scss-export-default: #dee2e6;--quarto-scss-export-secondary: #6c757d;--quarto-scss-export-success: #198754;--quarto-scss-export-info: #0dcaf0;--quarto-scss-export-warning: #ffc107;--quarto-scss-export-danger: #dc3545;--quarto-scss-export-light: #f8f9fa;--quarto-scss-export-dark: #212529;--quarto-scss-export-primary-text-emphasis: rgb(5.2, 44, 101.2);--quarto-scss-export-secondary-text-emphasis: rgb(43.2, 46.8, 50);--quarto-scss-export-success-text-emphasis: rgb(10, 54, 33.6);--quarto-scss-export-info-text-emphasis: rgb(5.2, 80.8, 96);--quarto-scss-export-warning-text-emphasis: rgb(102, 77.2, 2.8);--quarto-scss-export-danger-text-emphasis: rgb(88, 21.2, 27.6);--quarto-scss-export-light-text-emphasis: #495057;--quarto-scss-export-dark-text-emphasis: #495057;--quarto-scss-export-primary-bg-subtle: rgb(206.6, 226, 254.6);--quarto-scss-export-secondary-bg-subtle: rgb(225.6, 227.4, 229);--quarto-scss-export-success-bg-subtle: rgb(209, 231, 220.8);--quarto-scss-export-info-bg-subtle: rgb(206.6, 244.4, 252);--quarto-scss-export-warning-bg-subtle: rgb(255, 242.6, 205.4);--quarto-scss-export-danger-bg-subtle: rgb(248, 214.6, 217.8);--quarto-scss-export-light-bg-subtle: rgb(251.5, 252, 252.5);--quarto-scss-export-dark-bg-subtle: #ced4da;--quarto-scss-export-primary-border-subtle: rgb(158.2, 197, 254.2);--quarto-scss-export-secondary-border-subtle: rgb(196.2, 199.8, 203);--quarto-scss-export-success-border-subtle: rgb(163, 207, 186.6);--quarto-scss-export-info-border-subtle: rgb(158.2, 233.8, 249);--quarto-scss-export-warning-border-subtle: rgb(255, 230.2, 155.8);--quarto-scss-export-danger-border-subtle: rgb(241, 174.2, 180.6);--quarto-scss-export-light-border-subtle: #e9ecef;--quarto-scss-export-dark-border-subtle: #adb5bd;--quarto-scss-export-body-text-align: ;--quarto-scss-export-body-color: #212529;--quarto-scss-export-body-bg: #ffffff;--quarto-scss-export-body-secondary-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-body-secondary-bg: #e9ecef;--quarto-scss-export-body-tertiary-color: rgba(33, 37, 41, 0.5);--quarto-scss-export-body-tertiary-bg: #f8f9fa;--quarto-scss-export-body-emphasis-color: #000;--quarto-scss-export-link-hover-color: rgb(10.4, 88, 202.4);--quarto-scss-export-link-hover-decoration: ;--quarto-scss-export-border-color-translucent: rgba(0, 0, 0, 0.175);--quarto-scss-export-component-active-bg: #0d6efd;--quarto-scss-export-component-active-color: #ffffff;--quarto-scss-export-focus-ring-color: rgba(13, 110, 253, 0.25);--quarto-scss-export-headings-font-family: ;--quarto-scss-export-headings-font-style: ;--quarto-scss-export-display-font-family: ;--quarto-scss-export-display-font-style: ;--quarto-scss-export-text-muted: rgba(33, 37, 41, 0.75);--quarto-scss-export-blockquote-footer-color: #6c757d;--quarto-scss-export-blockquote-border-color: #e9ecef;--quarto-scss-export-hr-bg-color: ;--quarto-scss-export-hr-height: ;--quarto-scss-export-hr-border-color: ;--quarto-scss-export-legend-font-weight: ;--quarto-scss-export-mark-bg: rgb(255, 242.6, 205.4);--quarto-scss-export-table-color: #212529;--quarto-scss-export-table-bg: #ffffff;--quarto-scss-export-table-accent-bg: transparent;--quarto-scss-export-table-th-font-weight: ;--quarto-scss-export-table-striped-color: #212529;--quarto-scss-export-table-striped-bg: rgba(0, 0, 0, 0.05);--quarto-scss-export-table-active-color: #212529;--quarto-scss-export-table-active-bg: rgba(0, 0, 0, 0.1);--quarto-scss-export-table-hover-color: #212529;--quarto-scss-export-table-hover-bg: rgba(0, 0, 0, 0.075);--quarto-scss-export-table-caption-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-input-btn-font-family: ;--quarto-scss-export-input-btn-focus-color: rgba(13, 110, 253, 0.25);--quarto-scss-export-btn-color: #212529;--quarto-scss-export-btn-font-family: ;--quarto-scss-export-btn-white-space: ;--quarto-scss-export-btn-link-color: #0d6efd;--quarto-scss-export-btn-link-hover-color: rgb(10.4, 88, 202.4);--quarto-scss-export-btn-link-disabled-color: #6c757d;--quarto-scss-export-form-text-font-style: ;--quarto-scss-export-form-text-font-weight: ;--quarto-scss-export-form-text-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-form-label-font-size: ;--quarto-scss-export-form-label-font-style: ;--quarto-scss-export-form-label-font-weight: ;--quarto-scss-export-form-label-color: ;--quarto-scss-export-input-font-family: ;--quarto-scss-export-input-disabled-color: ;--quarto-scss-export-input-disabled-bg: #e9ecef;--quarto-scss-export-input-disabled-border-color: ;--quarto-scss-export-input-color: #212529;--quarto-scss-export-input-focus-bg: #ffffff;--quarto-scss-export-input-focus-border-color: rgb(134, 182.5, 254);--quarto-scss-export-input-focus-color: #212529;--quarto-scss-export-input-placeholder-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-input-plaintext-color: #212529;--quarto-scss-export-form-check-label-color: ;--quarto-scss-export-form-check-transition: ;--quarto-scss-export-form-check-input-bg: #ffffff;--quarto-scss-export-form-check-input-focus-border: rgb(134, 182.5, 254);--quarto-scss-export-form-check-input-checked-color: #ffffff;--quarto-scss-export-form-check-input-checked-bg-color: #0d6efd;--quarto-scss-export-form-check-input-checked-border-color: #0d6efd;--quarto-scss-export-form-check-input-indeterminate-color: #ffffff;--quarto-scss-export-form-check-input-indeterminate-bg-color: #0d6efd;--quarto-scss-export-form-check-input-indeterminate-border-color: #0d6efd;--quarto-scss-export-form-switch-color: rgba(0, 0, 0, 0.25);--quarto-scss-export-form-switch-focus-color: rgb(134, 182.5, 254);--quarto-scss-export-form-switch-checked-color: #ffffff;--quarto-scss-export-input-group-addon-color: #212529;--quarto-scss-export-input-group-addon-bg: #f8f9fa;--quarto-scss-export-input-group-addon-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-form-select-font-family: ;--quarto-scss-export-form-select-color: #212529;--quarto-scss-export-form-select-bg: #ffffff;--quarto-scss-export-form-select-disabled-color: ;--quarto-scss-export-form-select-disabled-bg: #e9ecef;--quarto-scss-export-form-select-disabled-border-color: ;--quarto-scss-export-form-select-indicator-color: #343a40;--quarto-scss-export-form-select-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-form-select-focus-border-color: rgb(134, 182.5, 254);--quarto-scss-export-form-range-track-bg: #f8f9fa;--quarto-scss-export-form-range-thumb-bg: #0d6efd;--quarto-scss-export-form-range-thumb-active-bg: rgb(182.4, 211.5, 254.4);--quarto-scss-export-form-range-thumb-disabled-bg: rgba(33, 37, 41, 0.75);--quarto-scss-export-form-file-button-color: #212529;--quarto-scss-export-form-file-button-bg: #f8f9fa;--quarto-scss-export-form-file-button-hover-bg: #e9ecef;--quarto-scss-export-form-floating-label-disabled-color: #6c757d;--quarto-scss-export-form-feedback-font-style: ;--quarto-scss-export-form-feedback-valid-color: #198754;--quarto-scss-export-form-feedback-invalid-color: #dc3545;--quarto-scss-export-form-feedback-icon-valid-color: #198754;--quarto-scss-export-form-feedback-icon-invalid-color: #dc3545;--quarto-scss-export-form-valid-color: #198754;--quarto-scss-export-form-valid-border-color: #198754;--quarto-scss-export-form-invalid-color: #dc3545;--quarto-scss-export-form-invalid-border-color: #dc3545;--quarto-scss-export-nav-link-font-size: ;--quarto-scss-export-nav-link-font-weight: ;--quarto-scss-export-nav-link-color: #0d6efd;--quarto-scss-export-nav-link-hover-color: rgb(10.4, 88, 202.4);--quarto-scss-export-nav-link-disabled-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-nav-tabs-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-nav-tabs-link-hover-border-color: #e9ecef #e9ecef rgb(221.7, 222.3, 222.9);--quarto-scss-export-nav-tabs-link-active-color: #000;--quarto-scss-export-nav-tabs-link-active-bg: #ffffff;--quarto-scss-export-nav-pills-link-active-bg: #0d6efd;--quarto-scss-export-nav-pills-link-active-color: #ffffff;--quarto-scss-export-nav-underline-link-active-color: #000;--quarto-scss-export-navbar-padding-x: ;--quarto-scss-export-navbar-light-contrast: #ffffff;--quarto-scss-export-navbar-dark-contrast: #ffffff;--quarto-scss-export-navbar-light-icon-color: rgba(255, 255, 255, 0.75);--quarto-scss-export-navbar-dark-icon-color: rgba(255, 255, 255, 0.75);--quarto-scss-export-dropdown-color: #212529;--quarto-scss-export-dropdown-bg: #ffffff;--quarto-scss-export-dropdown-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-dropdown-divider-bg: rgba(0, 0, 0, 0.175);--quarto-scss-export-dropdown-link-color: #212529;--quarto-scss-export-dropdown-link-hover-color: #212529;--quarto-scss-export-dropdown-link-hover-bg: #f8f9fa;--quarto-scss-export-dropdown-link-active-bg: #0d6efd;--quarto-scss-export-dropdown-link-active-color: #ffffff;--quarto-scss-export-dropdown-link-disabled-color: rgba(33, 37, 41, 0.5);--quarto-scss-export-dropdown-header-color: #6c757d;--quarto-scss-export-dropdown-dark-color: #dee2e6;--quarto-scss-export-dropdown-dark-bg: #343a40;--quarto-scss-export-dropdown-dark-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-dropdown-dark-divider-bg: rgba(0, 0, 0, 0.175);--quarto-scss-export-dropdown-dark-box-shadow: ;--quarto-scss-export-dropdown-dark-link-color: #dee2e6;--quarto-scss-export-dropdown-dark-link-hover-color: #ffffff;--quarto-scss-export-dropdown-dark-link-hover-bg: rgba(255, 255, 255, 0.15);--quarto-scss-export-dropdown-dark-link-active-color: #ffffff;--quarto-scss-export-dropdown-dark-link-active-bg: #0d6efd;--quarto-scss-export-dropdown-dark-link-disabled-color: #adb5bd;--quarto-scss-export-dropdown-dark-header-color: #adb5bd;--quarto-scss-export-pagination-color: #0d6efd;--quarto-scss-export-pagination-bg: #ffffff;--quarto-scss-export-pagination-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-pagination-focus-color: rgb(10.4, 88, 202.4);--quarto-scss-export-pagination-focus-bg: #e9ecef;--quarto-scss-export-pagination-hover-color: rgb(10.4, 88, 202.4);--quarto-scss-export-pagination-hover-bg: #f8f9fa;--quarto-scss-export-pagination-hover-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-pagination-active-color: #ffffff;--quarto-scss-export-pagination-active-bg: #0d6efd;--quarto-scss-export-pagination-active-border-color: #0d6efd;--quarto-scss-export-pagination-disabled-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-pagination-disabled-bg: #e9ecef;--quarto-scss-export-pagination-disabled-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-card-title-color: ;--quarto-scss-export-card-subtitle-color: ;--quarto-scss-export-card-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-card-box-shadow: ;--quarto-scss-export-card-cap-bg: rgba(33, 37, 41, 0.03);--quarto-scss-export-card-cap-color: ;--quarto-scss-export-card-height: ;--quarto-scss-export-card-color: ;--quarto-scss-export-card-bg: #ffffff;--quarto-scss-export-accordion-color: #212529;--quarto-scss-export-accordion-bg: #ffffff;--quarto-scss-export-accordion-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-accordion-button-color: #212529;--quarto-scss-export-accordion-button-bg: #ffffff;--quarto-scss-export-accordion-button-active-bg: rgb(206.6, 226, 254.6);--quarto-scss-export-accordion-button-active-color: rgb(5.2, 44, 101.2);--quarto-scss-export-accordion-button-focus-border-color: rgb(134, 182.5, 254);--quarto-scss-export-accordion-icon-color: #212529;--quarto-scss-export-accordion-icon-active-color: rgb(5.2, 44, 101.2);--quarto-scss-export-tooltip-color: #ffffff;--quarto-scss-export-tooltip-bg: #000;--quarto-scss-export-tooltip-margin: ;--quarto-scss-export-tooltip-arrow-color: ;--quarto-scss-export-form-feedback-tooltip-line-height: ;--quarto-scss-export-popover-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-popover-header-bg: #e9ecef;--quarto-scss-export-popover-body-color: #212529;--quarto-scss-export-popover-arrow-color: #ffffff;--quarto-scss-export-popover-arrow-outer-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-toast-color: ;--quarto-scss-export-toast-background-color: rgba(255, 255, 255, 0.85);--quarto-scss-export-toast-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-toast-header-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-toast-header-background-color: rgba(255, 255, 255, 0.85);--quarto-scss-export-toast-header-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-badge-color: #ffffff;--quarto-scss-export-modal-content-color: ;--quarto-scss-export-modal-content-bg: #ffffff;--quarto-scss-export-modal-content-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-modal-backdrop-bg: #000;--quarto-scss-export-modal-header-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-modal-footer-bg: ;--quarto-scss-export-modal-footer-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-progress-bg: #e9ecef;--quarto-scss-export-progress-bar-color: #ffffff;--quarto-scss-export-progress-bar-bg: #0d6efd;--quarto-scss-export-list-group-color: #212529;--quarto-scss-export-list-group-bg: #ffffff;--quarto-scss-export-list-group-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-list-group-hover-bg: #f8f9fa;--quarto-scss-export-list-group-active-bg: #0d6efd;--quarto-scss-export-list-group-active-color: #ffffff;--quarto-scss-export-list-group-active-border-color: #0d6efd;--quarto-scss-export-list-group-disabled-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-list-group-disabled-bg: #ffffff;--quarto-scss-export-list-group-action-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-list-group-action-hover-color: #000;--quarto-scss-export-list-group-action-active-color: #212529;--quarto-scss-export-list-group-action-active-bg: #e9ecef;--quarto-scss-export-thumbnail-bg: #ffffff;--quarto-scss-export-thumbnail-border-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-figure-caption-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-breadcrumb-font-size: ;--quarto-scss-export-breadcrumb-bg: ;--quarto-scss-export-breadcrumb-divider-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-breadcrumb-active-color: rgba(33, 37, 41, 0.75);--quarto-scss-export-breadcrumb-border-radius: ;--quarto-scss-export-carousel-control-color: #ffffff;--quarto-scss-export-carousel-indicator-active-bg: #ffffff;--quarto-scss-export-carousel-caption-color: #ffffff;--quarto-scss-export-carousel-dark-indicator-active-bg: #000;--quarto-scss-export-carousel-dark-caption-color: #000;--quarto-scss-export-btn-close-color: #000;--quarto-scss-export-offcanvas-border-color: rgba(0, 0, 0, 0.175);--quarto-scss-export-offcanvas-bg-color: #ffffff;--quarto-scss-export-offcanvas-color: #212529;--quarto-scss-export-offcanvas-backdrop-bg: #000;--quarto-scss-export-code-color-dark: white;--quarto-scss-export-kbd-color: #ffffff;--quarto-scss-export-kbd-bg: #212529;--quarto-scss-export-nested-kbd-font-weight: ;--quarto-scss-export-pre-bg: #f8f9fa;--quarto-scss-export-pre-color: #000;--quarto-scss-export-bslib-page-sidebar-title-bg: #517699;--quarto-scss-export-bslib-page-sidebar-title-color: #ffffff;--quarto-scss-export-bslib-sidebar-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.05);--quarto-scss-export-bslib-sidebar-toggle-bg: rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.1);--quarto-scss-export-mermaid-bg-color: #ffffff;--quarto-scss-export-mermaid-edge-color: #6c757d;--quarto-scss-export-mermaid-node-fg-color: #212529;--quarto-scss-export-mermaid-fg-color: #212529;--quarto-scss-export-mermaid-fg-color--lighter: rgb(55.7432432432, 62.5, 69.2567567568);--quarto-scss-export-mermaid-fg-color--lightest: rgb(78.4864864865, 88, 97.5135135135);--quarto-scss-export-mermaid-label-bg-color: #ffffff;--quarto-scss-export-mermaid-label-fg-color: #0d6efd;--quarto-scss-export-mermaid-node-bg-color: rgba(13, 110, 253, 0.1);--quarto-scss-export-code-block-border-left-color: rgb(221.7, 222.3, 222.9);--quarto-scss-export-callout-color-note: #0d6efd;--quarto-scss-export-callout-color-tip: #198754;--quarto-scss-export-callout-color-important: #dc3545;--quarto-scss-export-callout-color-caution: #fd7e14;--quarto-scss-export-callout-color-warning: #ffc107} \ No newline at end of file diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-icons.css b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-icons.css new file mode 100644 index 000000000..82b40f57e --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-icons.css @@ -0,0 +1,2106 @@ +/*! + * Bootstrap Icons v1.13.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +@font-face { + font-display: block; + font-family: "bootstrap-icons"; + src: +url("./bootstrap-icons.woff?e34853135f9e39acf64315236852cd5a") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } +.bi-1-circle-fill::before { content: "\f796"; } +.bi-1-circle::before { content: "\f797"; } +.bi-1-square-fill::before { content: "\f798"; } +.bi-1-square::before { content: "\f799"; } +.bi-2-circle-fill::before { content: "\f79c"; } +.bi-2-circle::before { content: "\f79d"; } +.bi-2-square-fill::before { content: "\f79e"; } +.bi-2-square::before { content: "\f79f"; } +.bi-3-circle-fill::before { content: "\f7a2"; } +.bi-3-circle::before { content: "\f7a3"; } +.bi-3-square-fill::before { content: "\f7a4"; } +.bi-3-square::before { content: "\f7a5"; } +.bi-4-circle-fill::before { content: "\f7a8"; } +.bi-4-circle::before { content: "\f7a9"; } +.bi-4-square-fill::before { content: "\f7aa"; } +.bi-4-square::before { content: "\f7ab"; } +.bi-5-circle-fill::before { content: "\f7ae"; } +.bi-5-circle::before { content: "\f7af"; } +.bi-5-square-fill::before { content: "\f7b0"; } +.bi-5-square::before { content: "\f7b1"; } +.bi-6-circle-fill::before { content: "\f7b4"; } +.bi-6-circle::before { content: "\f7b5"; } +.bi-6-square-fill::before { content: "\f7b6"; } +.bi-6-square::before { content: "\f7b7"; } +.bi-7-circle-fill::before { content: "\f7ba"; } +.bi-7-circle::before { content: "\f7bb"; } +.bi-7-square-fill::before { content: "\f7bc"; } +.bi-7-square::before { content: "\f7bd"; } +.bi-8-circle-fill::before { content: "\f7c0"; } +.bi-8-circle::before { content: "\f7c1"; } +.bi-8-square-fill::before { content: "\f7c2"; } +.bi-8-square::before { content: "\f7c3"; } +.bi-9-circle-fill::before { content: "\f7c6"; } +.bi-9-circle::before { content: "\f7c7"; } +.bi-9-square-fill::before { content: "\f7c8"; } +.bi-9-square::before { content: "\f7c9"; } +.bi-airplane-engines-fill::before { content: "\f7ca"; } +.bi-airplane-engines::before { content: "\f7cb"; } +.bi-airplane-fill::before { content: "\f7cc"; } +.bi-airplane::before { content: "\f7cd"; } +.bi-alexa::before { content: "\f7ce"; } +.bi-alipay::before { content: "\f7cf"; } +.bi-android::before { content: "\f7d0"; } +.bi-android2::before { content: "\f7d1"; } +.bi-box-fill::before { content: "\f7d2"; } +.bi-box-seam-fill::before { content: "\f7d3"; } +.bi-browser-chrome::before { content: "\f7d4"; } +.bi-browser-edge::before { content: "\f7d5"; } +.bi-browser-firefox::before { content: "\f7d6"; } +.bi-browser-safari::before { content: "\f7d7"; } +.bi-c-circle-fill::before { content: "\f7da"; } +.bi-c-circle::before { content: "\f7db"; } +.bi-c-square-fill::before { content: "\f7dc"; } +.bi-c-square::before { content: "\f7dd"; } +.bi-capsule-pill::before { content: "\f7de"; } +.bi-capsule::before { content: "\f7df"; } +.bi-car-front-fill::before { content: "\f7e0"; } +.bi-car-front::before { content: "\f7e1"; } +.bi-cassette-fill::before { content: "\f7e2"; } +.bi-cassette::before { content: "\f7e3"; } +.bi-cc-circle-fill::before { content: "\f7e6"; } +.bi-cc-circle::before { content: "\f7e7"; } +.bi-cc-square-fill::before { content: "\f7e8"; } +.bi-cc-square::before { content: "\f7e9"; } +.bi-cup-hot-fill::before { content: "\f7ea"; } +.bi-cup-hot::before { content: "\f7eb"; } +.bi-currency-rupee::before { content: "\f7ec"; } +.bi-dropbox::before { content: "\f7ed"; } +.bi-escape::before { content: "\f7ee"; } +.bi-fast-forward-btn-fill::before { content: "\f7ef"; } +.bi-fast-forward-btn::before { content: "\f7f0"; } +.bi-fast-forward-circle-fill::before { content: "\f7f1"; } +.bi-fast-forward-circle::before { content: "\f7f2"; } +.bi-fast-forward-fill::before { content: "\f7f3"; } +.bi-fast-forward::before { content: "\f7f4"; } +.bi-filetype-sql::before { content: "\f7f5"; } +.bi-fire::before { content: "\f7f6"; } +.bi-google-play::before { content: "\f7f7"; } +.bi-h-circle-fill::before { content: "\f7fa"; } +.bi-h-circle::before { content: "\f7fb"; } +.bi-h-square-fill::before { content: "\f7fc"; } +.bi-h-square::before { content: "\f7fd"; } +.bi-indent::before { content: "\f7fe"; } +.bi-lungs-fill::before { content: "\f7ff"; } +.bi-lungs::before { content: "\f800"; } +.bi-microsoft-teams::before { content: "\f801"; } +.bi-p-circle-fill::before { content: "\f804"; } +.bi-p-circle::before { content: "\f805"; } +.bi-p-square-fill::before { content: "\f806"; } +.bi-p-square::before { content: "\f807"; } +.bi-pass-fill::before { content: "\f808"; } +.bi-pass::before { content: "\f809"; } +.bi-prescription::before { content: "\f80a"; } +.bi-prescription2::before { content: "\f80b"; } +.bi-r-circle-fill::before { content: "\f80e"; } +.bi-r-circle::before { content: "\f80f"; } +.bi-r-square-fill::before { content: "\f810"; } +.bi-r-square::before { content: "\f811"; } +.bi-repeat-1::before { content: "\f812"; } +.bi-repeat::before { content: "\f813"; } +.bi-rewind-btn-fill::before { content: "\f814"; } +.bi-rewind-btn::before { content: "\f815"; } +.bi-rewind-circle-fill::before { content: "\f816"; } +.bi-rewind-circle::before { content: "\f817"; } +.bi-rewind-fill::before { content: "\f818"; } +.bi-rewind::before { content: "\f819"; } +.bi-train-freight-front-fill::before { content: "\f81a"; } +.bi-train-freight-front::before { content: "\f81b"; } +.bi-train-front-fill::before { content: "\f81c"; } +.bi-train-front::before { content: "\f81d"; } +.bi-train-lightrail-front-fill::before { content: "\f81e"; } +.bi-train-lightrail-front::before { content: "\f81f"; } +.bi-truck-front-fill::before { content: "\f820"; } +.bi-truck-front::before { content: "\f821"; } +.bi-ubuntu::before { content: "\f822"; } +.bi-unindent::before { content: "\f823"; } +.bi-unity::before { content: "\f824"; } +.bi-universal-access-circle::before { content: "\f825"; } +.bi-universal-access::before { content: "\f826"; } +.bi-virus::before { content: "\f827"; } +.bi-virus2::before { content: "\f828"; } +.bi-wechat::before { content: "\f829"; } +.bi-yelp::before { content: "\f82a"; } +.bi-sign-stop-fill::before { content: "\f82b"; } +.bi-sign-stop-lights-fill::before { content: "\f82c"; } +.bi-sign-stop-lights::before { content: "\f82d"; } +.bi-sign-stop::before { content: "\f82e"; } +.bi-sign-turn-left-fill::before { content: "\f82f"; } +.bi-sign-turn-left::before { content: "\f830"; } +.bi-sign-turn-right-fill::before { content: "\f831"; } +.bi-sign-turn-right::before { content: "\f832"; } +.bi-sign-turn-slight-left-fill::before { content: "\f833"; } +.bi-sign-turn-slight-left::before { content: "\f834"; } +.bi-sign-turn-slight-right-fill::before { content: "\f835"; } +.bi-sign-turn-slight-right::before { content: "\f836"; } +.bi-sign-yield-fill::before { content: "\f837"; } +.bi-sign-yield::before { content: "\f838"; } +.bi-ev-station-fill::before { content: "\f839"; } +.bi-ev-station::before { content: "\f83a"; } +.bi-fuel-pump-diesel-fill::before { content: "\f83b"; } +.bi-fuel-pump-diesel::before { content: "\f83c"; } +.bi-fuel-pump-fill::before { content: "\f83d"; } +.bi-fuel-pump::before { content: "\f83e"; } +.bi-0-circle-fill::before { content: "\f83f"; } +.bi-0-circle::before { content: "\f840"; } +.bi-0-square-fill::before { content: "\f841"; } +.bi-0-square::before { content: "\f842"; } +.bi-rocket-fill::before { content: "\f843"; } +.bi-rocket-takeoff-fill::before { content: "\f844"; } +.bi-rocket-takeoff::before { content: "\f845"; } +.bi-rocket::before { content: "\f846"; } +.bi-stripe::before { content: "\f847"; } +.bi-subscript::before { content: "\f848"; } +.bi-superscript::before { content: "\f849"; } +.bi-trello::before { content: "\f84a"; } +.bi-envelope-at-fill::before { content: "\f84b"; } +.bi-envelope-at::before { content: "\f84c"; } +.bi-regex::before { content: "\f84d"; } +.bi-text-wrap::before { content: "\f84e"; } +.bi-sign-dead-end-fill::before { content: "\f84f"; } +.bi-sign-dead-end::before { content: "\f850"; } +.bi-sign-do-not-enter-fill::before { content: "\f851"; } +.bi-sign-do-not-enter::before { content: "\f852"; } +.bi-sign-intersection-fill::before { content: "\f853"; } +.bi-sign-intersection-side-fill::before { content: "\f854"; } +.bi-sign-intersection-side::before { content: "\f855"; } +.bi-sign-intersection-t-fill::before { content: "\f856"; } +.bi-sign-intersection-t::before { content: "\f857"; } +.bi-sign-intersection-y-fill::before { content: "\f858"; } +.bi-sign-intersection-y::before { content: "\f859"; } +.bi-sign-intersection::before { content: "\f85a"; } +.bi-sign-merge-left-fill::before { content: "\f85b"; } +.bi-sign-merge-left::before { content: "\f85c"; } +.bi-sign-merge-right-fill::before { content: "\f85d"; } +.bi-sign-merge-right::before { content: "\f85e"; } +.bi-sign-no-left-turn-fill::before { content: "\f85f"; } +.bi-sign-no-left-turn::before { content: "\f860"; } +.bi-sign-no-parking-fill::before { content: "\f861"; } +.bi-sign-no-parking::before { content: "\f862"; } +.bi-sign-no-right-turn-fill::before { content: "\f863"; } +.bi-sign-no-right-turn::before { content: "\f864"; } +.bi-sign-railroad-fill::before { content: "\f865"; } +.bi-sign-railroad::before { content: "\f866"; } +.bi-building-add::before { content: "\f867"; } +.bi-building-check::before { content: "\f868"; } +.bi-building-dash::before { content: "\f869"; } +.bi-building-down::before { content: "\f86a"; } +.bi-building-exclamation::before { content: "\f86b"; } +.bi-building-fill-add::before { content: "\f86c"; } +.bi-building-fill-check::before { content: "\f86d"; } +.bi-building-fill-dash::before { content: "\f86e"; } +.bi-building-fill-down::before { content: "\f86f"; } +.bi-building-fill-exclamation::before { content: "\f870"; } +.bi-building-fill-gear::before { content: "\f871"; } +.bi-building-fill-lock::before { content: "\f872"; } +.bi-building-fill-slash::before { content: "\f873"; } +.bi-building-fill-up::before { content: "\f874"; } +.bi-building-fill-x::before { content: "\f875"; } +.bi-building-fill::before { content: "\f876"; } +.bi-building-gear::before { content: "\f877"; } +.bi-building-lock::before { content: "\f878"; } +.bi-building-slash::before { content: "\f879"; } +.bi-building-up::before { content: "\f87a"; } +.bi-building-x::before { content: "\f87b"; } +.bi-buildings-fill::before { content: "\f87c"; } +.bi-buildings::before { content: "\f87d"; } +.bi-bus-front-fill::before { content: "\f87e"; } +.bi-bus-front::before { content: "\f87f"; } +.bi-ev-front-fill::before { content: "\f880"; } +.bi-ev-front::before { content: "\f881"; } +.bi-globe-americas::before { content: "\f882"; } +.bi-globe-asia-australia::before { content: "\f883"; } +.bi-globe-central-south-asia::before { content: "\f884"; } +.bi-globe-europe-africa::before { content: "\f885"; } +.bi-house-add-fill::before { content: "\f886"; } +.bi-house-add::before { content: "\f887"; } +.bi-house-check-fill::before { content: "\f888"; } +.bi-house-check::before { content: "\f889"; } +.bi-house-dash-fill::before { content: "\f88a"; } +.bi-house-dash::before { content: "\f88b"; } +.bi-house-down-fill::before { content: "\f88c"; } +.bi-house-down::before { content: "\f88d"; } +.bi-house-exclamation-fill::before { content: "\f88e"; } +.bi-house-exclamation::before { content: "\f88f"; } +.bi-house-gear-fill::before { content: "\f890"; } +.bi-house-gear::before { content: "\f891"; } +.bi-house-lock-fill::before { content: "\f892"; } +.bi-house-lock::before { content: "\f893"; } +.bi-house-slash-fill::before { content: "\f894"; } +.bi-house-slash::before { content: "\f895"; } +.bi-house-up-fill::before { content: "\f896"; } +.bi-house-up::before { content: "\f897"; } +.bi-house-x-fill::before { content: "\f898"; } +.bi-house-x::before { content: "\f899"; } +.bi-person-add::before { content: "\f89a"; } +.bi-person-down::before { content: "\f89b"; } +.bi-person-exclamation::before { content: "\f89c"; } +.bi-person-fill-add::before { content: "\f89d"; } +.bi-person-fill-check::before { content: "\f89e"; } +.bi-person-fill-dash::before { content: "\f89f"; } +.bi-person-fill-down::before { content: "\f8a0"; } +.bi-person-fill-exclamation::before { content: "\f8a1"; } +.bi-person-fill-gear::before { content: "\f8a2"; } +.bi-person-fill-lock::before { content: "\f8a3"; } +.bi-person-fill-slash::before { content: "\f8a4"; } +.bi-person-fill-up::before { content: "\f8a5"; } +.bi-person-fill-x::before { content: "\f8a6"; } +.bi-person-gear::before { content: "\f8a7"; } +.bi-person-lock::before { content: "\f8a8"; } +.bi-person-slash::before { content: "\f8a9"; } +.bi-person-up::before { content: "\f8aa"; } +.bi-scooter::before { content: "\f8ab"; } +.bi-taxi-front-fill::before { content: "\f8ac"; } +.bi-taxi-front::before { content: "\f8ad"; } +.bi-amd::before { content: "\f8ae"; } +.bi-database-add::before { content: "\f8af"; } +.bi-database-check::before { content: "\f8b0"; } +.bi-database-dash::before { content: "\f8b1"; } +.bi-database-down::before { content: "\f8b2"; } +.bi-database-exclamation::before { content: "\f8b3"; } +.bi-database-fill-add::before { content: "\f8b4"; } +.bi-database-fill-check::before { content: "\f8b5"; } +.bi-database-fill-dash::before { content: "\f8b6"; } +.bi-database-fill-down::before { content: "\f8b7"; } +.bi-database-fill-exclamation::before { content: "\f8b8"; } +.bi-database-fill-gear::before { content: "\f8b9"; } +.bi-database-fill-lock::before { content: "\f8ba"; } +.bi-database-fill-slash::before { content: "\f8bb"; } +.bi-database-fill-up::before { content: "\f8bc"; } +.bi-database-fill-x::before { content: "\f8bd"; } +.bi-database-fill::before { content: "\f8be"; } +.bi-database-gear::before { content: "\f8bf"; } +.bi-database-lock::before { content: "\f8c0"; } +.bi-database-slash::before { content: "\f8c1"; } +.bi-database-up::before { content: "\f8c2"; } +.bi-database-x::before { content: "\f8c3"; } +.bi-database::before { content: "\f8c4"; } +.bi-houses-fill::before { content: "\f8c5"; } +.bi-houses::before { content: "\f8c6"; } +.bi-nvidia::before { content: "\f8c7"; } +.bi-person-vcard-fill::before { content: "\f8c8"; } +.bi-person-vcard::before { content: "\f8c9"; } +.bi-sina-weibo::before { content: "\f8ca"; } +.bi-tencent-qq::before { content: "\f8cb"; } +.bi-wikipedia::before { content: "\f8cc"; } +.bi-alphabet-uppercase::before { content: "\f2a5"; } +.bi-alphabet::before { content: "\f68a"; } +.bi-amazon::before { content: "\f68d"; } +.bi-arrows-collapse-vertical::before { content: "\f690"; } +.bi-arrows-expand-vertical::before { content: "\f695"; } +.bi-arrows-vertical::before { content: "\f698"; } +.bi-arrows::before { content: "\f6a2"; } +.bi-ban-fill::before { content: "\f6a3"; } +.bi-ban::before { content: "\f6b6"; } +.bi-bing::before { content: "\f6c2"; } +.bi-cake::before { content: "\f6e0"; } +.bi-cake2::before { content: "\f6ed"; } +.bi-cookie::before { content: "\f6ee"; } +.bi-copy::before { content: "\f759"; } +.bi-crosshair::before { content: "\f769"; } +.bi-crosshair2::before { content: "\f794"; } +.bi-emoji-astonished-fill::before { content: "\f795"; } +.bi-emoji-astonished::before { content: "\f79a"; } +.bi-emoji-grimace-fill::before { content: "\f79b"; } +.bi-emoji-grimace::before { content: "\f7a0"; } +.bi-emoji-grin-fill::before { content: "\f7a1"; } +.bi-emoji-grin::before { content: "\f7a6"; } +.bi-emoji-surprise-fill::before { content: "\f7a7"; } +.bi-emoji-surprise::before { content: "\f7ac"; } +.bi-emoji-tear-fill::before { content: "\f7ad"; } +.bi-emoji-tear::before { content: "\f7b2"; } +.bi-envelope-arrow-down-fill::before { content: "\f7b3"; } +.bi-envelope-arrow-down::before { content: "\f7b8"; } +.bi-envelope-arrow-up-fill::before { content: "\f7b9"; } +.bi-envelope-arrow-up::before { content: "\f7be"; } +.bi-feather::before { content: "\f7bf"; } +.bi-feather2::before { content: "\f7c4"; } +.bi-floppy-fill::before { content: "\f7c5"; } +.bi-floppy::before { content: "\f7d8"; } +.bi-floppy2-fill::before { content: "\f7d9"; } +.bi-floppy2::before { content: "\f7e4"; } +.bi-gitlab::before { content: "\f7e5"; } +.bi-highlighter::before { content: "\f7f8"; } +.bi-marker-tip::before { content: "\f802"; } +.bi-nvme-fill::before { content: "\f803"; } +.bi-nvme::before { content: "\f80c"; } +.bi-opencollective::before { content: "\f80d"; } +.bi-pci-card-network::before { content: "\f8cd"; } +.bi-pci-card-sound::before { content: "\f8ce"; } +.bi-radar::before { content: "\f8cf"; } +.bi-send-arrow-down-fill::before { content: "\f8d0"; } +.bi-send-arrow-down::before { content: "\f8d1"; } +.bi-send-arrow-up-fill::before { content: "\f8d2"; } +.bi-send-arrow-up::before { content: "\f8d3"; } +.bi-sim-slash-fill::before { content: "\f8d4"; } +.bi-sim-slash::before { content: "\f8d5"; } +.bi-sourceforge::before { content: "\f8d6"; } +.bi-substack::before { content: "\f8d7"; } +.bi-threads-fill::before { content: "\f8d8"; } +.bi-threads::before { content: "\f8d9"; } +.bi-transparency::before { content: "\f8da"; } +.bi-twitter-x::before { content: "\f8db"; } +.bi-type-h4::before { content: "\f8dc"; } +.bi-type-h5::before { content: "\f8dd"; } +.bi-type-h6::before { content: "\f8de"; } +.bi-backpack-fill::before { content: "\f8df"; } +.bi-backpack::before { content: "\f8e0"; } +.bi-backpack2-fill::before { content: "\f8e1"; } +.bi-backpack2::before { content: "\f8e2"; } +.bi-backpack3-fill::before { content: "\f8e3"; } +.bi-backpack3::before { content: "\f8e4"; } +.bi-backpack4-fill::before { content: "\f8e5"; } +.bi-backpack4::before { content: "\f8e6"; } +.bi-brilliance::before { content: "\f8e7"; } +.bi-cake-fill::before { content: "\f8e8"; } +.bi-cake2-fill::before { content: "\f8e9"; } +.bi-duffle-fill::before { content: "\f8ea"; } +.bi-duffle::before { content: "\f8eb"; } +.bi-exposure::before { content: "\f8ec"; } +.bi-gender-neuter::before { content: "\f8ed"; } +.bi-highlights::before { content: "\f8ee"; } +.bi-luggage-fill::before { content: "\f8ef"; } +.bi-luggage::before { content: "\f8f0"; } +.bi-mailbox-flag::before { content: "\f8f1"; } +.bi-mailbox2-flag::before { content: "\f8f2"; } +.bi-noise-reduction::before { content: "\f8f3"; } +.bi-passport-fill::before { content: "\f8f4"; } +.bi-passport::before { content: "\f8f5"; } +.bi-person-arms-up::before { content: "\f8f6"; } +.bi-person-raised-hand::before { content: "\f8f7"; } +.bi-person-standing-dress::before { content: "\f8f8"; } +.bi-person-standing::before { content: "\f8f9"; } +.bi-person-walking::before { content: "\f8fa"; } +.bi-person-wheelchair::before { content: "\f8fb"; } +.bi-shadows::before { content: "\f8fc"; } +.bi-suitcase-fill::before { content: "\f8fd"; } +.bi-suitcase-lg-fill::before { content: "\f8fe"; } +.bi-suitcase-lg::before { content: "\f8ff"; } +.bi-suitcase::before { content: "\f900"; } +.bi-suitcase2-fill::before { content: "\f901"; } +.bi-suitcase2::before { content: "\f902"; } +.bi-vignette::before { content: "\f903"; } +.bi-bluesky::before { content: "\f7f9"; } +.bi-tux::before { content: "\f904"; } +.bi-beaker-fill::before { content: "\f905"; } +.bi-beaker::before { content: "\f906"; } +.bi-flask-fill::before { content: "\f907"; } +.bi-flask-florence-fill::before { content: "\f908"; } +.bi-flask-florence::before { content: "\f909"; } +.bi-flask::before { content: "\f90a"; } +.bi-leaf-fill::before { content: "\f90b"; } +.bi-leaf::before { content: "\f90c"; } +.bi-measuring-cup-fill::before { content: "\f90d"; } +.bi-measuring-cup::before { content: "\f90e"; } +.bi-unlock2-fill::before { content: "\f90f"; } +.bi-unlock2::before { content: "\f910"; } +.bi-battery-low::before { content: "\f911"; } +.bi-anthropic::before { content: "\f912"; } +.bi-apple-music::before { content: "\f913"; } +.bi-claude::before { content: "\f914"; } +.bi-openai::before { content: "\f915"; } +.bi-perplexity::before { content: "\f916"; } +.bi-css::before { content: "\f917"; } +.bi-javascript::before { content: "\f918"; } +.bi-typescript::before { content: "\f919"; } +.bi-fork-knife::before { content: "\f91a"; } +.bi-globe-americas-fill::before { content: "\f91b"; } +.bi-globe-asia-australia-fill::before { content: "\f91c"; } +.bi-globe-central-south-asia-fill::before { content: "\f91d"; } +.bi-globe-europe-africa-fill::before { content: "\f91e"; } diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-icons.woff b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-icons.woff new file mode 100644 index 000000000..a4fa4f024 Binary files /dev/null and b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap-icons.woff differ diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap.min.js b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap.min.js new file mode 100644 index 000000000..e8f21f703 --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/bootstrap/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),s=t=>{t.dispatchEvent(new Event(i))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,m=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},g=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,_=(t,e,n=!0)=>{if(!n)return void g(t);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),g(t))};e.addEventListener(i,a),setTimeout((()=>{r||s(e)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=I(t);return C.has(o)||(o=t),[n,s,o]}function S(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return P(s,{delegateTarget:r}),n.oneOff&&N.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return P(n,{delegateTarget:t}),i.oneOff&&N.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function D(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function $(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&D(t,e,i,r.callable,r.delegationSelector)}function I(t){return t=t.replace(y,""),T[t]||t}const N={on(t,e,i,n){S(t,e,i,n,!1)},one(t,e,i,n){S(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))$(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(w,"");a&&!e.includes(s)||D(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;D(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==I(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=P(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function P(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function M(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function j(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const F={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${j(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${j(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=M(t.dataset[n])}return e},getDataAttribute:(t,e)=>M(t.getAttribute(`data-bs-${j(e)}`))};class H{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?F.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?F.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],r=o(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(r))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${r}" but expected type "${s}".`)}var i}}class W extends H{constructor(t,i){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),N.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.1"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const B=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return n(e)},z={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))},getSelectorFromElement(t){const e=B(t);return e&&z.findOne(e)?e:null},getElementFromSelector(t){const e=B(t);return e?z.findOne(e):null},getMultipleElementsFromSelector(t){const e=B(t);return e?z.find(e):[]}},R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;N.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const s=z.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))},q=".bs.alert",V=`close${q}`,K=`closed${q}`;class Q extends W{static get NAME(){return"alert"}close(){if(N.trigger(this._element,V).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),N.trigger(this._element,K),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Q.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(Q,"close"),m(Q);const X='[data-bs-toggle="button"]';class Y extends W{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=Y.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}N.on(document,"click.bs.button.data-api",X,(t=>{t.preventDefault();const e=t.target.closest(X);Y.getOrCreateInstance(e).toggle()})),m(Y);const U=".bs.swipe",G=`touchstart${U}`,J=`touchmove${U}`,Z=`touchend${U}`,tt=`pointerdown${U}`,et=`pointerup${U}`,it={endCallback:null,leftCallback:null,rightCallback:null},nt={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class st extends H{constructor(t,e){super(),this._element=t,t&&st.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return it}static get DefaultType(){return nt}static get NAME(){return"swipe"}dispose(){N.off(this._element,U)}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),g(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&g(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(N.on(this._element,tt,(t=>this._start(t))),N.on(this._element,et,(t=>this._end(t))),this._element.classList.add("pointer-event")):(N.on(this._element,G,(t=>this._start(t))),N.on(this._element,J,(t=>this._move(t))),N.on(this._element,Z,(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const ot=".bs.carousel",rt=".data-api",at="next",lt="prev",ct="left",ht="right",dt=`slide${ot}`,ut=`slid${ot}`,ft=`keydown${ot}`,pt=`mouseenter${ot}`,mt=`mouseleave${ot}`,gt=`dragstart${ot}`,_t=`load${ot}${rt}`,bt=`click${ot}${rt}`,vt="carousel",yt="active",wt=".active",At=".carousel-item",Et=wt+At,Tt={ArrowLeft:ht,ArrowRight:ct},Ct={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},Ot={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class xt extends W{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=z.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===vt&&this.cycle()}static get Default(){return Ct}static get DefaultType(){return Ot}static get NAME(){return"carousel"}next(){this._slide(at)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(lt)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?N.one(this._element,ut,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void N.one(this._element,ut,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?at:lt;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&N.on(this._element,ft,(t=>this._keydown(t))),"hover"===this._config.pause&&(N.on(this._element,pt,(()=>this.pause())),N.on(this._element,mt,(()=>this._maybeEnableCycle()))),this._config.touch&&st.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of z.find(".carousel-item img",this._element))N.on(t,gt,(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(ct)),rightCallback:()=>this._slide(this._directionToOrder(ht)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new st(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=Tt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=z.findOne(wt,this._indicatorsElement);e.classList.remove(yt),e.removeAttribute("aria-current");const i=z.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(yt),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===at,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>N.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r(dt).defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(yt),i.classList.remove(yt,c,l),this._isSliding=!1,r(ut)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return z.findOne(Et,this._element)}_getItems(){return z.find(At,this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===ct?lt:at:t===ct?at:lt}_orderToDirection(t){return p()?t===lt?ct:ht:t===lt?ht:ct}static jQueryInterface(t){return this.each((function(){const e=xt.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}N.on(document,bt,"[data-bs-slide], [data-bs-slide-to]",(function(t){const e=z.getElementFromSelector(this);if(!e||!e.classList.contains(vt))return;t.preventDefault();const i=xt.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===F.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),N.on(window,_t,(()=>{const t=z.find('[data-bs-ride="carousel"]');for(const e of t)xt.getOrCreateInstance(e)})),m(xt);const kt=".bs.collapse",Lt=`show${kt}`,St=`shown${kt}`,Dt=`hide${kt}`,$t=`hidden${kt}`,It=`click${kt}.data-api`,Nt="show",Pt="collapse",Mt="collapsing",jt=`:scope .${Pt} .${Pt}`,Ft='[data-bs-toggle="collapse"]',Ht={parent:null,toggle:!0},Wt={parent:"(null|element)",toggle:"boolean"};class Bt extends W{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=z.find(Ft);for(const t of i){const e=z.getSelectorFromElement(t),i=z.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return Ht}static get DefaultType(){return Wt}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>Bt.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(N.trigger(this._element,Lt).defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(Pt),this._element.classList.add(Mt),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt,Nt),this._element.style[e]="",N.trigger(this._element,St)}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(N.trigger(this._element,Dt).defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(Mt),this._element.classList.remove(Pt,Nt);for(const t of this._triggerArray){const e=z.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(Mt),this._element.classList.add(Pt),N.trigger(this._element,$t)}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(Nt)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(Ft);for(const e of t){const t=z.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=z.find(jt,this._config.parent);return z.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=Bt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}N.on(document,It,Ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of z.getMultipleElementsFromSelector(this))Bt.getOrCreateInstance(t,{toggle:!1}).toggle()})),m(Bt);var zt="top",Rt="bottom",qt="right",Vt="left",Kt="auto",Qt=[zt,Rt,qt,Vt],Xt="start",Yt="end",Ut="clippingParents",Gt="viewport",Jt="popper",Zt="reference",te=Qt.reduce((function(t,e){return t.concat([e+"-"+Xt,e+"-"+Yt])}),[]),ee=[].concat(Qt,[Kt]).reduce((function(t,e){return t.concat([e,e+"-"+Xt,e+"-"+Yt])}),[]),ie="beforeRead",ne="read",se="afterRead",oe="beforeMain",re="main",ae="afterMain",le="beforeWrite",ce="write",he="afterWrite",de=[ie,ne,se,oe,re,ae,le,ce,he];function ue(t){return t?(t.nodeName||"").toLowerCase():null}function fe(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function pe(t){return t instanceof fe(t).Element||t instanceof Element}function me(t){return t instanceof fe(t).HTMLElement||t instanceof HTMLElement}function ge(t){return"undefined"!=typeof ShadowRoot&&(t instanceof fe(t).ShadowRoot||t instanceof ShadowRoot)}const _e={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];me(s)&&ue(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});me(n)&&ue(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function be(t){return t.split("-")[0]}var ve=Math.max,ye=Math.min,we=Math.round;function Ae(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Ee(){return!/^((?!chrome|android).)*safari/i.test(Ae())}function Te(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&me(t)&&(s=t.offsetWidth>0&&we(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&we(n.height)/t.offsetHeight||1);var r=(pe(t)?fe(t):window).visualViewport,a=!Ee()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Ce(t){var e=Te(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Oe(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&ge(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function xe(t){return fe(t).getComputedStyle(t)}function ke(t){return["table","td","th"].indexOf(ue(t))>=0}function Le(t){return((pe(t)?t.ownerDocument:t.document)||window.document).documentElement}function Se(t){return"html"===ue(t)?t:t.assignedSlot||t.parentNode||(ge(t)?t.host:null)||Le(t)}function De(t){return me(t)&&"fixed"!==xe(t).position?t.offsetParent:null}function $e(t){for(var e=fe(t),i=De(t);i&&ke(i)&&"static"===xe(i).position;)i=De(i);return i&&("html"===ue(i)||"body"===ue(i)&&"static"===xe(i).position)?e:i||function(t){var e=/firefox/i.test(Ae());if(/Trident/i.test(Ae())&&me(t)&&"fixed"===xe(t).position)return null;var i=Se(t);for(ge(i)&&(i=i.host);me(i)&&["html","body"].indexOf(ue(i))<0;){var n=xe(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function Ie(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Ne(t,e,i){return ve(t,ye(e,i))}function Pe(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function Me(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const je={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=be(i.placement),l=Ie(a),c=[Vt,qt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return Pe("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:Me(t,Qt))}(s.padding,i),d=Ce(o),u="y"===l?zt:Vt,f="y"===l?Rt:qt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=$e(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=Ne(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Oe(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function Fe(t){return t.split("-")[1]}var He={top:"auto",right:"auto",bottom:"auto",left:"auto"};function We(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=Vt,y=zt,w=window;if(c){var A=$e(i),E="clientHeight",T="clientWidth";A===fe(i)&&"static"!==xe(A=Le(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===zt||(s===Vt||s===qt)&&o===Yt)&&(y=Rt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==Vt&&(s!==zt&&s!==Rt||o!==Yt)||(v=qt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&He),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:we(i*s)/s||0,y:we(n*s)/s||0}}({x:f,y:m},fe(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const Be={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:be(e.placement),variation:Fe(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,We(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,We(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var ze={passive:!0};const Re={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=fe(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,ze)})),a&&l.addEventListener("resize",i.update,ze),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,ze)})),a&&l.removeEventListener("resize",i.update,ze)}},data:{}};var qe={left:"right",right:"left",bottom:"top",top:"bottom"};function Ve(t){return t.replace(/left|right|bottom|top/g,(function(t){return qe[t]}))}var Ke={start:"end",end:"start"};function Qe(t){return t.replace(/start|end/g,(function(t){return Ke[t]}))}function Xe(t){var e=fe(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ye(t){return Te(Le(t)).left+Xe(t).scrollLeft}function Ue(t){var e=xe(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ge(t){return["html","body","#document"].indexOf(ue(t))>=0?t.ownerDocument.body:me(t)&&Ue(t)?t:Ge(Se(t))}function Je(t,e){var i;void 0===e&&(e=[]);var n=Ge(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=fe(n),r=s?[o].concat(o.visualViewport||[],Ue(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Je(Se(r)))}function Ze(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function ti(t,e,i){return e===Gt?Ze(function(t,e){var i=fe(t),n=Le(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Ee();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+Ye(t),y:l}}(t,i)):pe(e)?function(t,e){var i=Te(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Ze(function(t){var e,i=Le(t),n=Xe(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ve(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ve(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+Ye(t),l=-n.scrollTop;return"rtl"===xe(s||i).direction&&(a+=ve(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Le(t)))}function ei(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?be(s):null,r=s?Fe(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case zt:e={x:a,y:i.y-n.height};break;case Rt:e={x:a,y:i.y+i.height};break;case qt:e={x:i.x+i.width,y:l};break;case Vt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?Ie(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case Xt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Yt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ii(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?Ut:a,c=i.rootBoundary,h=void 0===c?Gt:c,d=i.elementContext,u=void 0===d?Jt:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=Pe("number"!=typeof g?g:Me(g,Qt)),b=u===Jt?Zt:Jt,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Je(Se(t)),i=["absolute","fixed"].indexOf(xe(t).position)>=0&&me(t)?$e(t):t;return pe(i)?e.filter((function(t){return pe(t)&&Oe(t,i)&&"body"!==ue(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=ti(t,i,n);return e.top=ve(s.top,e.top),e.right=ye(s.right,e.right),e.bottom=ye(s.bottom,e.bottom),e.left=ve(s.left,e.left),e}),ti(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(pe(y)?y:y.contextElement||Le(t.elements.popper),l,h,r),A=Te(t.elements.reference),E=ei({reference:A,element:v,strategy:"absolute",placement:s}),T=Ze(Object.assign({},v,E)),C=u===Jt?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Jt&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[qt,Rt].indexOf(t)>=0?1:-1,i=[zt,Rt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function ni(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?ee:l,h=Fe(n),d=h?a?te:te.filter((function(t){return Fe(t)===h})):Qt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ii(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[be(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const si={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=be(g),b=l||(_!==g&&p?function(t){if(be(t)===Kt)return[];var e=Ve(t);return[Qe(t),e,Qe(e)]}(g):[Ve(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(be(i)===Kt?ni(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=ii(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),$=L?k?qt:Vt:k?Rt:zt;y[S]>w[S]&&($=Ve($));var I=Ve($),N=[];if(o&&N.push(D[x]<=0),a&&N.push(D[$]<=0,D[I]<=0),N.every((function(t){return t}))){T=O,E=!1;break}A.set(O,N)}if(E)for(var P=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==P(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function oi(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function ri(t){return[zt,qt,Rt,Vt].some((function(e){return t[e]>=0}))}const ai={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ii(e,{elementContext:"reference"}),a=ii(e,{altBoundary:!0}),l=oi(r,n),c=oi(a,s,o),h=ri(l),d=ri(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},li={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=ee.reduce((function(t,i){return t[i]=function(t,e,i){var n=be(t),s=[Vt,zt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[Vt,qt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},ci={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=ei({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},hi={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ii(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=be(e.placement),b=Fe(e.placement),v=!b,y=Ie(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?zt:Vt,D="y"===y?Rt:qt,$="y"===y?"height":"width",I=A[y],N=I+g[S],P=I-g[D],M=f?-T[$]/2:0,j=b===Xt?E[$]:T[$],F=b===Xt?-T[$]:-E[$],H=e.elements.arrow,W=f&&H?Ce(H):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=Ne(0,E[$],W[$]),V=v?E[$]/2-M-q-z-O.mainAxis:j-q-z-O.mainAxis,K=v?-E[$]/2+M+q+R+O.mainAxis:F+q+R+O.mainAxis,Q=e.elements.arrow&&$e(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=I+K-Y,G=Ne(f?ye(N,I+V-Y-X):N,I,f?ve(P,U):P);A[y]=G,k[y]=G-I}if(a){var J,Z="x"===y?zt:Vt,tt="x"===y?Rt:qt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[zt,Vt].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=Ne(t,e,i);return n>i?i:n}(at,et,lt):Ne(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function di(t,e,i){void 0===i&&(i=!1);var n,s,o=me(e),r=me(e)&&function(t){var e=t.getBoundingClientRect(),i=we(e.width)/t.offsetWidth||1,n=we(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=Le(e),l=Te(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==ue(e)||Ue(a))&&(c=(n=e)!==fe(n)&&me(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:Xe(n)),me(e)?((h=Te(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=Ye(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function ui(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var fi={placement:"bottom",modifiers:[],strategy:"absolute"};function pi(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(F.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...g(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Ti,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=qi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=z.find(Ni);for(const i of e){const e=qi.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Ei,Ti].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Ii)?this:z.prev(this,Ii)[0]||z.next(this,Ii)[0]||z.findOne(Ii,t.delegateTarget.parentNode),o=qi.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}N.on(document,Si,Ii,qi.dataApiKeydownHandler),N.on(document,Si,Pi,qi.dataApiKeydownHandler),N.on(document,Li,qi.clearMenus),N.on(document,Di,qi.clearMenus),N.on(document,Li,Ii,(function(t){t.preventDefault(),qi.getOrCreateInstance(this).toggle()})),m(qi);const Vi="backdrop",Ki="show",Qi=`mousedown.bs.${Vi}`,Xi={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Yi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class Ui extends H{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return Xi}static get DefaultType(){return Yi}static get NAME(){return Vi}show(t){if(!this._config.isVisible)return void g(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(Ki),this._emulateAnimation((()=>{g(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Ki),this._emulateAnimation((()=>{this.dispose(),g(t)}))):g(t)}dispose(){this._isAppended&&(N.off(this._element,Qi),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),N.on(t,Qi,(()=>{g(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const Gi=".bs.focustrap",Ji=`focusin${Gi}`,Zi=`keydown.tab${Gi}`,tn="backward",en={autofocus:!0,trapElement:null},nn={autofocus:"boolean",trapElement:"element"};class sn extends H{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return en}static get DefaultType(){return nn}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),N.off(document,Gi),N.on(document,Ji,(t=>this._handleFocusin(t))),N.on(document,Zi,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,N.off(document,Gi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=z.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===tn?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?tn:"forward")}}const on=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",rn=".sticky-top",an="padding-right",ln="margin-right";class cn{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,an,(e=>e+t)),this._setElementAttributes(on,an,(e=>e+t)),this._setElementAttributes(rn,ln,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,an),this._resetElementAttributes(on,an),this._resetElementAttributes(rn,ln)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&F.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=F.getDataAttribute(t,e);null!==i?(F.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of z.find(t,this._element))e(i)}}const hn=".bs.modal",dn=`hide${hn}`,un=`hidePrevented${hn}`,fn=`hidden${hn}`,pn=`show${hn}`,mn=`shown${hn}`,gn=`resize${hn}`,_n=`click.dismiss${hn}`,bn=`mousedown.dismiss${hn}`,vn=`keydown.dismiss${hn}`,yn=`click${hn}.data-api`,wn="modal-open",An="show",En="modal-static",Tn={backdrop:!0,focus:!0,keyboard:!0},Cn={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class On extends W{constructor(t,e){super(t,e),this._dialog=z.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new cn,this._addEventListeners()}static get Default(){return Tn}static get DefaultType(){return Cn}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||N.trigger(this._element,pn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(wn),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(N.trigger(this._element,dn).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(An),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){N.off(window,hn),N.off(this._dialog,hn),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new Ui({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=z.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(An),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,N.trigger(this._element,mn,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){N.on(this._element,vn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),N.on(window,gn,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),N.on(this._element,bn,(t=>{N.one(this._element,_n,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(wn),this._resetAdjustments(),this._scrollBar.reset(),N.trigger(this._element,fn)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(N.trigger(this._element,un).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(En)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(En),this._queueCallback((()=>{this._element.classList.remove(En),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=On.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}N.on(document,yn,'[data-bs-toggle="modal"]',(function(t){const e=z.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),N.one(e,pn,(t=>{t.defaultPrevented||N.one(e,fn,(()=>{a(this)&&this.focus()}))}));const i=z.findOne(".modal.show");i&&On.getInstance(i).hide(),On.getOrCreateInstance(e).toggle(this)})),R(On),m(On);const xn=".bs.offcanvas",kn=".data-api",Ln=`load${xn}${kn}`,Sn="show",Dn="showing",$n="hiding",In=".offcanvas.show",Nn=`show${xn}`,Pn=`shown${xn}`,Mn=`hide${xn}`,jn=`hidePrevented${xn}`,Fn=`hidden${xn}`,Hn=`resize${xn}`,Wn=`click${xn}${kn}`,Bn=`keydown.dismiss${xn}`,zn={backdrop:!0,keyboard:!0,scroll:!1},Rn={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class qn extends W{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return zn}static get DefaultType(){return Rn}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||N.trigger(this._element,Nn,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new cn).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Dn),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Sn),this._element.classList.remove(Dn),N.trigger(this._element,Pn,{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(N.trigger(this._element,Mn).defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add($n),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Sn,$n),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new cn).reset(),N.trigger(this._element,Fn)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new Ui({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():N.trigger(this._element,jn)}:null})}_initializeFocusTrap(){return new sn({trapElement:this._element})}_addEventListeners(){N.on(this._element,Bn,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():N.trigger(this._element,jn))}))}static jQueryInterface(t){return this.each((function(){const e=qn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}N.on(document,Wn,'[data-bs-toggle="offcanvas"]',(function(t){const e=z.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;N.one(e,Fn,(()=>{a(this)&&this.focus()}));const i=z.findOne(In);i&&i!==e&&qn.getInstance(i).hide(),qn.getOrCreateInstance(e).toggle(this)})),N.on(window,Ln,(()=>{for(const t of z.find(In))qn.getOrCreateInstance(t).show()})),N.on(window,Hn,(()=>{for(const t of z.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&qn.getOrCreateInstance(t).hide()})),R(qn),m(qn);const Vn={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},Kn=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Qn=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Xn=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!Kn.has(i)||Boolean(Qn.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Yn={allowList:Vn,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Un={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Gn={entry:"(string|element|function|null)",selector:"(string|element)"};class Jn extends H{constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Yn}static get DefaultType(){return Un}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Gn)}_setContent(t,e,i){const n=z.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Xn(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return g(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Zn=new Set(["sanitize","allowList","sanitizeFn"]),ts="fade",es="show",is=".modal",ns="hide.bs.modal",ss="hover",os="focus",rs={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},as={allowList:Vn,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},ls={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class cs extends W{constructor(t,e){if(void 0===vi)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return as}static get DefaultType(){return ls}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),N.off(this._element.closest(is),ns,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=N.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),N.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.on(t,"mouseover",h);this._queueCallback((()=>{N.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!N.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(es),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))N.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger[os]=!1,this._activeTrigger[ss]=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),N.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(ts,es),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(ts),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Jn({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(ts)}_isShown(){return this.tip&&this.tip.classList.contains(es)}_createPopper(t){const e=g(this._config.placement,[this,t,this._element]),i=rs[e.toUpperCase()];return bi(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return g(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...g(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)N.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===ss?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===ss?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");N.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?os:ss]=!0,e._enter()})),N.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?os:ss]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},N.on(this._element.closest(is),ns,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=F.getDataAttributes(this._element);for(const t of Object.keys(e))Zn.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=cs.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(cs);const hs={...cs.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},ds={...cs.DefaultType,content:"(null|string|element|function)"};class us extends cs{static get Default(){return hs}static get DefaultType(){return ds}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=us.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(us);const fs=".bs.scrollspy",ps=`activate${fs}`,ms=`click${fs}`,gs=`load${fs}.data-api`,_s="active",bs="[href]",vs=".nav-link",ys=`${vs}, .nav-item > ${vs}, .list-group-item`,ws={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},As={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class Es extends W{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return ws}static get DefaultType(){return As}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(N.off(this._config.target,ms),N.on(this._config.target,ms,bs,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=z.find(bs,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=z.findOne(decodeURI(e.hash),this._element);a(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(_s),this._activateParents(t),N.trigger(this._element,ps,{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))z.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(_s);else for(const e of z.parents(t,".nav, .list-group"))for(const t of z.prev(e,ys))t.classList.add(_s)}_clearActiveClass(t){t.classList.remove(_s);const e=z.find(`${bs}.${_s}`,t);for(const t of e)t.classList.remove(_s)}static jQueryInterface(t){return this.each((function(){const e=Es.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(window,gs,(()=>{for(const t of z.find('[data-bs-spy="scroll"]'))Es.getOrCreateInstance(t)})),m(Es);const Ts=".bs.tab",Cs=`hide${Ts}`,Os=`hidden${Ts}`,xs=`show${Ts}`,ks=`shown${Ts}`,Ls=`click${Ts}`,Ss=`keydown${Ts}`,Ds=`load${Ts}`,$s="ArrowLeft",Is="ArrowRight",Ns="ArrowUp",Ps="ArrowDown",Ms="Home",js="End",Fs="active",Hs="fade",Ws="show",Bs=":not(.dropdown-toggle)",zs='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',Rs=`.nav-link${Bs}, .list-group-item${Bs}, [role="tab"]${Bs}, ${zs}`,qs=`.${Fs}[data-bs-toggle="tab"], .${Fs}[data-bs-toggle="pill"], .${Fs}[data-bs-toggle="list"]`;class Vs extends W{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),N.on(this._element,Ss,(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?N.trigger(e,Cs,{relatedTarget:t}):null;N.trigger(t,xs,{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(Fs),this._activate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),N.trigger(t,ks,{relatedTarget:e})):t.classList.add(Ws)}),t,t.classList.contains(Hs)))}_deactivate(t,e){t&&(t.classList.remove(Fs),t.blur(),this._deactivate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),N.trigger(t,Os,{relatedTarget:e})):t.classList.remove(Ws)}),t,t.classList.contains(Hs)))}_keydown(t){if(![$s,Is,Ns,Ps,Ms,js].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=this._getChildren().filter((t=>!l(t)));let i;if([Ms,js].includes(t.key))i=e[t.key===Ms?0:e.length-1];else{const n=[Is,Ps].includes(t.key);i=b(e,t.target,n,!0)}i&&(i.focus({preventScroll:!0}),Vs.getOrCreateInstance(i).show())}_getChildren(){return z.find(Rs,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=z.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=z.findOne(t,i);s&&s.classList.toggle(n,e)};n(".dropdown-toggle",Fs),n(".dropdown-menu",Ws),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(Fs)}_getInnerElement(t){return t.matches(Rs)?t:z.findOne(Rs,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=Vs.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}N.on(document,Ls,zs,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||Vs.getOrCreateInstance(this).show()})),N.on(window,Ds,(()=>{for(const t of z.find(qs))Vs.getOrCreateInstance(t)})),m(Vs);const Ks=".bs.toast",Qs=`mouseover${Ks}`,Xs=`mouseout${Ks}`,Ys=`focusin${Ks}`,Us=`focusout${Ks}`,Gs=`hide${Ks}`,Js=`hidden${Ks}`,Zs=`show${Ks}`,to=`shown${Ks}`,eo="hide",io="show",no="showing",so={animation:"boolean",autohide:"boolean",delay:"number"},oo={animation:!0,autohide:!0,delay:5e3};class ro extends W{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return oo}static get DefaultType(){return so}static get NAME(){return"toast"}show(){N.trigger(this._element,Zs).defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(eo),d(this._element),this._element.classList.add(io,no),this._queueCallback((()=>{this._element.classList.remove(no),N.trigger(this._element,to),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(N.trigger(this._element,Gs).defaultPrevented||(this._element.classList.add(no),this._queueCallback((()=>{this._element.classList.add(eo),this._element.classList.remove(no,io),N.trigger(this._element,Js)}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(io),super.dispose()}isShown(){return this._element.classList.contains(io)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){N.on(this._element,Qs,(t=>this._onInteraction(t,!0))),N.on(this._element,Xs,(t=>this._onInteraction(t,!1))),N.on(this._element,Ys,(t=>this._onInteraction(t,!0))),N.on(this._element,Us,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=ro.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(ro),m(ro),{Alert:Q,Button:Y,Carousel:xt,Collapse:Bt,Dropdown:qi,Modal:On,Offcanvas:qn,Popover:us,ScrollSpy:Es,Tab:Vs,Toast:ro,Tooltip:cs}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/clipboard/clipboard.min.js b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/clipboard/clipboard.min.js new file mode 100644 index 000000000..1103f811e --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/clipboard/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1.anchorjs-link,.anchorjs-link:focus{opacity:1}",A.sheet.cssRules.length),A.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",A.sheet.cssRules.length),A.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',A.sheet.cssRules.length)),h=document.querySelectorAll("[id]"),t=[].map.call(h,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),A=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||A||!1}}}); +// @license-end \ No newline at end of file diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/popper.min.js b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/popper.min.js new file mode 100644 index 000000000..e3726d728 --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/popper.min.js @@ -0,0 +1,6 @@ +/** + * @popperjs/core v2.11.7 - MIT License + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Popper={})}(this,(function(e){"use strict";function t(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function n(e){return e instanceof t(e).Element||e instanceof Element}function r(e){return e instanceof t(e).HTMLElement||e instanceof HTMLElement}function o(e){return"undefined"!=typeof ShadowRoot&&(e instanceof t(e).ShadowRoot||e instanceof ShadowRoot)}var i=Math.max,a=Math.min,s=Math.round;function f(){var e=navigator.userAgentData;return null!=e&&e.brands&&Array.isArray(e.brands)?e.brands.map((function(e){return e.brand+"/"+e.version})).join(" "):navigator.userAgent}function c(){return!/^((?!chrome|android).)*safari/i.test(f())}function p(e,o,i){void 0===o&&(o=!1),void 0===i&&(i=!1);var a=e.getBoundingClientRect(),f=1,p=1;o&&r(e)&&(f=e.offsetWidth>0&&s(a.width)/e.offsetWidth||1,p=e.offsetHeight>0&&s(a.height)/e.offsetHeight||1);var u=(n(e)?t(e):window).visualViewport,l=!c()&&i,d=(a.left+(l&&u?u.offsetLeft:0))/f,h=(a.top+(l&&u?u.offsetTop:0))/p,m=a.width/f,v=a.height/p;return{width:m,height:v,top:h,right:d+m,bottom:h+v,left:d,x:d,y:h}}function u(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function l(e){return e?(e.nodeName||"").toLowerCase():null}function d(e){return((n(e)?e.ownerDocument:e.document)||window.document).documentElement}function h(e){return p(d(e)).left+u(e).scrollLeft}function m(e){return t(e).getComputedStyle(e)}function v(e){var t=m(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function y(e,n,o){void 0===o&&(o=!1);var i,a,f=r(n),c=r(n)&&function(e){var t=e.getBoundingClientRect(),n=s(t.width)/e.offsetWidth||1,r=s(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(n),m=d(n),y=p(e,c,o),g={scrollLeft:0,scrollTop:0},b={x:0,y:0};return(f||!f&&!o)&&(("body"!==l(n)||v(m))&&(g=(i=n)!==t(i)&&r(i)?{scrollLeft:(a=i).scrollLeft,scrollTop:a.scrollTop}:u(i)),r(n)?((b=p(n,!0)).x+=n.clientLeft,b.y+=n.clientTop):m&&(b.x=h(m))),{x:y.left+g.scrollLeft-b.x,y:y.top+g.scrollTop-b.y,width:y.width,height:y.height}}function g(e){var t=p(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function b(e){return"html"===l(e)?e:e.assignedSlot||e.parentNode||(o(e)?e.host:null)||d(e)}function x(e){return["html","body","#document"].indexOf(l(e))>=0?e.ownerDocument.body:r(e)&&v(e)?e:x(b(e))}function w(e,n){var r;void 0===n&&(n=[]);var o=x(e),i=o===(null==(r=e.ownerDocument)?void 0:r.body),a=t(o),s=i?[a].concat(a.visualViewport||[],v(o)?o:[]):o,f=n.concat(s);return i?f:f.concat(w(b(s)))}function O(e){return["table","td","th"].indexOf(l(e))>=0}function j(e){return r(e)&&"fixed"!==m(e).position?e.offsetParent:null}function E(e){for(var n=t(e),i=j(e);i&&O(i)&&"static"===m(i).position;)i=j(i);return i&&("html"===l(i)||"body"===l(i)&&"static"===m(i).position)?n:i||function(e){var t=/firefox/i.test(f());if(/Trident/i.test(f())&&r(e)&&"fixed"===m(e).position)return null;var n=b(e);for(o(n)&&(n=n.host);r(n)&&["html","body"].indexOf(l(n))<0;){var i=m(n);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||t&&"filter"===i.willChange||t&&i.filter&&"none"!==i.filter)return n;n=n.parentNode}return null}(e)||n}var D="top",A="bottom",L="right",P="left",M="auto",k=[D,A,L,P],W="start",B="end",H="viewport",T="popper",R=k.reduce((function(e,t){return e.concat([t+"-"+W,t+"-"+B])}),[]),S=[].concat(k,[M]).reduce((function(e,t){return e.concat([t,t+"-"+W,t+"-"+B])}),[]),V=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function q(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}function C(e){return e.split("-")[0]}function N(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&o(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function I(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function _(e,r,o){return r===H?I(function(e,n){var r=t(e),o=d(e),i=r.visualViewport,a=o.clientWidth,s=o.clientHeight,f=0,p=0;if(i){a=i.width,s=i.height;var u=c();(u||!u&&"fixed"===n)&&(f=i.offsetLeft,p=i.offsetTop)}return{width:a,height:s,x:f+h(e),y:p}}(e,o)):n(r)?function(e,t){var n=p(e,!1,"fixed"===t);return n.top=n.top+e.clientTop,n.left=n.left+e.clientLeft,n.bottom=n.top+e.clientHeight,n.right=n.left+e.clientWidth,n.width=e.clientWidth,n.height=e.clientHeight,n.x=n.left,n.y=n.top,n}(r,o):I(function(e){var t,n=d(e),r=u(e),o=null==(t=e.ownerDocument)?void 0:t.body,a=i(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),s=i(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),f=-r.scrollLeft+h(e),c=-r.scrollTop;return"rtl"===m(o||n).direction&&(f+=i(n.clientWidth,o?o.clientWidth:0)-a),{width:a,height:s,x:f,y:c}}(d(e)))}function F(e,t,o,s){var f="clippingParents"===t?function(e){var t=w(b(e)),o=["absolute","fixed"].indexOf(m(e).position)>=0&&r(e)?E(e):e;return n(o)?t.filter((function(e){return n(e)&&N(e,o)&&"body"!==l(e)})):[]}(e):[].concat(t),c=[].concat(f,[o]),p=c[0],u=c.reduce((function(t,n){var r=_(e,n,s);return t.top=i(r.top,t.top),t.right=a(r.right,t.right),t.bottom=a(r.bottom,t.bottom),t.left=i(r.left,t.left),t}),_(e,p,s));return u.width=u.right-u.left,u.height=u.bottom-u.top,u.x=u.left,u.y=u.top,u}function U(e){return e.split("-")[1]}function z(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function X(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?C(o):null,a=o?U(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case D:t={x:s,y:n.y-r.height};break;case A:t={x:s,y:n.y+n.height};break;case L:t={x:n.x+n.width,y:f};break;case P:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?z(i):null;if(null!=c){var p="y"===c?"height":"width";switch(a){case W:t[c]=t[c]-(n[p]/2-r[p]/2);break;case B:t[c]=t[c]+(n[p]/2-r[p]/2)}}return t}function Y(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function G(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function J(e,t){void 0===t&&(t={});var r=t,o=r.placement,i=void 0===o?e.placement:o,a=r.strategy,s=void 0===a?e.strategy:a,f=r.boundary,c=void 0===f?"clippingParents":f,u=r.rootBoundary,l=void 0===u?H:u,h=r.elementContext,m=void 0===h?T:h,v=r.altBoundary,y=void 0!==v&&v,g=r.padding,b=void 0===g?0:g,x=Y("number"!=typeof b?b:G(b,k)),w=m===T?"reference":T,O=e.rects.popper,j=e.elements[y?w:m],E=F(n(j)?j:j.contextElement||d(e.elements.popper),c,l,s),P=p(e.elements.reference),M=X({reference:P,element:O,strategy:"absolute",placement:i}),W=I(Object.assign({},O,M)),B=m===T?W:P,R={top:E.top-B.top+x.top,bottom:B.bottom-E.bottom+x.bottom,left:E.left-B.left+x.left,right:B.right-E.right+x.right},S=e.modifiersData.offset;if(m===T&&S){var V=S[i];Object.keys(R).forEach((function(e){var t=[L,A].indexOf(e)>=0?1:-1,n=[D,A].indexOf(e)>=0?"y":"x";R[e]+=V[n]*t}))}return R}var K={placement:"bottom",modifiers:[],strategy:"absolute"};function Q(){for(var e=arguments.length,t=new Array(e),n=0;n=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[P,L].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},se={left:"right",right:"left",bottom:"top",top:"bottom"};function fe(e){return e.replace(/left|right|bottom|top/g,(function(e){return se[e]}))}var ce={start:"end",end:"start"};function pe(e){return e.replace(/start|end/g,(function(e){return ce[e]}))}function ue(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?S:f,p=U(r),u=p?s?R:R.filter((function(e){return U(e)===p})):k,l=u.filter((function(e){return c.indexOf(e)>=0}));0===l.length&&(l=u);var d=l.reduce((function(t,n){return t[n]=J(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[C(n)],t}),{});return Object.keys(d).sort((function(e,t){return d[e]-d[t]}))}var le={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.flipVariations,h=void 0===d||d,m=n.allowedAutoPlacements,v=t.options.placement,y=C(v),g=f||(y===v||!h?[fe(v)]:function(e){if(C(e)===M)return[];var t=fe(e);return[pe(e),t,pe(t)]}(v)),b=[v].concat(g).reduce((function(e,n){return e.concat(C(n)===M?ue(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:h,allowedAutoPlacements:m}):n)}),[]),x=t.rects.reference,w=t.rects.popper,O=new Map,j=!0,E=b[0],k=0;k=0,S=R?"width":"height",V=J(t,{placement:B,boundary:p,rootBoundary:u,altBoundary:l,padding:c}),q=R?T?L:P:T?A:D;x[S]>w[S]&&(q=fe(q));var N=fe(q),I=[];if(i&&I.push(V[H]<=0),s&&I.push(V[q]<=0,V[N]<=0),I.every((function(e){return e}))){E=B,j=!1;break}O.set(B,I)}if(j)for(var _=function(e){var t=b.find((function(t){var n=O.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return E=t,"break"},F=h?3:1;F>0;F--){if("break"===_(F))break}t.placement!==E&&(t.modifiersData[r]._skip=!0,t.placement=E,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function de(e,t,n){return i(e,a(t,n))}var he={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,s=void 0===o||o,f=n.altAxis,c=void 0!==f&&f,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.padding,h=n.tether,m=void 0===h||h,v=n.tetherOffset,y=void 0===v?0:v,b=J(t,{boundary:p,rootBoundary:u,padding:d,altBoundary:l}),x=C(t.placement),w=U(t.placement),O=!w,j=z(x),M="x"===j?"y":"x",k=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,R="number"==typeof T?{mainAxis:T,altAxis:T}:Object.assign({mainAxis:0,altAxis:0},T),S=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,V={x:0,y:0};if(k){if(s){var q,N="y"===j?D:P,I="y"===j?A:L,_="y"===j?"height":"width",F=k[j],X=F+b[N],Y=F-b[I],G=m?-H[_]/2:0,K=w===W?B[_]:H[_],Q=w===W?-H[_]:-B[_],Z=t.elements.arrow,$=m&&Z?g(Z):{width:0,height:0},ee=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=ee[N],ne=ee[I],re=de(0,B[_],$[_]),oe=O?B[_]/2-G-re-te-R.mainAxis:K-re-te-R.mainAxis,ie=O?-B[_]/2+G+re+ne+R.mainAxis:Q+re+ne+R.mainAxis,ae=t.elements.arrow&&E(t.elements.arrow),se=ae?"y"===j?ae.clientTop||0:ae.clientLeft||0:0,fe=null!=(q=null==S?void 0:S[j])?q:0,ce=F+ie-fe,pe=de(m?a(X,F+oe-fe-se):X,F,m?i(Y,ce):Y);k[j]=pe,V[j]=pe-F}if(c){var ue,le="x"===j?D:P,he="x"===j?A:L,me=k[M],ve="y"===M?"height":"width",ye=me+b[le],ge=me-b[he],be=-1!==[D,P].indexOf(x),xe=null!=(ue=null==S?void 0:S[M])?ue:0,we=be?ye:me-B[ve]-H[ve]-xe+R.altAxis,Oe=be?me+B[ve]+H[ve]-xe-R.altAxis:ge,je=m&&be?function(e,t,n){var r=de(e,t,n);return r>n?n:r}(we,me,Oe):de(m?we:ye,me,m?Oe:ge);k[M]=je,V[M]=je-me}t.modifiersData[r]=V}},requiresIfExists:["offset"]};var me={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,s=C(n.placement),f=z(s),c=[P,L].indexOf(s)>=0?"height":"width";if(i&&a){var p=function(e,t){return Y("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:G(e,k))}(o.padding,n),u=g(i),l="y"===f?D:P,d="y"===f?A:L,h=n.rects.reference[c]+n.rects.reference[f]-a[f]-n.rects.popper[c],m=a[f]-n.rects.reference[f],v=E(i),y=v?"y"===f?v.clientHeight||0:v.clientWidth||0:0,b=h/2-m/2,x=p[l],w=y-u[c]-p[d],O=y/2-u[c]/2+b,j=de(x,O,w),M=f;n.modifiersData[r]=((t={})[M]=j,t.centerOffset=j-O,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&N(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ve(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function ye(e){return[D,L,A,P].some((function(t){return e[t]>=0}))}var ge={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=J(t,{elementContext:"reference"}),s=J(t,{altBoundary:!0}),f=ve(a,r),c=ve(s,o,i),p=ye(f),u=ye(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":u})}},be=Z({defaultModifiers:[ee,te,oe,ie]}),xe=[ee,te,oe,ie,ae,le,he,me,ge],we=Z({defaultModifiers:xe});e.applyStyles=ie,e.arrow=me,e.computeStyles=oe,e.createPopper=we,e.createPopperLite=be,e.defaultModifiers=xe,e.detectOverflow=J,e.eventListeners=ee,e.flip=le,e.hide=ge,e.offset=ae,e.popperGenerator=Z,e.popperOffsets=te,e.preventOverflow=he,Object.defineProperty(e,"__esModule",{value:!0})})); + diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/quarto-syntax-highlighting-64a204ab8560d761af7679ceaba22944.css b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/quarto-syntax-highlighting-64a204ab8560d761af7679ceaba22944.css new file mode 100644 index 000000000..c8e339748 --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/quarto-syntax-highlighting-64a204ab8560d761af7679ceaba22944.css @@ -0,0 +1,236 @@ +/* quarto syntax highlight colors */ +:root { + --quarto-hl-ot-color: #003B4F; + --quarto-hl-at-color: #657422; + --quarto-hl-ss-color: #20794D; + --quarto-hl-an-color: #5E5E5E; + --quarto-hl-fu-color: #4758AB; + --quarto-hl-st-color: #20794D; + --quarto-hl-cf-color: #003B4F; + --quarto-hl-op-color: #5E5E5E; + --quarto-hl-er-color: #AD0000; + --quarto-hl-bn-color: #AD0000; + --quarto-hl-al-color: #AD0000; + --quarto-hl-va-color: #111111; + --quarto-hl-bu-color: inherit; + --quarto-hl-ex-color: inherit; + --quarto-hl-pp-color: #AD0000; + --quarto-hl-in-color: #5E5E5E; + --quarto-hl-vs-color: #20794D; + --quarto-hl-wa-color: #5E5E5E; + --quarto-hl-do-color: #5E5E5E; + --quarto-hl-im-color: #00769E; + --quarto-hl-ch-color: #20794D; + --quarto-hl-dt-color: #AD0000; + --quarto-hl-fl-color: #AD0000; + --quarto-hl-co-color: #5E5E5E; + --quarto-hl-cv-color: #5E5E5E; + --quarto-hl-cn-color: #8f5902; + --quarto-hl-sc-color: #5E5E5E; + --quarto-hl-dv-color: #AD0000; + --quarto-hl-kw-color: #003B4F; +} + +/* other quarto variables */ +:root { + --quarto-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +/* syntax highlight based on Pandoc's rules */ +pre > code.sourceCode > span { + color: #003B4F; +} + +code.sourceCode > span { + color: #003B4F; +} + +div.sourceCode, +div.sourceCode pre.sourceCode { + color: #003B4F; +} + +/* Normal */ +code span { + color: #003B4F; +} + +/* Alert */ +code span.al { + color: #AD0000; + font-style: inherit; +} + +/* Annotation */ +code span.an { + color: #5E5E5E; + font-style: inherit; +} + +/* Attribute */ +code span.at { + color: #657422; + font-style: inherit; +} + +/* BaseN */ +code span.bn { + color: #AD0000; + font-style: inherit; +} + +/* BuiltIn */ +code span.bu { + font-style: inherit; +} + +/* ControlFlow */ +code span.cf { + color: #003B4F; + font-weight: bold; + font-style: inherit; +} + +/* Char */ +code span.ch { + color: #20794D; + font-style: inherit; +} + +/* Constant */ +code span.cn { + color: #8f5902; + font-style: inherit; +} + +/* Comment */ +code span.co { + color: #5E5E5E; + font-style: inherit; +} + +/* CommentVar */ +code span.cv { + color: #5E5E5E; + font-style: italic; +} + +/* Documentation */ +code span.do { + color: #5E5E5E; + font-style: italic; +} + +/* DataType */ +code span.dt { + color: #AD0000; + font-style: inherit; +} + +/* DecVal */ +code span.dv { + color: #AD0000; + font-style: inherit; +} + +/* Error */ +code span.er { + color: #AD0000; + font-style: inherit; +} + +/* Extension */ +code span.ex { + font-style: inherit; +} + +/* Float */ +code span.fl { + color: #AD0000; + font-style: inherit; +} + +/* Function */ +code span.fu { + color: #4758AB; + font-style: inherit; +} + +/* Import */ +code span.im { + color: #00769E; + font-style: inherit; +} + +/* Information */ +code span.in { + color: #5E5E5E; + font-style: inherit; +} + +/* Keyword */ +code span.kw { + color: #003B4F; + font-weight: bold; + font-style: inherit; +} + +/* Operator */ +code span.op { + color: #5E5E5E; + font-style: inherit; +} + +/* Other */ +code span.ot { + color: #003B4F; + font-style: inherit; +} + +/* Preprocessor */ +code span.pp { + color: #AD0000; + font-style: inherit; +} + +/* SpecialChar */ +code span.sc { + color: #5E5E5E; + font-style: inherit; +} + +/* SpecialString */ +code span.ss { + color: #20794D; + font-style: inherit; +} + +/* String */ +code span.st { + color: #20794D; + font-style: inherit; +} + +/* Variable */ +code span.va { + color: #111111; + font-style: inherit; +} + +/* VerbatimString */ +code span.vs { + color: #20794D; + font-style: inherit; +} + +/* Warning */ +code span.wa { + color: #5E5E5E; + font-style: italic; +} + +.prevent-inlining { + content: " { + // Find any conflicting margin elements and add margins to the + // top to prevent overlap + const marginChildren = window.document.querySelectorAll( + ".column-margin.column-container > *, .margin-caption, .aside" + ); + + let lastBottom = 0; + for (const marginChild of marginChildren) { + if (marginChild.offsetParent !== null) { + // clear the top margin so we recompute it + marginChild.style.marginTop = null; + const top = marginChild.getBoundingClientRect().top + window.scrollY; + if (top < lastBottom) { + const marginChildStyle = window.getComputedStyle(marginChild); + const marginBottom = parseFloat(marginChildStyle["marginBottom"]); + const margin = lastBottom - top + marginBottom; + marginChild.style.marginTop = `${margin}px`; + } + const styles = window.getComputedStyle(marginChild); + const marginTop = parseFloat(styles["marginTop"]); + lastBottom = top + marginChild.getBoundingClientRect().height + marginTop; + } + } +}; + +window.document.addEventListener("DOMContentLoaded", function (_event) { + // Recompute the position of margin elements anytime the body size changes + if (window.ResizeObserver) { + const resizeObserver = new window.ResizeObserver( + throttle(() => { + layoutMarginEls(); + if ( + window.document.body.getBoundingClientRect().width < 990 && + isReaderMode() + ) { + quartoToggleReader(); + } + }, 50) + ); + resizeObserver.observe(window.document.body); + } + + const tocEl = window.document.querySelector('nav.toc-active[role="doc-toc"]'); + const sidebarEl = window.document.getElementById("quarto-sidebar"); + const leftTocEl = window.document.getElementById("quarto-sidebar-toc-left"); + const marginSidebarEl = window.document.getElementById( + "quarto-margin-sidebar" + ); + // function to determine whether the element has a previous sibling that is active + const prevSiblingIsActiveLink = (el) => { + const sibling = el.previousElementSibling; + if (sibling && sibling.tagName === "A") { + return sibling.classList.contains("active"); + } else { + return false; + } + }; + + // dispatch for htmlwidgets + // they use slideenter event to trigger resize + function fireSlideEnter() { + const event = window.document.createEvent("Event"); + event.initEvent("slideenter", true, true); + window.document.dispatchEvent(event); + } + + const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]'); + tabs.forEach((tab) => { + tab.addEventListener("shown.bs.tab", fireSlideEnter); + }); + + // dispatch for shiny + // they use BS shown and hidden events to trigger rendering + function distpatchShinyEvents(previous, current) { + if (window.jQuery) { + if (previous) { + window.jQuery(previous).trigger("hidden"); + } + if (current) { + window.jQuery(current).trigger("shown"); + } + } + } + + // tabby.js listener: Trigger event for htmlwidget and shiny + document.addEventListener( + "tabby", + function (event) { + fireSlideEnter(); + distpatchShinyEvents(event.detail.previousTab, event.detail.tab); + }, + false + ); + + // Track scrolling and mark TOC links as active + // get table of contents and sidebar (bail if we don't have at least one) + const tocLinks = tocEl + ? [...tocEl.querySelectorAll("a[data-scroll-target]")] + : []; + const makeActive = (link) => tocLinks[link].classList.add("active"); + const removeActive = (link) => tocLinks[link].classList.remove("active"); + const removeAllActive = () => + [...Array(tocLinks.length).keys()].forEach((link) => removeActive(link)); + + // activate the anchor for a section associated with this TOC entry + tocLinks.forEach((link) => { + link.addEventListener("click", () => { + if (link.href.indexOf("#") !== -1) { + const anchor = link.href.split("#")[1]; + const heading = window.document.querySelector( + `[data-anchor-id="${anchor}"]` + ); + if (heading) { + // Add the class + heading.classList.add("reveal-anchorjs-link"); + + // function to show the anchor + const handleMouseout = () => { + heading.classList.remove("reveal-anchorjs-link"); + heading.removeEventListener("mouseout", handleMouseout); + }; + + // add a function to clear the anchor when the user mouses out of it + heading.addEventListener("mouseout", handleMouseout); + } + } + }); + }); + + const sections = tocLinks.map((link) => { + const target = link.getAttribute("data-scroll-target"); + if (target.startsWith("#")) { + return window.document.getElementById(decodeURI(`${target.slice(1)}`)); + } else { + return window.document.querySelector(decodeURI(`${target}`)); + } + }); + + const sectionMargin = 200; + let currentActive = 0; + // track whether we've initialized state the first time + let init = false; + + const updateActiveLink = () => { + // The index from bottom to top (e.g. reversed list) + let sectionIndex = -1; + if ( + window.innerHeight + window.pageYOffset >= + window.document.body.offsetHeight + ) { + // This is the no-scroll case where last section should be the active one + sectionIndex = 0; + } else { + // This finds the last section visible on screen that should be made active + sectionIndex = [...sections].reverse().findIndex((section) => { + if (section) { + return window.pageYOffset >= section.offsetTop - sectionMargin; + } else { + return false; + } + }); + } + if (sectionIndex > -1) { + const current = sections.length - sectionIndex - 1; + if (current !== currentActive) { + removeAllActive(); + currentActive = current; + makeActive(current); + if (init) { + window.dispatchEvent(sectionChanged); + } + init = true; + } + } + }; + + const inHiddenRegion = (top, bottom, hiddenRegions) => { + for (const region of hiddenRegions) { + if (top <= region.bottom && bottom >= region.top) { + return true; + } + } + return false; + }; + + const categorySelector = "header.quarto-title-block .quarto-category"; + const activateCategories = (href) => { + // Find any categories + // Surround them with a link pointing back to: + // #category=Authoring + try { + const categoryEls = window.document.querySelectorAll(categorySelector); + for (const categoryEl of categoryEls) { + const categoryText = categoryEl.textContent; + if (categoryText) { + const link = `${href}#category=${encodeURIComponent(categoryText)}`; + const linkEl = window.document.createElement("a"); + linkEl.setAttribute("href", link); + for (const child of categoryEl.childNodes) { + linkEl.append(child); + } + categoryEl.appendChild(linkEl); + } + } + } catch { + // Ignore errors + } + }; + function hasTitleCategories() { + return window.document.querySelector(categorySelector) !== null; + } + + function offsetRelativeUrl(url) { + const offset = getMeta("quarto:offset"); + return offset ? offset + url : url; + } + + function offsetAbsoluteUrl(url) { + const offset = getMeta("quarto:offset"); + const baseUrl = new URL(offset, window.location); + + const projRelativeUrl = url.replace(baseUrl, ""); + if (projRelativeUrl.startsWith("/")) { + return projRelativeUrl; + } else { + return "/" + projRelativeUrl; + } + } + + // read a meta tag value + function getMeta(metaName) { + const metas = window.document.getElementsByTagName("meta"); + for (let i = 0; i < metas.length; i++) { + if (metas[i].getAttribute("name") === metaName) { + return metas[i].getAttribute("content"); + } + } + return ""; + } + + async function findAndActivateCategories() { + // Categories search with listing only use path without query + const currentPagePath = offsetAbsoluteUrl( + window.location.origin + window.location.pathname + ); + const response = await fetch(offsetRelativeUrl("listings.json")); + if (response.status == 200) { + return response.json().then(function (listingPaths) { + const listingHrefs = []; + for (const listingPath of listingPaths) { + const pathWithoutLeadingSlash = listingPath.listing.substring(1); + for (const item of listingPath.items) { + const encodedItem = encodeURI(item); + if ( + encodedItem === currentPagePath || + encodedItem === currentPagePath + "index.html" + ) { + // Resolve this path against the offset to be sure + // we already are using the correct path to the listing + // (this adjusts the listing urls to be rooted against + // whatever root the page is actually running against) + const relative = offsetRelativeUrl(pathWithoutLeadingSlash); + const baseUrl = window.location; + const resolvedPath = new URL(relative, baseUrl); + listingHrefs.push(resolvedPath.pathname); + break; + } + } + } + + // Look up the tree for a nearby linting and use that if we find one + const nearestListing = findNearestParentListing( + offsetAbsoluteUrl(window.location.pathname), + listingHrefs + ); + if (nearestListing) { + activateCategories(nearestListing); + } else { + // See if the referrer is a listing page for this item + const referredRelativePath = offsetAbsoluteUrl(document.referrer); + const referrerListing = listingHrefs.find((listingHref) => { + const isListingReferrer = + listingHref === referredRelativePath || + listingHref === referredRelativePath + "index.html"; + return isListingReferrer; + }); + + if (referrerListing) { + // Try to use the referrer if possible + activateCategories(referrerListing); + } else if (listingHrefs.length > 0) { + // Otherwise, just fall back to the first listing + activateCategories(listingHrefs[0]); + } + } + }); + } + } + if (hasTitleCategories()) { + findAndActivateCategories(); + } + + const findNearestParentListing = (href, listingHrefs) => { + if (!href || !listingHrefs) { + return undefined; + } + // Look up the tree for a nearby linting and use that if we find one + const relativeParts = href.substring(1).split("/"); + while (relativeParts.length > 0) { + const path = relativeParts.join("/"); + for (const listingHref of listingHrefs) { + if (listingHref.startsWith(path)) { + return listingHref; + } + } + relativeParts.pop(); + } + + return undefined; + }; + + const manageSidebarVisiblity = (el, placeholderDescriptor) => { + let isVisible = true; + let elRect; + + return (hiddenRegions) => { + if (el === null) { + return; + } + + // Find the last element of the TOC + const lastChildEl = el.lastElementChild; + + if (lastChildEl) { + // Converts the sidebar to a menu + const convertToMenu = () => { + for (const child of el.children) { + child.style.opacity = 0; + child.style.overflow = "hidden"; + child.style.pointerEvents = "none"; + } + + nexttick(() => { + const toggleContainer = window.document.createElement("div"); + toggleContainer.style.width = "100%"; + toggleContainer.classList.add("zindex-over-content"); + toggleContainer.classList.add("quarto-sidebar-toggle"); + toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom + toggleContainer.id = placeholderDescriptor.id; + toggleContainer.style.position = "fixed"; + + const toggleIcon = window.document.createElement("i"); + toggleIcon.classList.add("quarto-sidebar-toggle-icon"); + toggleIcon.classList.add("bi"); + toggleIcon.classList.add("bi-caret-down-fill"); + + const toggleTitle = window.document.createElement("div"); + const titleEl = window.document.body.querySelector( + placeholderDescriptor.titleSelector + ); + if (titleEl) { + toggleTitle.append( + titleEl.textContent || titleEl.innerText, + toggleIcon + ); + } + toggleTitle.classList.add("zindex-over-content"); + toggleTitle.classList.add("quarto-sidebar-toggle-title"); + toggleContainer.append(toggleTitle); + + const toggleContents = window.document.createElement("div"); + toggleContents.classList = el.classList; + toggleContents.classList.add("zindex-over-content"); + toggleContents.classList.add("quarto-sidebar-toggle-contents"); + for (const child of el.children) { + if (child.id === "toc-title") { + continue; + } + + const clone = child.cloneNode(true); + clone.style.opacity = 1; + clone.style.pointerEvents = null; + clone.style.display = null; + toggleContents.append(clone); + } + toggleContents.style.height = "0px"; + const positionToggle = () => { + // position the element (top left of parent, same width as parent) + if (!elRect) { + elRect = el.getBoundingClientRect(); + } + toggleContainer.style.left = `${elRect.left}px`; + toggleContainer.style.top = `${elRect.top}px`; + toggleContainer.style.width = `${elRect.width}px`; + }; + positionToggle(); + + toggleContainer.append(toggleContents); + el.parentElement.prepend(toggleContainer); + + // Process clicks + let tocShowing = false; + // Allow the caller to control whether this is dismissed + // when it is clicked (e.g. sidebar navigation supports + // opening and closing the nav tree, so don't dismiss on click) + const clickEl = placeholderDescriptor.dismissOnClick + ? toggleContainer + : toggleTitle; + + const closeToggle = () => { + if (tocShowing) { + toggleContainer.classList.remove("expanded"); + toggleContents.style.height = "0px"; + tocShowing = false; + } + }; + + // Get rid of any expanded toggle if the user scrolls + window.document.addEventListener( + "scroll", + throttle(() => { + closeToggle(); + }, 50) + ); + + // Handle positioning of the toggle + window.addEventListener( + "resize", + throttle(() => { + elRect = undefined; + positionToggle(); + }, 50) + ); + + window.addEventListener("quarto-hrChanged", () => { + elRect = undefined; + }); + + // Process the click + clickEl.onclick = () => { + if (!tocShowing) { + toggleContainer.classList.add("expanded"); + toggleContents.style.height = null; + tocShowing = true; + } else { + closeToggle(); + } + }; + }); + }; + + // Converts a sidebar from a menu back to a sidebar + const convertToSidebar = () => { + for (const child of el.children) { + child.style.opacity = 1; + child.style.overflow = null; + child.style.pointerEvents = null; + } + + const placeholderEl = window.document.getElementById( + placeholderDescriptor.id + ); + if (placeholderEl) { + placeholderEl.remove(); + } + + el.classList.remove("rollup"); + }; + + if (isReaderMode()) { + convertToMenu(); + isVisible = false; + } else { + // Find the top and bottom o the element that is being managed + const elTop = el.offsetTop; + const elBottom = + elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight; + + if (!isVisible) { + // If the element is current not visible reveal if there are + // no conflicts with overlay regions + if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) { + convertToSidebar(); + isVisible = true; + } + } else { + // If the element is visible, hide it if it conflicts with overlay regions + // and insert a placeholder toggle (or if we're in reader mode) + if (inHiddenRegion(elTop, elBottom, hiddenRegions)) { + convertToMenu(); + isVisible = false; + } + } + } + } + }; + }; + + const tabEls = document.querySelectorAll('a[data-bs-toggle="tab"]'); + for (const tabEl of tabEls) { + const id = tabEl.getAttribute("data-bs-target"); + if (id) { + const columnEl = document.querySelector( + `${id} .column-margin, .tabset-margin-content` + ); + if (columnEl) + tabEl.addEventListener("shown.bs.tab", function (event) { + const el = event.srcElement; + if (el) { + const visibleCls = `${el.id}-margin-content`; + // walk up until we find a parent tabset + let panelTabsetEl = el.parentElement; + while (panelTabsetEl) { + if (panelTabsetEl.classList.contains("panel-tabset")) { + break; + } + panelTabsetEl = panelTabsetEl.parentElement; + } + + if (panelTabsetEl) { + const prevSib = panelTabsetEl.previousElementSibling; + if ( + prevSib && + prevSib.classList.contains("tabset-margin-container") + ) { + const childNodes = prevSib.querySelectorAll( + ".tabset-margin-content" + ); + for (const childEl of childNodes) { + if (childEl.classList.contains(visibleCls)) { + childEl.classList.remove("collapse"); + } else { + childEl.classList.add("collapse"); + } + } + } + } + } + + layoutMarginEls(); + }); + } + } + + // Manage the visibility of the toc and the sidebar + const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, { + id: "quarto-toc-toggle", + titleSelector: "#toc-title", + dismissOnClick: true, + }); + const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, { + id: "quarto-sidebarnav-toggle", + titleSelector: ".title", + dismissOnClick: false, + }); + let tocLeftScrollVisibility; + if (leftTocEl) { + tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, { + id: "quarto-lefttoc-toggle", + titleSelector: "#toc-title", + dismissOnClick: true, + }); + } + + // Find the first element that uses formatting in special columns + const conflictingEls = window.document.body.querySelectorAll( + '[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]' + ); + + // Filter all the possibly conflicting elements into ones + // the do conflict on the left or ride side + const arrConflictingEls = Array.from(conflictingEls); + const leftSideConflictEls = arrConflictingEls.filter((el) => { + if (el.tagName === "ASIDE") { + return false; + } + return Array.from(el.classList).find((className) => { + return ( + className !== "column-body" && + className.startsWith("column-") && + !className.endsWith("right") && + !className.endsWith("container") && + className !== "column-margin" + ); + }); + }); + const rightSideConflictEls = arrConflictingEls.filter((el) => { + if (el.tagName === "ASIDE") { + return true; + } + + const hasMarginCaption = Array.from(el.classList).find((className) => { + return className == "margin-caption"; + }); + if (hasMarginCaption) { + return true; + } + + return Array.from(el.classList).find((className) => { + return ( + className !== "column-body" && + !className.endsWith("container") && + className.startsWith("column-") && + !className.endsWith("left") + ); + }); + }); + + const kOverlapPaddingSize = 10; + function toRegions(els) { + return els.map((el) => { + const boundRect = el.getBoundingClientRect(); + const top = + boundRect.top + + document.documentElement.scrollTop - + kOverlapPaddingSize; + return { + top, + bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize, + }; + }); + } + + let hasObserved = false; + const visibleItemObserver = (els) => { + let visibleElements = [...els]; + const intersectionObserver = new IntersectionObserver( + (entries, _observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + if (visibleElements.indexOf(entry.target) === -1) { + visibleElements.push(entry.target); + } + } else { + visibleElements = visibleElements.filter((visibleEntry) => { + return visibleEntry !== entry; + }); + } + }); + + if (!hasObserved) { + hideOverlappedSidebars(); + } + hasObserved = true; + }, + {} + ); + els.forEach((el) => { + intersectionObserver.observe(el); + }); + + return { + getVisibleEntries: () => { + return visibleElements; + }, + }; + }; + + const rightElementObserver = visibleItemObserver(rightSideConflictEls); + const leftElementObserver = visibleItemObserver(leftSideConflictEls); + + const hideOverlappedSidebars = () => { + marginScrollVisibility(toRegions(rightElementObserver.getVisibleEntries())); + sidebarScrollVisiblity(toRegions(leftElementObserver.getVisibleEntries())); + if (tocLeftScrollVisibility) { + tocLeftScrollVisibility( + toRegions(leftElementObserver.getVisibleEntries()) + ); + } + }; + + window.quartoToggleReader = () => { + // Applies a slow class (or removes it) + // to update the transition speed + const slowTransition = (slow) => { + const manageTransition = (id, slow) => { + const el = document.getElementById(id); + if (el) { + if (slow) { + el.classList.add("slow"); + } else { + el.classList.remove("slow"); + } + } + }; + + manageTransition("TOC", slow); + manageTransition("quarto-sidebar", slow); + }; + const readerMode = !isReaderMode(); + setReaderModeValue(readerMode); + + // If we're entering reader mode, slow the transition + if (readerMode) { + slowTransition(readerMode); + } + highlightReaderToggle(readerMode); + hideOverlappedSidebars(); + + // If we're exiting reader mode, restore the non-slow transition + if (!readerMode) { + slowTransition(!readerMode); + } + }; + + const highlightReaderToggle = (readerMode) => { + const els = document.querySelectorAll(".quarto-reader-toggle"); + if (els) { + els.forEach((el) => { + if (readerMode) { + el.classList.add("reader"); + } else { + el.classList.remove("reader"); + } + }); + } + }; + + const setReaderModeValue = (val) => { + if (window.location.protocol !== "file:") { + window.localStorage.setItem("quarto-reader-mode", val); + } else { + localReaderMode = val; + } + }; + + const isReaderMode = () => { + if (window.location.protocol !== "file:") { + return window.localStorage.getItem("quarto-reader-mode") === "true"; + } else { + return localReaderMode; + } + }; + let localReaderMode = null; + + const tocOpenDepthStr = tocEl?.getAttribute("data-toc-expanded"); + const tocOpenDepth = tocOpenDepthStr ? Number(tocOpenDepthStr) : 1; + + // Walk the TOC and collapse/expand nodes + // Nodes are expanded if: + // - they are top level + // - they have children that are 'active' links + // - they are directly below an link that is 'active' + const walk = (el, depth) => { + // Tick depth when we enter a UL + if (el.tagName === "UL") { + depth = depth + 1; + } + + // It this is active link + let isActiveNode = false; + if (el.tagName === "A" && el.classList.contains("active")) { + isActiveNode = true; + } + + // See if there is an active child to this element + let hasActiveChild = false; + for (const child of el.children) { + hasActiveChild = walk(child, depth) || hasActiveChild; + } + + // Process the collapse state if this is an UL + if (el.tagName === "UL") { + if (tocOpenDepth === -1 && depth > 1) { + // toc-expand: false + el.classList.add("collapse"); + } else if ( + depth <= tocOpenDepth || + hasActiveChild || + prevSiblingIsActiveLink(el) + ) { + el.classList.remove("collapse"); + } else { + el.classList.add("collapse"); + } + + // untick depth when we leave a UL + depth = depth - 1; + } + return hasActiveChild || isActiveNode; + }; + + // walk the TOC and expand / collapse any items that should be shown + if (tocEl) { + updateActiveLink(); + walk(tocEl, 0); + } + + // Throttle the scroll event and walk peridiocally + window.document.addEventListener( + "scroll", + throttle(() => { + if (tocEl) { + updateActiveLink(); + walk(tocEl, 0); + } + if (!isReaderMode()) { + hideOverlappedSidebars(); + } + }, 5) + ); + window.addEventListener( + "resize", + throttle(() => { + if (tocEl) { + updateActiveLink(); + walk(tocEl, 0); + } + if (!isReaderMode()) { + hideOverlappedSidebars(); + } + }, 10) + ); + hideOverlappedSidebars(); + highlightReaderToggle(isReaderMode()); +}); + +tabsets.init(); + +function throttle(func, wait) { + let waiting = false; + return function () { + if (!waiting) { + func.apply(this, arguments); + waiting = true; + setTimeout(function () { + waiting = false; + }, wait); + } + }; +} + +function nexttick(func) { + return setTimeout(func, 0); +} diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tabsets/tabsets.js b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tabsets/tabsets.js new file mode 100644 index 000000000..51345d0ed --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tabsets/tabsets.js @@ -0,0 +1,95 @@ +// grouped tabsets + +export function init() { + window.addEventListener("pageshow", (_event) => { + function getTabSettings() { + const data = localStorage.getItem("quarto-persistent-tabsets-data"); + if (!data) { + localStorage.setItem("quarto-persistent-tabsets-data", "{}"); + return {}; + } + if (data) { + return JSON.parse(data); + } + } + + function setTabSettings(data) { + localStorage.setItem( + "quarto-persistent-tabsets-data", + JSON.stringify(data) + ); + } + + function setTabState(groupName, groupValue) { + const data = getTabSettings(); + data[groupName] = groupValue; + setTabSettings(data); + } + + function toggleTab(tab, active) { + const tabPanelId = tab.getAttribute("aria-controls"); + const tabPanel = document.getElementById(tabPanelId); + if (active) { + tab.classList.add("active"); + tabPanel.classList.add("active"); + } else { + tab.classList.remove("active"); + tabPanel.classList.remove("active"); + } + } + + function toggleAll(selectedGroup, selectorsToSync) { + for (const [thisGroup, tabs] of Object.entries(selectorsToSync)) { + const active = selectedGroup === thisGroup; + for (const tab of tabs) { + toggleTab(tab, active); + } + } + } + + function findSelectorsToSyncByLanguage() { + const result = {}; + const tabs = Array.from( + document.querySelectorAll(`div[data-group] a[id^='tabset-']`) + ); + for (const item of tabs) { + const div = item.parentElement.parentElement.parentElement; + const group = div.getAttribute("data-group"); + if (!result[group]) { + result[group] = {}; + } + const selectorsToSync = result[group]; + const value = item.innerHTML; + if (!selectorsToSync[value]) { + selectorsToSync[value] = []; + } + selectorsToSync[value].push(item); + } + return result; + } + + function setupSelectorSync() { + const selectorsToSync = findSelectorsToSyncByLanguage(); + Object.entries(selectorsToSync).forEach(([group, tabSetsByValue]) => { + Object.entries(tabSetsByValue).forEach(([value, items]) => { + items.forEach((item) => { + item.addEventListener("click", (_event) => { + setTabState(group, value); + toggleAll(value, selectorsToSync[group]); + }); + }); + }); + }); + return selectorsToSync; + } + + const selectorsToSync = setupSelectorSync(); + for (const [group, selectedName] of Object.entries(getTabSettings())) { + const selectors = selectorsToSync[group]; + // it's possible that stale state gives us empty selections, so we explicitly check here. + if (selectors) { + toggleAll(selectedName, selectors); + } + } + }); +} diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tippy.css b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tippy.css new file mode 100644 index 000000000..e6ae635cb --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tippy.css @@ -0,0 +1 @@ +.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1} \ No newline at end of file diff --git a/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tippy.umd.min.js b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tippy.umd.min.js new file mode 100644 index 000000000..ca292be32 --- /dev/null +++ b/overstorey_staging/TF24_flexible_allometry_demo_files/libs/quarto-html/tippy.umd.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@popperjs/core")):"function"==typeof define&&define.amd?define(["@popperjs/core"],t):(e=e||self).tippy=t(e.Popper)}(this,(function(e){"use strict";var t={passive:!0,capture:!0},n=function(){return document.body};function r(e,t,n){if(Array.isArray(e)){var r=e[t];return null==r?Array.isArray(n)?n[t]:n:r}return e}function o(e,t){var n={}.toString.call(e);return 0===n.indexOf("[object")&&n.indexOf(t+"]")>-1}function i(e,t){return"function"==typeof e?e.apply(void 0,t):e}function a(e,t){return 0===t?e:function(r){clearTimeout(n),n=setTimeout((function(){e(r)}),t)};var n}function s(e,t){var n=Object.assign({},e);return t.forEach((function(e){delete n[e]})),n}function u(e){return[].concat(e)}function c(e,t){-1===e.indexOf(t)&&e.push(t)}function p(e){return e.split("-")[0]}function f(e){return[].slice.call(e)}function l(e){return Object.keys(e).reduce((function(t,n){return void 0!==e[n]&&(t[n]=e[n]),t}),{})}function d(){return document.createElement("div")}function v(e){return["Element","Fragment"].some((function(t){return o(e,t)}))}function m(e){return o(e,"MouseEvent")}function g(e){return!(!e||!e._tippy||e._tippy.reference!==e)}function h(e){return v(e)?[e]:function(e){return o(e,"NodeList")}(e)?f(e):Array.isArray(e)?e:f(document.querySelectorAll(e))}function b(e,t){e.forEach((function(e){e&&(e.style.transitionDuration=t+"ms")}))}function y(e,t){e.forEach((function(e){e&&e.setAttribute("data-state",t)}))}function w(e){var t,n=u(e)[0];return null!=n&&null!=(t=n.ownerDocument)&&t.body?n.ownerDocument:document}function E(e,t,n){var r=t+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(t){e[r](t,n)}))}function O(e,t){for(var n=t;n;){var r;if(e.contains(n))return!0;n=null==n.getRootNode||null==(r=n.getRootNode())?void 0:r.host}return!1}var x={isTouch:!1},C=0;function T(){x.isTouch||(x.isTouch=!0,window.performance&&document.addEventListener("mousemove",A))}function A(){var e=performance.now();e-C<20&&(x.isTouch=!1,document.removeEventListener("mousemove",A)),C=e}function L(){var e=document.activeElement;if(g(e)){var t=e._tippy;e.blur&&!t.state.isVisible&&e.blur()}}var D=!!("undefined"!=typeof window&&"undefined"!=typeof document)&&!!window.msCrypto,R=Object.assign({appendTo:n,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),k=Object.keys(R);function P(e){var t=(e.plugins||[]).reduce((function(t,n){var r,o=n.name,i=n.defaultValue;o&&(t[o]=void 0!==e[o]?e[o]:null!=(r=R[o])?r:i);return t}),{});return Object.assign({},e,t)}function j(e,t){var n=Object.assign({},t,{content:i(t.content,[e])},t.ignoreAttributes?{}:function(e,t){return(t?Object.keys(P(Object.assign({},R,{plugins:t}))):k).reduce((function(t,n){var r=(e.getAttribute("data-tippy-"+n)||"").trim();if(!r)return t;if("content"===n)t[n]=r;else try{t[n]=JSON.parse(r)}catch(e){t[n]=r}return t}),{})}(e,t.plugins));return n.aria=Object.assign({},R.aria,n.aria),n.aria={expanded:"auto"===n.aria.expanded?t.interactive:n.aria.expanded,content:"auto"===n.aria.content?t.interactive?null:"describedby":n.aria.content},n}function M(e,t){e.innerHTML=t}function V(e){var t=d();return!0===e?t.className="tippy-arrow":(t.className="tippy-svg-arrow",v(e)?t.appendChild(e):M(t,e)),t}function I(e,t){v(t.content)?(M(e,""),e.appendChild(t.content)):"function"!=typeof t.content&&(t.allowHTML?M(e,t.content):e.textContent=t.content)}function S(e){var t=e.firstElementChild,n=f(t.children);return{box:t,content:n.find((function(e){return e.classList.contains("tippy-content")})),arrow:n.find((function(e){return e.classList.contains("tippy-arrow")||e.classList.contains("tippy-svg-arrow")})),backdrop:n.find((function(e){return e.classList.contains("tippy-backdrop")}))}}function N(e){var t=d(),n=d();n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1");var r=d();function o(n,r){var o=S(t),i=o.box,a=o.content,s=o.arrow;r.theme?i.setAttribute("data-theme",r.theme):i.removeAttribute("data-theme"),"string"==typeof r.animation?i.setAttribute("data-animation",r.animation):i.removeAttribute("data-animation"),r.inertia?i.setAttribute("data-inertia",""):i.removeAttribute("data-inertia"),i.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?i.setAttribute("role",r.role):i.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||I(a,e.props),r.arrow?s?n.arrow!==r.arrow&&(i.removeChild(s),i.appendChild(V(r.arrow))):i.appendChild(V(r.arrow)):s&&i.removeChild(s)}return r.className="tippy-content",r.setAttribute("data-state","hidden"),I(r,e.props),t.appendChild(n),n.appendChild(r),o(e.props,e.props),{popper:t,onUpdate:o}}N.$$tippy=!0;var B=1,H=[],U=[];function _(o,s){var v,g,h,C,T,A,L,k,M=j(o,Object.assign({},R,P(l(s)))),V=!1,I=!1,N=!1,_=!1,F=[],W=a(we,M.interactiveDebounce),X=B++,Y=(k=M.plugins).filter((function(e,t){return k.indexOf(e)===t})),$={id:X,reference:o,popper:d(),popperInstance:null,props:M,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:Y,clearDelayTimeouts:function(){clearTimeout(v),clearTimeout(g),cancelAnimationFrame(h)},setProps:function(e){if($.state.isDestroyed)return;ae("onBeforeUpdate",[$,e]),be();var t=$.props,n=j(o,Object.assign({},t,l(e),{ignoreAttributes:!0}));$.props=n,he(),t.interactiveDebounce!==n.interactiveDebounce&&(ce(),W=a(we,n.interactiveDebounce));t.triggerTarget&&!n.triggerTarget?u(t.triggerTarget).forEach((function(e){e.removeAttribute("aria-expanded")})):n.triggerTarget&&o.removeAttribute("aria-expanded");ue(),ie(),J&&J(t,n);$.popperInstance&&(Ce(),Ae().forEach((function(e){requestAnimationFrame(e._tippy.popperInstance.forceUpdate)})));ae("onAfterUpdate",[$,e])},setContent:function(e){$.setProps({content:e})},show:function(){var e=$.state.isVisible,t=$.state.isDestroyed,o=!$.state.isEnabled,a=x.isTouch&&!$.props.touch,s=r($.props.duration,0,R.duration);if(e||t||o||a)return;if(te().hasAttribute("disabled"))return;if(ae("onShow",[$],!1),!1===$.props.onShow($))return;$.state.isVisible=!0,ee()&&(z.style.visibility="visible");ie(),de(),$.state.isMounted||(z.style.transition="none");if(ee()){var u=re(),p=u.box,f=u.content;b([p,f],0)}A=function(){var e;if($.state.isVisible&&!_){if(_=!0,z.offsetHeight,z.style.transition=$.props.moveTransition,ee()&&$.props.animation){var t=re(),n=t.box,r=t.content;b([n,r],s),y([n,r],"visible")}se(),ue(),c(U,$),null==(e=$.popperInstance)||e.forceUpdate(),ae("onMount",[$]),$.props.animation&&ee()&&function(e,t){me(e,t)}(s,(function(){$.state.isShown=!0,ae("onShown",[$])}))}},function(){var e,t=$.props.appendTo,r=te();e=$.props.interactive&&t===n||"parent"===t?r.parentNode:i(t,[r]);e.contains(z)||e.appendChild(z);$.state.isMounted=!0,Ce()}()},hide:function(){var e=!$.state.isVisible,t=$.state.isDestroyed,n=!$.state.isEnabled,o=r($.props.duration,1,R.duration);if(e||t||n)return;if(ae("onHide",[$],!1),!1===$.props.onHide($))return;$.state.isVisible=!1,$.state.isShown=!1,_=!1,V=!1,ee()&&(z.style.visibility="hidden");if(ce(),ve(),ie(!0),ee()){var i=re(),a=i.box,s=i.content;$.props.animation&&(b([a,s],o),y([a,s],"hidden"))}se(),ue(),$.props.animation?ee()&&function(e,t){me(e,(function(){!$.state.isVisible&&z.parentNode&&z.parentNode.contains(z)&&t()}))}(o,$.unmount):$.unmount()},hideWithInteractivity:function(e){ne().addEventListener("mousemove",W),c(H,W),W(e)},enable:function(){$.state.isEnabled=!0},disable:function(){$.hide(),$.state.isEnabled=!1},unmount:function(){$.state.isVisible&&$.hide();if(!$.state.isMounted)return;Te(),Ae().forEach((function(e){e._tippy.unmount()})),z.parentNode&&z.parentNode.removeChild(z);U=U.filter((function(e){return e!==$})),$.state.isMounted=!1,ae("onHidden",[$])},destroy:function(){if($.state.isDestroyed)return;$.clearDelayTimeouts(),$.unmount(),be(),delete o._tippy,$.state.isDestroyed=!0,ae("onDestroy",[$])}};if(!M.render)return $;var q=M.render($),z=q.popper,J=q.onUpdate;z.setAttribute("data-tippy-root",""),z.id="tippy-"+$.id,$.popper=z,o._tippy=$,z._tippy=$;var G=Y.map((function(e){return e.fn($)})),K=o.hasAttribute("aria-expanded");return he(),ue(),ie(),ae("onCreate",[$]),M.showOnCreate&&Le(),z.addEventListener("mouseenter",(function(){$.props.interactive&&$.state.isVisible&&$.clearDelayTimeouts()})),z.addEventListener("mouseleave",(function(){$.props.interactive&&$.props.trigger.indexOf("mouseenter")>=0&&ne().addEventListener("mousemove",W)})),$;function Q(){var e=$.props.touch;return Array.isArray(e)?e:[e,0]}function Z(){return"hold"===Q()[0]}function ee(){var e;return!(null==(e=$.props.render)||!e.$$tippy)}function te(){return L||o}function ne(){var e=te().parentNode;return e?w(e):document}function re(){return S(z)}function oe(e){return $.state.isMounted&&!$.state.isVisible||x.isTouch||C&&"focus"===C.type?0:r($.props.delay,e?0:1,R.delay)}function ie(e){void 0===e&&(e=!1),z.style.pointerEvents=$.props.interactive&&!e?"":"none",z.style.zIndex=""+$.props.zIndex}function ae(e,t,n){var r;(void 0===n&&(n=!0),G.forEach((function(n){n[e]&&n[e].apply(n,t)})),n)&&(r=$.props)[e].apply(r,t)}function se(){var e=$.props.aria;if(e.content){var t="aria-"+e.content,n=z.id;u($.props.triggerTarget||o).forEach((function(e){var r=e.getAttribute(t);if($.state.isVisible)e.setAttribute(t,r?r+" "+n:n);else{var o=r&&r.replace(n,"").trim();o?e.setAttribute(t,o):e.removeAttribute(t)}}))}}function ue(){!K&&$.props.aria.expanded&&u($.props.triggerTarget||o).forEach((function(e){$.props.interactive?e.setAttribute("aria-expanded",$.state.isVisible&&e===te()?"true":"false"):e.removeAttribute("aria-expanded")}))}function ce(){ne().removeEventListener("mousemove",W),H=H.filter((function(e){return e!==W}))}function pe(e){if(!x.isTouch||!N&&"mousedown"!==e.type){var t=e.composedPath&&e.composedPath()[0]||e.target;if(!$.props.interactive||!O(z,t)){if(u($.props.triggerTarget||o).some((function(e){return O(e,t)}))){if(x.isTouch)return;if($.state.isVisible&&$.props.trigger.indexOf("click")>=0)return}else ae("onClickOutside",[$,e]);!0===$.props.hideOnClick&&($.clearDelayTimeouts(),$.hide(),I=!0,setTimeout((function(){I=!1})),$.state.isMounted||ve())}}}function fe(){N=!0}function le(){N=!1}function de(){var e=ne();e.addEventListener("mousedown",pe,!0),e.addEventListener("touchend",pe,t),e.addEventListener("touchstart",le,t),e.addEventListener("touchmove",fe,t)}function ve(){var e=ne();e.removeEventListener("mousedown",pe,!0),e.removeEventListener("touchend",pe,t),e.removeEventListener("touchstart",le,t),e.removeEventListener("touchmove",fe,t)}function me(e,t){var n=re().box;function r(e){e.target===n&&(E(n,"remove",r),t())}if(0===e)return t();E(n,"remove",T),E(n,"add",r),T=r}function ge(e,t,n){void 0===n&&(n=!1),u($.props.triggerTarget||o).forEach((function(r){r.addEventListener(e,t,n),F.push({node:r,eventType:e,handler:t,options:n})}))}function he(){var e;Z()&&(ge("touchstart",ye,{passive:!0}),ge("touchend",Ee,{passive:!0})),(e=$.props.trigger,e.split(/\s+/).filter(Boolean)).forEach((function(e){if("manual"!==e)switch(ge(e,ye),e){case"mouseenter":ge("mouseleave",Ee);break;case"focus":ge(D?"focusout":"blur",Oe);break;case"focusin":ge("focusout",Oe)}}))}function be(){F.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),F=[]}function ye(e){var t,n=!1;if($.state.isEnabled&&!xe(e)&&!I){var r="focus"===(null==(t=C)?void 0:t.type);C=e,L=e.currentTarget,ue(),!$.state.isVisible&&m(e)&&H.forEach((function(t){return t(e)})),"click"===e.type&&($.props.trigger.indexOf("mouseenter")<0||V)&&!1!==$.props.hideOnClick&&$.state.isVisible?n=!0:Le(e),"click"===e.type&&(V=!n),n&&!r&&De(e)}}function we(e){var t=e.target,n=te().contains(t)||z.contains(t);"mousemove"===e.type&&n||function(e,t){var n=t.clientX,r=t.clientY;return e.every((function(e){var t=e.popperRect,o=e.popperState,i=e.props.interactiveBorder,a=p(o.placement),s=o.modifiersData.offset;if(!s)return!0;var u="bottom"===a?s.top.y:0,c="top"===a?s.bottom.y:0,f="right"===a?s.left.x:0,l="left"===a?s.right.x:0,d=t.top-r+u>i,v=r-t.bottom-c>i,m=t.left-n+f>i,g=n-t.right-l>i;return d||v||m||g}))}(Ae().concat(z).map((function(e){var t,n=null==(t=e._tippy.popperInstance)?void 0:t.state;return n?{popperRect:e.getBoundingClientRect(),popperState:n,props:M}:null})).filter(Boolean),e)&&(ce(),De(e))}function Ee(e){xe(e)||$.props.trigger.indexOf("click")>=0&&V||($.props.interactive?$.hideWithInteractivity(e):De(e))}function Oe(e){$.props.trigger.indexOf("focusin")<0&&e.target!==te()||$.props.interactive&&e.relatedTarget&&z.contains(e.relatedTarget)||De(e)}function xe(e){return!!x.isTouch&&Z()!==e.type.indexOf("touch")>=0}function Ce(){Te();var t=$.props,n=t.popperOptions,r=t.placement,i=t.offset,a=t.getReferenceClientRect,s=t.moveTransition,u=ee()?S(z).arrow:null,c=a?{getBoundingClientRect:a,contextElement:a.contextElement||te()}:o,p=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!s}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(e){var t=e.state;if(ee()){var n=re().box;["placement","reference-hidden","escaped"].forEach((function(e){"placement"===e?n.setAttribute("data-placement",t.placement):t.attributes.popper["data-popper-"+e]?n.setAttribute("data-"+e,""):n.removeAttribute("data-"+e)})),t.attributes.popper={}}}}];ee()&&u&&p.push({name:"arrow",options:{element:u,padding:3}}),p.push.apply(p,(null==n?void 0:n.modifiers)||[]),$.popperInstance=e.createPopper(c,z,Object.assign({},n,{placement:r,onFirstUpdate:A,modifiers:p}))}function Te(){$.popperInstance&&($.popperInstance.destroy(),$.popperInstance=null)}function Ae(){return f(z.querySelectorAll("[data-tippy-root]"))}function Le(e){$.clearDelayTimeouts(),e&&ae("onTrigger",[$,e]),de();var t=oe(!0),n=Q(),r=n[0],o=n[1];x.isTouch&&"hold"===r&&o&&(t=o),t?v=setTimeout((function(){$.show()}),t):$.show()}function De(e){if($.clearDelayTimeouts(),ae("onUntrigger",[$,e]),$.state.isVisible){if(!($.props.trigger.indexOf("mouseenter")>=0&&$.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(e.type)>=0&&V)){var t=oe(!1);t?g=setTimeout((function(){$.state.isVisible&&$.hide()}),t):h=requestAnimationFrame((function(){$.hide()}))}}else ve()}}function F(e,n){void 0===n&&(n={});var r=R.plugins.concat(n.plugins||[]);document.addEventListener("touchstart",T,t),window.addEventListener("blur",L);var o=Object.assign({},n,{plugins:r}),i=h(e).reduce((function(e,t){var n=t&&_(t,o);return n&&e.push(n),e}),[]);return v(e)?i[0]:i}F.defaultProps=R,F.setDefaultProps=function(e){Object.keys(e).forEach((function(t){R[t]=e[t]}))},F.currentInput=x;var W=Object.assign({},e.applyStyles,{effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow)}}),X={mouseover:"mouseenter",focusin:"focus",click:"click"};var Y={name:"animateFill",defaultValue:!1,fn:function(e){var t;if(null==(t=e.props.render)||!t.$$tippy)return{};var n=S(e.popper),r=n.box,o=n.content,i=e.props.animateFill?function(){var e=d();return e.className="tippy-backdrop",y([e],"hidden"),e}():null;return{onCreate:function(){i&&(r.insertBefore(i,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",e.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(i){var e=r.style.transitionDuration,t=Number(e.replace("ms",""));o.style.transitionDelay=Math.round(t/10)+"ms",i.style.transitionDuration=e,y([i],"visible")}},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&y([i],"hidden")}}}};var $={clientX:0,clientY:0},q=[];function z(e){var t=e.clientX,n=e.clientY;$={clientX:t,clientY:n}}var J={name:"followCursor",defaultValue:!1,fn:function(e){var t=e.reference,n=w(e.props.triggerTarget||t),r=!1,o=!1,i=!0,a=e.props;function s(){return"initial"===e.props.followCursor&&e.state.isVisible}function u(){n.addEventListener("mousemove",f)}function c(){n.removeEventListener("mousemove",f)}function p(){r=!0,e.setProps({getReferenceClientRect:null}),r=!1}function f(n){var r=!n.target||t.contains(n.target),o=e.props.followCursor,i=n.clientX,a=n.clientY,s=t.getBoundingClientRect(),u=i-s.left,c=a-s.top;!r&&e.props.interactive||e.setProps({getReferenceClientRect:function(){var e=t.getBoundingClientRect(),n=i,r=a;"initial"===o&&(n=e.left+u,r=e.top+c);var s="horizontal"===o?e.top:r,p="vertical"===o?e.right:n,f="horizontal"===o?e.bottom:r,l="vertical"===o?e.left:n;return{width:p-l,height:f-s,top:s,right:p,bottom:f,left:l}}})}function l(){e.props.followCursor&&(q.push({instance:e,doc:n}),function(e){e.addEventListener("mousemove",z)}(n))}function d(){0===(q=q.filter((function(t){return t.instance!==e}))).filter((function(e){return e.doc===n})).length&&function(e){e.removeEventListener("mousemove",z)}(n)}return{onCreate:l,onDestroy:d,onBeforeUpdate:function(){a=e.props},onAfterUpdate:function(t,n){var i=n.followCursor;r||void 0!==i&&a.followCursor!==i&&(d(),i?(l(),!e.state.isMounted||o||s()||u()):(c(),p()))},onMount:function(){e.props.followCursor&&!o&&(i&&(f($),i=!1),s()||u())},onTrigger:function(e,t){m(t)&&($={clientX:t.clientX,clientY:t.clientY}),o="focus"===t.type},onHidden:function(){e.props.followCursor&&(p(),c(),i=!0)}}}};var G={name:"inlinePositioning",defaultValue:!1,fn:function(e){var t,n=e.reference;var r=-1,o=!1,i=[],a={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(o){var a=o.state;e.props.inlinePositioning&&(-1!==i.indexOf(a.placement)&&(i=[]),t!==a.placement&&-1===i.indexOf(a.placement)&&(i.push(a.placement),e.setProps({getReferenceClientRect:function(){return function(e){return function(e,t,n,r){if(n.length<2||null===e)return t;if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||t;switch(e){case"top":case"bottom":var o=n[0],i=n[n.length-1],a="top"===e,s=o.top,u=i.bottom,c=a?o.left:i.left,p=a?o.right:i.right;return{top:s,bottom:u,left:c,right:p,width:p-c,height:u-s};case"left":case"right":var f=Math.min.apply(Math,n.map((function(e){return e.left}))),l=Math.max.apply(Math,n.map((function(e){return e.right}))),d=n.filter((function(t){return"left"===e?t.left===f:t.right===l})),v=d[0].top,m=d[d.length-1].bottom;return{top:v,bottom:m,left:f,right:l,width:l-f,height:m-v};default:return t}}(p(e),n.getBoundingClientRect(),f(n.getClientRects()),r)}(a.placement)}})),t=a.placement)}};function s(){var t;o||(t=function(e,t){var n;return{popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat(((null==(n=e.popperOptions)?void 0:n.modifiers)||[]).filter((function(e){return e.name!==t.name})),[t])})}}(e.props,a),o=!0,e.setProps(t),o=!1)}return{onCreate:s,onAfterUpdate:s,onTrigger:function(t,n){if(m(n)){var o=f(e.reference.getClientRects()),i=o.find((function(e){return e.left-2<=n.clientX&&e.right+2>=n.clientX&&e.top-2<=n.clientY&&e.bottom+2>=n.clientY})),a=o.indexOf(i);r=a>-1?a:r}},onHidden:function(){r=-1}}}};var K={name:"sticky",defaultValue:!1,fn:function(e){var t=e.reference,n=e.popper;function r(t){return!0===e.props.sticky||e.props.sticky===t}var o=null,i=null;function a(){var s=r("reference")?(e.popperInstance?e.popperInstance.state.elements.reference:t).getBoundingClientRect():null,u=r("popper")?n.getBoundingClientRect():null;(s&&Q(o,s)||u&&Q(i,u))&&e.popperInstance&&e.popperInstance.update(),o=s,i=u,e.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){e.props.sticky&&a()}}}};function Q(e,t){return!e||!t||(e.top!==t.top||e.right!==t.right||e.bottom!==t.bottom||e.left!==t.left)}return F.setDefaultProps({plugins:[Y,J,G,K],render:N}),F.createSingleton=function(e,t){var n;void 0===t&&(t={});var r,o=e,i=[],a=[],c=t.overrides,p=[],f=!1;function l(){a=o.map((function(e){return u(e.props.triggerTarget||e.reference)})).reduce((function(e,t){return e.concat(t)}),[])}function v(){i=o.map((function(e){return e.reference}))}function m(e){o.forEach((function(t){e?t.enable():t.disable()}))}function g(e){return o.map((function(t){var n=t.setProps;return t.setProps=function(o){n(o),t.reference===r&&e.setProps(o)},function(){t.setProps=n}}))}function h(e,t){var n=a.indexOf(t);if(t!==r){r=t;var s=(c||[]).concat("content").reduce((function(e,t){return e[t]=o[n].props[t],e}),{});e.setProps(Object.assign({},s,{getReferenceClientRect:"function"==typeof s.getReferenceClientRect?s.getReferenceClientRect:function(){var e;return null==(e=i[n])?void 0:e.getBoundingClientRect()}}))}}m(!1),v(),l();var b={fn:function(){return{onDestroy:function(){m(!0)},onHidden:function(){r=null},onClickOutside:function(e){e.props.showOnCreate&&!f&&(f=!0,r=null)},onShow:function(e){e.props.showOnCreate&&!f&&(f=!0,h(e,i[0]))},onTrigger:function(e,t){h(e,t.currentTarget)}}}},y=F(d(),Object.assign({},s(t,["overrides"]),{plugins:[b].concat(t.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat((null==(n=t.popperOptions)?void 0:n.modifiers)||[],[W])})})),w=y.show;y.show=function(e){if(w(),!r&&null==e)return h(y,i[0]);if(!r||null!=e){if("number"==typeof e)return i[e]&&h(y,i[e]);if(o.indexOf(e)>=0){var t=e.reference;return h(y,t)}return i.indexOf(e)>=0?h(y,e):void 0}},y.showNext=function(){var e=i[0];if(!r)return y.show(0);var t=i.indexOf(r);y.show(i[t+1]||e)},y.showPrevious=function(){var e=i[i.length-1];if(!r)return y.show(e);var t=i.indexOf(r),n=i[t-1]||e;y.show(n)};var E=y.setProps;return y.setProps=function(e){c=e.overrides||c,E(e)},y.setInstances=function(e){m(!0),p.forEach((function(e){return e()})),o=e,m(!1),v(),l(),p=g(y),y.setProps({triggerTarget:a})},p=g(y),y},F.delegate=function(e,n){var r=[],o=[],i=!1,a=n.target,c=s(n,["target"]),p=Object.assign({},c,{trigger:"manual",touch:!1}),f=Object.assign({touch:R.touch},c,{showOnCreate:!0}),l=F(e,p);function d(e){if(e.target&&!i){var t=e.target.closest(a);if(t){var r=t.getAttribute("data-tippy-trigger")||n.trigger||R.trigger;if(!t._tippy&&!("touchstart"===e.type&&"boolean"==typeof f.touch||"touchstart"!==e.type&&r.indexOf(X[e.type])<0)){var s=F(t,f);s&&(o=o.concat(s))}}}}function v(e,t,n,o){void 0===o&&(o=!1),e.addEventListener(t,n,o),r.push({node:e,eventType:t,handler:n,options:o})}return u(l).forEach((function(e){var n=e.destroy,a=e.enable,s=e.disable;e.destroy=function(e){void 0===e&&(e=!0),e&&o.forEach((function(e){e.destroy()})),o=[],r.forEach((function(e){var t=e.node,n=e.eventType,r=e.handler,o=e.options;t.removeEventListener(n,r,o)})),r=[],n()},e.enable=function(){a(),o.forEach((function(e){return e.enable()})),i=!1},e.disable=function(){s(),o.forEach((function(e){return e.disable()})),i=!0},function(e){var n=e.reference;v(n,"touchstart",d,t),v(n,"mouseover",d),v(n,"focusin",d),v(n,"click",d)}(e)})),l},F.hideAll=function(e){var t=void 0===e?{}:e,n=t.exclude,r=t.duration;U.forEach((function(e){var t=!1;if(n&&(t=g(n)?e.reference===n:e.popper===n.popper),!t){var o=e.props.duration;e.setProps({duration:r}),e.hide(),e.state.isDestroyed||e.setProps({duration:o})}}))},F.roundArrow='',F})); + diff --git a/overstorey_staging/allometry_demo_helpers.R b/overstorey_staging/allometry_demo_helpers.R new file mode 100644 index 000000000..14e5a601b --- /dev/null +++ b/overstorey_staging/allometry_demo_helpers.R @@ -0,0 +1,273 @@ +## Shared computation for TF24_flexible_allometry_demo.qmd (#516). +## +## Kept out of the qmd so it can be exercised by a test rather than only by +## rendering: a chunk that runs is not a chunk that is checked, and prose beside +## a number survives the number being falsified. + +## A TF24 strategy with the plasticity switch at `a_pl0` (0 = fixed allometry). +tf24_allometry_strategy <- function(a_pl0 = 1.0, ...) { + s <- TF24_Strategy(...) + s$pars$a_pl0 <- a_pl0 + s +} + +## A light, well-lit environment with a prescribed soil water content, so the +## demo can drive the carbon balance directly rather than through rainfall and +## the soil's own dynamics. +tf24_demo_env <- function(theta_soil, n_depths = 5L, canopy_top = 40) { + env <- Environment("TF24") + env$set_soil_number_of_depths(n_depths) + env$set_soil_water_state(rep(theta_soil, n_depths)) + env$set_fixed_environment(1.0, canopy_top) + env +} + +## The gate's response, swept over SOIL WATER rather than over the reserve pool. +## The gate reads the marginal leaf's carbon balance now (#516), so the pool is +## no longer the axis it responds to -- and holding reserves full while sweeping +## soil water is exactly the demonstration that it is not. +allometry_gate_map <- function(a_pl0 = 1.0, height = 5, + theta = seq(0.08, 0.35, length.out = 40L)) { + s <- tf24_allometry_strategy(a_pl0, collect_all_auxiliary = TRUE) + out <- lapply(theta, function(th) { + env <- tf24_demo_env(th) + ind <- TF24_Individual(s) + ind$set_state("height", height) + ind$set_initial_states(env) # reserves at a_st3 of capacity throughout + ind$compute_rates(env) + data.frame(theta_soil = th, + margin = ind$aux("leaf_marginal_return"), + dphi = ind$rate("log_area_leaf_departure"), + dpsi = ind$rate("log_area_sapwood_departure"), + dheight = ind$rate("height")) + }) + cbind(do.call(rbind, out), a_pl0 = a_pl0) +} + +## A wet stand left to self-thin, so suppressed plants can be compared with +## dominants. Shade is as much the point as drought: a plant losing the light +## race has the same problem as one losing water, and the same lever. +allometry_self_thinning <- function(a_pl0 = 1.0, mpl = 25, lma = 0.0825, + birth_rate = 20, rain = 1.5) { + p <- scm_base_parameters("TF24") + p$max_patch_lifetime <- mpl + p <- add_strategies(p, trait_matrix(lma, "lma"), hyperpar = TF24_hyperpar, + birth_rate = birth_rate) + p$strategies[[1]]$pars$a_pl0 <- a_pl0 + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.428 * 0.5, 5)) + env$extrinsic_drivers_set_constant("rainfall", rain) + out <- run_scm(p, env, Control(), collect = TRUE) + d <- out$species + d <- d[is.finite(d$height) & d$density > 0, ] + d$canopy_fraction <- exp(d$log_area_leaf_departure) + d$huber_ratio <- exp(d$log_area_sapwood_departure) + d$survivorship <- exp(-d$mortality) + d$a_pl0 <- a_pl0 + list(cohorts = d, R0 = out$offspring_production) +} + +## Step one plant through a prescribed soil-water history, so a drought and its +## recovery can both be seen. The ODE is integrated within each interval at +## fixed soil water and the state carried across, which is a piecewise-constant +## driver rather than a smooth one -- adequate for a demo, and stated so the +## reader does not mistake it for how the SCM drives soil water. +allometry_trajectory <- function(a_pl0, soil_history, dt = 0.1, height0 = 4) { + s <- tf24_allometry_strategy(a_pl0, collect_all_auxiliary = TRUE) + ind <- TF24_Individual(s) + ind$set_state("height", height0) + ind$set_initial_states(tf24_demo_env(soil_history$theta[[1]])) + + nms <- ind$ode_names + rows <- vector("list", nrow(soil_history)) + t_now <- 0 + + for (i in seq_len(nrow(soil_history))) { + env <- tf24_demo_env(soil_history$theta[[i]]) + span <- soil_history$duration[[i]] + steps <- max(1L, as.integer(round(span / dt))) + for (k in seq_len(steps)) { + y <- ind$ode_state + res <- grow_individual_to_time(ind, dt, env) + ind$ode_state <- as.numeric(res$state[1, ]) + t_now <- t_now + dt + } + ind$compute_rates(env) + st <- setNames(as.numeric(ind$ode_state), nms) + rows[[i]] <- data.frame( + time = t_now, + theta_soil = soil_history$theta[[i]], + height = st[["height"]], + phi = st[["log_area_leaf_departure"]], + psi = st[["log_area_sapwood_departure"]], + survivorship = exp(-st[["mortality"]]), + area_leaf = ind$aux("competition_effect"), + area_sapwood = ind$aux("area_sapwood"), + P = ind$aux("net_mass_production_dt"), + a_pl0 = a_pl0) + } + d <- do.call(rbind, rows) + ## Two derived quantities the narrative turns on: the canopy relative to what + ## its height prefers, and the Huber value relative to its preferred one. + d$canopy_fraction <- exp(d$phi) + d$huber_ratio <- exp(d$psi) + d$P_per_area <- d$P / d$area_leaf + d +} + +## A drought with a recovery either side of it. +demo_soil_history <- function(wet = 0.30, dry = 0.11, + years_wet = 3, years_dry = 4, + step = 0.25) { + seg <- function(theta, years) { + n <- as.integer(round(years / step)) + data.frame(theta = rep(theta, n), duration = rep(step, n)) + } + rbind(seg(wet, years_wet), seg(dry, years_dry), seg(wet, years_wet)) +} + +## The allometric curves themselves, taken from the strategy's own C++ expansion +## rather than re-derived in R, so a reference line in a plot cannot drift from +## the model it is a reference for. +allometry_reference_curve <- function(s, heights) { + expand <- get("TF24_strategy_expand_allometry", envir = asNamespace("plant")) + zero <- rep(0, length(heights)) + z <- expand(s, heights, zero, zero) + data.frame(height = heights, + area_leaf = z$area_leaf, + area_sapwood = z$area_sapwood) +} + +## The carbon budget split by whether a cost scales with leaf area, which is what +## the shedding criterion rests on. Returns the three terms plus the elasticity +## of per-leaf assimilation to hydraulic supply. +## +## `eta` is estimated by differencing at FIXED sapwood area -- lower the leaf +## departure by d and raise the sapwood departure by d, so A_s is unchanged. That +## is what real thinning does; letting A_s follow A down the pipe model measures +## something else entirely. +allometry_carbon_terms <- function(height, theta_soil, d = 0.02, phi = 0) { + p <- TF24_Strategy()$pars + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) + cc <- p$a_bio * p$a_y + CONV <- 60 * 60 * 12 * 365 / 1e6 # per-second to annual, mol + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + + at <- function(ph, ps) { + e <- tf24_demo_env(theta_soil) + i <- TF24_Individual(s) + i$set_state("height", height) + i$set_state("log_area_leaf_departure", ph) + i$set_state("log_area_sapwood_departure", ps) + i$set_initial_states(e) + i$compute_rates(e) + A <- i$aux("competition_effect") + list(A = A, A_s = i$aux("area_sapwood"), + abar = (i$aux("profit") + i$aux("shadow_cost")) * CONV, + P = i$aux("net_mass_production_dt")) + } + + a <- at(phi, 0) + b <- at(phi - d, d) # same A_s, less A + stopifnot(abs(b$A_s / a$A_s - 1) < 1e-9) + + ## Costs that scale with leaf area: leaf, fine root, and bark (pinned to leaf + ## area). Sapwood is the one that does not. + per_area <- cc * (p$r_l * p$lma + p$r_r * p$a_r1 + + p$r_b * p$a_b1 * p$theta * height * eta_c * p$rho) + + (p$k_l * p$lma + p$k_r * p$a_r1 + + p$k_b * p$a_b1 * p$theta * height * eta_c * p$rho) + m_s <- a$A_s * height * eta_c * p$rho + dPdA <- (b$P - a$P) / (b$A - a$A) + + ## eta is recovered from the measured dP/dA and the (exact) decomposition, + ## NOT by differencing abar. The profit auxes misreport assimilation off the + ## trajectory by ~2 per cent, which is small against the level but comparable + ## to the difference being taken, so a direct estimate of eta is unusable + ## while dP/dA -- a difference of P itself -- is not. + list(height = height, theta_soil = theta_soil, + gain = cc * a$abar * a$A, + g = per_area * a$A, + s = cc * p$r_s * m_s + p$k_s * m_s, + P = a$P, + kappa = per_area / (cc * a$abar), + eta = 1 - (dPdA + per_area) / (cc * a$abar), + dPdA = dPdA) +} + +## The sapwood controller's signal, swept over the Huber value at fixed height +## and leaf area (#516). Returns the marginal growth return R_s beside the growth +## rate it is the derivative of, so the two can be plotted on the same axis and +## the zero-crossing checked against the peak rather than asserted. +allometry_sapwood_controller <- function(theta_soil, height = 10, a_sw = 1.0, + psi = seq(-0.3, 0.7, length.out = 41L)) { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_sw <- a_sw + out <- lapply(psi, function(p) { + env <- tf24_demo_env(theta_soil) + ind <- TF24_Individual(s) + ind$set_state("height", height) + ind$set_state("log_area_sapwood_departure", p) + ind$set_initial_states(env) + ind$compute_rates(env) + data.frame(psi = p, huber_ratio = exp(p), + R_s = ind$aux("sapwood_marginal_return"), + dheight = ind$rate("height"), + P = ind$aux("net_mass_production_dt")) + }) + d <- do.call(rbind, out) + d$theta_soil <- theta_soil + d$height <- height + d +} + +## Step one plant: acclimate wet, zero the mortality integral, drought, recover. +## Zeroing mortality is what makes sizes comparable -- otherwise a tall plant's +## answer is dominated by the lifetime of hazard it took to get tall, and the +## drought's own contribution is unreadable. +allometry_drought <- function(a_pl0, height, theta_dry, years_dry = 4, + wet = 0.30, acclimate = 2, recover = 4, + a_sw = 0, dt = 0.1) { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_pl0 <- a_pl0 + s$pars$a_sw <- a_sw + ind <- TF24_Individual(s) + ind$set_state("height", height) + ind$set_initial_states(tf24_demo_env(wet)) + run <- function(theta, years) { + env <- tf24_demo_env(theta) + for (k in seq_len(as.integer(round(years / dt)))) { + res <- try(grow_individual_to_time(ind, dt, env), silent = TRUE) + if (inherits(res, "try-error")) return(FALSE) + ind$ode_state <- as.numeric(res$state[1, ]) + } + TRUE + } + if (!run(wet, acclimate)) return(NULL) + ind$set_state("mortality", 0) + if (!run(theta_dry, years_dry)) return(NULL) + if (!run(wet, recover)) return(NULL) + st <- setNames(as.numeric(ind$ode_state), ind$ode_names) + data.frame(a_pl0 = a_pl0, height = height, theta_dry = theta_dry, + years_dry = years_dry, + survivorship = exp(-st[["mortality"]]), + canopy = exp(st[["log_area_leaf_departure"]]), + huber = exp(st[["log_area_sapwood_departure"]])) +} + +## The intensity-by-size grid the "does not buy survival" section rests on. +allometry_drought_grid <- function(heights = c(10, 20, 24), + thetas = c(0.145, 0.140, 0.135), + years_dry = 4) { + g <- expand.grid(height = heights, theta_dry = thetas) + out <- lapply(seq_len(nrow(g)), function(i) { + a <- allometry_drought(0.0, g$height[i], g$theta_dry[i], years_dry) + b <- allometry_drought(1.0, g$height[i], g$theta_dry[i], years_dry) + if (is.null(a) || is.null(b)) return(NULL) + data.frame(height = g$height[i], theta_dry = g$theta_dry[i], + S_fixed = a$survivorship, S_shed = b$survivorship, + min_canopy = b$canopy, gain = b$survivorship / a$survivorship) + }) + do.call(rbind, out) +} diff --git a/scripts/run_scenario_gateway.R b/scripts/run_scenario_gateway.R index 59d86699f..0cdd9c3d1 100644 --- a/scripts/run_scenario_gateway.R +++ b/scripts/run_scenario_gateway.R @@ -34,8 +34,7 @@ workers <- as.integer(Sys.getenv("SCENARIO_WORKERS", ctrl <- scenario_control() message(sprintf("Running scenarios (max_patch_lifetime = %g, workers = %d, %s) ...", mpl, workers, - if (ctrl$node_density_in_birth_date) "density in birth date" - else "density in height")) + sprintf("density in %s", ctrl$node_density_coordinate))) scorecard <- run_scenarios(ctrl = ctrl, max_patch_lifetime = mpl, workers = workers) diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index c9198c8f4..eb001f72a 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -4305,6 +4305,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// Node___FF16__FF16_Env__density_in_birth_date__get +bool Node___FF16__FF16_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_); +RcppExport SEXP _plant_Node___FF16__FF16_Env__density_in_birth_date__get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 > >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Node___FF16__FF16_Env__density_in_birth_date__get(obj_)); + return rcpp_result_gen; +END_RCPP +} // Node___FF16__FF16_Env__fecundity__get double Node___FF16__FF16_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_); RcppExport SEXP _plant_Node___FF16__FF16_Env__fecundity__get(SEXP obj_SEXP) { @@ -4486,6 +4497,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// Node___TF24__TF24_Env__density_in_birth_date__get +bool Node___TF24__TF24_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_); +RcppExport SEXP _plant_Node___TF24__TF24_Env__density_in_birth_date__get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 > >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Node___TF24__TF24_Env__density_in_birth_date__get(obj_)); + return rcpp_result_gen; +END_RCPP +} // Node___TF24__TF24_Env__fecundity__get double Node___TF24__TF24_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_); RcppExport SEXP _plant_Node___TF24__TF24_Env__fecundity__get(SEXP obj_SEXP) { @@ -4667,6 +4689,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// Node___TF24f__TF24_Env__density_in_birth_date__get +bool Node___TF24f__TF24_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_); +RcppExport SEXP _plant_Node___TF24f__TF24_Env__density_in_birth_date__get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 > >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Node___TF24f__TF24_Env__density_in_birth_date__get(obj_)); + return rcpp_result_gen; +END_RCPP +} // Node___TF24f__TF24_Env__fecundity__get double Node___TF24f__TF24_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_); RcppExport SEXP _plant_Node___TF24f__TF24_Env__fecundity__get(SEXP obj_SEXP) { @@ -4848,6 +4881,17 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// Node___K93__K93_Env__density_in_birth_date__get +bool Node___K93__K93_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_); +RcppExport SEXP _plant_Node___K93__K93_Env__density_in_birth_date__get(SEXP obj_SEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< plant::RcppR6::RcppR6 > >::type obj_(obj_SEXP); + rcpp_result_gen = Rcpp::wrap(Node___K93__K93_Env__density_in_birth_date__get(obj_)); + return rcpp_result_gen; +END_RCPP +} // Node___K93__K93_Env__fecundity__get double Node___K93__K93_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_); RcppExport SEXP _plant_Node___K93__K93_Env__fecundity__get(SEXP obj_SEXP) { @@ -12930,6 +12974,7 @@ static const R_CallMethodDef CallEntries[] = { {"_plant_Node___FF16__FF16_Env__log_density__get", (DL_FUNC) &_plant_Node___FF16__FF16_Env__log_density__get, 1}, {"_plant_Node___FF16__FF16_Env__introduction_time__get", (DL_FUNC) &_plant_Node___FF16__FF16_Env__introduction_time__get, 1}, {"_plant_Node___FF16__FF16_Env__growth_rate_at_birth__get", (DL_FUNC) &_plant_Node___FF16__FF16_Env__growth_rate_at_birth__get, 1}, + {"_plant_Node___FF16__FF16_Env__density_in_birth_date__get", (DL_FUNC) &_plant_Node___FF16__FF16_Env__density_in_birth_date__get, 1}, {"_plant_Node___FF16__FF16_Env__fecundity__get", (DL_FUNC) &_plant_Node___FF16__FF16_Env__fecundity__get, 1}, {"_plant_Node___FF16__FF16_Env__ode_size__get", (DL_FUNC) &_plant_Node___FF16__FF16_Env__ode_size__get, 1}, {"_plant_Node___FF16__FF16_Env__ode_state__get", (DL_FUNC) &_plant_Node___FF16__FF16_Env__ode_state__get, 1}, @@ -12946,6 +12991,7 @@ static const R_CallMethodDef CallEntries[] = { {"_plant_Node___TF24__TF24_Env__log_density__get", (DL_FUNC) &_plant_Node___TF24__TF24_Env__log_density__get, 1}, {"_plant_Node___TF24__TF24_Env__introduction_time__get", (DL_FUNC) &_plant_Node___TF24__TF24_Env__introduction_time__get, 1}, {"_plant_Node___TF24__TF24_Env__growth_rate_at_birth__get", (DL_FUNC) &_plant_Node___TF24__TF24_Env__growth_rate_at_birth__get, 1}, + {"_plant_Node___TF24__TF24_Env__density_in_birth_date__get", (DL_FUNC) &_plant_Node___TF24__TF24_Env__density_in_birth_date__get, 1}, {"_plant_Node___TF24__TF24_Env__fecundity__get", (DL_FUNC) &_plant_Node___TF24__TF24_Env__fecundity__get, 1}, {"_plant_Node___TF24__TF24_Env__ode_size__get", (DL_FUNC) &_plant_Node___TF24__TF24_Env__ode_size__get, 1}, {"_plant_Node___TF24__TF24_Env__ode_state__get", (DL_FUNC) &_plant_Node___TF24__TF24_Env__ode_state__get, 1}, @@ -12962,6 +13008,7 @@ static const R_CallMethodDef CallEntries[] = { {"_plant_Node___TF24f__TF24_Env__log_density__get", (DL_FUNC) &_plant_Node___TF24f__TF24_Env__log_density__get, 1}, {"_plant_Node___TF24f__TF24_Env__introduction_time__get", (DL_FUNC) &_plant_Node___TF24f__TF24_Env__introduction_time__get, 1}, {"_plant_Node___TF24f__TF24_Env__growth_rate_at_birth__get", (DL_FUNC) &_plant_Node___TF24f__TF24_Env__growth_rate_at_birth__get, 1}, + {"_plant_Node___TF24f__TF24_Env__density_in_birth_date__get", (DL_FUNC) &_plant_Node___TF24f__TF24_Env__density_in_birth_date__get, 1}, {"_plant_Node___TF24f__TF24_Env__fecundity__get", (DL_FUNC) &_plant_Node___TF24f__TF24_Env__fecundity__get, 1}, {"_plant_Node___TF24f__TF24_Env__ode_size__get", (DL_FUNC) &_plant_Node___TF24f__TF24_Env__ode_size__get, 1}, {"_plant_Node___TF24f__TF24_Env__ode_state__get", (DL_FUNC) &_plant_Node___TF24f__TF24_Env__ode_state__get, 1}, @@ -12978,6 +13025,7 @@ static const R_CallMethodDef CallEntries[] = { {"_plant_Node___K93__K93_Env__log_density__get", (DL_FUNC) &_plant_Node___K93__K93_Env__log_density__get, 1}, {"_plant_Node___K93__K93_Env__introduction_time__get", (DL_FUNC) &_plant_Node___K93__K93_Env__introduction_time__get, 1}, {"_plant_Node___K93__K93_Env__growth_rate_at_birth__get", (DL_FUNC) &_plant_Node___K93__K93_Env__growth_rate_at_birth__get, 1}, + {"_plant_Node___K93__K93_Env__density_in_birth_date__get", (DL_FUNC) &_plant_Node___K93__K93_Env__density_in_birth_date__get, 1}, {"_plant_Node___K93__K93_Env__fecundity__get", (DL_FUNC) &_plant_Node___K93__K93_Env__fecundity__get, 1}, {"_plant_Node___K93__K93_Env__ode_size__get", (DL_FUNC) &_plant_Node___K93__K93_Env__ode_size__get, 1}, {"_plant_Node___K93__K93_Env__ode_state__get", (DL_FUNC) &_plant_Node___K93__K93_Env__ode_state__get, 1}, diff --git a/src/RcppR6.cpp b/src/RcppR6.cpp index f657a447e..fd99a6c18 100644 --- a/src/RcppR6.cpp +++ b/src/RcppR6.cpp @@ -1706,6 +1706,11 @@ double Node___FF16__FF16_Env__growth_rate_at_birth__get(plant::RcppR6::RcppR6growth_rate_at_birth(); } +// [[Rcpp::export]] +bool Node___FF16__FF16_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_) { + return obj_->density_in_birth_date(); +} + // [[Rcpp::export]] double Node___FF16__FF16_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_) { return obj_->fecundity(); @@ -1781,6 +1786,11 @@ double Node___TF24__TF24_Env__growth_rate_at_birth__get(plant::RcppR6::RcppR6growth_rate_at_birth(); } +// [[Rcpp::export]] +bool Node___TF24__TF24_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_) { + return obj_->density_in_birth_date(); +} + // [[Rcpp::export]] double Node___TF24__TF24_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_) { return obj_->fecundity(); @@ -1856,6 +1866,11 @@ double Node___TF24f__TF24_Env__growth_rate_at_birth__get(plant::RcppR6::RcppR6

growth_rate_at_birth(); } +// [[Rcpp::export]] +bool Node___TF24f__TF24_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_) { + return obj_->density_in_birth_date(); +} + // [[Rcpp::export]] double Node___TF24f__TF24_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_) { return obj_->fecundity(); @@ -1931,6 +1946,11 @@ double Node___K93__K93_Env__growth_rate_at_birth__get(plant::RcppR6::RcppR6growth_rate_at_birth(); } +// [[Rcpp::export]] +bool Node___K93__K93_Env__density_in_birth_date__get(plant::RcppR6::RcppR6 > obj_) { + return obj_->density_in_birth_date(); +} + // [[Rcpp::export]] double Node___K93__K93_Env__fecundity__get(plant::RcppR6::RcppR6 > obj_) { return obj_->fecundity(); diff --git a/src/control.cpp b/src/control.cpp index f3aa11d63..4c39fb805 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -31,7 +31,7 @@ Control::Control() { node_gradient_direction = -1; node_gradient_richardson = false; node_gradient_richardson_depth = 4; - node_density_in_birth_date = false; + node_density_coordinate = "auto"; ode_step_size_initial = 1e-6; ode_step_size_min = 1e-6; diff --git a/src/tf24_strategy.cpp b/src/tf24_strategy.cpp index 7b8260e3b..2bbc3579d 100644 --- a/src/tf24_strategy.cpp +++ b/src/tf24_strategy.cpp @@ -75,11 +75,20 @@ void TF24_Strategy::refresh_indices () { aux_idx_stom_cond_CO2 = aux_index.at("stom_cond_CO2"); aux_idx_assimilation = aux_index.at("assimilation"); aux_idx_Tleaf = aux_index.at("Tleaf"); + aux_idx_leaf_marginal_return = aux_index.at("leaf_marginal_return"); + aux_idx_sapwood_marginal_return = + aux_index.at("sapwood_marginal_return"); // area_sapwood is only registered when collect_all_auxiliary is set. aux_idx_area_sapwood = aux_index.count("area_sapwood") ? aux_index.at("area_sapwood") : -1; state_idx_area_heartwood = state_index.at("area_heartwood"); state_idx_mass_heartwood = state_index.at("mass_heartwood"); state_idx_storage = state_index.at("storage"); + state_idx_log_area_leaf_departure = + state_index.at("log_area_leaf_departure"); + state_idx_log_area_sapwood_departure = + state_index.at("log_area_sapwood_departure"); + state_idx_leaf_marginal_tracked = + state_index.at("leaf_marginal_return_tracked"); } // [eqn 2] area_leaf (inverse of [eqn 3]) @@ -97,6 +106,14 @@ double TF24_Strategy::area_sapwood(double area_leaf) const { return area_leaf * pars.theta; } +// The conducting area a plant actually has, as against the one its leaf area +// prefers. At a resting departure sapwood_per_leaf_area() returns pars.theta +// unchanged, so this is bit-identical to the overload above. +double TF24_Strategy::area_sapwood(double area_leaf, + double sapwood_departure) const { + return area_leaf * sapwood_per_leaf_area(sapwood_departure); +} + double TF24_Strategy::mass_sapwood(double area_sapwood, double height) const { return area_sapwood * height * eta_c * pars.rho; } @@ -143,9 +160,21 @@ double TF24_Strategy::mass_above_ground(double mass_leaf, double mass_bark, // for updating auxiliary state void TF24_Strategy::update_dependent_aux(const int index, Internals& vars) { - if (index == HEIGHT_INDEX) { - double height = vars.state(HEIGHT_INDEX); - vars.set_aux(aux_idx_competition_effect, area_leaf(height)); + // Leaf area depends on BOTH height and the departure state, so either write + // has to refresh it. Individual::set_ode_state refreshes per slot in slot + // order, so the height pass (slot 0) necessarily reads the departure still + // sitting in vars from the previous evaluation; the departure pass recomputes + // from both, which is why it must not be a partial update. Whichever fires + // last leaves the aux consistent with the whole state vector. + if (index == HEIGHT_INDEX || index == state_idx_log_area_leaf_departure) { + const double height = vars.state(HEIGHT_INDEX); + // A = A*(h) * exp(phi). With plasticity off phi is exactly 0 and exp(0) is + // exactly 1, so this is bit-identical to the plain area_leaf(height) it + // replaces -- the multiplication is exact and cannot be reassociated, + // there being no addition for an FMA to fuse (#516). + const double departure = vars.state(state_idx_log_area_leaf_departure); + vars.set_aux(aux_idx_competition_effect, + area_leaf(height) * std::exp(departure)); vars.set_aux(aux_idx_height_inverse, 1.0 / height); } } @@ -155,11 +184,57 @@ void TF24_Strategy::update_dependent_aux(const int index, Internals& vars) { // i.e. setting rates of ode vars from the state and updating aux vars void TF24_Strategy::compute_rates(const TF24_Environment& environment, Internals& vars) { double height = vars.state(HEIGHT_INDEX); + // The Huber value's departure from theta. Read once here and threaded through + // every sapwood quantity below, so the conducting area a plant has and the + // one its leaf area prefers cannot disagree between two call sites. + const double sapwood_departure = + vars.state(state_idx_log_area_sapwood_departure); double area_leaf_ = vars.aux(aux_idx_competition_effect); + // --- Reserves, read BEFORE production ------------------------------------- + // The replacement gate is a function of the reserve fraction and it changes + // what turnover costs, so r has to be known before net production is formed. + // Nothing is recomputed to get it there: S is a state and S_max depends only + // on states, so this is the same arithmetic in an earlier place. It also + // means a pool outside its domain is refused before the leaf is solved, which + // is the expensive part of the step being rejected. + const double S = vars.state(state_idx_storage); + const double S_max = + storage_capacity(area_leaf_, height, sapwood_departure); + // Refused only where the pool is negative by more than round-off on its own + // scale. The tolerance is not slack: at r = 0 the rate is the charge alone and + // so non-negative, so a draining cohort approaches the boundary and its last + // bits are round-off on a state near zero. Comparing against an exact zero + // refuses nearly every attempt there, which rejects nothing real. + if (S < -storage_domain_tol * S_max) { + odelia::util::stop_domain( + "TF24 storage is negative (" + util::format_double(S) + + " kg): the pool's flow does not leave [0, capacity], so this is a step " + "that overshot the empty boundary"); + } + const double r = S_max > 0.0 ? S / S_max : 0.0; + const double net_mass_production_dt_ = net_mass_production_dt(environment, height, area_leaf_, - vars.aux(aux_idx_height_inverse)); + vars.aux(aux_idx_height_inverse), + sapwood_departure, + vars.state(state_idx_log_area_leaf_departure), + vars.state(state_idx_leaf_marginal_tracked)); + + vars.set_aux(aux_idx_leaf_marginal_return, marginal_leaf_return_); + + // The running mean chases the instantaneous balance at a_pl4. A first-order + // filter, so the memory is 1/a_pl4 and nothing about it can overshoot. + vars.set_rate(state_idx_leaf_marginal_tracked, + pars.a_pl4 * (marginal_leaf_return_ - + vars.state(state_idx_leaf_marginal_tracked))); + + // Read back the shares the budget above actually charged, rather than forming + // them again: the carbon not spent and the tissue lost are two halves of one + // decision, and they balance only if they come from one number. + const double withheld = withheld_leaf_; + const double withheld_sapwood = withheld_sapwood_; + const double replacement = 1.0 - withheld; // store the aux sate vars.set_aux(aux_idx_net_mass_production_dt, net_mass_production_dt_); @@ -212,20 +287,7 @@ void TF24_Strategy::compute_rates(const TF24_Environment& environment, Internal // corrupt is the meaning of the state, because mortality reads the ratio and // grows without bound below zero. So the pool is refused there rather than // floored, and the stepper shrinks and retries (#609, #610). - const double S = vars.state(state_idx_storage); - const double S_max = storage_capacity(area_leaf_, height); - // Refused only where the pool is negative by more than round-off on its own - // scale. The tolerance is not slack: at r = 0 the rate is the charge alone and - // so non-negative, so a draining cohort approaches the boundary and its last - // bits are round-off on a state near zero. Comparing against an exact zero - // refuses nearly every attempt there, which rejects nothing real. - if (S < -storage_domain_tol * S_max) { - odelia::util::stop_domain( - "TF24 storage is negative (" + util::format_double(S) + - " kg): the pool's flow does not leave [0, capacity], so this is a step " - "that overshot the empty boundary"); - } - const double r = S_max > 0.0 ? S / S_max : 0.0; + // The pool and the reserve fraction were read above, before production. // Reserve-gated growth (#517), following Daniel's intuition that a plant // should not grow unless it has ample carbon in storage. Growth and // reproduction proceed at the *production* rate, but scaled by a smooth gate @@ -246,18 +308,70 @@ void TF24_Strategy::compute_rates(const TF24_Environment& environment, Internal const double growth_flux = Ppos * G; const double fraction_allocation_reproduction_ = fraction_allocation_reproduction(height); - const double darea_leaf_dmass_live_ = darea_leaf_dmass_live(area_leaf_); const double fraction_allocation_growth_ = fraction_allocation_growth(height); - const double area_leaf_dt = growth_flux * fraction_allocation_growth_ * darea_leaf_dmass_live_; - vars.set_rate(HEIGHT_INDEX, dheight_darea_leaf(area_leaf_) * area_leaf_dt); + // --- Where the growth flux goes (#516) ------------------------------------ + // Growth moves a plant ALONG its allometry, plasticity moves it OFF, and + // rebuilding moves it back. Keeping those three separate is what makes the + // resting model exact and the departed one interpretable. + // + // So the allometric derivatives are evaluated at the leaf area the plant's + // HEIGHT implies, area_leaf(height), not at the leaf area it actually has. + // They are properties of the curve, and a plant's place on the curve is given + // by its height; its leaf area is a departure from that. Evaluated this way, + // extension is exactly departure-preserving for any departure, so the whole + // of the departure's motion is plasticity. At rest the two coincide bitwise + // (exp(0) == 1), so this is the same number the fixed model used. + const double area_leaf_star = area_leaf(height); + const double darea_leaf_dmass_live_ = + darea_leaf_dmass_live(area_leaf_star, sapwood_departure); + + // The share of growth redirected into closing the canopy gap: it vanishes + // exactly when the gap closes, widens as the gap does, and is gated by the + // SAME reserve signal that decides replacement. + // + // ⚠️ THE `replacement` FACTOR IS LOAD-BEARING, not a refinement. Without it + // the gap alone drives rebuilding, so a starving plant withholds replacement + // and spends its growth flux rebuilding at the same time -- contradictory, + // since carbon enough to rebuild is carbon enough to maintain. Measured, the + // unconditioned form rebuilt at ~1.5/yr against shedding's 0.42/yr, so the + // canopy thinned by 5 per cent and stalled, and the Huber value fell instead + // of rising because rebuilding adds leaf area without sapwood. Gating both on + // the same signal makes a plant rebuild exactly to the degree it is willing + // to maintain. + // + // The departure cannot go positive under these dynamics -- shedding only + // lowers it and this share only raises it, stopping at zero -- so the form + // needs no bound. + const double leaf_departure = vars.state(state_idx_log_area_leaf_departure); + const double rebuild_share = + replacement * (1.0 - std::exp(leaf_departure / pars.a_pl2)); + const double extension_share = 1.0 - rebuild_share; + + const double area_leaf_dt = + extension_share * growth_flux * fraction_allocation_growth_ * + darea_leaf_dmass_live_; + + // Height follows extension alone, so rebuilding a canopy buys no height and + // height still cannot fall: every factor here is non-negative. + vars.set_rate(HEIGHT_INDEX, dheight_darea_leaf(area_leaf_star) * area_leaf_dt); vars.set_rate(FECUNDITY_INDEX, fecundity_dt(growth_flux, fraction_allocation_reproduction_)); + // Rebuilding buys leaf area at unchanged height, and it buys the WHOLE + // package -- leaf, fine root, and the sapwood and bark that supply it -- at + // the ratio the plant prefers rather than the one it has. Buying leaf alone + // diluted the Huber value, and measured, that dilution dominated: plants + // finished under-built rather than over-built (#516). + const double rebuild_rel = + rebuild_share * growth_flux * fraction_allocation_growth_ / + (mass_live_per_area_leaf_at_height(height) * area_leaf_); + // Sapwood -> heartwood conversion is turnover-driven, so it proceeds // regardless of carbon status (previously gated behind net>0). - vars.set_rate(state_idx_area_heartwood, area_heartwood_dt(area_leaf_)); - const double area_sapwood_ = area_sapwood(area_leaf_); + vars.set_rate(state_idx_area_heartwood, + area_heartwood_dt(area_leaf_, sapwood_departure)); + const double area_sapwood_ = area_sapwood(area_leaf_, sapwood_departure); const double mass_sapwood_ = mass_sapwood(area_sapwood_, height); vars.set_rate(state_idx_mass_heartwood, mass_heartwood_dt(mass_sapwood_)); @@ -292,6 +406,115 @@ void TF24_Strategy::compute_rates(const TF24_Environment& environment, Internal // the gate withheld, Ppos(1 - G) ~ 1.2e-4 of production, leaves the budget. vars.set_rate(state_idx_storage, charge * (1.0 - r) - drain * r); + // The canopy's departure from the leaf area its height prefers (#516). Held + // at zero here, so leaf area is still exactly the allometric value and this + // commit changes no result: what it buys is the coordinate the plasticity + // terms will be written on, and a checkpoint at which "the state was added" + // and "the behaviour changed" are separately attributable. + // + // Zero is the resting value rather than a placeholder, so the state is inert + // rather than merely unused: the exact flow keeps phi at 0, and an integrator + // stepping a rate of exactly 0.0 leaves the state exactly 0.0. + // --- The two departures (#516) -------------------------------------------- + // Relative rates, so both are scale-free: the same withheld fraction thins a + // seedling's canopy and an adult's by the same proportion, which is what + // keeps these parameters from repeating storage_prod_eps's mistake (#620) of + // being an absolute constant against fluxes spanning six orders. + // + // Leaf area loses the turnover it did not replace and regains what rebuilding + // buys. Thinning is therefore bounded by k_l -- a plant declines to replace + // what died rather than actively shedding -- so the canopy cannot empty + // faster than its leaves turn over. + vars.set_rate(state_idx_log_area_leaf_departure, + rebuild_rel - withheld * pars.k_l); + + + // The Huber value's departure is the DIFFERENCE of the two losses, so the + // drought acclimation falls out of the arithmetic rather than being imposed: + // leaf area thins at up to k_l = 0.457/yr while conducting area is only lost + // to heartwood at k_s = 0.2/yr, and withholding both raises sapwood per leaf + // area. The excess is then renewed less (withheld_sapwood > withheld), which + // is the restoring force. + // + // The last term is exact geometry, not a parameter: rebuilding adds leaf area + // and sapwood in the ratio theta, so it moves the two logs by b/A and + // theta*b/A_s, whose difference is (b/A) * (exp(-psi) - 1). It vanishes at + // psi = 0, which is what leaves the inward-pointing boundary flow intact. + // --- Sapwood chases the ratio that maximises GROWTH (#516) ----------------- + // An integral controller on the marginal return: dpsi/dt = a_sw * R_s, which + // converges exactly onto R_s = 0 and needs no separate tracked state, because + // integrating IS averaging. A small a_sw therefore makes the stem respond to + // the MEAN of a signal that swings with the weather. + // + // R_s is the marginal return of sapwood area, in growth rather than in + // production. Growth is F * f_g * D with D = darea_leaf_dmass_live, so + // d(growth)/dpsi proportional to dP/dpsi - P * (dm_sap/dA) * D + // the second term being the price of the extra stem, paid in forgone leaf + // area. Dropping it optimises production instead, which peaks near 3.3x the + // pipe-model ratio against growth's 1.4-1.8x. + // + // Divided by the gross assimilation flux to make it dimensionless. That + // denominator is strictly positive, unlike P, so the sign of R_s is the sign + // of the growth derivative everywhere including deep deficit. + double sapwood_marginal_ = 0.0; + if (pars.a_sw > 0.0 && shading_model_ != ShadingModel::DeepCrown) { + const double area_sapwood_now = area_sapwood(area_leaf_, sapwood_departure); + const double mass_sapwood_now = mass_sapwood(area_sapwood_now, height); + // Read, do not recompute: #617 replaced the height-linear denominator with + // a path integral, and a recomputed copy here would still have been on the + // old relation -- wrong by a factor 0.35 at 16 m, and silent. + const double kmax_now = leaf_specific_conductance_max_; + const double conv = pars.a_bio * pars.a_y; + // psi enters kmax and sapwood mass both as exp(psi), so d/dpsi of each is + // itself -- which is what makes these two terms so simple. + // ⚠️ SAPWOOD TURNOVER IS GATED, so its psi-derivative is not k_s * m_s. + // What the budget is actually charged is + // replacement_sapwood * k_s * m_s, replacement_sapwood ∝ exp(-psi/a_pl2) + // against m_s ∝ exp(psi), so the charge falls as exp((1 - 1/a_pl2) * psi) -- + // steeply, a_pl2 being well below one. Differentiating the UNGATED cost + // instead drops a term worth +6.8 kg/yr of 13.1 at the default, and moved + // the controller's zero from 1.35x the pipe-model ratio down to 1.05x. + // Respiration carries no such gate, so it keeps the plain exp(psi). + const double charged_sapwood_turnover = + (1.0 - withheld_sapwood) * pars.k_s * mass_sapwood_now; + const double dP_dpsi = + conv * area_leaf_ * dprofit_dkmax_ * kmax_now * 60*60*12*365/1e6 + - conv * pars.r_s * mass_sapwood_now + - charged_sapwood_turnover * (1.0 - 1.0 / pars.a_pl2); + const double dmass_sap_dA = + dmass_sapwood_darea_leaf(area_leaf_star, sapwood_departure); + const double gross = maintenance_flux_; + if (gross > 0.0) { + // ⚠️ SCALED BY CARBON AVAILABILITY, because re-proportioning the stem is + // an allocation decision and has to be paid for out of the growth flux. + // Without this the drift raises area_sapwood at fixed leaf area -- real + // tissue -- while the budget is charged nothing, so a plant in deficit + // would keep thickening on carbon it does not have. The reserve gate G is + // NOT the right switch on its own: at soil 0.13 reserves are still full so + // G ~ 1, and what has gone to zero is Ppos. growth_flux carries both. + // + // The factor is a share of throughput, so it is smooth, lies in [0, 1), + // and vanishes with the growth flux. Symmetric on purpose: scaling only + // the building direction would put a kink at R_s = 0, and the turnover + // route out of an over-built stem stays open regardless, being a real + // mass flow. Being strictly positive it cannot move the zero, so the + // controller still converges on the growth optimum -- it only sets how + // fast, which is what a_sw is for. + const double availability = + growth_flux / (growth_flux + maintenance_flux_); + sapwood_marginal_ = availability * + (dP_dpsi - net_mass_production_dt_ * dmass_sap_dA * + darea_leaf_dmass_live_) / gross; + } + } + + vars.set_aux(aux_idx_sapwood_marginal_return, sapwood_marginal_); + + vars.set_rate(state_idx_log_area_sapwood_departure, + withheld * pars.k_l - withheld_sapwood * pars.k_s + + rebuild_rel * (std::exp(-sapwood_departure) - 1.0) + + pars.a_sw * sapwood_marginal_); + // [eqn 21] - Instantaneous mortality rate, now driven by relative reserves r. vars.set_rate(MORTALITY_INDEX, mortality_dt(r, vars.state(MORTALITY_INDEX))); @@ -355,11 +578,15 @@ double TF24_Strategy::respiration_root(double mass) const { } // [eqn 14] Total turnover -double TF24_Strategy::turnover(double mass_leaf, double mass_bark, +double TF24_Strategy::turnover(double replacement_leaf, + double replacement_sapwood, double mass_leaf, + double mass_bark, double mass_sapwood, double mass_root) const { - return turnover_leaf(mass_leaf) + + // At both fractions = 1 this is bit-identical to charging the whole flux -- + // 1.0 * x is exactly x, and the four terms are summed in the same order. + return replacement_leaf * turnover_leaf(mass_leaf) + turnover_bark(mass_bark) + - turnover_sapwood(mass_sapwood) + + replacement_sapwood * turnover_sapwood(mass_sapwood) + turnover_root(mass_root); } @@ -392,12 +619,15 @@ double TF24_Strategy::net_mass_production_dt_A(double assimilation, double respi // Used by establishment_probability() and compute_rates(). double TF24_Strategy::net_mass_production_dt(const TF24_Environment& environment, double height, double area_leaf_, - double height_inverse) { + double height_inverse, + double sapwood_departure, + double leaf_departure, + double tracked_marginal) { // height_inverse (= 1/height) is supplied by the shared individual.h interface // (cached aux); unused here as the TF24 root-water path works in height directly. (void)height_inverse; const double mass_leaf_ = mass_leaf(area_leaf_); - const double area_sapwood_ = area_sapwood(area_leaf_); + const double area_sapwood_ = area_sapwood(area_leaf_, sapwood_departure); const double mass_sapwood_ = mass_sapwood(area_sapwood_, height); const double area_bark_ = area_bark(area_leaf_); const double mass_bark_ = mass_bark(area_bark_, height); @@ -434,7 +664,17 @@ double TF24_Strategy::net_mass_production_dt(const TF24_Environment& environment // then bit-identical to the height-linear code it replaces. const double stem_path_length = stem_hydraulics::effective_path_length( height * eta_c, pars.L_tip, stem_path_exponent_); - const double leaf_specific_conductance_max = pars.K_s * pars.theta / stem_path_length; + // ⚠️ NUMERATOR IS THE STATE, NOT pars.theta (#516). Supply per unit leaf area + // follows the Huber value the plant actually carries, so a stem that keeps its + // conducting area while the canopy thins supplies each remaining leaf better. + // That is the acclimation half of #516, and it is also what the sapwood + // controller differentiates: psi enters here as exp(psi), which is why + // d(kmax)/d(psi) is just kmax. Stored so the controller reads the SAME value + // rather than recomputing it -- recomputing it is how the two silently drift + // apart when the denominator changes, as it just did in #617. + const double leaf_specific_conductance_max = + pars.K_s * sapwood_per_leaf_area(sapwood_departure) / stem_path_length; + leaf_specific_conductance_max_ = leaf_specific_conductance_max; // sapwood volume per leaf area (pars.theta * height * eta_c) used to be passed // to the leaf, which stored it and never read it. Dropped with the other three @@ -527,7 +767,12 @@ double TF24_Strategy::net_mass_production_dt(const TF24_Environment& environment // (profit_, transpiration_, soil_consumption_, opt_psi_stem_, ...) set. Only // the radiation argument varies between calls; every other input is // depth-independent and already computed above. + // Remembered so the sapwood sensitivity below can re-set the physiology at the + // same light without re-deriving it. Under DeepCrown this holds the LAST + // quadrature point's radiation, which is why that path is refused there. + double last_radiation_ = 0.0; auto optimise_at = [&](double radiation) { + last_radiation_ = radiation; leaf.set_physiology(root_network_, radiation, psi_soil, soil_depths_, leaf_specific_conductance_max, environment.get_atm_vpd(), environment.get_ca(), environment.get_leaf_temp(), environment.get_atm_o2_kpa(), environment.get_atm_kpa()); solve_leaf(); }; @@ -629,6 +874,68 @@ double TF24_Strategy::net_mass_production_dt(const TF24_Environment& environment // int profit*q dz + lambda_o * int E*q dz == int (A - Theta~)*q dz // exactly. Move either assignment away from the other and this stops holding. const double carbon_profit_ = leaf.profit_ + leaf.shadow_cost(); + + // --- How much would more conducting area be worth? (#516) ------------------ + // d(profit)/d(kmax) at the operating point the leaf just found. By the + // ENVELOPE THEOREM this needs no second optimisation: profit is already + // maximised over the collar potential, so the indirect term through psi* + // vanishes and what remains is the partial derivative at a known point. + // phylloptim reports d(profit)/d(psi) as ~1e-15 at its optimum, which is that + // statement measured rather than assumed. + // + // So this re-EVALUATES at the same psi* with kmax nudged; it does not re-solve. + // There is no root-find inside the difference, so it has none of the tol/h + // noise floor that differencing through a solver would. + // + // Skipped entirely at a_sw = 0, which is the default, so the hot path is + // untouched unless sapwood acclimation is switched on. + dprofit_dkmax_ = 0.0; + if (pars.a_sw > 0.0 && shading_model_ != ShadingModel::DeepCrown) { + // ⚠️ THIS COSTS A SECOND FULL LEAF SOLVE, and there is no way around it. + // + // The obvious shortcut is the envelope theorem: profit is already optimised, + // so re-evaluate at the collar potential already found and the indirect term + // vanishes. THAT ARGUMENT IS WRONG HERE, and it was believed long enough to + // ship. It holds for opt_psi_stem_, which really is chosen to maximise + // profit. It does NOT hold for opt_root_psi_, which is found by a ROOT FIND + // -- the collar potential at which the soil-root network's supply matches + // the leaf's demand. A constraint, not an optimum, so d(profit)/d(collar) is + // not zero and dropping the indirect term drops a real quantity. + // + // Measured: holding the collar fixed under-reports d(profit)/d(kmax) by + // 15-19 per cent, which put the controller's zero at 1.22x the pipe-model + // ratio where growth actually peaks at 1.28x. Re-solving matches a finite + // difference of the model's own assimilation to 0.09 per cent and lands the + // zero exactly on the peak. The error was invisible in wet soil, where the + // grid was too coarse to resolve it. + // + // The cost is confined to a_sw > 0; at the default the block never runs. + // + // THE STEP IS MEASURED, NOT ASSUMED. profit comes through a solve with its + // own internal tolerances, so its effective precision is far short of + // machine epsilon. 1e-3 relative sits clear of that noise floor while + // staying deep in the linear regime; sweeping it 1e-6 to 1e-3 moved the + // result by 0.3 per cent, so the step is not what limits accuracy here. + const double dk = 1e-3 * leaf_specific_conductance_max; + leaf.set_physiology(root_network_, last_radiation_, psi_soil, soil_depths_, + leaf_specific_conductance_max + dk, + environment.get_atm_vpd(), environment.get_ca(), + environment.get_leaf_temp(), + environment.get_atm_o2_kpa(), environment.get_atm_kpa()); + solve_leaf(); + const double profit_up = leaf.profit_ + leaf.shadow_cost(); + dprofit_dkmax_ = (profit_up - carbon_profit_) / dk; + // Put the leaf back where it was -- a third solve. Every aux below reads the + // leaf's members, and a leaf left at the perturbed conductance would report + // a plant that does not exist. + leaf.set_physiology(root_network_, last_radiation_, psi_soil, soil_depths_, + leaf_specific_conductance_max, + environment.get_atm_vpd(), environment.get_ca(), + environment.get_leaf_temp(), + environment.get_atm_o2_kpa(), environment.get_atm_kpa()); + solve_leaf(); + } + //TODO: one point constant ratio and integral width for daylength // convert assimilation per leaf area per second (umol m^-2 s^-1) to canopy-level total yearly assimilation (mol yr^-1) // converts to canopy area, then years, then mols @@ -636,8 +943,61 @@ double TF24_Strategy::net_mass_production_dt(const TF24_Environment& environment // const double assimilation_ = assimilation(environment, height, area_leaf_); const double respiration_ = respiration(mass_leaf_, mass_sapwood_, mass_bark_, mass_root_); + // --- Is the marginal leaf paying for itself? (#516) ------------------------ + // The gate reads this rather than the reserve pool, following Manzoni et al. + // 2015: maximising a season's carbon gain over leaf area gives dG/dL = 0, i.e. + // shed once a leaf stops covering its own upkeep. That criterion fires while + // the plant is still carbon-rich -- waiting for reserves to run down IS the + // evergreen strategy in that paper, and it is the one that loses a long + // drought. Robinson's mulga agree from the field: 85 per cent of trees shed, + // the healthiest included, and shedders are indistinguishable from survivors + // until a year in. + // + // ⚠️ ONLY COSTS THAT SCALE WITH LEAF AREA BELONG HERE, because only those are + // what a marginal leaf brings with it: its own upkeep, its fine root and its + // bark (both pinned to leaf area). Sapwood is excluded deliberately -- it is + // carried whether or not this leaf exists, so charging it here would make the + // marginal leaf look unprofitable for a cost it is not responsible for, and + // would make a tall plant shed for being tall. + const double scaling_respiration_ = + respiration_leaf(mass_leaf_) + respiration_bark(mass_bark_) + + respiration_root(mass_root_); + const double scaling_turnover_ = + turnover_leaf(mass_leaf_) + turnover_bark(mass_bark_) + + turnover_root(mass_root_); + const double scaling_cost_ = + pars.a_bio * pars.a_y * scaling_respiration_ + scaling_turnover_; + const double scaling_gain_ = pars.a_bio * pars.a_y * assimilation_; + // Dimensionless, and zero exactly at Manzoni's break-even, so the gate's + // centre is a pure number whose default of 0 IS that optimum. + marginal_leaf_return_ = scaling_cost_ > 0.0 + ? (scaling_gain_ - scaling_cost_) / scaling_cost_ + : 0.0; + + // The gate can be formed here, in the SAME pass: the marginal return is built + // from gross costs, so it does not depend on what is charged below. A second + // pass would mean a second leaf solve, which is the expensive part of the step. + // The gate reads the TRACKED marginal return, not the instantaneous one that + // was just computed: assimilation swings with the weather, and a plant that + // shed on every dry week would be neither physical nor integrable. + const double replacement_leaf = + 1.0 - (1.0 - replacement_fraction(tracked_marginal)) * + shedding_gate(leaf_departure); + const double replacement_sapwood = + sapwood_replacement_fraction(replacement_leaf, sapwood_departure); + withheld_leaf_ = 1.0 - replacement_leaf; + withheld_sapwood_ = 1.0 - replacement_sapwood; + const double turnover_ = - turnover(mass_leaf_, mass_bark_, mass_sapwood_, mass_root_); + turnover(replacement_leaf, replacement_sapwood, mass_leaf_, mass_bark_, + mass_sapwood_, mass_root_); + // The plant's maintenance bill, which the sapwood controller divides by to + // get a dimensionless return. It is used instead of assimilation or profit + // because it is STRICTLY POSITIVE while the plant has tissue: profit is net + // of leaf respiration and goes negative in exactly the drought where the + // controller most needs a sign, and a denominator that changes sign would + // flip the direction the stem moves. + maintenance_flux_ = pars.a_bio * pars.a_y * respiration_ + turnover_; return net_mass_production_dt_A(assimilation_, respiration_, turnover_); } @@ -686,9 +1046,10 @@ double TF24_Strategy::fecundity_dt(double net_mass_production_dt, (pars.omega + pars.a_f3); } -double TF24_Strategy::darea_leaf_dmass_live(double area_leaf) const { +double TF24_Strategy::darea_leaf_dmass_live(double area_leaf, + double sapwood_departure) const { return 1.0/( dmass_leaf_darea_leaf(area_leaf) - + dmass_sapwood_darea_leaf(area_leaf) + + dmass_sapwood_darea_leaf(area_leaf, sapwood_departure) + dmass_bark_darea_leaf(area_leaf) + dmass_root_darea_leaf(area_leaf)); } @@ -703,13 +1064,23 @@ double TF24_Strategy::dmass_leaf_darea_leaf(double /* area_leaf */) const { } // Mass of stem needed for new unit area leaf, d m_s / d a_l -double TF24_Strategy::dmass_sapwood_darea_leaf(double area_leaf) const { - return pars.rho * eta_c * pars.a_l1 * pars.theta * (pars.a_l2 + 1.0) * pow(area_leaf, pars.a_l2); +double TF24_Strategy::dmass_sapwood_darea_leaf(double area_leaf, + double sapwood_departure) const { + // Priced at the Huber value the plant ACTUALLY carries. At rest + // sapwood_per_leaf_area() returns pars.theta unchanged, so this is bitwise + // the expression it replaces. + return pars.rho * eta_c * pars.a_l1 * sapwood_per_leaf_area(sapwood_departure) * + (pars.a_l2 + 1.0) * pow(area_leaf, pars.a_l2); } // Mass of bark needed for new unit area leaf, d m_b / d a_l double TF24_Strategy::dmass_bark_darea_leaf(double area_leaf) const { - return pars.a_b1 * dmass_sapwood_darea_leaf(area_leaf); + // At a RESTING sapwood departure deliberately: bark follows leaf area, so it + // must not pick up the Huber value's excursion. Expressed as a_b1 times the + // sapwood form at zero departure rather than written out, because floating + // point multiplication is not associative -- writing the product flat changes + // the last bits and moved a whole SCM trajectory when first tried. + return pars.a_b1 * dmass_sapwood_darea_leaf(area_leaf, 0.0); } // Mass of root needed for new unit area leaf, d m_r / d a_l @@ -729,8 +1100,9 @@ double TF24_Strategy::area_sapwood_dt(double area_leaf_dt) const { // Note, unlike others, heartwood growth does not depend on leaf area growth, but // rather existing sapwood -double TF24_Strategy::area_heartwood_dt(double area_leaf) const { - return pars.k_s * area_sapwood(area_leaf); +double TF24_Strategy::area_heartwood_dt(double area_leaf, + double sapwood_departure) const { + return pars.k_s * area_sapwood(area_leaf, sapwood_departure); } // Growth rate of bark area at base per unit time @@ -743,7 +1115,10 @@ double TF24_Strategy::area_stem_dt(double area_leaf, double area_leaf_dt) const { return area_sapwood_dt(area_leaf_dt) + area_bark_dt(area_leaf_dt) + - area_heartwood_dt(area_leaf); + // At the resting Huber value: this reporting helper is handed sizes, not a + // state vector, so it cannot see the departure. Its callers are the R-facing + // expansion path, which reconstructs a plant on its own trajectory. + area_heartwood_dt(area_leaf, 0.0); } // Growth rate of basal diameter_stem per unit time @@ -831,8 +1206,10 @@ double TF24_Strategy::mortality_storage_dependent_dt(double relative_reserves) c // NSC storage capacity: scales with sapwood mass (per Daniel, #517). mass_sapwood // = area_sapwood(area_leaf) * height * eta_c * rho. -double TF24_Strategy::storage_capacity(double area_leaf_, double height) const { - return pars.a_st1 * mass_sapwood(area_sapwood(area_leaf_), height); +double TF24_Strategy::storage_capacity(double area_leaf_, double height, + double sapwood_departure) const { + return pars.a_st1 * + mass_sapwood(area_sapwood(area_leaf_, sapwood_departure), height); } // Seed the storage state for a newly germinated individual at a_st3 fraction of @@ -844,14 +1221,34 @@ void TF24_Strategy::set_initial_states(const TF24_Environment& environment, const double height = vars.state(HEIGHT_INDEX); const double area_leaf_ = area_leaf(height); vars.set_state(state_idx_storage, - pars.a_st3 * storage_capacity(area_leaf_, height)); + pars.a_st3 * + storage_capacity(area_leaf_, height, + vars.state(state_idx_log_area_sapwood_departure))); + + // Seed the tracked marginal balance from the plant's own first evaluation. + // Left at zero it would start every seedling exactly at the gate's centre, + // withholding half its replacement from birth; and a running mean has to + // start somewhere its own history would have put it. Costs one leaf solve per + // birth, against one per derivative evaluation, so it is not on the hot path. + net_mass_production_dt(environment, vars); + vars.set_state(state_idx_leaf_marginal_tracked, marginal_leaf_return_); } // [eqn 20] Survival of seedlings during establishment double TF24_Strategy::establishment_probability(const TF24_Environment& environment) { return establishment_probability( environment, - net_mass_production_dt(environment, height_0, area_leaf_0, 1.0 / height_0)); + net_mass_production_dt(environment, height_0, area_leaf_0, 1.0 / height_0, + // A germinating seed is on its allometry by + // definition -- height_0 is solved from seed mass, + // and area_leaf_0 from height_0 -- so both of its + // departures are the resting ones. The gate then + // reads the seed's own marginal return, which is the + // point: a seedling whose leaves cannot pay for + // themselves establishes worse, and now says so. It + // has no history yet, so the tracked balance starts + // at break-even. + 0.0, 0.0, 0.0)); } // Both forms above end here. The carbon is birth-size carbon either way, whatever @@ -935,6 +1332,19 @@ void TF24_Strategy::prepare_strategy() { "' is not supported for the TF24 strategy"); } + // ⚠️ Sapwood acclimation needs d(profit)/d(kmax), which is measured by + // re-evaluating the leaf at ONE radiation. Under deep-crown, carbon_profit_ + // is an integral over crown positions instead, so that single-point + // difference is not its derivative. Refuse rather than skip: skipping leaves + // the controller with only its (negative) cost term, so the stem would shrink + // without bound and the run would look plausible the whole way down. + if (pars.a_sw > 0.0 && shading_model_ == ShadingModel::DeepCrown) { + throw std::invalid_argument( + "TF24 sapwood acclimation (a_sw > 0) is not supported with the " + "deep-crown shading model: the sapwood sensitivity is measured at a " + "single radiation and deep-crown integrates over the crown"); + } + canopy_shape.initialise(pars.eta, shading_model_); eta_c = CanopyShape::eta_c(pars.eta); diff --git a/tests/testthat/_problems/test-allometry-demo-212.R b/tests/testthat/_problems/test-allometry-demo-212.R new file mode 100644 index 000000000..3bb5b05e5 --- /dev/null +++ b/tests/testthat/_problems/test-allometry-demo-212.R @@ -0,0 +1,53 @@ +# Extracted from test-allometry-demo.R:212 + +# prequel ---------------------------------------------------------------------- +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +# test ------------------------------------------------------------------------- +skip_if_not(file.exists(demo_helpers), "demo helpers not present") +skip_on_cran() +source(demo_helpers, local = TRUE) +z <- lapply(c(5, 10, 15, 20), allometry_carbon_terms, theta_soil = 0.20) +eta <- vapply(z, `[[`, numeric(1), "eta") +kappa <- vapply(z, `[[`, numeric(1), "kappa") +dPdA <- vapply(z, `[[`, numeric(1), "dPdA") +expect_true(all(diff(eta) > 0)) +expect_true(all(diff(kappa) > 0)) +expect_lt(eta[[1]], 1) +expect_gt(eta[[3]], 1) diff --git a/tests/testthat/_problems/test-allometry-demo-253.R b/tests/testthat/_problems/test-allometry-demo-253.R new file mode 100644 index 000000000..a2dde9ea1 --- /dev/null +++ b/tests/testthat/_problems/test-allometry-demo-253.R @@ -0,0 +1,48 @@ +# Extracted from test-allometry-demo.R:253 + +# setup ------------------------------------------------------------------------ +library(testthat) +test_env <- simulate_test_env(package = "plant", path = "..") +attach(test_env, warn.conflicts = FALSE) + +# prequel ---------------------------------------------------------------------- +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +# test ------------------------------------------------------------------------- +ctl <- lapply(c(0.30, 0.20, 0.15), allometry_sapwood_controller) diff --git a/tests/testthat/_problems/test-allometry-demo-268.R b/tests/testthat/_problems/test-allometry-demo-268.R new file mode 100644 index 000000000..627be8daf --- /dev/null +++ b/tests/testthat/_problems/test-allometry-demo-268.R @@ -0,0 +1,54 @@ +# Extracted from test-allometry-demo.R:268 + +# prequel ---------------------------------------------------------------------- +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +# test ------------------------------------------------------------------------- +skip_if_not(file.exists(demo_helpers), "demo helpers not present") +skip_on_cran() +source(demo_helpers, local = TRUE) +ctl <- lapply(c(0.30, 0.20, 0.15), allometry_sapwood_controller) +names(ctl) <- c("wet", "moist", "dry") +for (nm in c("wet", "moist")) { + d <- ctl[[nm]] + expect_equal(d$huber_ratio[which.min(abs(d$R_s))], + d$huber_ratio[which.max(d$dheight)]) + } +peak <- vapply(ctl, function(d) d$huber_ratio[which.max(d$dheight)], numeric(1)) +expect_equal(unname(round(peak[["wet"]], 2)), 1.28) diff --git a/tests/testthat/_problems/test-allometry-demo-269.R b/tests/testthat/_problems/test-allometry-demo-269.R new file mode 100644 index 000000000..a06dd521a --- /dev/null +++ b/tests/testthat/_problems/test-allometry-demo-269.R @@ -0,0 +1,55 @@ +# Extracted from test-allometry-demo.R:269 + +# prequel ---------------------------------------------------------------------- +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +# test ------------------------------------------------------------------------- +skip_if_not(file.exists(demo_helpers), "demo helpers not present") +skip_on_cran() +source(demo_helpers, local = TRUE) +ctl <- lapply(c(0.30, 0.20, 0.15), allometry_sapwood_controller) +names(ctl) <- c("wet", "moist", "dry") +for (nm in c("wet", "moist")) { + d <- ctl[[nm]] + expect_equal(d$huber_ratio[which.min(abs(d$R_s))], + d$huber_ratio[which.max(d$dheight)]) + } +peak <- vapply(ctl, function(d) d$huber_ratio[which.max(d$dheight)], numeric(1)) +expect_equal(unname(round(peak[["wet"]], 2)), 1.28) +expect_equal(unname(round(peak[["moist"]], 2)), 1.35) diff --git a/tests/testthat/_problems/test-allometry-demo-274.R b/tests/testthat/_problems/test-allometry-demo-274.R new file mode 100644 index 000000000..5d440f1c9 --- /dev/null +++ b/tests/testthat/_problems/test-allometry-demo-274.R @@ -0,0 +1,57 @@ +# Extracted from test-allometry-demo.R:274 + +# prequel ---------------------------------------------------------------------- +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +# test ------------------------------------------------------------------------- +skip_if_not(file.exists(demo_helpers), "demo helpers not present") +skip_on_cran() +source(demo_helpers, local = TRUE) +ctl <- lapply(c(0.30, 0.20, 0.15), allometry_sapwood_controller) +names(ctl) <- c("wet", "moist", "dry") +for (nm in c("wet", "moist")) { + d <- ctl[[nm]] + expect_equal(d$huber_ratio[which.min(abs(d$R_s))], + d$huber_ratio[which.max(d$dheight)]) + } +peak <- vapply(ctl, function(d) d$huber_ratio[which.max(d$dheight)], numeric(1)) +expect_equal(unname(round(peak[["wet"]], 2)), 1.28) +expect_equal(unname(round(peak[["moist"]], 2)), 1.35) +expect_gt(peak[["dry"]], peak[["moist"]]) +expect_lt(ctl$dry$dheight[[1]], 1e-8) diff --git a/tests/testthat/_problems/test-allometry-demo-275.R b/tests/testthat/_problems/test-allometry-demo-275.R new file mode 100644 index 000000000..3da9db1b5 --- /dev/null +++ b/tests/testthat/_problems/test-allometry-demo-275.R @@ -0,0 +1,58 @@ +# Extracted from test-allometry-demo.R:275 + +# prequel ---------------------------------------------------------------------- +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +# test ------------------------------------------------------------------------- +skip_if_not(file.exists(demo_helpers), "demo helpers not present") +skip_on_cran() +source(demo_helpers, local = TRUE) +ctl <- lapply(c(0.30, 0.20, 0.15), allometry_sapwood_controller) +names(ctl) <- c("wet", "moist", "dry") +for (nm in c("wet", "moist")) { + d <- ctl[[nm]] + expect_equal(d$huber_ratio[which.min(abs(d$R_s))], + d$huber_ratio[which.max(d$dheight)]) + } +peak <- vapply(ctl, function(d) d$huber_ratio[which.max(d$dheight)], numeric(1)) +expect_equal(unname(round(peak[["wet"]], 2)), 1.28) +expect_equal(unname(round(peak[["moist"]], 2)), 1.35) +expect_gt(peak[["dry"]], peak[["moist"]]) +expect_lt(ctl$dry$dheight[[1]], 1e-8) +expect_lt(abs(ctl$dry$R_s[[1]]), 1e-8) diff --git a/tests/testthat/_problems/test-allometry-demo-276.R b/tests/testthat/_problems/test-allometry-demo-276.R new file mode 100644 index 000000000..3da91b3a3 --- /dev/null +++ b/tests/testthat/_problems/test-allometry-demo-276.R @@ -0,0 +1,59 @@ +# Extracted from test-allometry-demo.R:276 + +# prequel ---------------------------------------------------------------------- +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +# test ------------------------------------------------------------------------- +skip_if_not(file.exists(demo_helpers), "demo helpers not present") +skip_on_cran() +source(demo_helpers, local = TRUE) +ctl <- lapply(c(0.30, 0.20, 0.15), allometry_sapwood_controller) +names(ctl) <- c("wet", "moist", "dry") +for (nm in c("wet", "moist")) { + d <- ctl[[nm]] + expect_equal(d$huber_ratio[which.min(abs(d$R_s))], + d$huber_ratio[which.max(d$dheight)]) + } +peak <- vapply(ctl, function(d) d$huber_ratio[which.max(d$dheight)], numeric(1)) +expect_equal(unname(round(peak[["wet"]], 2)), 1.28) +expect_equal(unname(round(peak[["moist"]], 2)), 1.35) +expect_gt(peak[["dry"]], peak[["moist"]]) +expect_lt(ctl$dry$dheight[[1]], 1e-8) +expect_lt(abs(ctl$dry$R_s[[1]]), 1e-8) +expect_gt(ctl$dry$R_s[[which.min(abs(ctl$dry$huber_ratio - 1.35))]], 0.05) diff --git a/tests/testthat/_problems/test-model-version-95.R b/tests/testthat/_problems/test-model-version-95.R new file mode 100644 index 000000000..623b78c8e --- /dev/null +++ b/tests/testthat/_problems/test-model-version-95.R @@ -0,0 +1,5 @@ +# Extracted from test-model-version.R:95 + +# +# Failed to extract test: +# Failed to find test at line 95. diff --git a/tests/testthat/_problems/test-scenario-gateway-101.R b/tests/testthat/_problems/test-scenario-gateway-101.R new file mode 100644 index 000000000..06869cdd5 --- /dev/null +++ b/tests/testthat/_problems/test-scenario-gateway-101.R @@ -0,0 +1,56 @@ +# Extracted from test-scenario-gateway.R:101 + +# test ------------------------------------------------------------------------- +skip_on_cran() +skip_if_not(nzchar(Sys.getenv("PLANT_RUN_SCENARIOS")), + "Set PLANT_RUN_SCENARIOS=1 to run the (slow) scenario gateway.") +baseline_path <- test_path("test_data", "scenario_baseline.rds") +skip_if_not(file.exists(baseline_path), "No recorded scenario baseline.") +baseline <- readRDS(baseline_path) +mpl <- attr(baseline, "max_patch_lifetime") +if (is.null(mpl)) mpl <- 100 +workers <- as.integer(Sys.getenv("SCENARIO_WORKERS", "1")) +current <- run_scenarios(max_patch_lifetime = mpl, workers = workers) +b <- baseline[order(baseline$scenario_id), ] +cur <- current[order(current$scenario_id), ] +expect_equal(cur$scenario_id, b$scenario_id) +tol <- as.numeric(Sys.getenv("SCENARIO_TOL", "1e-3")) +differs <- function(x, y) { + (is.na(x) != is.na(y)) | (!is.na(x) & !is.na(y) & x != y) + } +report <- function(col, label) { + if (!col %in% names(b) || !col %in% names(cur)) { + return(NULL) + } + changed <- differs(b[[col]], cur[[col]]) + if (!any(changed)) { + return(NULL) + } + sprintf("%s %s", label, + paste(sprintf("%s: %s -> %s", b$scenario_id[changed], + b[[col]][changed], cur[[col]][changed]), + collapse = "; ")) + } +from <- b$offspring_production +to <- cur$offspring_production +rel <- ifelse(is.na(from) | is.na(to), NA_real_, + ifelse(from == 0, ifelse(to == 0, 0, Inf), (to - from) / from)) +moved <- differs(from, to) & (is.na(rel) | abs(rel) > tol) +numeric_report <- if (any(moved)) { + sprintf("offspring_production moved on %d/%d scenario(s) (tol %g)", + sum(moved), length(moved), tol) + } +msgs <- c(report("observed", "observed"), report("persists", "persists"), + numeric_report) +if (length(msgs)) { + tbl <- paste(c(sprintf("%-4s %14s %14s %10s", "id", "baseline", + "current", "rel"), + sprintf("%-4s %14.7g %14.7g %10.3g%s", b$scenario_id, + from, to, rel, ifelse(moved, " *", ""))), + collapse = "\n") + fail(paste0("Scenario outcomes changed vs baseline ", + "(re-bless via `make bless-scenarios` if intended): ", + paste(msgs, collapse = " | "), "\n", tbl)) + } else { + succeed() + } diff --git a/tests/testthat/_problems/test-strategy-tf24-1066.R b/tests/testthat/_problems/test-strategy-tf24-1066.R new file mode 100644 index 000000000..e6aa59976 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-1066.R @@ -0,0 +1,45 @@ +# Extracted from test-strategy-tf24.R:1066 + +# prequel ---------------------------------------------------------------------- +tf24_storage_capacity_r <- function(height, s = TF24_Strategy()) { + z <- rep(0, length(height)) + s$pars$a_st1 * TF24_strategy_expand_allometry(s, height, z, z)$mass_sapwood +} +tf24_storage_at <- function(storage, height = 5, light = 1, theta = 0.4, + s = TF24_Strategy()) { + env <- Environment("TF24") + env$set_fixed_environment(light, height_max = 150) + env$set_soil_water_state(rep(theta, env$get_soil_number_of_depths())) + env$time <- 5 + ind <- Individual("TF24", "TF24_Env")(s) + ind$set_state("height", height) + ind$set_state("storage", storage) + ind$compute_rates(env) + list(dS = ind$internals$rates[[match("storage", ind$ode_names)]], + P = ind$aux("net_mass_production_dt")) +} +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} + +# test ------------------------------------------------------------------------- +env <- tf24_departure_env() +s <- TF24_Strategy(collect_all_auxiliary = TRUE) +growth_at <- function(psi, h = 10) { + ind <- TF24_Individual(s) + ind$set_state("height", h) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ind$compute_rates(env) + c(P = ind$aux("net_mass_production_dt"), dh = ind$rate("height")) + } +psis <- seq(0, 2.4, by = 0.3) +out <- vapply(psis, growth_at, numeric(2)) +P <- out["P", ] +G <- out["dh", ] +expect_gt(which.max(P), 1) +expect_gt(which.max(G), 1) diff --git a/tests/testthat/_problems/test-strategy-tf24-1069.R b/tests/testthat/_problems/test-strategy-tf24-1069.R new file mode 100644 index 000000000..d63162a3d --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-1069.R @@ -0,0 +1,48 @@ +# Extracted from test-strategy-tf24.R:1069 + +# prequel ---------------------------------------------------------------------- +tf24_storage_capacity_r <- function(height, s = TF24_Strategy()) { + z <- rep(0, length(height)) + s$pars$a_st1 * TF24_strategy_expand_allometry(s, height, z, z)$mass_sapwood +} +tf24_storage_at <- function(storage, height = 5, light = 1, theta = 0.4, + s = TF24_Strategy()) { + env <- Environment("TF24") + env$set_fixed_environment(light, height_max = 150) + env$set_soil_water_state(rep(theta, env$get_soil_number_of_depths())) + env$time <- 5 + ind <- Individual("TF24", "TF24_Env")(s) + ind$set_state("height", height) + ind$set_state("storage", storage) + ind$compute_rates(env) + list(dS = ind$internals$rates[[match("storage", ind$ode_names)]], + P = ind$aux("net_mass_production_dt")) +} +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} + +# test ------------------------------------------------------------------------- +env <- tf24_departure_env() +s <- TF24_Strategy(collect_all_auxiliary = TRUE) +growth_at <- function(psi, h = 10) { + ind <- TF24_Individual(s) + ind$set_state("height", h) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ind$compute_rates(env) + c(P = ind$aux("net_mass_production_dt"), dh = ind$rate("height")) + } +psis <- seq(0, 2.4, by = 0.3) +out <- vapply(psis, growth_at, numeric(2)) +P <- out["P", ] +G <- out["dh", ] +expect_gt(which.max(P), 1) +expect_gt(which.max(G), 1) +expect_lt(which.max(G), which.max(P)) +expect_lt(exp(psis[which.max(G)]), 2.5) +expect_gt(exp(psis[which.max(P)]), 2.5) diff --git a/tests/testthat/_problems/test-strategy-tf24-1090.R b/tests/testthat/_problems/test-strategy-tf24-1090.R new file mode 100644 index 000000000..8faf94da0 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-1090.R @@ -0,0 +1,47 @@ +# Extracted from test-strategy-tf24.R:1090 + +# prequel ---------------------------------------------------------------------- +tf24_storage_capacity_r <- function(height, s = TF24_Strategy()) { + z <- rep(0, length(height)) + s$pars$a_st1 * TF24_strategy_expand_allometry(s, height, z, z)$mass_sapwood +} +tf24_storage_at <- function(storage, height = 5, light = 1, theta = 0.4, + s = TF24_Strategy()) { + env <- Environment("TF24") + env$set_fixed_environment(light, height_max = 150) + env$set_soil_water_state(rep(theta, env$get_soil_number_of_depths())) + env$time <- 5 + ind <- Individual("TF24", "TF24_Env")(s) + ind$set_state("height", height) + ind$set_state("storage", storage) + ind$compute_rates(env) + list(dS = ind$internals$rates[[match("storage", ind$ode_names)]], + P = ind$aux("net_mass_production_dt")) +} +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} +tf24_sapwood_probe <- function(psi, theta_soil, a_sw = 1.0, height = 10) { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_sw <- a_sw + env <- Environment("TF24") + env$set_soil_number_of_depths(5L) + env$set_soil_water_state(rep(theta_soil, 5L)) + env$set_fixed_environment(1.0, 40) + ind <- TF24_Individual(s) + ind$set_state("height", height) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ind$compute_rates(env) + list(R_s = ind$aux("sapwood_marginal_return"), + dpsi = ind$rate("log_area_sapwood_departure"), + dheight = ind$rate("height")) +} + +# test ------------------------------------------------------------------------- +dry <- tf24_sapwood_probe(0.2, 0.13) +expect_identical(dry$R_s, 0.0) diff --git a/tests/testthat/_problems/test-strategy-tf24-1103.R b/tests/testthat/_problems/test-strategy-tf24-1103.R new file mode 100644 index 000000000..5918e0bbe --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-1103.R @@ -0,0 +1,49 @@ +# Extracted from test-strategy-tf24.R:1103 + +# prequel ---------------------------------------------------------------------- +tf24_storage_capacity_r <- function(height, s = TF24_Strategy()) { + z <- rep(0, length(height)) + s$pars$a_st1 * TF24_strategy_expand_allometry(s, height, z, z)$mass_sapwood +} +tf24_storage_at <- function(storage, height = 5, light = 1, theta = 0.4, + s = TF24_Strategy()) { + env <- Environment("TF24") + env$set_fixed_environment(light, height_max = 150) + env$set_soil_water_state(rep(theta, env$get_soil_number_of_depths())) + env$time <- 5 + ind <- Individual("TF24", "TF24_Env")(s) + ind$set_state("height", height) + ind$set_state("storage", storage) + ind$compute_rates(env) + list(dS = ind$internals$rates[[match("storage", ind$ode_names)]], + P = ind$aux("net_mass_production_dt")) +} +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} +tf24_sapwood_probe <- function(psi, theta_soil, a_sw = 1.0, height = 10) { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_sw <- a_sw + env <- Environment("TF24") + env$set_soil_number_of_depths(5L) + env$set_soil_water_state(rep(theta_soil, 5L)) + env$set_fixed_environment(1.0, 40) + ind <- TF24_Individual(s) + ind$set_state("height", height) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ind$compute_rates(env) + list(R_s = ind$aux("sapwood_marginal_return"), + dpsi = ind$rate("log_area_sapwood_departure"), + dheight = ind$rate("height")) +} + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy() +s$pars$a_sw <- 1.0 +s$control$shading_model <- "deep_crown" +expect_error(TF24_Individual(s), "deep-crown") diff --git a/tests/testthat/_problems/test-strategy-tf24-113.R b/tests/testthat/_problems/test-strategy-tf24-113.R new file mode 100644 index 000000000..d23eb6d8e --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-113.R @@ -0,0 +1,22 @@ +# Extracted from test-strategy-tf24.R:113 + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy() +p <- TF24_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) diff --git a/tests/testthat/_problems/test-strategy-tf24-1135.R b/tests/testthat/_problems/test-strategy-tf24-1135.R new file mode 100644 index 000000000..7ca6d4e83 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-1135.R @@ -0,0 +1,59 @@ +# Extracted from test-strategy-tf24.R:1135 + +# prequel ---------------------------------------------------------------------- +tf24_storage_capacity_r <- function(height, s = TF24_Strategy()) { + z <- rep(0, length(height)) + s$pars$a_st1 * TF24_strategy_expand_allometry(s, height, z, z)$mass_sapwood +} +tf24_storage_at <- function(storage, height = 5, light = 1, theta = 0.4, + s = TF24_Strategy()) { + env <- Environment("TF24") + env$set_fixed_environment(light, height_max = 150) + env$set_soil_water_state(rep(theta, env$get_soil_number_of_depths())) + env$time <- 5 + ind <- Individual("TF24", "TF24_Env")(s) + ind$set_state("height", height) + ind$set_state("storage", storage) + ind$compute_rates(env) + list(dS = ind$internals$rates[[match("storage", ind$ode_names)]], + P = ind$aux("net_mass_production_dt")) +} +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} +tf24_sapwood_probe <- function(psi, theta_soil, a_sw = 1.0, height = 10) { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_sw <- a_sw + env <- Environment("TF24") + env$set_soil_number_of_depths(5L) + env$set_soil_water_state(rep(theta_soil, 5L)) + env$set_fixed_environment(1.0, 40) + ind <- TF24_Individual(s) + ind$set_state("height", height) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ind$compute_rates(env) + list(R_s = ind$aux("sapwood_marginal_return"), + dpsi = ind$rate("log_area_sapwood_departure"), + dheight = ind$rate("height")) +} + +# test ------------------------------------------------------------------------- +psi <- seq(0, 0.6, by = 0.025) +d <- vapply(psi, function(p) { + r <- tf24_sapwood_probe(p, 0.20) + c(r$R_s, r$dheight) + }, numeric(2)) +R_s <- d[1, ] +dh <- d[2, ] +expect_gt(R_s[[1]], 0) +expect_lt(R_s[[length(R_s)]], 0) +expect_equal(sum(diff(sign(R_s)) != 0), 1L) +psi_zero <- psi[which.min(abs(R_s))] +psi_peak <- psi[which.max(dh)] +expect_equal(psi_zero, psi_peak) +expect_gt(exp(psi_peak), 1.2) diff --git a/tests/testthat/_problems/test-strategy-tf24-118.R b/tests/testthat/_problems/test-strategy-tf24-118.R new file mode 100644 index 000000000..684545fb9 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-118.R @@ -0,0 +1,26 @@ +# Extracted from test-strategy-tf24.R:118 + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy() +p <- TF24_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) +s <- TF24_Strategy(collect_all_auxiliary=TRUE) +expect_true(s$collect_all_auxiliary) +p <- TF24_Individual(s) +expect_equal(p$aux_size, 14) diff --git a/tests/testthat/_problems/test-strategy-tf24-119.R b/tests/testthat/_problems/test-strategy-tf24-119.R new file mode 100644 index 000000000..0ef035981 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-119.R @@ -0,0 +1,27 @@ +# Extracted from test-strategy-tf24.R:119 + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy() +p <- TF24_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) +s <- TF24_Strategy(collect_all_auxiliary=TRUE) +expect_true(s$collect_all_auxiliary) +p <- TF24_Individual(s) +expect_equal(p$aux_size, 14) +expect_equal(length(p$internals$auxs), 14) diff --git a/tests/testthat/_problems/test-strategy-tf24-135.R b/tests/testthat/_problems/test-strategy-tf24-135.R new file mode 100644 index 000000000..7cdc9200c --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-135.R @@ -0,0 +1,43 @@ +# Extracted from test-strategy-tf24.R:135 + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy() +p <- TF24_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) +s <- TF24_Strategy(collect_all_auxiliary=TRUE) +expect_true(s$collect_all_auxiliary) +p <- TF24_Individual(s) +expect_equal(p$aux_size, 14) +expect_equal(length(p$internals$auxs), 14) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return", + "area_sapwood" + )) diff --git a/tests/testthat/_problems/test-strategy-tf24-403.R b/tests/testthat/_problems/test-strategy-tf24-403.R new file mode 100644 index 000000000..91e9362e0 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-403.R @@ -0,0 +1,25 @@ +# Extracted from test-strategy-tf24.R:403 + +# test ------------------------------------------------------------------------- +linear <- function(p) { + # Every strategy, not just the first: resetting only strategies[[1]] leaves + # the second species on the path integral and silently compares two + # different models. + for (i in seq_along(p$strategies)) { + s <- p$strategies[[i]] + s$pars$D_c <- 0 + s$pars$theta_c <- 0 + s$pars$L_tip <- 0 + s$pars$K_s <- 1 + p$strategies[[i]] <- s + } + p + } +p0 <- scm_base_parameters("TF24") +env <- Environment("TF24") +ctrl <- Control() +p0$max_patch_lifetime <- 5 +p1 <- add_strategies(p0, trait_matrix(c(0.0825, 5), c("lma", "hmat")), + hyperpar = TF24_hyperpar, birth_rate = list(20)) +out <- run_scm(linear(p1), env, ctrl) +expect_equal(out$offspring_production, 30.22207354, tolerance = 2e-2) diff --git a/tests/testthat/_problems/test-strategy-tf24-408.R b/tests/testthat/_problems/test-strategy-tf24-408.R new file mode 100644 index 000000000..f0aac1979 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-408.R @@ -0,0 +1,29 @@ +# Extracted from test-strategy-tf24.R:408 + +# test ------------------------------------------------------------------------- +linear <- function(p) { + # Every strategy, not just the first: resetting only strategies[[1]] leaves + # the second species on the path integral and silently compares two + # different models. + for (i in seq_along(p$strategies)) { + s <- p$strategies[[i]] + s$pars$D_c <- 0 + s$pars$theta_c <- 0 + s$pars$L_tip <- 0 + s$pars$K_s <- 1 + p$strategies[[i]] <- s + } + p + } +p0 <- scm_base_parameters("TF24") +env <- Environment("TF24") +ctrl <- Control() +p0$max_patch_lifetime <- 5 +p1 <- add_strategies(p0, trait_matrix(c(0.0825, 5), c("lma", "hmat")), + hyperpar = TF24_hyperpar, birth_rate = list(20)) +out <- run_scm(linear(p1), env, ctrl) +expect_equal(out$offspring_production, 30.22207354, tolerance = 2e-2) +p2 <- add_strategies(p0, trait_matrix(c(0.0825, 0.10, 5, 5), c("lma", "hmat")), + hyperpar = TF24_hyperpar, birth_rate = list(20, 20)) +out2 <- run_scm(linear(p2), env, ctrl) +expect_equal(out2$offspring_production[[1]], 23.20349831, tolerance = 2e-2) diff --git a/tests/testthat/_problems/test-strategy-tf24-409.R b/tests/testthat/_problems/test-strategy-tf24-409.R new file mode 100644 index 000000000..acb31a6c9 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-409.R @@ -0,0 +1,30 @@ +# Extracted from test-strategy-tf24.R:409 + +# test ------------------------------------------------------------------------- +linear <- function(p) { + # Every strategy, not just the first: resetting only strategies[[1]] leaves + # the second species on the path integral and silently compares two + # different models. + for (i in seq_along(p$strategies)) { + s <- p$strategies[[i]] + s$pars$D_c <- 0 + s$pars$theta_c <- 0 + s$pars$L_tip <- 0 + s$pars$K_s <- 1 + p$strategies[[i]] <- s + } + p + } +p0 <- scm_base_parameters("TF24") +env <- Environment("TF24") +ctrl <- Control() +p0$max_patch_lifetime <- 5 +p1 <- add_strategies(p0, trait_matrix(c(0.0825, 5), c("lma", "hmat")), + hyperpar = TF24_hyperpar, birth_rate = list(20)) +out <- run_scm(linear(p1), env, ctrl) +expect_equal(out$offspring_production, 30.22207354, tolerance = 2e-2) +p2 <- add_strategies(p0, trait_matrix(c(0.0825, 0.10, 5, 5), c("lma", "hmat")), + hyperpar = TF24_hyperpar, birth_rate = list(20, 20)) +out2 <- run_scm(linear(p2), env, ctrl) +expect_equal(out2$offspring_production[[1]], 23.20349831, tolerance = 2e-2) +expect_lt(out2$offspring_production[[2]], 0.5) diff --git a/tests/testthat/_problems/test-strategy-tf24-769.R b/tests/testthat/_problems/test-strategy-tf24-769.R new file mode 100644 index 000000000..d36a514ca --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-769.R @@ -0,0 +1,44 @@ +# Extracted from test-strategy-tf24.R:769 + +# prequel ---------------------------------------------------------------------- +tf24_storage_capacity_r <- function(height, s = TF24_Strategy()) { + z <- rep(0, length(height)) + s$pars$a_st1 * TF24_strategy_expand_allometry(s, height, z, z)$mass_sapwood +} +tf24_storage_at <- function(storage, height = 5, light = 1, theta = 0.4, + s = TF24_Strategy()) { + env <- Environment("TF24") + env$set_fixed_environment(light, height_max = 150) + env$set_soil_water_state(rep(theta, env$get_soil_number_of_depths())) + env$time <- 5 + ind <- Individual("TF24", "TF24_Env")(s) + ind$set_state("height", height) + ind$set_state("storage", storage) + ind$compute_rates(env) + list(dS = ind$internals$rates[[match("storage", ind$ode_names)]], + P = ind$aux("net_mass_production_dt")) +} +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy(collect_all_auxiliary = TRUE) +s$pars$a_pl0 <- 1.0 +probe <- function(theta_soil) { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(theta_soil, 5)) + env$set_fixed_environment(1.0, 40) + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_initial_states(env) # reserves at a_st3 = 0.8 of capacity + ind$compute_rates(env) + list(dphi = ind$rate("log_area_leaf_departure"), + dpsi = ind$rate("log_area_sapwood_departure"), + margin = ind$aux("leaf_marginal_return", "sapwood_marginal_return")) + } diff --git a/tests/testthat/_problems/test-strategy-tf24-812.R b/tests/testthat/_problems/test-strategy-tf24-812.R new file mode 100644 index 000000000..43992b7b5 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-812.R @@ -0,0 +1,44 @@ +# Extracted from test-strategy-tf24.R:812 + +# prequel ---------------------------------------------------------------------- +tf24_storage_capacity_r <- function(height, s = TF24_Strategy()) { + z <- rep(0, length(height)) + s$pars$a_st1 * TF24_strategy_expand_allometry(s, height, z, z)$mass_sapwood +} +tf24_storage_at <- function(storage, height = 5, light = 1, theta = 0.4, + s = TF24_Strategy()) { + env <- Environment("TF24") + env$set_fixed_environment(light, height_max = 150) + env$set_soil_water_state(rep(theta, env$get_soil_number_of_depths())) + env$time <- 5 + ind <- Individual("TF24", "TF24_Env")(s) + ind$set_state("height", height) + ind$set_state("storage", storage) + ind$compute_rates(env) + list(dS = ind$internals$rates[[match("storage", ind$ode_names)]], + P = ind$aux("net_mass_production_dt")) +} +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy(collect_all_auxiliary = TRUE) +s$pars$a_pl0 <- 1.0 +wet <- Environment("TF24") +wet$set_soil_number_of_depths(5) +wet$set_soil_water_state(rep(0.30, 5)) +wet$set_fixed_environment(1.0, 40) +dry <- Environment("TF24") +dry$set_soil_number_of_depths(5) +dry$set_soil_water_state(rep(0.11, 5)) +dry$set_fixed_environment(1.0, 40) +ind <- TF24_Individual(s) +ind$set_state("height", 5.0) +ind$set_initial_states(wet) +ind$compute_rates(dry) +expect_lt(ind$aux("leaf_marginal_return", "sapwood_marginal_return"), 0) diff --git a/tests/testthat/_problems/test-strategy-tf24-89.R b/tests/testthat/_problems/test-strategy-tf24-89.R new file mode 100644 index 000000000..313220dc3 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-89.R @@ -0,0 +1,83 @@ +# Extracted from test-strategy-tf24.R:89 + +# test ------------------------------------------------------------------------- +expected_pars <- list( + a_l2 = 0.306, + S_D = 0.25, + a_y = 0.7, + a_l1 = 5.44, + a_r1 = 0.07, + a_b1 = 0.17, + r_b = 8024 / 608, + r_l = 39.27 / 0.1978791, + r_r = 217, + r_s = 4012/608, + a_f3 = 3.0*3.8e-5, + a_bio = 0.0245, + d_I = 0.01, + a_dG1 = 5.5, + a_dG2 = 20, + a_st1 = 0.10, + a_st2 = 0.10, + a_st3 = 0.8, + a_pl0 = 0.0, + a_pl1 = 0.0, + a_pl2 = 0.2, + a_pl3 = 0.05, + a_pl4 = 3.0, + a_p1 = 151.177775377968, + a_p2 = 0.204716166503633, + a_f1 = 1, + a_f2 = 50, + a_d0 = 0.1, + eta = 12, + hmat = 16.5958691, + k_b = 0.2, + k_l = 0.4565855, + k_r = 1, + k_s = 0.2, + lma = 0.1978791, + rho = 608, + omega = 3.8e-5, + theta = 1.0/4669, + k_I = 0.5, + vcmax_25 = 96, + stem_P50 = 1.85, + K_s = 1, + stem_c = log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16)), + stem_b = 1.85 /((-log(1 - 50.0 / 100.0))^(1 / (log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16))))), + psi_crit = (1.85 /((-log(1 - 50.0 / 100.0))^(1 / (log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16))))))*log(1/0.05)^(1/(log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16)))), + beta1 = 20000, + TF24_beta2 = 1.5, + TF24_cost_scale = 7.5, + TF24_floor_lambda_o = 0, + jmax_25 = 157.44, + a = 0.3, + curv_fact_elec_trans = 0.7, + curv_fact_colim = 0.99, + var_sapwood_volume_cost = 1, + nmass_l = 0.013, + nmass_s = 0.00198, + nmass_b = 0.0034, + nmass_r = 0.00335, + dmass_dN = 0, + root_depth_shape_eta = 0.2, + root_c = 2.680147, + root_b = 3.898245, + root_psi_crit = 3.898245 * log(1 / 0.05)^(1 / 2.680147), + rooting_depth_max = 1.5, + recruitment_decay = 0, + use_energy_balance = 0, + d = 0.05) +expected_top <- c("pars", "control", "collect_all_auxiliary", + "birth_rate_x", "birth_rate_y", "is_variable_birth_rate") +s <- TF24_Strategy() +expect_inherits(s, "TF24_Strategy") +expect_identical(sort(names(s)), sort(expected_top)) +expect_identical(s$control, Control()) +expect_identical(s$collect_all_auxiliary, FALSE) +expect_identical(s$birth_rate_x, numeric(0)) +expect_identical(s$birth_rate_y, c(1.0)) +expect_identical(s$is_variable_birth_rate, FALSE) +pars_keys <- sort(names(expected_pars)) +expect_identical(sort(names(s$pars)), pars_keys) diff --git a/tests/testthat/_problems/test-strategy-tf24-97.R b/tests/testthat/_problems/test-strategy-tf24-97.R new file mode 100644 index 000000000..ddb9afea1 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-97.R @@ -0,0 +1,6 @@ +# Extracted from test-strategy-tf24.R:97 + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy() +p <- TF24_Individual(s) +expect_equal(p$aux_size, 13) diff --git a/tests/testthat/_problems/test-strategy-tf24-98.R b/tests/testthat/_problems/test-strategy-tf24-98.R new file mode 100644 index 000000000..cb43f0142 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24-98.R @@ -0,0 +1,7 @@ +# Extracted from test-strategy-tf24.R:98 + +# test ------------------------------------------------------------------------- +s <- TF24_Strategy() +p <- TF24_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) diff --git a/tests/testthat/_problems/test-strategy-tf24f-116.R b/tests/testthat/_problems/test-strategy-tf24f-116.R new file mode 100644 index 000000000..db25e45f5 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-116.R @@ -0,0 +1,6 @@ +# Extracted from test-strategy-tf24f.R:116 + +# test ------------------------------------------------------------------------- +s <- TF24f_Strategy() +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 13) diff --git a/tests/testthat/_problems/test-strategy-tf24f-117.R b/tests/testthat/_problems/test-strategy-tf24f-117.R new file mode 100644 index 000000000..1e6990956 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-117.R @@ -0,0 +1,7 @@ +# Extracted from test-strategy-tf24f.R:117 + +# test ------------------------------------------------------------------------- +s <- TF24f_Strategy() +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) diff --git a/tests/testthat/_problems/test-strategy-tf24f-132.R b/tests/testthat/_problems/test-strategy-tf24f-132.R new file mode 100644 index 000000000..e4fac4133 --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-132.R @@ -0,0 +1,22 @@ +# Extracted from test-strategy-tf24f.R:132 + +# test ------------------------------------------------------------------------- +s <- TF24f_Strategy() +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) diff --git a/tests/testthat/_problems/test-strategy-tf24f-137.R b/tests/testthat/_problems/test-strategy-tf24f-137.R new file mode 100644 index 000000000..0c8b9b19c --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-137.R @@ -0,0 +1,26 @@ +# Extracted from test-strategy-tf24f.R:137 + +# test ------------------------------------------------------------------------- +s <- TF24f_Strategy() +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) +s <- TF24f_Strategy(collect_all_auxiliary=TRUE) +expect_true(s$collect_all_auxiliary) +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 14) diff --git a/tests/testthat/_problems/test-strategy-tf24f-138.R b/tests/testthat/_problems/test-strategy-tf24f-138.R new file mode 100644 index 000000000..0bfce65cc --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-138.R @@ -0,0 +1,27 @@ +# Extracted from test-strategy-tf24f.R:138 + +# test ------------------------------------------------------------------------- +s <- TF24f_Strategy() +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) +s <- TF24f_Strategy(collect_all_auxiliary=TRUE) +expect_true(s$collect_all_auxiliary) +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 14) +expect_equal(length(p$internals$auxs), 14) diff --git a/tests/testthat/_problems/test-strategy-tf24f-154.R b/tests/testthat/_problems/test-strategy-tf24f-154.R new file mode 100644 index 000000000..a75e9147a --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-154.R @@ -0,0 +1,43 @@ +# Extracted from test-strategy-tf24f.R:154 + +# test ------------------------------------------------------------------------- +s <- TF24f_Strategy() +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 13) +expect_equal(length(p$internals$auxs), 13) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return" + )) +s <- TF24f_Strategy(collect_all_auxiliary=TRUE) +expect_true(s$collect_all_auxiliary) +p <- TF24f_Individual(s) +expect_equal(p$aux_size, 14) +expect_equal(length(p$internals$auxs), 14) +expect_equal(p$aux_names, c( + "competition_effect", + "height_inverse", + "net_mass_production_dt", + "root_mass", + "opt_psi_stem", + "opt_root_psi", + "transpiration", + "E_up_", + "profit", + "shadow_cost", + "stom_cond_CO2", + "assimilation", + "leaf_marginal_return", + "area_sapwood" + )) diff --git a/tests/testthat/_problems/test-strategy-tf24f-326.R b/tests/testthat/_problems/test-strategy-tf24f-326.R new file mode 100644 index 000000000..95e59cffe --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-326.R @@ -0,0 +1,22 @@ +# Extracted from test-strategy-tf24f.R:326 + +# test ------------------------------------------------------------------------- +mk <- function(strat) { + p0 <- scm_base_parameters(strat) + p0$max_patch_lifetime <- 5 + add_strategies(p0, trait_matrix(c(0.0825, 5), c("lma", "hmat")), + hyperpar = get(paste0(strat, "_hyperpar")), birth_rate = list(20)) + } +set_k_acclim <- function(p, k) { + s <- p$strategies[[1]] + s$k_acclim <- k + p$strategies[[1]] <- s + p + } +expect_true("opt_root_psi_state" %in% TF24f_Individual()$ode_names) +pf <- mk("TF24f") +slow <- run_scm(set_k_acclim(pf, 0.1), Environment("TF24f"), Control())$offspring_production +fast <- run_scm(set_k_acclim(pf, 10), Environment("TF24f"), Control())$offspring_production +expect_length(fast, 1) +expect_true(is.finite(fast) && fast > 0) +expect_gt(abs(fast - slow) / slow, 0.05) diff --git a/tests/testthat/_problems/test-strategy-tf24f-92.R b/tests/testthat/_problems/test-strategy-tf24f-92.R new file mode 100644 index 000000000..3d4258bdb --- /dev/null +++ b/tests/testthat/_problems/test-strategy-tf24f-92.R @@ -0,0 +1,84 @@ +# Extracted from test-strategy-tf24f.R:92 + +# test ------------------------------------------------------------------------- +expected_pars <- list( + a_l2 = 0.306, + S_D = 0.25, + a_y = 0.7, + a_l1 = 5.44, + a_r1 = 0.07, + a_b1 = 0.17, + r_b = 8024 / 608, + r_l = 39.27 / 0.1978791, + r_r = 217, + r_s = 4012/608, + a_f3 = 3.0*3.8e-5, + a_bio = 0.0245, + d_I = 0.01, + a_dG1 = 5.5, + a_dG2 = 20, + a_st1 = 0.10, + a_st2 = 0.10, + a_st3 = 0.8, + a_pl0 = 0.0, + a_pl1 = 0.0, + a_pl2 = 0.2, + a_pl3 = 0.05, + a_pl4 = 3.0, + a_p1 = 151.177775377968, + a_p2 = 0.204716166503633, + a_f1 = 1, + a_f2 = 50, + a_d0 = 0.1, + eta = 12, + hmat = 16.5958691, + k_b = 0.2, + k_l = 0.4565855, + k_r = 1, + k_s = 0.2, + lma = 0.1978791, + rho = 608, + omega = 3.8e-5, + theta = 1.0/4669, + k_I = 0.5, + vcmax_25 = 96, + stem_P50 = 1.85, + K_s = 1, + stem_c = log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16)), + stem_b = 1.85 /((-log(1 - 50.0 / 100.0))^(1 / (log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16))))), + psi_crit = (1.85 /((-log(1 - 50.0 / 100.0))^(1 / (log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16))))))*log(1/0.05)^(1/(log(log(1-0.5)/log(1-0.88))/(log(1.85) - log(5.16)))), + beta1 = 20000, + TF24_beta2 = 1.5, + TF24_cost_scale = 7.5, + TF24_floor_lambda_o = 0, + jmax_25 = 157.44, + a = 0.3, + curv_fact_elec_trans = 0.7, + curv_fact_colim = 0.99, + var_sapwood_volume_cost = 1, + nmass_l = 0.013, + nmass_s = 0.00198, + nmass_b = 0.0034, + nmass_r = 0.00335, + dmass_dN = 0, + root_depth_shape_eta = 0.2, + root_c = 2.680147, + root_b = 3.898245, + root_psi_crit = 3.898245 * log(1 / 0.05)^(1 / 2.680147), + rooting_depth_max = 1.5, + recruitment_decay = 0, + use_energy_balance = 0, + d = 0.05) +expected_top <- c("pars", "control", "collect_all_auxiliary", + "birth_rate_x", "birth_rate_y", "is_variable_birth_rate", + "k_acclim", "psi_fd_step", "use_ad_gradient") +s <- TF24f_Strategy() +expect_inherits(s, "TF24f_Strategy") +expect_identical(sort(names(s)), sort(expected_top)) +expect_identical(s$control, Control()) +expect_identical(s$collect_all_auxiliary, FALSE) +expect_identical(s$birth_rate_x, numeric(0)) +expect_identical(s$birth_rate_y, c(1.0)) +expect_identical(s$is_variable_birth_rate, FALSE) +pars_keys <- sort(names(expected_pars)) +expect_identical(sort(names(s$pars)), pars_keys) diff --git a/tests/testthat/_snaps/model-version.md b/tests/testthat/_snaps/model-version.md index 59955fa43..41daeeb6f 100644 --- a/tests/testthat/_snaps/model-version.md +++ b/tests/testthat/_snaps/model-version.md @@ -6,10 +6,10 @@ "names": { "type": "character", "attributes": {}, - "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_in_birth_date", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.S_D", "pars.a_b1", "pars.a_bio", "pars.a_d0", "pars.a_dG1", "pars.a_dG2", "pars.a_f1", "pars.a_f2", "pars.a_f3", "pars.a_l1", "pars.a_l2", "pars.a_p1", "pars.a_p2", "pars.a_r1", "pars.a_y", "pars.d_I", "pars.eta", "pars.hmat", "pars.k_I", "pars.k_b", "pars.k_l", "pars.k_r", "pars.k_s", "pars.lma", "pars.omega", "pars.r_b", "pars.r_l", "pars.r_r", "pars.r_s", "pars.recruitment_decay", "pars.rho", "pars.theta"] + "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_coordinate", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.S_D", "pars.a_b1", "pars.a_bio", "pars.a_d0", "pars.a_dG1", "pars.a_dG2", "pars.a_f1", "pars.a_f2", "pars.a_f3", "pars.a_l1", "pars.a_l2", "pars.a_p1", "pars.a_p2", "pars.a_r1", "pars.a_y", "pars.d_I", "pars.eta", "pars.hmat", "pars.k_I", "pars.k_b", "pars.k_l", "pars.k_r", "pars.k_s", "pars.lma", "pars.omega", "pars.r_b", "pars.r_l", "pars.r_r", "pars.r_s", "pars.recruitment_decay", "pars.rho", "pars.theta"] } }, - "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "FALSE", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "FF16@v1", "0.25", "0.17000000000000001", "0.024500000000000001", "0.10000000000000001", "5.5", "20", "1", "50", "0.00011400000000000001", "5.4400000000000004", "0.30599999999999999", "151.177775377968", "0.204716166503633", "0.070000000000000007", "0.69999999999999996", "0.01", "12", "16.595869100000002", "0.5", "0.20000000000000001", "0.45658549999999998", "1", "0.20000000000000001", "0.1978791", "3.8000000000000002e-05", "13.197368421052632", "198.45451086041933", "217", "6.5986842105263159", "0", "608", "0.00021417862497322766"] + "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "auto", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "FF16@v1", "0.25", "0.17000000000000001", "0.024500000000000001", "0.10000000000000001", "5.5", "20", "1", "50", "0.00011400000000000001", "5.4400000000000004", "0.30599999999999999", "151.177775377968", "0.204716166503633", "0.070000000000000007", "0.69999999999999996", "0.01", "12", "16.595869100000002", "0.5", "0.20000000000000001", "0.45658549999999998", "1", "0.20000000000000001", "0.1978791", "3.8000000000000002e-05", "13.197368421052632", "198.45451086041933", "217", "6.5986842105263159", "0", "608", "0.00021417862497322766"] } # scientific surface of K93 matches its declared version @@ -20,10 +20,10 @@ "names": { "type": "character", "attributes": {}, - "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_in_birth_date", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.S_D", "pars.b_0", "pars.b_1", "pars.b_2", "pars.c_0", "pars.c_1", "pars.d_0", "pars.d_1", "pars.eta", "pars.height_0", "pars.k_I"] + "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_coordinate", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.S_D", "pars.b_0", "pars.b_1", "pars.b_2", "pars.c_0", "pars.c_1", "pars.d_0", "pars.d_1", "pars.eta", "pars.height_0", "pars.k_I"] } }, - "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "FALSE", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "K93@v1", "1", "0.058999999999999997", "0.012", "0.00040999999999999999", "0.0080000000000000002", "0.00044000000000000002", "0.00072999999999999996", "0.043999999999999997", "12", "2", "0.01"] + "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "auto", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "K93@v1", "1", "0.058999999999999997", "0.012", "0.00040999999999999999", "0.0080000000000000002", "0.00044000000000000002", "0.00072999999999999996", "0.043999999999999997", "12", "2", "0.01"] } # scientific surface of TF24 matches its declared version @@ -34,10 +34,10 @@ "names": { "type": "character", "attributes": {}, - "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_in_birth_date", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.D_c", "pars.K_s", "pars.L_tip", "pars.S_D", "pars.TF24_beta2", "pars.TF24_cost_scale", "pars.TF24_floor_lambda_o", "pars.a", "pars.a_b1", "pars.a_bio", "pars.a_d0", "pars.a_dG1", "pars.a_dG2", "pars.a_f1", "pars.a_f2", "pars.a_f3", "pars.a_l1", "pars.a_l2", "pars.a_p1", "pars.a_p2", "pars.a_r1", "pars.a_st1", "pars.a_st2", "pars.a_st3", "pars.a_y", "pars.beta1", "pars.curv_fact_colim", "pars.curv_fact_elec_trans", "pars.d", "pars.d_I", "pars.dmass_dN", "pars.eta", "pars.hmat", "pars.jmax_25", "pars.k_I", "pars.k_b", "pars.k_l", "pars.k_r", "pars.k_s", "pars.lma", "pars.nmass_b", "pars.nmass_l", "pars.nmass_r", "pars.nmass_s", "pars.omega", "pars.psi_crit", "pars.r_b", "pars.r_l", "pars.r_r", "pars.r_s", "pars.recruitment_decay", "pars.rho", "pars.root_b", "pars.root_c", "pars.root_depth_shape_eta", "pars.root_psi_crit", "pars.rooting_depth_max", "pars.stem_P50", "pars.stem_b", "pars.stem_c", "pars.theta", "pars.theta_c", "pars.use_energy_balance", "pars.var_sapwood_volume_cost", "pars.vcmax_25"] + "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_coordinate", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.D_c", "pars.K_s", "pars.L_tip", "pars.S_D", "pars.TF24_beta2", "pars.TF24_cost_scale", "pars.TF24_floor_lambda_o", "pars.a", "pars.a_b1", "pars.a_bio", "pars.a_d0", "pars.a_dG1", "pars.a_dG2", "pars.a_f1", "pars.a_f2", "pars.a_f3", "pars.a_l1", "pars.a_l2", "pars.a_p1", "pars.a_p2", "pars.a_pl0", "pars.a_pl1", "pars.a_pl2", "pars.a_pl3", "pars.a_pl4", "pars.a_r1", "pars.a_st1", "pars.a_st2", "pars.a_st3", "pars.a_sw", "pars.a_y", "pars.beta1", "pars.curv_fact_colim", "pars.curv_fact_elec_trans", "pars.d", "pars.d_I", "pars.dmass_dN", "pars.eta", "pars.hmat", "pars.jmax_25", "pars.k_I", "pars.k_b", "pars.k_l", "pars.k_r", "pars.k_s", "pars.lma", "pars.nmass_b", "pars.nmass_l", "pars.nmass_r", "pars.nmass_s", "pars.omega", "pars.psi_crit", "pars.r_b", "pars.r_l", "pars.r_r", "pars.r_s", "pars.recruitment_decay", "pars.rho", "pars.root_b", "pars.root_c", "pars.root_depth_shape_eta", "pars.root_psi_crit", "pars.rooting_depth_max", "pars.stem_P50", "pars.stem_b", "pars.stem_c", "pars.theta", "pars.theta_c", "pars.use_energy_balance", "pars.var_sapwood_volume_cost", "pars.vcmax_25"] } }, - "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "FALSE", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "TF24@v10", "0.20000000000000001", "0.33577377016801868", "0.02", "0.25", "1.5", "7.5", "0", "0.29999999999999999", "0.17000000000000001", "0.024500000000000001", "0.10000000000000001", "5.5", "20", "1", "50", "0.00011400000000000001", "5.4400000000000004", "0.30599999999999999", "151.177775377968", "0.204716166503633", "0.070000000000000007", "0.10000000000000001", "0.10000000000000001", "0.80000000000000004", "0.69999999999999996", "20000", "0.98999999999999999", "0.69999999999999996", "0.050000000000000003", "0.01", "0", "12", "16.595869100000002", "157.44", "0.5", "0.20000000000000001", "0.45658549999999998", "1", "0.20000000000000001", "0.1978791", "0.0033999999999999998", "0.012999999999999999", "0.0033500000000000001", "0.00198", "3.8000000000000002e-05", "7.0854928681315172", "13.197368421052632", "198.45451086041933", "217", "6.5986842105263159", "0", "608", "3.8982450000000002", "2.6801469999999998", "0.20000000000000001", "5.8702825428827037", "1.5", "1.8500000000000001", "2.5894373183081751", "1.0899851679673995", "0.00021417862497322766", "0", "0", "1", "96"] + "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "auto", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "TF24@v11", "0.20000000000000001", "0.33577377016801868", "0.02", "0.25", "1.5", "7.5", "0", "0.29999999999999999", "0.17000000000000001", "0.024500000000000001", "0.10000000000000001", "5.5", "20", "1", "50", "0.00011400000000000001", "5.4400000000000004", "0.30599999999999999", "151.177775377968", "0.204716166503633", "0", "0", "0.20000000000000001", "0.050000000000000003", "3", "0.070000000000000007", "0.10000000000000001", "0.10000000000000001", "0.80000000000000004", "0", "0.69999999999999996", "20000", "0.98999999999999999", "0.69999999999999996", "0.050000000000000003", "0.01", "0", "12", "16.595869100000002", "157.44", "0.5", "0.20000000000000001", "0.45658549999999998", "1", "0.20000000000000001", "0.1978791", "0.0033999999999999998", "0.012999999999999999", "0.0033500000000000001", "0.00198", "3.8000000000000002e-05", "7.0854928681315172", "13.197368421052632", "198.45451086041933", "217", "6.5986842105263159", "0", "608", "3.8982450000000002", "2.6801469999999998", "0.20000000000000001", "5.8702825428827037", "1.5", "1.8500000000000001", "2.5894373183081751", "1.0899851679673995", "0.00021417862497322766", "0", "0", "1", "96"] } # scientific surface of TF24f matches its declared version @@ -48,9 +48,9 @@ "names": { "type": "character", "attributes": {}, - "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_in_birth_date", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.D_c", "pars.K_s", "pars.L_tip", "pars.S_D", "pars.TF24_beta2", "pars.TF24_cost_scale", "pars.TF24_floor_lambda_o", "pars.a", "pars.a_b1", "pars.a_bio", "pars.a_d0", "pars.a_dG1", "pars.a_dG2", "pars.a_f1", "pars.a_f2", "pars.a_f3", "pars.a_l1", "pars.a_l2", "pars.a_p1", "pars.a_p2", "pars.a_r1", "pars.a_st1", "pars.a_st2", "pars.a_st3", "pars.a_y", "pars.beta1", "pars.curv_fact_colim", "pars.curv_fact_elec_trans", "pars.d", "pars.d_I", "pars.dmass_dN", "pars.eta", "pars.hmat", "pars.jmax_25", "pars.k_I", "pars.k_b", "pars.k_l", "pars.k_r", "pars.k_s", "pars.lma", "pars.nmass_b", "pars.nmass_l", "pars.nmass_r", "pars.nmass_s", "pars.omega", "pars.psi_crit", "pars.r_b", "pars.r_l", "pars.r_r", "pars.r_s", "pars.recruitment_decay", "pars.rho", "pars.root_b", "pars.root_c", "pars.root_depth_shape_eta", "pars.root_psi_crit", "pars.rooting_depth_max", "pars.stem_P50", "pars.stem_b", "pars.stem_c", "pars.theta", "pars.theta_c", "pars.use_energy_balance", "pars.var_sapwood_volume_cost", "pars.vcmax_25"] + "value": ["birth_rate_x", "birth_rate_y", "control.GSS_tol_abs", "control.ci_abs_tol", "control.ci_niter", "control.fixed_time_step", "control.function_integration_rule", "control.node_density_coordinate", "control.node_gradient_direction", "control.node_gradient_eps", "control.node_gradient_richardson", "control.node_gradient_richardson_depth", "control.ode_a_dydt", "control.ode_a_y", "control.ode_step_size_initial", "control.ode_step_size_max", "control.ode_step_size_min", "control.ode_tol_abs", "control.ode_tol_rel", "control.offspring_production_iterations", "control.offspring_production_tol", "control.ppa_layer_optical_depth", "control.ppa_layer_smoothing", "control.save_RK45_cache", "control.schedule_eps", "control.schedule_nsteps", "control.schedule_verbose", "control.shading_model", "control.vulnerability_curve_ncontrol", "is_variable_birth_rate", "model_id", "pars.D_c", "pars.K_s", "pars.L_tip", "pars.S_D", "pars.TF24_beta2", "pars.TF24_cost_scale", "pars.TF24_floor_lambda_o", "pars.a", "pars.a_b1", "pars.a_bio", "pars.a_d0", "pars.a_dG1", "pars.a_dG2", "pars.a_f1", "pars.a_f2", "pars.a_f3", "pars.a_l1", "pars.a_l2", "pars.a_p1", "pars.a_p2", "pars.a_pl0", "pars.a_pl1", "pars.a_pl2", "pars.a_pl3", "pars.a_pl4", "pars.a_r1", "pars.a_st1", "pars.a_st2", "pars.a_st3", "pars.a_sw", "pars.a_y", "pars.beta1", "pars.curv_fact_colim", "pars.curv_fact_elec_trans", "pars.d", "pars.d_I", "pars.dmass_dN", "pars.eta", "pars.hmat", "pars.jmax_25", "pars.k_I", "pars.k_b", "pars.k_l", "pars.k_r", "pars.k_s", "pars.lma", "pars.nmass_b", "pars.nmass_l", "pars.nmass_r", "pars.nmass_s", "pars.omega", "pars.psi_crit", "pars.r_b", "pars.r_l", "pars.r_r", "pars.r_s", "pars.recruitment_decay", "pars.rho", "pars.root_b", "pars.root_c", "pars.root_depth_shape_eta", "pars.root_psi_crit", "pars.rooting_depth_max", "pars.stem_P50", "pars.stem_b", "pars.stem_c", "pars.theta", "pars.theta_c", "pars.use_energy_balance", "pars.var_sapwood_volume_cost", "pars.vcmax_25"] } }, - "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "FALSE", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "TF24f@v10.1", "0.20000000000000001", "0.33577377016801868", "0.02", "0.25", "1.5", "7.5", "0", "0.29999999999999999", "0.17000000000000001", "0.024500000000000001", "0.10000000000000001", "5.5", "20", "1", "50", "0.00011400000000000001", "5.4400000000000004", "0.30599999999999999", "151.177775377968", "0.204716166503633", "0.070000000000000007", "0.10000000000000001", "0.10000000000000001", "0.80000000000000004", "0.69999999999999996", "20000", "0.98999999999999999", "0.69999999999999996", "0.050000000000000003", "0.01", "0", "12", "16.595869100000002", "157.44", "0.5", "0.20000000000000001", "0.45658549999999998", "1", "0.20000000000000001", "0.1978791", "0.0033999999999999998", "0.012999999999999999", "0.0033500000000000001", "0.00198", "3.8000000000000002e-05", "7.0854928681315172", "13.197368421052632", "198.45451086041933", "217", "6.5986842105263159", "0", "608", "3.8982450000000002", "2.6801469999999998", "0.20000000000000001", "5.8702825428827037", "1.5", "1.8500000000000001", "2.5894373183081751", "1.0899851679673995", "0.00021417862497322766", "0", "0", "1", "96"] + "value": ["", "1", "0.001", "0.001", "1000", "0", "21", "auto", "-1", "9.9999999999999995e-07", "FALSE", "4", "0", "1", "9.9999999999999995e-07", "5", "9.9999999999999995e-07", "0.0001", "0.0001", "1000", "1e-08", "0.5", "0.29999999999999999", "FALSE", "0.02", "20", "FALSE", "", "100", "FALSE", "TF24f@v11.1", "0.20000000000000001", "0.33577377016801868", "0.02", "0.25", "1.5", "7.5", "0", "0.29999999999999999", "0.17000000000000001", "0.024500000000000001", "0.10000000000000001", "5.5", "20", "1", "50", "0.00011400000000000001", "5.4400000000000004", "0.30599999999999999", "151.177775377968", "0.204716166503633", "0", "0", "0.20000000000000001", "0.050000000000000003", "3", "0.070000000000000007", "0.10000000000000001", "0.10000000000000001", "0.80000000000000004", "0", "0.69999999999999996", "20000", "0.98999999999999999", "0.69999999999999996", "0.050000000000000003", "0.01", "0", "12", "16.595869100000002", "157.44", "0.5", "0.20000000000000001", "0.45658549999999998", "1", "0.20000000000000001", "0.1978791", "0.0033999999999999998", "0.012999999999999999", "0.0033500000000000001", "0.00198", "3.8000000000000002e-05", "7.0854928681315172", "13.197368421052632", "198.45451086041933", "217", "6.5986842105263159", "0", "608", "3.8982450000000002", "2.6801469999999998", "0.20000000000000001", "5.8702825428827037", "1.5", "1.8500000000000001", "2.5894373183081751", "1.0899851679673995", "0.00021417862497322766", "0", "0", "1", "96"] } diff --git a/tests/testthat/test-allometry-demo.R b/tests/testthat/test-allometry-demo.R new file mode 100644 index 000000000..e4967d78d --- /dev/null +++ b/tests/testthat/test-allometry-demo.R @@ -0,0 +1,357 @@ +# Guards the numbers TF24_flexible_allometry_demo.qmd asserts in prose, and +# checks that its "The mathematics" appendix IS the model. +# +# The demo's chunks all run, but a chunk that runs is not a chunk that is +# checked: prose beside a number survives the number being falsified. Two claims +# in earlier drafts did exactly that -- a Huber-value rise quoted from a shorter +# drought than the one plotted, and a caption promising arrows that were never +# drawn -- and both rendered clean. + +demo_helpers <- test_path("..", "..", "overstorey_staging", + "allometry_demo_helpers.R") + +test_that("the flexible-allometry demo's claims still hold", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + history <- demo_soil_history(wet = 0.30, dry = 0.11, + years_wet = 2, years_dry = 4) + fixed <- allometry_trajectory(0.0, history, dt = 0.25) + flex <- allometry_trajectory(1.0, history, dt = 0.25) + + ## Tolerances are loose because these are integrated trajectories, not closed + ## forms; what is guarded is the claim, not the digits. + + ## The canopy thins substantially, and the fixed plant does not move at all. + expect_lt(min(flex$canopy_fraction), 0.4) + expect_equal(max(abs(fixed$canopy_fraction - 1)), 0, tolerance = 1e-8) + + ## Stem per leaf rises, and psi >= 0 is invariant so it never drops below 1. + expect_gt(max(flex$huber_ratio), 1.5) + expect_gte(min(flex$huber_ratio), 1 - 1e-8) + + ## The canopy floor holds: thinning stops at a_pl3 of the preferred canopy, + ## which is what keeps leaf area in a range where the arithmetic means + ## something. + expect_gte(min(flex$canopy_fraction), TF24_Strategy()$pars$a_pl3 - 1e-8) + + ## It rebuilds afterwards. + expect_gt(tail(flex$canopy_fraction, 1), 0.8) + + ## Height never falls, in either model. + expect_true(all(diff(flex$height) >= -1e-10)) + expect_true(all(diff(fixed$height) >= -1e-10)) + + ## THE ISSUE THE DEMO EXISTS TO FLAG: thinning buys almost no survival, and + ## costs height. If either moves materially the demo's conclusion has changed + ## and its prose needs rewriting -- which is the point of asserting them. + expect_lt(max(flex$survivorship / fixed$survivorship), 1.10) + expect_gt(tail(fixed$height, 1) - tail(flex$height, 1), 1.0) +}) + +test_that("the gate responds to soil water, not to the reserve pool", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + gate <- allometry_gate_map(a_pl0 = 1.0, height = 5, + theta = c(0.10, 0.13, 0.15, 0.20, 0.30)) + + ## Reserves are held at a_st3 of capacity across the whole sweep, so a + ## reserve-gated version could not respond anywhere on this axis. + wet <- gate[gate$theta_soil >= 0.20, ] + dry <- gate[gate$theta_soil <= 0.13, ] + + expect_true(all(wet$margin > 0)) # leaves pay for themselves + expect_true(all(dry$margin < 0)) # they do not + expect_true(all(abs(wet$dphi) < 1e-9)) # so no thinning when wet + expect_true(all(dry$dphi < -0.1)) # and thinning when dry + expect_true(all(dry$dpsi > 0)) # stem per leaf rises + expect_true(all(gate$dheight >= 0)) # height never falls +}) + +test_that("suppressed plants in a wet stand thin; dominants do not", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + thin <- allometry_self_thinning(a_pl0 = 1.0, mpl = 15) + d <- thin$cohorts[thin$cohorts$time == max(thin$cohorts$time), ] + d <- d[order(-d$height), ] + + ## Shade is as much the point as drought, and nothing in the model knows about + ## canopy position: the light gradient does all of it. + expect_equal(d$canopy_fraction[[1]], 1, tolerance = 1e-6) # the dominant + expect_lt(min(d$canopy_fraction), 0.9) # someone thinned + + ## The floor holds here too -- this is the case where, without it, a + ## suppressed cohort reached canopy 0.000 with stem-per-leaf 1.3e9. + expect_gte(min(d$canopy_fraction), TF24_Strategy()$pars$a_pl3 - 1e-8) + expect_true(all(is.finite(d$huber_ratio))) + expect_lt(max(d$huber_ratio), 1e3) +}) + +# An independent R implementation of the equations written out in the demo's +# "The mathematics" appendix, checked against what the C++ actually computes. +# +# Written from the prose rather than from the source, so a divergence between +# the two shows up here. Constants not exposed to R are repeated with the member +# they mirror named: if one changes this fails, which is the intent. +tf24_departure_rates_r <- function(s, height, phi, psi, tracked, P, A) { + p <- s$pars + storage_gate_width <- 0.1 # TF24_Strategy::storage_gate_width + storage_prod_eps <- 1e-4 # TF24_Strategy::storage_prod_eps + plasticity_gate_width <- 0.02 # TF24_Strategy::plasticity_gate_width + eta_c <- 1 - 2 / (1 + p$eta) + 1 / (1 + 2 * p$eta) # CanopyShape::eta_c + + ## The gate reads the TRACKED marginal balance, and its effect tapers to + ## nothing at the canopy floor. + rho_carbon <- 1 - p$a_pl0 / (1 + exp((tracked - p$a_pl1) / plasticity_gate_width)) + shed_gate <- 1 - exp((log(p$a_pl3) - phi) / p$a_pl2) + rho_l <- 1 - (1 - rho_carbon) * shed_gate + rho_s <- rho_l * exp(-psi / p$a_pl2) + u_l <- 1 - rho_l + u_s <- 1 - rho_s + + ## Reserves still gate growth, as they did before. + A_s <- p$theta * A * exp(psi) + S_max <- p$a_st1 * A_s * height * eta_c * p$rho + ## (r is supplied by the caller through P's own individual; recomputed here + ## only for the growth gate.) + list(rho_l = rho_l, u_l = u_l, u_s = u_s, S_max = S_max, + finish = function(r) { + G <- 1 / (1 + exp(-(r - p$a_st2) / storage_gate_width)) + Ppos <- 0.5 * (P + sqrt(P^2 + storage_prod_eps^2)) + F <- Ppos * G + f_g <- 1 - p$a_f1 / (1 + exp(p$a_f2 * (1 - height / p$hmat))) + sigma <- rho_l * (1 - exp(phi / p$a_pl2)) + c_reb <- p$lma + p$a_r1 + + p$theta * height * eta_c * p$rho * (1 + p$a_b1) + b <- sigma * F * f_g / (c_reb * A) + list(dphi = b - u_l * p$k_l, + dpsi = u_l * p$k_l - u_s * p$k_s + b * (exp(-psi) - 1)) + }) +} + +test_that("the demo's equations reproduce the C++ departure rates", { + skip_on_cran() + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_fixed_environment(1.0, 40) + + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_pl0 <- 1.0 + + grid <- expand.grid(height = c(1, 5, 15), + phi = c(0, -0.4, -1.5), + psi = c(0, 0.3, 1.2), + theta_soil = c(0.11, 0.15, 0.30)) + + for (i in seq_len(nrow(grid))) { + g <- grid[i, ] + env$set_soil_water_state(rep(g$theta_soil, 5)) + ind <- TF24_Individual(s) + ind$set_state("height", g$height) + ind$set_state("log_area_leaf_departure", g$phi) + ind$set_state("log_area_sapwood_departure", g$psi) + ind$set_initial_states(env) + ind$compute_rates(env) + + parts <- tf24_departure_rates_r( + s, g$height, g$phi, g$psi, + tracked = ind$state("leaf_marginal_return_tracked"), + P = ind$aux("net_mass_production_dt"), + A = ind$aux("competition_effect")) + want <- parts$finish(ind$state("storage") / parts$S_max) + + label <- sprintf("h=%g phi=%g psi=%g soil=%g", + g$height, g$phi, g$psi, g$theta_soil) + expect_equal(ind$rate("log_area_leaf_departure"), want$dphi, + tolerance = 1e-10, info = label) + expect_equal(ind$rate("log_area_sapwood_departure"), want$dpsi, + tolerance = 1e-10, info = label) + } +}) + +test_that("the shedding criterion's carbon decomposition is exact", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + ## P = c*abar*A - g(h)*A - s(h,A_s). This is the model's own budget + ## rearranged, not an approximation of it, and the demo's criterion is + ## nothing but its derivative -- so if this stops holding exactly, the whole + ## analytical section is void rather than merely imprecise. + for (h in c(5, 10, 15, 20)) { + z <- allometry_carbon_terms(h, theta_soil = 0.20) + expect_equal(z$gain - z$g - z$s, z$P, tolerance = 1e-10, + info = sprintf("height %g", h)) + } +}) + +test_that("the elasticity rises with height, and the criterion tracks dP/dA", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + z <- lapply(c(5, 10, 15, 20), allometry_carbon_terms, theta_soil = 0.20) + eta <- vapply(z, `[[`, numeric(1), "eta") + kappa <- vapply(z, `[[`, numeric(1), "kappa") + dPdA <- vapply(z, `[[`, numeric(1), "dPdA") + + ## kmax ~ 1/h, so a taller plant is more supply-limited and relieving that + ## limitation is worth more. This is what closes the gap in which tall plants + ## died without ever shedding. + expect_true(all(diff(eta) > 0)) + expect_true(all(diff(kappa) > 0)) + + ## Somewhere above mid-height the elasticity passes 1, and beyond that leaf + ## area is actively counterproductive: removing leaves raises TOTAL + ## assimilation. Where the crossing sits is set by the height-resistance + ## relation, so it moved when #617 replaced that with a path integral (eta at + ## 15 m went from above 1 to 1.03, and it is 1.40 at 20 m). The crossing + ## EXISTING is the claim; its location is the hydraulics' to set. + expect_lt(eta[[1]], 1) # short plants: supply is not binding + expect_gt(eta[[length(eta)]], 1) # tall ones: it is + + ## The criterion and the measured derivative agree in sign. (Not independent + ## -- eta is recovered through the decomposition, because the profit auxes + ## cannot difference abar reliably -- but it does guard the arithmetic.) + expect_equal(eta > 1 - kappa, dPdA < 0) + + ## A short 5 m plant in moist soil should not shed; a tall one should. + expect_gt(dPdA[[1]], 0) + expect_lt(dPdA[[4]], 0) +}) + +test_that("shedding is measured at fixed sapwood, which is what thinning does", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + ## Letting sapwood follow leaf area down the pipe model measures movement + ## ALONG the allometry, not thinning, and gets the sign wrong where it + ## matters. allometry_carbon_terms() holds A_s fixed and asserts it does; this + ## checks the assertion is load-bearing by confirming the two differ. + z <- allometry_carbon_terms(15, theta_soil = 0.20) + expect_lt(z$dPdA, 0) # at fixed sapwood: shedding helps + + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + along <- function(phi) { + e <- tf24_demo_env(0.20) + i <- TF24_Individual(s) + i$set_state("height", 15) + i$set_state("log_area_leaf_departure", phi) # psi left at 0: A_s follows A + i$set_initial_states(e); i$compute_rates(e) + c(A = i$aux("competition_effect"), P = i$aux("net_mass_production_dt")) + } + a <- along(0); b <- along(-0.02) + expect_gt((b[["P"]] - a[["P"]]) / (b[["A"]] - a[["A"]]), 0) # opposite sign +}) + +test_that("the demo's sapwood-controller claims hold", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + ## Guards the numbers the demo states in prose. A chunk that runs is not a + ## chunk that is checked, and the claim here -- that the controller's zero + ## sits on the growth peak -- is the one the whole derivation exists to make. + ctl <- lapply(c(0.30, 0.20, 0.15), allometry_sapwood_controller) + names(ctl) <- c("wet", "moist", "dry") + + ## ⚠️ THE ZERO IS FOUND BY SIGN CHANGE, not by min|R_s|. R_s has a SECOND zero + ## at the thin-stem end, where supply collapses, production goes negative and + ## the availability factor switches the controller off. That one is spurious + ## for this purpose and it is also repelling (R_s jumps to +0.25 immediately + ## above it), so a plant never rests there -- but min|R_s| finds it whenever + ## the grid reaches far enough down, and reports the controller as broken. + crossing <- function(d) { + sg <- sign(d$R_s) + i <- which(sg[-length(sg)] > 0 & sg[-1] <= 0) + d$huber_ratio[i[length(i)]] + } + for (nm in names(ctl)) { + d <- ctl[[nm]] + expect_equal(crossing(d), d$huber_ratio[which.max(d$dheight)], + tolerance = 0.02) + } + + ## The optimum moves with soil water: a drier plant wants MORE stem per leaf. + ## Levels are not pinned -- they are the hydraulics' to set, and #617 moved + ## them all -- but the ordering is the model's own claim. + peak <- vapply(ctl, function(d) d$huber_ratio[which.max(d$dheight)], numeric(1)) + expect_lt(peak[["wet"]], peak[["moist"]]) + expect_lt(peak[["moist"]], peak[["dry"]]) + + ## The wart the demo admits to: where the plant cannot grow at all, the + ## controller is switched off rather than pointing uphill. After #617 a 10 m + ## plant is solvent at soil 0.15, so this needs soil 0.12 to show -- which is + ## itself the point, the band moved with the hydraulics. + starved <- allometry_sapwood_controller(0.12) + expect_true(all(starved$dheight < 1e-6)) + expect_true(all(abs(starved$R_s) < 1e-8)) +}) + +test_that("the demo's 'does not buy survival' claims still hold", { + skip_if_not(file.exists(demo_helpers), "demo helpers not present") + skip_on_cran() + source(demo_helpers, local = TRUE) + + ## This section rotted once already: it carried pre-#617 numbers describing a + ## tall-plant cliff that no longer existed, and rendered clean the whole time + ## because its tables are prose rather than chunks. These guard the claims. + g <- allometry_drought_grid() + + ## 1. THE ORDERING, which is the section's decisive argument. At soil 0.145 + ## every plant is healthy and none thins; by 0.140 a 10 m plant is at one + ## in a million and its canopy STILL has not moved. Mortality saturates at + ## a milder drought than shedding begins at. + mild <- g[g$theta_dry == 0.145, ] + expect_true(all(mild$min_canopy > 0.99)) + expect_true(all(abs(mild$gain - 1) < 0.01)) + + mid10 <- g[g$theta_dry == 0.140 & g$height == 10, ] + expect_equal(mid10$min_canopy, 1, tolerance = 1e-3) # has not thinned + expect_lt(mid10$S_fixed, 1e-5) # and is already dead + + ## 2. NO RESCUE. The large ratios sit between two very small numbers, so the + ## ratio alone must never be quoted as a survival benefit. + expect_gt(max(g$gain), 5) # ratios do get large + rescued <- g$S_fixed < 0.05 & g$S_shed > 0.2 + expect_false(any(rescued)) + + ## 2b. The trajectory the section quotes: shedding ends BELOW parity, and the + ## height cost is about four metres. Measured on demo_soil_history's own + ## arguments -- quoting a number from a nearby-but-different run is how the + ## Huber-value claim went wrong in an earlier draft. + hist <- demo_soil_history(wet = 0.30, dry = 0.11, years_wet = 2, years_dry = 4) + tf <- allometry_trajectory(0.0, hist, dt = 0.25) + tx <- allometry_trajectory(1.0, hist, dt = 0.25) + ratio <- tail(tx$survivorship, 1) / tail(tf$survivorship, 1) + expect_lt(ratio, 1) # no gain; slightly worse + expect_gt(ratio, 0.9) + drop <- tail(tf$height, 1) - tail(tx$height, 1) + expect_gt(drop, 3); expect_lt(drop, 5) # ~4 m shorter + expect_lt(min(tx$canopy_fraction), 0.25) # it really does thin + + ## 3. Thinning improves the per-leaf carbon balance but cannot close it -- + ## the argument that REPLACED "thinning cuts income just as fast" when the + ## stem path integral landed. An interior optimum, and still negative. + per_area <- vapply(c(0, -0.7, -1.6, -2.3, -3.0, -4.0), function(k) { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + ind <- TF24_Individual(s) + ind$set_state("height", 10) + ind$set_state("log_area_leaf_departure", k) + ind$set_state("log_area_sapwood_departure", -k * 0.35) + env <- tf24_demo_env(0.13) + ind$set_initial_states(env) + ind$compute_rates(env) + ind$aux("net_mass_production_dt") / ind$aux("competition_effect") + }, numeric(1)) + expect_true(all(per_area < 0)) # never reaches balance + expect_gt(per_area[[4]], per_area[[1]]) # but thinning helps + expect_gt(which.max(per_area), 1) # interior optimum + expect_lt(which.max(per_area), length(per_area)) +}) diff --git a/tests/testthat/test-control.R b/tests/testthat/test-control.R index f9f4caa6d..e5233b464 100644 --- a/tests/testthat/test-control.R +++ b/tests/testthat/test-control.R @@ -5,7 +5,7 @@ test_that("Defaults", { node_gradient_direction = -1L, node_gradient_richardson = FALSE, node_gradient_richardson_depth = 4, # size_t, so not int - node_density_in_birth_date = FALSE, + node_density_coordinate = "auto", ode_a_dydt = 0.0, ode_a_y = 1.0, diff --git a/tests/testthat/test-density-coordinate.R b/tests/testthat/test-density-coordinate.R index 0e75bec06..dafb3d6e2 100644 --- a/tests/testthat/test-density-coordinate.R +++ b/tests/testthat/test-density-coordinate.R @@ -1,5 +1,5 @@ # Carrying the SCM's size distribution in birth date rather than in height -# (Control$node_density_in_birth_date). +# (Control$node_density_coordinate). # # The two coordinates describe the same population, so for a strategy whose # growth is a function of size alone they must agree in the limit of a fine @@ -39,7 +39,7 @@ size_only_parameters <- function(x) { offspring_in_coordinate <- function(p, x, birth_date, step_max = NULL) { ctrl <- Control() - ctrl$node_density_in_birth_date <- birth_date + ctrl$node_density_coordinate <- if (birth_date) "birth_date" else "height" if (!is.null(step_max)) { ctrl$ode_step_size_max <- step_max } @@ -63,7 +63,7 @@ short_run <- local({ add_strategies(p0, trait_matrix(0.059, "b_0"), birth_rate = 1.0) } ctrl <- Control() - ctrl$node_density_in_birth_date <- birth_date + ctrl$node_density_coordinate <- if (birth_date) "birth_date" else "height" scm <- SCM(x, environment_type(x))(p, Environment(x), empty_events(), ctrl) scm$collect <- TRUE scm$run() @@ -183,7 +183,7 @@ test_that("the birth-date quadrature grid is strictly increasing", { test_that("a repeated birth date drops a node out of the competition integral", { build <- function(birth_date, times) { ctrl <- Control() - ctrl$node_density_in_birth_date <- birth_date + ctrl$node_density_coordinate <- if (birth_date) "birth_date" else "height" st <- FF16_Strategy() st$control <- ctrl s <- Species("FF16", "FF16_Env")(st) @@ -286,7 +286,7 @@ test_that("the boundary node's birth date tracks patch time", { for (x in c("FF16", "K93")) { p <- size_only_parameters(x) ctrl <- Control() - ctrl$node_density_in_birth_date <- TRUE + ctrl$node_density_coordinate <- "birth_date" patch <- Patch(x, environment_type(x))(p, Environment(x), ctrl) for (t in c(0.0, 1.5, 7.25)) { @@ -312,7 +312,7 @@ test_that("nodes sharing a birth date are rejected in birth-date coordinates", { ## A faithful resume carries per-node times, so both coordinates accept it. p_ok <- set_initial_state(p, state) ctrl_bd <- Control() - ctrl_bd$node_density_in_birth_date <- TRUE + ctrl_bd$node_density_coordinate <- "birth_date" expect_no_error(Patch(x, e)(p_ok, Environment(x), ctrl_bd)) ## Drop them and every node inherits the boundary node's birth date. @@ -336,7 +336,7 @@ test_that("nodes sharing a birth date are rejected in birth-date coordinates", { test_that("the patch control decides the coordinate for every species", { x <- "FF16"; e <- "FF16_Env" ctrl_bd <- Control() - ctrl_bd$node_density_in_birth_date <- TRUE + ctrl_bd$node_density_coordinate <- "birth_date" p0 <- scm_base_parameters(x) p <- add_strategies(p0, trait_matrix(c(0.08, 0.2), "lma"), @@ -376,7 +376,7 @@ log_density_gap <- function(refine) { } one <- function(birth_date) { ctrl <- Control() - ctrl$node_density_in_birth_date <- birth_date + ctrl$node_density_coordinate <- if (birth_date) "birth_date" else "height" scm <- SCM("FF16", "FF16_Env")(interleave_schedule(p_of(), refine), Environment("FF16"), empty_events(), ctrl) scm$run() @@ -500,7 +500,7 @@ test_that("the collected state carries both densities", { test_that("resume reads the raw state, so it is unaffected by the conversion", { x <- "FF16"; e <- "FF16_Env" ctrl <- Control() - ctrl$node_density_in_birth_date <- TRUE + ctrl$node_density_coordinate <- "birth_date" scm <- collected_run(TRUE) state <- export_patch_state(scm, step = max(2L, length(scm$history) %/% 2L)) @@ -684,3 +684,68 @@ test_that("a competitively excluded species is no worse off", { ## And its relative error is of the same order as the rest. expect_lt(rel[[1]], 3 * max(rel[-1])) }) + +## The coordinate is a per-model default, not a global one ------------------ +## +## The height coordinate's compression term is only the transport equation's +## compression when growth is a function of size alone, so it is not a free +## numerical choice: TF24 carries reserves that feed back into growth and needs +## the birth-date coordinate, while FF16 and K93 do not and keep the coordinate +## they were calibrated in. Control therefore defaults to "auto" and each model +## resolves it. These guard the resolution itself, which no convergence test +## above can see -- they all set the coordinate explicitly. + +test_that("Control leaves the coordinate to the model by default", { + expect_identical(Control()$node_density_coordinate, "auto") +}) + +test_that("auto resolves to the coordinate each model requires", { + resolved <- function(x, ctrl = Control()) { + ## K93 is parameterised on b_0, not lma, and an unknown trait name is now + ## refused (#637), so each model gets a trait it actually has. + p <- scm_base_parameters(x) + p$max_patch_lifetime <- 5 + p <- if (x == "K93") { + add_strategies(p, trait_matrix(0.059, "b_0"), birth_rate = list(20)) + } else { + add_strategies(p, trait_matrix(0.0825, "lma"), + hyperpar = hyperpar(x), birth_rate = list(20)) + } + run_scm(p, Environment(x), ctrl)$patch$species[[1]]$density_in_birth_date + } + + ## TF24's two coordinates disagree by several times, so this is the whole + ## point of the default rather than a preference. + expect_true(resolved("TF24")) + ## FF16's agree to ~5e-5 and K93's to ~5.6e-7, and both are calibrated in + ## height, so they must not move. + expect_false(resolved("FF16")) + expect_false(resolved("K93")) + + ## An explicit setting is an override and beats the model's own requirement, + ## which is what keeps both arms of the comparisons above reachable. + expect_false(resolved("TF24", Control(node_density_coordinate = "height"))) + expect_true(resolved("FF16", Control(node_density_coordinate = "birth_date"))) +}) + +test_that("an unrecognised coordinate is refused rather than guessed", { + p <- scm_base_parameters("FF16") + p$max_patch_lifetime <- 5 + p <- add_strategies(p, trait_matrix(0.0825, "lma"), birth_rate = list(20)) + + ## The two coordinates do not agree for a model with carried state, so a typo + ## silently read as one of them would come back as a plausible number rather + ## than an error. Each near miss must name what was expected. + for (bad in c("birthdate", "birth date", "Height", "birth_dates", "auto ")) { + expect_error(run_scm(p, Environment("FF16"), + Control(node_density_coordinate = bad)), + "Unknown node_density_coordinate") + } + + ## The empty string is the one non-"auto" value that is accepted, because it + ## is how Control already spells "let the model decide" for shading_model. + ## Asserted so the two conventions cannot drift apart silently. + expect_false(run_scm(p, Environment("FF16"), + Control(node_density_coordinate = ""))$ + patch$species[[1]]$density_in_birth_date) +}) diff --git a/tests/testthat/test-individual.R b/tests/testthat/test-individual.R index c8f74d97e..6dec42261 100644 --- a/tests/testthat/test-individual.R +++ b/tests/testthat/test-individual.R @@ -87,8 +87,14 @@ for (x in names(strategy_types)) { if(grepl("K93", x)) expect_equal(pl$ode_state, c(h0, m0, f0)) else if(grepl("TF24", x)) - # TF24 adds area_heartwood, mass_heartwood and the NSC storage pool (#517) - expect_equal(pl$ode_state, c(h0, m0, f0, 0, 0, 0)) + # TF24 carries extra states beyond the shared height/mortality/fecundity + # -- area_heartwood, mass_heartwood, the NSC storage pool (#517) and the + # leaf-area departure (#516) -- all of which are zero at birth before + # set_initial_states() runs. Sized from ode_names rather than written out, + # so adding a state that is zero here does not need this line edited; what + # is being asserted is "the first three are h/m/f and the rest are zero". + expect_equal(pl$ode_state, + c(h0, m0, f0, rep(0, length(pl$ode_names) - 3L))) else expect_equal(pl$ode_state, c(h0, m0, f0, 0, 0)) diff --git a/tests/testthat/test-node.R b/tests/testthat/test-node.R index f23db8325..601cdcf64 100644 --- a/tests/testthat/test-node.R +++ b/tests/testthat/test-node.R @@ -110,9 +110,14 @@ for (x in names(strategy_types)) { g <- plant$rate("height") ## Ode *values*: + ## The boundary condition differs by coordinate -- a density in height is + ## divided by the growth rate, a density in birth date is not -- so read the + ## coordinate off the node rather than assuming one. TF24 resolves Control's + ## "auto" to birth date; FF16 and K93 to height. + birth_date <- node$density_in_birth_date cmp <- c(plant$internals$states, 0, # offspring_produced_survival_weighted - log(pr_estab / g) # log density + if (birth_date) log(pr_estab) else log(pr_estab / g) # log density ) cmp[which(plant$ode_names == 'mortality')] <- -log(pr_estab) expect_equal(node$ode_state, cmp) @@ -120,10 +125,13 @@ for (x in names(strategy_types)) { expect_identical(node$fecundity, 0.0); ## Ode *rates*: + ## Only a density in height compresses as the spacing between neighbouring + ## sizes changes, so only that coordinate carries the gradient term. cmp <- c(plant$internals$rates, ## This is different to the approach in tree1? plant$rate("fecundity") * exp(-plant$state("mortality")), - -plant$rate("mortality") - node$growth_rate_gradient(env)) + -plant$rate("mortality") - + if (birth_date) 0 else node$growth_rate_gradient(env)) expect_equal(node$ode_rates, cmp) @@ -166,7 +174,7 @@ for (x in names(strategy_types)) { test_that(sprintf("density in birth date (%s)", x), { ctrl <- Control() - ctrl$node_density_in_birth_date <- TRUE + ctrl$node_density_coordinate <- "birth_date" s <- strategy_types[[x]]() s$control <- ctrl @@ -188,8 +196,13 @@ for (x in names(strategy_types)) { expect_equal(rates[[length(rates)]], -node$individual$rate("mortality")) - ## And the height coordinate keeps its compression term. + ## And the height coordinate keeps its compression term. Named explicitly: + ## TF24 resolves "auto" to birth date, so a default Control here would test + ## the same coordinate as the block above. s2 <- strategy_types[[x]]() + ctrl2 <- s2$control + ctrl2$node_density_coordinate <- "height" + s2$control <- ctrl2 node2 <- Node(x, e)(s2) node2$compute_initial_conditions(env, pr_patch_survival = 1, birth_rate = 2) node2$compute_rates(env, 1) diff --git a/tests/testthat/test-species.R b/tests/testthat/test-species.R index bc9f627d6..e84077402 100644 --- a/tests/testthat/test-species.R +++ b/tests/testthat/test-species.R @@ -1,13 +1,29 @@ strategy_types <- get_list_of_strategy_types() environment_types <- get_list_of_environment_types() +## The blocks below build a Species directly, outside any Patch, introduce nodes +## with the no-argument introduce_new_node() -- which leaves every node carrying +## the same birth date -- and compare the result against cmp_compute_competition, +## a height-coordinate oracle. They are therefore tests of the height trapezium +## and have to name that coordinate: TF24 resolves Control's "auto" to birth +## date, where coincident birth dates span zero width and the integral collapses +## to exactly 0. A real run cannot reach that state (Patch checks the birth dates +## are distinct and errors), but a bare Species has no such hook. +height_coordinate_strategy <- function(x) { + s <- strategy_types[[x]]() + ctrl <- s$control + ctrl$node_density_coordinate <- "height" + s$control <- ctrl + s +} + for (x in names(strategy_types)) { e <- environment_types[[x]] test_that("Basics", { env <- Environment(x) - s <- strategy_types[[x]]() + s <- height_coordinate_strategy(x) sp <- Species(x, e)(s) new_node <- Node(x, e)(s) plant <- Individual(x, e)(s) @@ -77,7 +93,7 @@ for (x in names(strategy_types)) { ## 1: empty species (no nodes) has no leaf area above any height: test_that("Empty species has no leaf area", { - sp <- Species(x, e)(strategy_types[[x]]()) + sp <- Species(x, e)(height_coordinate_strategy(x)) expect_equal(sp$compute_competition(0), 0) expect_equal(sp$compute_competition(10), 0) expect_equal(sp$compute_competition(Inf), 0) @@ -86,7 +102,7 @@ for (x in names(strategy_types)) { ## 2: Node up against boundary has no leaf area: test_that("species with only boundary node no leaf area", { env <- Environment(x) - sp <- Species(x, e)(strategy_types[[x]]()) + sp <- Species(x, e)(height_coordinate_strategy(x)) sp$introduce_new_node() sp$compute_rates(env, pr_patch_survival = 1, birth_rate = 1) expect_equal(sp$compute_competition(0), 0) @@ -104,7 +120,7 @@ for (x in names(strategy_types)) { ## 3: Single node; one round of trapezium: test_that("Leaf area sensible with one node", { env <- Environment(x) - sp <- Species(x, e)(strategy_types[[x]]()) + sp <- Species(x, e)(height_coordinate_strategy(x)) sp$compute_rates(env, pr_patch_survival = 1, birth_rate = 1) sp$introduce_new_node() h_top <- sp$height_max * 4 @@ -129,7 +145,7 @@ for (x in names(strategy_types)) { test_that("Leaf area sensible with two nodes", { env <- Environment(x) - sp <- Species(x, e)(strategy_types[[x]]()) + sp <- Species(x, e)(height_coordinate_strategy(x)) sp$compute_rates(env, pr_patch_survival = 1, birth_rate = 1) sp$introduce_new_node() h_top <- sp$height_max * 4 @@ -155,7 +171,7 @@ for (x in names(strategy_types)) { test_that("Leaf area sensible with three nodes", { env <- Environment(x) - sp <- Species(x, e)(strategy_types[[x]]()) + sp <- Species(x, e)(height_coordinate_strategy(x)) sp$compute_rates(env, pr_patch_survival = 1, birth_rate = 1) sp$introduce_new_node() h_top <- sp$height_max * 4 diff --git a/tests/testthat/test-stochastic-patch.R b/tests/testthat/test-stochastic-patch.R index 5333149b4..7cd25ec16 100644 --- a/tests/testthat/test-stochastic-patch.R +++ b/tests/testthat/test-stochastic-patch.R @@ -241,7 +241,13 @@ test_that("a stochastic recruit is born with its initial states seeded", { cmp <- Individual(x, e)(p$strategies[[1]]) cmp$set_initial_states(patch$environment) - expect_equal(patch$species[[1]]$individual_at(1)$ode_state, cmp$ode_state) + ## The tracked marginal balance is seeded from a leaf solve (#516), so it + ## inherits that solve's ~1e-5 sensitivity to how the environment was built, + ## where every other seeded state is exact. Compared at a tolerance for that + ## reason: a real seeding failure moves a state by orders of magnitude, not + ## by its sixth digit. + expect_equal(patch$species[[1]]$individual_at(1)$ode_state, cmp$ode_state, + tolerance = 1e-4) } }) diff --git a/tests/testthat/test-strategy-tf24.R b/tests/testthat/test-strategy-tf24.R index 8e68aeb05..3615c26ea 100644 --- a/tests/testthat/test-strategy-tf24.R +++ b/tests/testthat/test-strategy-tf24.R @@ -21,6 +21,12 @@ test_that("Defaults", { a_st1 = 0.10, a_st2 = 0.10, a_st3 = 0.8, + a_sw = 0.0, + a_pl0 = 0.0, + a_pl1 = 0.0, + a_pl2 = 0.2, + a_pl3 = 0.05, + a_pl4 = 3.0, a_p1 = 151.177775377968, a_p2 = 0.204716166503633, a_f1 = 1, @@ -96,8 +102,8 @@ test_that("TF24 collect_all_auxiliary option", { s <- TF24_Strategy() p <- TF24_Individual(s) - expect_equal(p$aux_size, 13) - expect_equal(length(p$internals$auxs), 13) + expect_equal(p$aux_size, 15) + expect_equal(length(p$internals$auxs), 15) expect_equal(p$aux_names, c( "competition_effect", "height_inverse", @@ -111,14 +117,14 @@ expect_equal(p$aux_names, c( "shadow_cost", "stom_cond_CO2", "assimilation", - "Tleaf" + "Tleaf", "leaf_marginal_return", "sapwood_marginal_return" )) s <- TF24_Strategy(collect_all_auxiliary=TRUE) expect_true(s$collect_all_auxiliary) p <- TF24_Individual(s) - expect_equal(p$aux_size, 14) - expect_equal(length(p$internals$auxs), 14) + expect_equal(p$aux_size, 16) + expect_equal(length(p$internals$auxs), 16) expect_equal(p$aux_names, c( "competition_effect", "height_inverse", @@ -132,7 +138,7 @@ expect_equal(p$aux_names, c( "shadow_cost", "stom_cond_CO2", "assimilation", - "Tleaf", + "Tleaf", "leaf_marginal_return", "sapwood_marginal_return", "area_sapwood" )) }) @@ -291,7 +297,11 @@ test_that("offspring arrival", { # orders of magnitude. p0 <- scm_base_parameters("TF24") env <- Environment("TF24") - ctrl <- Control() + # The height arm of the comparison below, named explicitly: TF24's default is + # now the birth-date coordinate ("auto" resolves to it), so a bare Control() + # here would silently run both arms in the same coordinate and compare a + # number against itself. + ctrl <- Control(node_density_coordinate = "height") p0$max_patch_lifetime <- 5 # one species @@ -351,7 +361,7 @@ test_that("offspring arrival", { # previously had no upper bound and the median cohort of a mature stand sat at # a reserve fraction of exactly 1 with the read clipped there, where it now # sits at 0.62 with nothing on the clip. - out_bd <- run_scm(p2, env, Control(node_density_in_birth_date = TRUE)) + out_bd <- run_scm(p2, env, Control(node_density_coordinate = "birth_date")) expect_equal(out_bd$offspring_production[[1]], 219.26680110, tolerance = 2e-2) expect_equal(out_bd$offspring_production[[2]], 34.58766277, tolerance = 2e-2) }) @@ -384,7 +394,13 @@ test_that("the height-linear parameters reproduce the pre-path-integral results" p0 <- scm_base_parameters("TF24") env <- Environment("TF24") - ctrl <- Control() + # ⚠️ PINNED TO THE HEIGHT COORDINATE. These are develop's pre-#516 values, and + # they were taken when Control()'s default resolved to the height coordinate + # for TF24. #516 makes "auto" resolve to birth_date for TF24, so a bare + # Control() here compares two coordinates rather than two hydraulic models -- + # it reads 404.5 against 30.2, which looks like a broken exactness test and is + # not one. The coordinate has to be named for the comparison to mean anything. + ctrl <- Control(node_density_coordinate = "height") p0$max_patch_lifetime <- 5 p1 <- add_strategies(p0, trait_matrix(c(0.0825, 5), c("lma", "hmat")), @@ -398,7 +414,7 @@ test_that("the height-linear parameters reproduce the pre-path-integral results" expect_equal(out2$offspring_production[[1]], 23.20349831, tolerance = 2e-2) expect_lt(out2$offspring_production[[2]], 0.5) - out_bd <- run_scm(linear(p2), env, Control(node_density_in_birth_date = TRUE)) + out_bd <- run_scm(linear(p2), env, Control(node_density_coordinate = "birth_date")) expect_equal(out_bd$offspring_production[[1]], 233.05915606, tolerance = 2e-2) expect_equal(out_bd$offspring_production[[2]], 43.63800899, tolerance = 2e-2) }) @@ -626,7 +642,7 @@ test_that("a run keeps every storage state inside [0, capacity]", { p$max_patch_lifetime <- 10 p <- add_strategies(p, trait_matrix(0.0825, "lma"), hyperpar = TF24_hyperpar, birth_rate = list(1.10)) - out <- run_scm(p, ctrl = Control(node_density_in_birth_date = TRUE), + out <- run_scm(p, ctrl = Control(node_density_coordinate = "birth_date"), collect = TRUE) d <- out$species @@ -658,3 +674,512 @@ test_that("a negative storage state is refused by name, not floored", { ind$set_state("storage", 1e-4) expect_no_error(ind$compute_rates(env)) }) + +## Leaf area as a state: the departure coordinate (#516) ------------------- +## +## Leaf area is carried as ln(A / A*(h)), the departure from the leaf area the +## height allometry prefers, rather than as a level. That choice is what makes +## the fixed-allometry model an *exact* special case: integrating A alongside +## height would make A = A*(h) a redundant invariant that Runge-Kutta preserves +## only to truncation error, so height's rate would read a drifted A. +## +## The risk these guard against is the opposite of a wrong number -- a state +## that is inert because it is unwired looks exactly like one that is inert +## because it is resting, and only the second is what this claims. + +tf24_departure_env <- function() { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.2, 5)) + env$set_fixed_environment(1.0, 40) + env +} + +test_that("the leaf-area departure rests at zero and is exactly inert", { + env <- tf24_departure_env() + ind <- TF24_Individual() + expect_true("log_area_leaf_departure" %in% ind$ode_names) + + ## Zero-initialised *is* the on-trajectory value, so a fresh individual needs + ## no seeding -- which is also why make_initial_state() and a resume are + ## correct without one. + expect_identical(ind$state("log_area_leaf_departure"), 0.0) + + ind$compute_rates(env) + ## Exactly zero, not merely small: the exactness of the special case rests on + ## the integrator stepping a rate of 0.0 and leaving the state at 0.0. + expect_identical(ind$rate("log_area_leaf_departure"), 0.0) +}) + +test_that("leaf area is the allometric value times exp(departure)", { + env <- tf24_departure_env() + s <- TF24_Strategy() + + for (h in c(0.4, 1.0, 5.0, 15.0)) { + ind <- TF24_Individual(s) + ind$set_state("height", h) + + ## At rest, exactly the plain allometry it replaced. Compared against the + ## strategy's own expand_allometry rather than a formula written out here, + ## so the allometry still lives in one place. + at_rest <- ind$aux("competition_effect") + expect_identical(at_rest, + TF24_strategy_expand_allometry(s, h, 0, 0)$area_leaf) + + ## And it moves, by exactly exp(phi). An unwired state would leave leaf + ## area pinned to the allometry whatever the departure said, and a ratio + ## is the sharpest form of the claim because the exp factor is the whole + ## content of the coordinate. + for (phi in c(-0.7, -0.1, 0.25)) { + ind$set_state("log_area_leaf_departure", phi) + expect_equal(ind$aux("competition_effect") / at_rest, exp(phi)) + } + } +}) + +test_that("a thinned canopy is an ordinary state, not a domain violation", { + env <- tf24_departure_env() + ind <- TF24_Individual() + ind$set_state("height", 5.0) + + ## The departure is a signed log ratio, so it must not be bounded below -- + ## a non-negative declaration would reject ordinary canopy thinning once the + ## plasticity terms are switched on. Half a canopy is -log(2). + for (phi in c(-log(2), -2.0, -5.0)) { + ind$set_state("log_area_leaf_departure", phi) + ind$set_initial_states(env) + expect_no_error(ind$compute_rates(env)) + expect_true(is.finite(ind$aux("net_mass_production_dt"))) + expect_gt(ind$aux("competition_effect"), 0) + } +}) + +test_that("the sapwood departure sets the Huber value and rests inert", { + env <- tf24_departure_env() + ind <- TF24_Individual(TF24_Strategy(collect_all_auxiliary = TRUE)) + expect_true("log_area_sapwood_departure" %in% ind$ode_names) + expect_identical(ind$state("log_area_sapwood_departure"), 0.0) + ind$compute_rates(env) + expect_identical(ind$rate("log_area_sapwood_departure"), 0.0) +}) + +test_that("sapwood area is theta * leaf area * exp(sapwood departure)", { + env <- tf24_departure_env() + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + theta <- s$pars$theta + + for (h in c(1.0, 5.0, 15.0)) { + ind <- TF24_Individual(s) + ind$set_state("height", h) + ind$compute_rates(env) + leaf <- ind$aux("competition_effect") + + ## At rest, exactly the pipe-model value. + expect_identical(ind$aux("area_sapwood"), leaf * theta) + + ## A stem that keeps its conducting area while the canopy thins carries a + ## higher Huber value, which is the whole mechanism: it is what makes + ## per-leaf-area maintenance cost rise and per-leaf-area hydraulic supply + ## improve as a plant thins out. + for (psi in c(-0.3, 0.4, 1.0)) { + ind$set_state("log_area_sapwood_departure", psi) + ind$compute_rates(env) + expect_equal(ind$aux("area_sapwood") / (leaf * theta), exp(psi)) + } + } +}) + +test_that("a departed Huber value carries through to storage capacity", { + env <- tf24_departure_env() + s <- TF24_Strategy() + cap <- function(psi) { + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ## Seeded at a_st3 of capacity, so the state reports capacity up to a + ## constant -- which is all a ratio needs. + ind$state("storage") + } + ## Capacity is a_st1 * mass_sapwood, and mass_sapwood is linear in sapwood + ## area, so it must inherit exp(psi) exactly. This is the route by which + ## freeing sapwood closes the mortality free lunch: shedding leaves no longer + ## shrinks the denominator of the reserve fraction that mortality reads. + for (psi in c(-0.5, 0.6)) { + expect_equal(cap(psi) / cap(0), exp(psi)) + } +}) + + +test_that("the gate reads the marginal leaf, not the reserve pool", { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_pl0 <- 1.0 + + probe <- function(theta_soil) { + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(theta_soil, 5)) + env$set_fixed_environment(1.0, 40) + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_initial_states(env) # reserves at a_st3 = 0.8 of capacity + ind$compute_rates(env) + list(dphi = ind$rate("log_area_leaf_departure"), + dpsi = ind$rate("log_area_sapwood_departure"), + margin = ind$aux("leaf_marginal_return")) + } + + wet <- probe(0.30) + dry <- probe(0.11) + + ## THE POINT OF THE CHANGE. Reserves sit at 0.8 of capacity in BOTH cases, so + ## a reserve-gated version could not fire at all here. The gate now reads + ## whether the marginal leaf covers its own upkeep -- Manzoni et al. (2015)'s + ## optimum -- so it fires while the plant is still carbon-rich, which is what + ## the field data show and what waiting for reserves cannot do. + expect_gt(wet$margin, 0) # leaves pay for themselves + expect_lt(dry$margin, 0) # they do not + expect_equal(wet$dphi, 0, tolerance = 1e-9) + expect_lt(dry$dphi, -0.1) + expect_gt(dry$dpsi, 0) + + ## Withholding cannot exceed the turnover it declines to replace, so thinning + ## is bounded by k_l however negative the balance goes. + expect_gte(dry$dphi, -s$pars$k_l) + + ## a_pl1 is a marginal return now, not a reserve level, and its default of + ## zero IS the break-even criterion. + expect_identical(TF24_Strategy()$pars$a_pl1, 0.0) +}) + +test_that("the gate reads a running mean, not the instantaneous balance", { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_pl0 <- 1.0 + + wet <- Environment("TF24"); wet$set_soil_number_of_depths(5) + wet$set_soil_water_state(rep(0.30, 5)); wet$set_fixed_environment(1.0, 40) + dry <- Environment("TF24"); dry$set_soil_number_of_depths(5) + dry$set_soil_water_state(rep(0.11, 5)); dry$set_fixed_environment(1.0, 40) + + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_initial_states(wet) # a history of good conditions + ind$compute_rates(dry) # then one dry evaluation + + ## Assimilation swings with the weather. A plant that shed on the strength of + ## a single dry evaluation would flicker in and out of leaf, so the gate reads + ## a running mean that a brief spell cannot move far. + expect_lt(ind$aux("leaf_marginal_return"), 0) # instantaneous: bad + expect_gt(ind$state("leaf_marginal_return_tracked"), 0) # the memory: still good + expect_equal(ind$rate("log_area_leaf_departure"), 0, tolerance = 1e-9) + + ## And the memory chases the instantaneous value at a_pl4, downward here. + expect_lt(ind$rate("leaf_marginal_return_tracked"), 0) + + ## Seeded from the plant's own first evaluation, so a newborn does not start + ## at the gate's centre withholding half its replacement. + fresh <- TF24_Individual(s) + fresh$set_state("height", 5.0) + fresh$set_initial_states(wet) + fresh$compute_rates(wet) + expect_equal(fresh$state("leaf_marginal_return_tracked"), + fresh$aux("leaf_marginal_return"), tolerance = 1e-8) + expect_equal(fresh$rate("leaf_marginal_return_tracked"), 0, tolerance = 1e-8) +}) + +test_that("the canopy floor bounds thinning, by the shape of the flow", { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_pl0 <- 1.0 + floor_phi <- log(s$pars$a_pl3) + + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.11, 5)) # deficit, so the gate is wide open + env$set_fixed_environment(1.0, 40) + + rate_at <- function(phi) { + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_state("log_area_leaf_departure", phi) + ind$set_initial_states(env) + ind$compute_rates(env) + ind$rate("log_area_leaf_departure") + } + + ## Thinning tapers to nothing AT the floor, so phi >= log(a_pl3) holds by the + ## form rather than by a clamp. That is what keeps leaf area in a range where + ## the arithmetic means something: without it the canopy decays exponentially + ## with no bound -- measured at 2e-8 for a fast-leaved species, and 0.000 for a + ## suppressed cohort in a plain wet stand, with divisions by leaf area + ## reaching 1e9 inside a solver step shared with live cohorts. + expect_lt(rate_at(-0.2), 0) # thinning freely + ## At the floor the shedding term is exactly zero, so what remains is the + ## rebuild term: the flow points INWARD (upward), not merely to a standstill. + ## That is the invariant working -- phi cannot cross log(a_pl3) from above. + expect_gte(rate_at(floor_phi), 0) + + ## Tapering rather than stepping, so the bound costs the solver nothing. + near <- rate_at(floor_phi + 0.02) + expect_lt(near, 0) + expect_gt(near, rate_at(floor_phi + 0.5)) + + ## A drought-deciduous species stays reachable by lowering the floor. Not the + ## habit this is aimed at, but it must not be excluded by construction. + s$pars$a_pl3 <- 1e-6 + expect_lt(rate_at(log(0.02)), -0.1) +}) + +test_that("a plant whose leaves pay for themselves replaces all of them", { + s <- TF24_Strategy() + s$pars$a_pl0 <- 1.0 + env <- Environment("TF24") + env$set_soil_number_of_depths(5) + env$set_soil_water_state(rep(0.30, 5)) + env$set_fixed_environment(1.0, 40) + + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_initial_states(env) + ind$compute_rates(env) + + expect_equal(ind$rate("log_area_leaf_departure"), 0, tolerance = 1e-9) + expect_equal(ind$rate("log_area_sapwood_departure"), 0, tolerance = 1e-9) +}) + +test_that("a_pl0 = 0 leaves both departures exactly inert", { + env <- tf24_departure_env() + expect_identical(TF24_Strategy()$pars$a_pl0, 0.0) + + ## The off switch is exact, not approximate: it zeroes the withheld fraction, + ## which leaves the resting model bit-identical. Asserted at reserve levels + ## that would otherwise thin hard. + for (storage in c(0.0, 1e-9)) { + ind <- TF24_Individual() + ind$set_state("height", 5.0) + ind$set_state("storage", storage) + ind$compute_rates(env) + expect_identical(ind$rate("log_area_leaf_departure"), 0.0) + expect_identical(ind$rate("log_area_sapwood_departure"), 0.0) + } +}) + +test_that("the Huber value has a restoring force and cannot fall below preferred", { + env <- tf24_departure_env() + s <- TF24_Strategy() + s$pars$a_pl0 <- 1.0 + k_l <- s$pars$k_l + k_s <- s$pars$k_s + + ## The gate reads the marginal leaf now, so stress is applied through soil + ## water rather than by draining the pool. + dry <- Environment("TF24") + dry$set_soil_number_of_depths(5) + dry$set_soil_water_state(rep(0.11, 5)) + dry$set_fixed_environment(1.0, 40) + rate_at <- function(psi, unused = 0) { + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(dry) + ind$compute_rates(dry) + ind$rate("log_area_sapwood_departure") + } + + ## psi >= 0 is invariant, and it is a property of the form rather than a + ## guard: at psi = 0 the two replacement fractions coincide, so the rate is + ## (1 - replacement) * (k_l - k_s), which is non-negative because k_l > k_s. + ## The flow at the boundary points inward, so a stem cannot end up with less + ## conducting area than its canopy prefers. + expect_gt(k_l, k_s) + expect_gte(rate_at(0.0, 0.0), 0) + + ## Excess sapwood is renewed less, so the departure is pulled back. This is + ## the restoring force that was missing: without it psi drifted, and measured, + ## it drifted the wrong way and left plants under-built. + expect_lt(rate_at(1.5, 0.0), rate_at(0.0, 0.0)) + + ## The restoring force is relative to carbon status, NOT absolute. Given + ## carbon to spend, an over-built stem is pulled back to its preferred ratio. + wet <- Environment("TF24") + wet$set_soil_number_of_depths(5) + wet$set_soil_water_state(rep(0.30, 5)) + wet$set_fixed_environment(1.0, 40) + ample <- function(psi) { + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(wet) + ind$compute_rates(wet) + ind$rate("log_area_sapwood_departure") + } + expect_lt(ample(1.5), 0) + expect_equal(ample(0.0), 0, tolerance = 1e-12) + + ## But with reserves EMPTY it keeps rising however over-built the stem is, + ## because withheld leaf turnover (k_l) outruns withheld sapwood renewal + ## (k_s) whatever psi does. That is arithmetic rather than a defect -- a plant + ## thinning its canopy at 46 per cent a year while losing conducting area at + ## 20 per cent really does raise its Huber value -- but it means neither + ## departure is bounded under a PERMANENT deficit. See the note (#516): a + ## plant in that state is dying, and what bounds it is mortality removing the + ## cohort, not the allometry. + expect_gt(rate_at(6.0, 0.0), 0) +}) + +test_that("rebuilding a canopy does not dilute the Huber value", { + env <- tf24_departure_env() + s <- TF24_Strategy() + s$pars$a_pl0 <- 1.0 + + ## A plant with a canopy gap and ample reserves rebuilds. Buying leaf area + ## alone would lower sapwood per leaf area; buying the whole package at the + ## preferred ratio must not, so at psi = 0 the rebuild contributes nothing to + ## the sapwood departure and the boundary flow stays non-negative. + ind <- TF24_Individual(s) + ind$set_state("height", 5.0) + ind$set_state("log_area_leaf_departure", -0.5) + ind$set_initial_states(env) # reserves ample, so rebuilding is on + ind$compute_rates(env) + + expect_gt(ind$rate("log_area_leaf_departure"), 0) # the canopy is rebuilding + expect_gte(ind$rate("log_area_sapwood_departure"), 0) +}) + +test_that("new growth is priced at the Huber value the plant actually carries", { + env <- tf24_departure_env() + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + + ## dmass_sapwood_darea_leaf used pars.theta, so a plant holding extra + ## conducting area got its hydraulic benefit for free and paid the pipe-model + ## price for new growth. That is most of why net production appeared to peak + ## at 3.3x the pipe-model ratio; priced properly, GROWTH peaks near 1.4-1.8x. + growth_at <- function(psi, h = 10) { + ind <- TF24_Individual(s) + ind$set_state("height", h) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ind$compute_rates(env) + c(P = ind$aux("net_mass_production_dt"), dh = ind$rate("height")) + } + + psis <- seq(0, 2.4, by = 0.3) + out <- vapply(psis, growth_at, numeric(2)) + P <- out["P", ]; G <- out["dh", ] + + ## Both have interior optima, and the growth one sits well below the + ## production one -- because extra stem is now paid for in forgone leaf growth. + ## The ORDERING is the invariant here, not the levels: #617 moved both optima + ## in (the path integral lowers resistance for tall plants, so extra sapwood + ## buys less), and pinning a level would have to be re-pinned by any change to + ## the hydraulics. What must survive is that growth's optimum is strictly + ## inside production's. + expect_gt(which.max(P), 1) + expect_lt(which.max(G), which.max(P)) + expect_lt(exp(psis[which.max(G)]), exp(psis[which.max(P)])) + + ## Bark stays pinned to leaf area, so it must NOT move with the departure: + ## at rest the whole thing is bitwise what it replaced, which the exactness + ## check elsewhere covers, and here the resting growth is simply positive. + expect_gt(G[[1]], 0) +}) + +## --- Sapwood tracks the Huber value that maximises GROWTH (#516) ----------- +## The defining property is not that the controller has the right sign, but that +## its zero sits on the argmax of dh/dt. Production and growth have different +## optima -- production keeps rising well past 3x the pipe-model ratio, because +## nothing in it charges the plant for the stem -- so a controller built on the +## wrong one is wrong in a way that still looks monotone and still converges. + +tf24_sapwood_probe <- function(psi, theta_soil, a_sw = 1.0, height = 10) { + s <- TF24_Strategy(collect_all_auxiliary = TRUE) + s$pars$a_sw <- a_sw + env <- Environment("TF24") + env$set_soil_number_of_depths(5L) + env$set_soil_water_state(rep(theta_soil, 5L)) + env$set_fixed_environment(1.0, 40) + ind <- TF24_Individual(s) + ind$set_state("height", height) + ind$set_state("log_area_sapwood_departure", psi) + ind$set_initial_states(env) + ind$compute_rates(env) + list(R_s = ind$aux("sapwood_marginal_return"), + dpsi = ind$rate("log_area_sapwood_departure"), + dheight = ind$rate("height")) +} + +test_that("sapwood acclimation is inert at a_sw = 0", { + ## a_sw = 0 is the default, and is what keeps the fixed-allometry model + ## recoverable: the controller must contribute exactly nothing, not merely a + ## small amount. Zero exactly, so it cannot perturb the stepper either. + off <- tf24_sapwood_probe(0.2, 0.20, a_sw = 0.0) + expect_identical(off$R_s, 0.0) + on <- tf24_sapwood_probe(0.2, 0.20, a_sw = 1.0) + expect_gt(abs(on$R_s), 1e-3) + ## and with the controller off the rate is whatever the mass flows alone say + expect_equal(on$dpsi - off$dpsi, on$R_s, tolerance = 1e-12) +}) + +test_that("the sapwood controller vanishes exactly at the growth optimum", { + # Spans BELOW the pipe model: after #617 a short plant's optimum is at + # psi < 0, so a grid starting at zero would report its left edge as the peak. + psi <- seq(-0.3, 0.6, by = 0.025) + d <- vapply(psi, function(p) { + r <- tf24_sapwood_probe(p, 0.20) + c(r$R_s, r$dheight) + }, numeric(2)) + R_s <- d[1, ]; dh <- d[2, ] + + ## R_s crosses zero exactly once, downwards. + expect_gt(R_s[[1]], 0) + expect_lt(R_s[[length(R_s)]], 0) + expect_equal(sum(diff(sign(R_s)) != 0), 1L) + + ## ...and it crosses where growth peaks. Compared on the grid rather than by + ## interpolation, so a controller optimising production instead (whose zero + ## sits far to the right, near 3x) fails rather than passing on a tolerance. + psi_zero <- psi[which.min(abs(R_s))] + psi_peak <- psi[which.max(dh)] + expect_equal(psi_zero, psi_peak) + + ## The optimum is genuinely NOT the pipe-model ratio, and -- the part that + ## cannot be reproduced by any single fixed theta -- it RISES WITH HEIGHT. + ## After #617 a 5 m plant wants less stem per leaf than the pipe model and a + ## 20 m plant wants more, so it is the trend that is asserted rather than a + ## level: the level moved from 1.35x to 1.05x when the path integral landed, + ## and would move again with the hydraulics. + peak_at <- function(h) { + d <- vapply(psi, function(p) tf24_sapwood_probe(p, 0.20, height = h)$dheight, + numeric(1)) + exp(psi[which.max(d)]) + } + expect_lt(peak_at(5), peak_at(10)) + expect_lt(peak_at(10), peak_at(16)) + expect_lt(peak_at(5), 1.0) # a short plant wants LESS than the pipe model + expect_gt(peak_at(16), 1.1) # a tall one wants more +}) + +test_that("the sapwood controller switches off when there is no carbon", { + ## Re-proportioning the stem is an allocation decision, so it must stop when + ## there is no growth flux to pay for it -- otherwise the drift builds real + ## tissue for free. Reserves are still full at this soil water, so the reserve + ## gate G alone would NOT catch this: what has gone to zero is production. + ## Not exactly zero: the availability factor is a smooth share of throughput, + ## so it goes to ~1e-11 rather than snapping to 0 -- which is the point, a + ## hard cut here would be a breakpoint in the rate. Negligible against the + ## ~0.26 the same probe returns in the wet. + dry <- tf24_sapwood_probe(0.2, 0.13) + expect_lt(abs(dry$R_s), 1e-8) + wet <- tf24_sapwood_probe(0.2, 0.20) + expect_gt(abs(wet$R_s), 1e-3) +}) + +test_that("sapwood acclimation is refused under deep crown", { + ## The sensitivity is measured at a single radiation, which deep-crown's + ## integrated profit is not a function of. Skipping it would leave the + ## controller with only its negative cost term and shrink the stem forever, + ## so this must fail loudly instead. + s <- TF24_Strategy() + s$pars$a_sw <- 1.0 + s$control$shading_model <- "deep-crown" + expect_error(TF24_Individual(s), "deep-crown") +}) diff --git a/tests/testthat/test-strategy-tf24f.R b/tests/testthat/test-strategy-tf24f.R index 57823e86c..1cb00621a 100644 --- a/tests/testthat/test-strategy-tf24f.R +++ b/tests/testthat/test-strategy-tf24f.R @@ -22,6 +22,12 @@ test_that("Defaults", { a_st1 = 0.10, a_st2 = 0.10, a_st3 = 0.8, + a_sw = 0.0, + a_pl0 = 0.0, + a_pl1 = 0.0, + a_pl2 = 0.2, + a_pl3 = 0.05, + a_pl4 = 3.0, a_p1 = 151.177775377968, a_p2 = 0.204716166503633, a_f1 = 1, @@ -115,8 +121,8 @@ test_that("TF24f collect_all_auxiliary option", { s <- TF24f_Strategy() p <- TF24f_Individual(s) - expect_equal(p$aux_size, 13) - expect_equal(length(p$internals$auxs), 13) + expect_equal(p$aux_size, 15) + expect_equal(length(p$internals$auxs), 15) expect_equal(p$aux_names, c( "competition_effect", "height_inverse", @@ -130,14 +136,14 @@ expect_equal(p$aux_names, c( "shadow_cost", "stom_cond_CO2", "assimilation", - "Tleaf" + "Tleaf", "leaf_marginal_return", "sapwood_marginal_return" )) s <- TF24f_Strategy(collect_all_auxiliary=TRUE) expect_true(s$collect_all_auxiliary) p <- TF24f_Individual(s) - expect_equal(p$aux_size, 14) - expect_equal(length(p$internals$auxs), 14) + expect_equal(p$aux_size, 16) + expect_equal(length(p$internals$auxs), 16) expect_equal(p$aux_names, c( "competition_effect", "height_inverse", @@ -151,7 +157,7 @@ expect_equal(p$aux_names, c( "shadow_cost", "stom_cond_CO2", "assimilation", - "Tleaf", + "Tleaf", "leaf_marginal_return", "sapwood_marginal_return", "area_sapwood" )) }) @@ -293,8 +299,8 @@ test_that("acclimation runs, is active, and converges to TF24", { # and a full patch runs end-to-end to a finite, positive offspring count. expect_true("opt_root_psi_state" %in% TF24f_Individual()$ode_names) pf <- mk("TF24f") - slow <- run_scm(set_k_acclim(pf, 0.1), Environment("TF24f"), Control())$offspring_production - fast <- run_scm(set_k_acclim(pf, 10), Environment("TF24f"), Control())$offspring_production + slow <- run_scm(set_k_acclim(pf, 0.001), Environment("TF24f"), Control())$offspring_production + fast <- run_scm(set_k_acclim(pf, 1), Environment("TF24f"), Control())$offspring_production expect_length(fast, 1) expect_true(is.finite(fast) && fast > 0) @@ -302,22 +308,23 @@ test_that("acclimation runs, is active, and converges to TF24", { # fitness, so the finite-difference psi optimisation is feeding back into # the demography rather than being a no-op. # - # Threshold relaxed from 0.1 to 0.05 when the stem path integral landed: - # with resistance lower above 1 m the penalty for tracking the optimal psi - # imperfectly is smaller, and this contrast fell from just over 10% to - # 8.7%. The 0.1 was a round number rather than a derived bound, and 8.7% - # is still decisively not a no-op. + # ⚠️ THE BRACKET STRADDLES A MAXIMUM, so it has to be chosen against the + # coordinate in use, not carried over. Offspring production is NOT + # monotone in k_acclim, and #516 moved where its peak sits: under the + # height coordinate the maximum was near k = 0.1, and under the birth-date + # coordinate TF24f now defaults to, it is near k = 1. Measured here at + # hmat = 5, max_patch_lifetime = 5: # - # Do NOT try to restore the margin by widening the k bracket: offspring - # production is NOT monotone in k_acclim. Measured here at hmat = 5, - # max_patch_lifetime = 5: + # k_acclim 0.001 0.01 0.1 1 10 + # birth-date 388.267 390.547 409.512 439.537 397.309 + # height 15.416 16.442 22.066 22.233 24.365 # - # k_acclim 0.001 0.01 0.1 10 - # offspring 69.462 70.884 76.608 69.932 - # - # There is a maximum near k = 0.1, so k = 0.01 and k = 10 differ by only - # 1.3% and a wider bracket gives a *smaller* contrast, not a larger one. - expect_gt(abs(fast - slow) / slow, 0.05) + # The old 0.1-vs-10 pair therefore compares two points on OPPOSITE SIDES + # of the birth-date peak and reads only 3.0% -- which looks like weak + # acclimation and is really a badly-placed bracket. Spanning 0.001 to 1 + # gives 13.2%, so the original 0.1 threshold stands rather than being + # relaxed again. + expect_gt(abs(fast - slow) / slow, 0.1) # (3) Consistent with TF24 "within reason": as the acclimation gain grows, # TF24f tracks the optimum that TF24 computes directly each step, so its