Repository: pcubillos/gen_tso (language: python)

Issue:
esasky viewer
I think this is the way to control it:
https://www.cosmos.esa.int/web/esdc/esasky-javascript-api
I'm looking for:
- [x] go to (RA, DEC)
- [x] draw circle of X-arcsec around target
- [x] find nearby stars (Gaia DR3) within 80-arcsec from the target
- [x] highlight selected target in the Acquisition Targets table
Implement target_acquisition modes
This requires
- [x] setting up the pandeia defaults
- [x] update the front-end
- [x] enable saturation calculations
- [x] enable S/N calculations
- [x] enable Gaia DR3 queries around the science target (ideally show candidates in the ESASky viewer)

esasky viewer
I think this is the way to control it:
https://www.cosmos.esa.int/web/esdc/esasky-javascript-api
I'm looking for:
- [x] go to (RA, DEC)
- [x] draw circle of X-arcsec around target
- [x] find nearby stars (Gaia DR3) within 80-arcsec from the target
- [x] highlight selected target in the Acquisition Targets table


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index a096077..9978501 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,8 @@
 *.DS_Store
 *~
 gen_tso/data/last_updated*
+gen_tso/data/target_search_history
+gen_tso/data/tess_candidates_tmp.txt
 
 # Byte-compiled / optimized / DLL files
 __pycache__/
diff --git a/docs/_quarto.yml b/docs/_quarto.yml
index d7ccc70..e9c3462 100644
--- a/docs/_quarto.yml
+++ b/docs/_quarto.yml
@@ -48,6 +48,8 @@ website:
       text: Installation
     - file: get_started.qmd
       text: Get started
+    - file: notebooks.qmd
+      text: Jupyter Notebooks
     - text: API
       href: api
 
diff --git a/docs/_quartodoc.yml b/docs/_quartodoc.yml
index 2789813..e66c5d5 100644
--- a/docs/_quartodoc.yml
+++ b/docs/_quartodoc.yml
@@ -24,4 +24,4 @@ quartodoc:
     package: gen_tso.catalogs
     contents:
     - Catalog
-    - load_trexolist_table
+    - load_trexolists
diff --git a/docs/notebooks.qmd b/docs/notebooks.qmd
new file mode 100644
index 0000000..71f8ddb
--- /dev/null
+++ b/docs/notebooks.qmd
@@ -0,0 +1,51 @@
+---
+title: Notebooks
+page-navigation: true
+format: 
+  html:
+    code-fold: false
+jupyter: python3
+---
+
+## Notebook demos
+
+
+For a demonstration of a line plot on a polar axis
+Show all transiting exoplanets observed in transmission:
+
+```{python}
+
+import gen_tso.catalogs as cat
+
+catalog = cat.Catalog()
+host = ''
+info = {}
+nplanets = len(catalog.targets)
+for target in catalog.targets:
+    has_transits = (
+        target.is_jwst and
+        target.is_transiting and
+        'transit' in target.trexo_data['event']
+    )
+
+    if has_transits:
+        obs = target.trexo_data
+        programs = obs['program']
+        events = obs['event']
+        status = obs['status']
+        mode = obs['mode']
+        nobs = len(events)
+        info[target.host] = [
+            f"    {programs[i]:24}  {mode[i]:20}  {status[i]}"
+            for i in range(nobs)
+            if events[i] == 'transit'
+            if status[i] not in ['Skipped', 'Failed', 'Withdrawn']
+        ]
+
+for key, observations in info.items():
+    print(f'\n{key}:')
+    for obs in observations:
+        print(obs)
+```
+
+
diff --git a/gen_tso/__main__.py b/gen_tso/__main__.py
index dd915a4..51b4037 100644
--- a/gen_tso/__main__.py
+++ b/gen_tso/__main__.py
@@ -25,7 +25,7 @@ def main():
     """
     reload = '--debug' in sys.argv
     app = os.path.realpath(os.path.dirname(__file__)) + '/gen_tso_app.py'
-    run_app(app, reload=reload, launch_browser=True)
+    run_app(app, reload=reload, launch_browser=True, dev_mode=False)
 
 
 if __name__ == "__main__":
diff --git a/gen_tso/catalogs/catalogs.py b/gen_tso/catalogs/catalogs.py
index eb2506a..4f5d405 100644
--- a/gen_tso/catalogs/catalogs.py
+++ b/gen_tso/catalogs/catalogs.py
@@ -9,10 +9,10 @@
     'load_aliases',
 ]
 
+from datetime import datetime
 from astropy.io import ascii
 import numpy as np
-from prompt_toolkit import prompt
-from prompt_toolkit.completion import WordCompleter
+import prompt_toolkit as ptk
 
 from ..utils import ROOT
 from . import utils as u
@@ -26,6 +26,11 @@ def find_target(targets=None):
     Parameters
     ----------
     targets: list of Target objects
+
+    Examples
+    --------
+    >>> import gen_tso.catalogs as cat
+    >>> target = cat.find_target()
     """
     if targets is None:
         targets = load_targets('nea_data.txt', is_confirmed=True)
@@ -35,13 +40,16 @@ def find_target(targets=None):
         aliases += target.aliases
     planets += list(aliases)
 
-    completer = WordCompleter(
+    completer = ptk.completion.WordCompleter(
         planets,
         sentence=True,
         match_middle=True,
     )
-    name = prompt(
-        'Enter Planet name: ',
+    session = ptk.PromptSession(
+        history=ptk.history.FileHistory(f'{ROOT}/data/target_search_history')
+    )
+    name = session.prompt(
+        "(Press 'tab' for autocomplete)\nEnter Planet name: ",
         completer=completer,
         complete_while_typing=False,
     )
@@ -71,20 +79,19 @@ def __init__(self):
         self.targets = nea_targets + tess_targets
 
         # JWST targets
-        jwst_hosts, trexo_ra, trexo_dec = load_trexolists(extract='coords')
-        njwst = len(jwst_hosts)
+        trexo_data = load_trexolists(grouped=True)
+        njwst = len(trexo_data)
         host_aliases = load_aliases(as_hosts=True)
-        #hosts = [target.host for target in self.targets]
-        #hosts_aka = u.invert_aliases(host_aliases)
-        for i in range(njwst):
-            if jwst_hosts[i] in host_aliases:
-                jwst_hosts[i] = host_aliases[jwst_hosts[i]]
-            # if host NEA name != planet NEA name
-            #if jwst_hosts[i] not in hosts:
-            #    print(jwst_hosts[i])
-            #    for host in hosts_aka[jwst_hosts[i]]:
-            #        if host in self.hosts:
-            #            jwst_hosts[i] = host
+
+        jwst_hosts = []
+        for jwst_target in trexo_data:
+            hosts = np.unique([
+                host_aliases[host] if host in host_aliases else host
+                for host in jwst_target['target']
+            ])
+            jwst_target['nea_hosts'] = hosts
+            jwst_hosts += list(hosts)
+        jwst_hosts = np.unique(jwst_hosts)
 
         planet_aliases = load_aliases()
         planets_aka = u.invert_aliases(planet_aliases)
@@ -92,8 +99,10 @@ def __init__(self):
         for target in self.targets:
             target.is_jwst = target.host in jwst_hosts and target.is_transiting
             if target.is_jwst:
-                j = list(jwst_hosts).index(target.host)
-                target.trexo_ra_dec = (trexo_ra[j], trexo_dec[j])
+                for j in range(njwst):
+                    if target.host in trexo_data[j]['nea_hosts']:
+                        break
+                target.trexo_data = trexo_data[j]
 
             if target.planet in planets_aka:
                 target.aliases = planets_aka[target.planet]
@@ -214,25 +223,58 @@ def load_targets(database='nea_data.txt', is_confirmed=np.nan):
     return targets
 
 
-def load_trexolists(grouped=False, trexo_file=None, extract='target'):
+def load_trexolists(grouped=False, trexo_file=None):
     """
-    Get the target names from the trexolists.csv file.
+    Get the data from the trexolists.csv file.
+    Note that trexolists know targets by their host star, not by
+    individual planets in a given system.
 
     Parameters
     ----------
     grouped: Bool
-        If False, return a 1D list of names.
-        If True, return a nested list of lists, with each item the
-        set of names for a same object.
-    trexo_list: String
+        - If False, return the a dictionary where each item contains
+          a 1D list for each individual program.
+        - If True, return list for each individual host, where each entry
+          contains a dictionary of 1D lists of all programs for the target.
+    trexo_file: String
         If None, extract data from default Gen TSO location.
         Otherwise, a path to a trexolists.csv file.
-    extract: String
-        If 'target' extract only the target names.
-        If 'coords' extract the RA and dec in addition to the target names.
-        Note that these coordinates are intentionally truncated so
-        that a same object has a unique RA,dec (and thus can be used
-        to identify the same target with the trexolists filters).
+
+    Examples
+    --------
+    >>> import gen_tso.catalogs as cat
+    >>>
+    >>> # Get data as lists of individual programs:
+    >>> trexo = cat.load_trexolists()
+    >>> print(trexo['target'])
+    ['L 168-9' 'HAT-P-14' 'WASP-80' 'WASP-80' 'WASP-69' 'GJ 436' ...]
+    >>>
+    >>> print(list(trexo))
+    ['target', 'trexo_name', 'program', 'ra', 'dec', 'event', 'mode', 'subarray', 'readout', 'groups', 'phase_start', 'phase_end', 'duration', 'date_start', 'plan_window', 'proprietary_period', 'status']
+
+    >>> # Get data as lists of (host) targets:
+    >>> trexo = cat.load_trexolists(grouped=True)
+    >>> trexo[19]
+    {'target': array(['WASP-43', 'WASP-43'], dtype='<U23'),
+    'trexo_name': array(['WASP-43', 'WASP-43'], dtype='<U23'),
+    'program': array(['GTO 1224 Birkmann', 'ERS 1366 Batalha'], dtype='<U22'),
+    'ra': array(['10:19:37.9634', '10:19:37.9649'], dtype='<U13'),
+    'dec': array(['-09:48:23.21', '-09:48:23.19'], dtype='<U12'),
+    'event': array(['phase', 'phase'], dtype='<U9'),
+    'mode': array(['NIRSPEC BOTS+G395H', 'MIRI LRS'], dtype='<U20'),
+    'subarray': array(['SUB2048', 'SLITLESSPRISM'], dtype='<U13'),
+    'readout': array(['NRSRAPID', 'FASTR1'], dtype='<U8'),
+    'groups': array([20, 64]),
+    'phase_start': array([0.18394, 0.13912]),
+    'phase_end': array([0.20955, 0.16473]),
+    'duration': array([28.57, 31.82]),
+    'date_start': array([datetime.datetime(2023, 5, 14, 9, 3, 30),
+           datetime.datetime(2022, 11, 30, 23, 36, 1)], dtype=object),
+    'plan_window': array(['X', 'X'], dtype='<U21'),
+    'proprietary_period': array([12,  0]),
+    'status': array(['Archived', 'Archived'], dtype='<U14'),
+    'truncated_ra': array('10:19', dtype='<U5'),
+    'truncated_dec': array('-09:48', dtype='<U6')}
     """
     if trexo_file is None:
         trexo_file = f'{ROOT}data/trexolists.csv'
@@ -242,49 +284,108 @@ def load_trexolists(grouped=False, trexo_file=None, extract='target'):
         format='csv', guess=False, fast_reader=False, comment='#',
     )
 
-    targets = trexolist_data['Target'].data
-    norm_targets = [
+    norm_targets = np.array([
         u.normalize_name(target)
-        for target in targets
+        for target in trexolist_data['Target']
+    ])
+    trexo_data = {
+        'target': norm_targets,
+        'trexo_name': np.array(trexolist_data['Target'])
+    }
+
+    category = trexolist_data['Category']
+    programs = trexolist_data['Program']
+    pi = trexolist_data['PI name']
+    trexo_data['program'] = np.array([
+        f"{categ} {prog} {name}"
+        for categ,prog,name in zip(category, programs, pi)
+    ])
+
+    trexo_data['ra'] = np.array(trexolist_data['R.A. 2000'])
+    trexo_data['dec'] = np.array(trexolist_data['Dec. 2000'])
+
+    trexo_data['event'] = np.array([
+        event.lower().replace('phasec', 'phase')
+        for event in trexolist_data['Event']
+    ])
+    # see_phase?
+
+    trexo_data['mode'] = np.array([
+        obs.replace('.', ' ')
+        for obs in trexolist_data['Mode']
+    ])
+    trexo_data['subarray'] = np.array(trexolist_data['Subarray'])
+    trexo_data['readout'] = np.array(trexolist_data['Readout pattern'])
+    trexo_data['groups'] = np.array(trexolist_data['Groups'])
+
+    trexo_data['phase_start'] = np.array([
+        np.nan if phase=='N/A' else float(phase)
+        for phase in trexolist_data['Start.Phase']
+    ])
+    trexo_data['phase_end'] = np.array([
+        np.nan if phase=='N/A' else float(phase)
+        for phase in trexolist_data['End.Phase']
+    ])
+    trexo_data['duration'] = np.array(trexolist_data['Hours'])
+
+    trexo_data['date_start'] = np.array([
+        np.nan if date=='X' else datetime.strptime(date,'%b_%d_%Y_%H:%M:%S')
+        for date in trexolist_data['Start date']
+    ])
+    trexo_data['date_start'] = np.array([
+        np.nan if date=='X' else datetime.strptime(date,'%b_%d_%Y_%H:%M:%S')
+        for date in trexolist_data['Start date']
+    ])
+    plan_window = [
+        date if '-' not in date else date[:date.index('-')]
+        for date in trexolist_data['Plan Windows']
     ]
+    trexo_data['plan_window'] = np.array([
+        np.nan if date=='X' else datetime.strptime(date,'%b%d,%Y')
+        for date in plan_window
+    ])
+    trexo_data['proprietary_period'] = np.array(trexolist_data['Prop.Period'])
 
-    ra = trexolist_data['R.A. 2000'].data
-    dec = trexolist_data['Dec. 2000'].data
-    truncated_ra = np.array([r[0:7] for r in ra])
-    truncated_dec = np.array([d[0:6] for d in dec])
+    trexo_data['status'] = np.array(trexolist_data['Status'])
 
     if not grouped:
-        unique_targets, u_idx = np.unique(norm_targets, return_index=True)
-        if extract == 'coords':
-            trexo_ra = truncated_ra[u_idx]
-            trexo_dec = truncated_dec[u_idx]
-            return unique_targets, trexo_ra, trexo_dec
-        return unique_targets
+        return trexo_data
 
     # Use RA and dec to detect aliases for a same object
+    truncated_ra = np.array([ra[0:5] for ra in trexo_data['ra']])
+    truncated_dec = np.array([dec[0:6] for dec in trexo_data['dec']])
+
+    ntargets = len(trexo_data['target'])
+    taken = np.zeros(ntargets, bool)
     target_sets = []
     trexo_ra = []
     trexo_dec = []
-    ntargets = len(targets)
-    taken = np.zeros(ntargets, bool)
     for i in range(ntargets):
         if taken[i]:
             continue
+        group_indices = [i]
         ra = truncated_ra[i]
         dec = truncated_dec[i]
+        trexo_ra.append(ra)
+        trexo_dec.append(dec)
         taken[i] = True
-        hosts = [norm_targets[i]]
         for j in range(i,ntargets):
             if truncated_ra[j]==ra and truncated_dec[j]==dec and not taken[j]:
-                hosts.append(norm_targets[j])
+                group_indices.append(j)
                 taken[j] = True
-        target_sets.append(list(np.unique(hosts)))
-        trexo_ra.append(ra)
-        trexo_dec.append(dec)
+        target_sets.append(group_indices)
+
+    grouped_data = []
+    for i,indices in enumerate(target_sets):
+        target = {}
+        for key in trexo_data.keys():
+            target[key] = trexo_data[key][indices]
+        target['truncated_ra'] = np.array(trexo_ra[i])
+        target['truncated_dec'] = np.array(trexo_dec[i])
+        grouped_data.append(target)
+
+    return grouped_data
 
-    if extract == 'coords':
-        return target_sets, trexo_ra, trexo_dec
-    return target_sets
 
 
 def load_aliases(as_hosts=False):
diff --git a/gen_tso/catalogs/fetch_catalogs.py b/gen_tso/catalogs/fetch_catalogs.py
index 70b5867..09d10b8 100644
--- a/gen_tso/catalogs/fetch_catalogs.py
+++ b/gen_tso/catalogs/fetch_catalogs.py
@@ -10,6 +10,7 @@
     'fetch_vizier_ks',
     'fetch_aliases',
     'fetch_tess_aliases',
+    'fetch_gaia_targets',
 ]
 
 import sys
@@ -23,8 +24,12 @@
 import pickle
 import warnings
 import re
+import socket
+import ssl
 
+from astropy.coordinates import SkyCoord
 import numpy as np
+from astroquery.gaia import Gaia
 from astroquery.simbad import Simbad as simbad
 from astroquery.vizier import Vizier
 from astropy.table import Table
@@ -181,7 +186,7 @@ def curate_aliases():
         tess_aliases = pickle.load(handle)
     aliases.update(tess_aliases)
 
-    jwst_names = list(load_trexolists())
+    jwst_names = list(load_trexolists()['target'])
     # Ensure to match against NEA host names for jwst targets
     for host,system in aliases.items():
         is_in = np.in1d(system['host_aliases'], jwst_names)
@@ -542,8 +547,12 @@ def fetch_aliases(hosts, output_file=None):
     host_aliases, planet_aliases = fetch_nea_aliases(hosts)
 
     # Keep track of trexolists aliases to cross-check:
-    jwst_names = load_trexolists()
-    jwst_aliases = load_trexolists(grouped=True)
+    trexo_data = load_trexolists(grouped=True)
+    jwst_aliases = [
+        list(np.unique(jwst_target['target']))
+        for jwst_target in trexo_data
+    ]
+    jwst_names = np.unique(np.concatenate(jwst_aliases))
 
     aliases = {}
     nhosts = len(hosts)
@@ -888,3 +897,116 @@ def scrap_nea_kmag(target):
     return kmag
 
 
+def fetch_gaia_targets(
+        ra_source, dec_source, max_separation=80.0, raise_errors=True,
+    ):
+    """
+    Search for Gaia DR3 stellar sources around a given target.
+
+    Parameters
+    ----------
+    ra_source: Float
+        Right ascension (deg) of target to query around.
+    dec_source: Float
+        Declination (deg) of target to query around.
+    max_angular_distance: Float
+        Maximum angular distance from target to consider (arcsec).
+        Consider that the visit splitting distance for NIRSpec TA is 38"
+    raise_errors: Bool
+        If True and there was an error while requesting the data,
+        raise the error.
+        If False and there was an error, print error to screen and
+        return a string identifying some known error types.
+
+    Returns
+    -------
+    names: 1D string array
+        Gaia DR3 stellar source names within max_separation from target
+    G_mag: 1D float array
+        Gaia G magnitude of found stellar sources
+    teff: 1D float array
+        Effective temperature (K) of found stellar source
+    log_g: 1D float array
+        log(g) of found stellar sources
+    ra: 1D float array
+        Right ascension (deg) of found stellar sources
+    dec: 1D float array
+        Declination (deg) of found stellar sources
+    separation: 1D float array
+        Angular separation (arcsec) of found stellar sources from target
+
+    Examples
+    --------
+    >>> import gen_tso.catalogs as cat
+
+    >>> # Stellar sources around WASP-69:
+    >>> ra_source = 315.0259661
+    >>> dec_source = -5.094857
+    >>> cat.fetch_gaia_targets(ra_source, dec_source)
+    """
+    max_sep_degrees = max_separation / 3600.0
+
+    try:
+        job = Gaia.launch_job_async(
+            f"""
+            SELECT * \
+            FROM gaiadr3.gaia_source \
+            WHERE CONTAINS(\
+                POINT(gaiadr3.gaia_source.ra, gaiadr3.gaia_source.dec),
+                CIRCLE({ra_source}, {dec_source}, {max_sep_degrees}))=1;""",
+            dump_to_file=False,
+        )
+    except Exception as e:
+        err_text = f"Gaia astroquery request failed with {e.__class__.__name__}"
+        if isinstance(e, socket.gaierror):
+            print(
+                f"\n{err_text}\n{str(e)}\n"
+                "Likely there's no internet connection at the moment\n"
+            )
+            exception = 'gaierror'
+        elif isinstance(e, requests.exceptions.HTTPError):
+            print(
+                f"\n{err_text}\n{str(e)}\n"
+                f"Probably the ESA server is down at the moment\n"
+            )
+            exception = 'gaierror'
+        elif isinstance(e, ssl.SSLError):
+            print(
+                f"\n{err_text}\n{str(e)}\n"
+                "If you got a 'SSL: CERTIFICATE_VERIFY_FAILED' error on an "
+                "OSX machine, try following the steps on this link: "
+                "https://stackoverflow.com/a/42334357 which will point you to "
+                "the ReadMe.rtf file in your Applications/Python 3.X folder\n"
+            )
+            exception = 'ssl'
+        else:
+            print(f"\n{err_text}\n{str(e)}")
+            exception = 'other'
+        if raise_errors:
+            raise e
+        return exception
+
+    resp = job.get_results()
+    targets = resp[~resp['teff_gspphot'].mask]
+
+    c1 = SkyCoord(ra_source, dec_source, unit='deg', frame='icrs')
+    separation = []
+    for i,target in enumerate(targets):
+        c2 = SkyCoord(target['ra'], target['dec'], unit='deg', frame='icrs')
+        sep = c1.separation(c2).to('arcsec').value
+        separation.append(sep)
+
+    sep_isort = np.argsort(separation)
+    for i,idx in enumerate(sep_isort):
+        target = targets[idx]
+
+    return (
+            targets['DESIGNATION'].data.data[sep_isort],
+            targets['phot_g_mean_mag'].data.data[sep_isort],
+            targets['teff_gspphot'].data.data[sep_isort],
+            targets['logg_gspphot'].data.data[sep_isort],
+            targets['ra'].data.data[sep_isort],
+            targets['dec'].data.data[sep_isort],
+            np.array(separation)[sep_isort],
+    )
+
diff --git a/gen_tso/catalogs/utils.py b/gen_tso/catalogs/utils.py
index 81e64b3..b91c599 100644
--- a/gen_tso/catalogs/utils.py
+++ b/gen_tso/catalogs/utils.py
@@ -6,6 +6,8 @@
 """
 
 __all__ = [
+    'esasky_js_circle',
+    'esasky_js_catalog',
     'normalize_name',
     'is_letter',
     'is_candidate',
@@ -22,6 +24,149 @@
 import numpy as np
 
 
+def esasky_js_circle(ra, dec, radius, color='#15B01A'):
+    """
+    Construct a JS command to draw a circle footprint for ESASky
+
+    Parameters
+    ----------
+    ra: Float
+        Right ascention of the center of the circle footprint (deg).
+    dec: Float
+        Declination of the center of the circle footprint (deg).
+    radius: Float
+        Radius of the circle footprint (deg).
+
+    Returns
+    -------
+    footprint: Dictionary
+        A dictionary with the command to draw a circle footprint
+        when converted to JSON format, e.g.:
+        command = json.dumps(footprint)
+
+    For details on the ESASky JS API see:
+    https://www.cosmos.esa.int/web/esdc/esasky-javascript-api
+
+    Examples
+    --------
+    >>> import gen_tso.catalogs.utils as u
+    >>> ra = 315.0259661
+    >>> dec = -5.094857
+    >>> radius = 80.0
+    >>> circle = u.esasky_js_circle(ra, dec, radius)
+    """
+    footprint = {
+        'event': 'overlayFootprints',
+        'content': {
+            'overlaySet': {
+                'type': 'FootprintListOverlay',
+                'overlayName': 'visit splitting distance',
+                'cooframe': 'J2000',
+                'color': color,
+                'lineWidth': 5,
+                'skyObjectList': [
+                    {'name': 'visit splitting distance',
+                     'id': 1,
+                     'stcs': f'CIRCLE ICRS {ra:.8f} {dec:.8f} {radius/3600:.4f}',
+                     'ra_deg': f'{ra:.8f}',
+                     'dec_deg': f'{dec:.8f}',
+                    }
+                ]
+            }
+        }
+    }
+    return footprint
+
+
+def json_target_property(name, value, format):
+    """
+    Create a json dictionary of a target's property (to be used on
+    an overlayCatalog for ESASky).
+    """
+    prop = {
+        'name': name,
+        'value': f'{value:{format}}',
+        'type': 'STRING'
+    }
+    return prop
+
+
+def json_target(index, name, ra, dec, g_mag, teff, logg, separation):
+    """
+    Create a json dictionary of a target (to be used on an overlayCatalog
+    for ESASky).
+    """
+    data = [
+        json_target_property('G mag', g_mag[index], '.2f'),
+        json_target_property('T eff', teff[index], '.1f'),
+        json_target_property('log(g)', logg[index], '.2f'),
+        json_target_property('Separation', separation[index], '.3f'),
+    ]
+
+    target = {
+        'name': name[index],
+        'id': index+1,
+        'ra': f'{ra[index]:.8f}',
+        'dec': f'{dec[index]:.8f}',
+        'data': data,
+    }
+    return target
+
+
+def esasky_js_catalog(query):
+    """
+    Construct a JS command to draw an overlayCatalog footprint for ESASky
+
+    Parameters
+    ----------
+    query: List of arrays
+        A list of arrays containing the names, g_mag, teff, logg,
+        ra, dec, and separation of a set of targets (see Examples).
+
+    Returns
+    -------
+    command: Dictionary
+        A dictionary with the command to draw an overlayCatalog
+        when converted to JSON format, e.g.:
+        js_command = json.dumps(command)
+
+    For details on the ESASky JS API see:
+    https://www.cosmos.esa.int/web/esdc/esasky-javascript-api
+
+    Examples
+    --------
+    >>> import gen_tso.catalogs as cat
+    >>> import gen_tso.catalogs.utils as u
+
+    >>> # Stellar sources around WASP-69:
+    >>> ra_source = 315.0259661
+    >>> dec_source = -5.094857
+    >>> query = cat.fetch_gaia_targets(ra_source, dec_source)
+    >>> circle = u.esasky_js_catalog(query)
+    """
+    names, g_mag, teff, logg, ra, dec, separation = query
+    ntargets = len(names)
+    targets = []
+    for i in range(ntargets):
+        target = json_target(i, names, ra, dec, g_mag, teff, logg, separation)
+        targets.append(target)
+
+    command = {
+        "event": 'overlayCatalogue',
+        'content': {
+            'overlaySet': {
+                'type': 'SourceListOverlay',
+                'overlayName': 'Nearby Gaia sources',
+                'cooframe': 'J2000',
+                'color': '#ee2345',
+                'lineWidth': 10,
+                'skyObjectList': targets,
+            }
+        }
+    }
+    return command
+
+
 def normalize_name(target):
     """
     Normalize target names into a 'more standard' format.
diff --git a/gen_tso/data/base_theme.css b/gen_tso/data/base_theme.css
new file mode 100644
index 0000000..f7c420d
--- /dev/null
+++ b/gen_tso/data/base_theme.css
@@ -0,0 +1,5 @@
+@import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&family=Source+Code+Pro:ital,wght@0,400;0,600;1,400;1,600&display=swap");:root{--bslib-bootstrap-version: 5;--bslib-preset-name: shiny;--bslib-preset-type: builtin}/*!
+   * 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: #007bc2;--bs-indigo: #4b00c1;--bs-purple: #74149c;--bs-pink: #bf007f;--bs-red: #c10000;--bs-orange: #f45100;--bs-yellow: #f9b928;--bs-green: #00891a;--bs-teal: #00bf7f;--bs-cyan: #03c7e8;--bs-black: #000;--bs-white: #fff;--bs-gray: #707782;--bs-gray-dark: #343A46;--bs-gray-100: #f8f8f8;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #cdd4da;--bs-gray-500: #8D959E;--bs-gray-600: #707782;--bs-gray-700: #48505F;--bs-gray-800: #343A46;--bs-gray-900: #1D1F21;--bs-default: #dee2e6;--bs-primary: #007bc2;--bs-secondary: #404040;--bs-success: #00891a;--bs-info: #03c7e8;--bs-warning: #f9b928;--bs-danger: #c10000;--bs-light: #f8f8f8;--bs-dark: #202020;--bs-default-rgb: 222,226,230;--bs-primary-rgb: 0,123,194;--bs-secondary-rgb: 64,64,64;--bs-success-rgb: 0,137,26;--bs-info-rgb: 3,199,232;--bs-warning-rgb: 249,185,40;--bs-danger-rgb: 193,0,0;--bs-light-rgb: 248,248,248;--bs-dark-rgb: 32,32,32;--bs-primary-text-emphasis: #00314e;--bs-secondary-text-emphasis: #1a1a1a;--bs-success-text-emphasis: #00370a;--bs-info-text-emphasis: #01505d;--bs-warning-text-emphasis: #644a10;--bs-danger-text-emphasis: #4d0000;--bs-light-text-emphasis: #48505F;--bs-dark-text-emphasis: #48505F;--bs-primary-bg-subtle: #cce5f3;--bs-secondary-bg-subtle: #d9d9d9;--bs-success-bg-subtle: #cce7d1;--bs-info-bg-subtle: #cdf4fa;--bs-warning-bg-subtle: #fef1d4;--bs-danger-bg-subtle: #f3cccc;--bs-light-bg-subtle: #fcfcfc;--bs-dark-bg-subtle: #cdd4da;--bs-primary-border-subtle: #99cae7;--bs-secondary-border-subtle: #b3b3b3;--bs-success-border-subtle: #99d0a3;--bs-info-border-subtle: #9ae9f6;--bs-warning-border-subtle: #fde3a9;--bs-danger-border-subtle: #e69999;--bs-light-border-subtle: #e9ecef;--bs-dark-border-subtle: #8D959E;--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: "Source Code Pro", 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-body-font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--bs-body-font-size:1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #1D1F21;--bs-body-color-rgb: 29,31,33;--bs-body-bg: #fff;--bs-body-bg-rgb: 255,255,255;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0,0,0;--bs-secondary-color: rgba(29,31,33,0.75);--bs-secondary-color-rgb: 29,31,33;--bs-secondary-bg: #e9ecef;--bs-secondary-bg-rgb: 233,236,239;--bs-tertiary-color: rgba(29,31,33,0.5);--bs-tertiary-color-rgb: 29,31,33;--bs-tertiary-bg: #f8f8f8;--bs-tertiary-bg-rgb: 248,248,248;--bs-heading-color: inherit;--bs-link-color: #007bc2;--bs-link-color-rgb: 0,123,194;--bs-link-decoration: underline;--bs-link-hover-color: #00629b;--bs-link-hover-color-rgb: 0,98,155;--bs-code-color: RGB(var(--bs-emphasis-color-rgb, 0, 0, 0));--bs-highlight-bg: #fef1d4;--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: #dee2e6;--bs-border-color-translucent: rgba(40,70,94,0.1);--bs-border-radius: 3px;--bs-border-radius-sm: .25rem;--bs-border-radius-lg: .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: 0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08);--bs-box-shadow-sm: 0px 0px 2px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.14),0px 2px 4px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.16);--bs-box-shadow-lg: 0px 4px 10px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.17);--bs-box-shadow-inset: inset 0 1px 2px rgba(0,0,0,0.075);--bs-focus-ring-width: .25rem;--bs-focus-ring-opacity: .25;--bs-focus-ring-color: rgba(0,123,194,0.25);--bs-form-valid-color: #00891a;--bs-form-valid-border-color: #00891a;--bs-form-invalid-color: #c10000;--bs-form-invalid-border-color: #c10000}[data-bs-theme="dark"]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222,226,230;--bs-body-bg: #1D1F21;--bs-body-bg-rgb: 29,31,33;--bs-emphasis-color: #fff;--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: #343A46;--bs-secondary-bg-rgb: 52,58,70;--bs-tertiary-color: rgba(222,226,230,0.5);--bs-tertiary-color-rgb: 222,226,230;--bs-tertiary-bg: #292d34;--bs-tertiary-bg-rgb: 41,45,52;--bs-primary-text-emphasis: #66b0da;--bs-secondary-text-emphasis: #8c8c8c;--bs-success-text-emphasis: #66b876;--bs-info-text-emphasis: #68ddf1;--bs-warning-text-emphasis: #fbd57e;--bs-danger-text-emphasis: #da6666;--bs-light-text-emphasis: #f8f8f8;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: #001927;--bs-secondary-bg-subtle: #0d0d0d;--bs-success-bg-subtle: #001b05;--bs-info-bg-subtle: #01282e;--bs-warning-bg-subtle: #322508;--bs-danger-bg-subtle: #270000;--bs-light-bg-subtle: #343A46;--bs-dark-bg-subtle: #1a1d23;--bs-primary-border-subtle: #004a74;--bs-secondary-border-subtle: #262626;--bs-success-border-subtle: #005210;--bs-info-border-subtle: #02778b;--bs-warning-border-subtle: #956f18;--bs-danger-border-subtle: #740000;--bs-light-border-subtle: #48505F;--bs-dark-border-subtle: #343A46;--bs-heading-color: inherit;--bs-link-color: #66b0da;--bs-link-hover-color: #85c0e1;--bs-link-color-rgb: 102,176,218;--bs-link-hover-color-rgb: 133,192,225;--bs-code-color: RGB(var(--bs-emphasis-color-rgb, 0, 0, 0));--bs-border-color: #495057;--bs-border-color-translucent: rgba(255,255,255,0.1);--bs-form-valid-color: #66b876;--bs-form-valid-border-color: #66b876;--bs-form-invalid-color: #da6666;--bs-form-invalid-border-color: #da6666}*,*::before,*::after{box-sizing:border-box}@media (prefers-reduced-motion: no-preference){:root{scroll-behavior:smooth}}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:2rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:.25}h6,.h6,h5,.h5,h4,.h4,h3,.h3,h2,.h2,h1,.h1{margin-top:0;margin-bottom:.5rem;font-weight:400;line-height:1.2;color:var(--bs-heading-color)}h1,.h1{font-size:calc(1.335rem + 1.02vw)}@media (min-width: 1200px){h1,.h1{font-size:2.1rem}}h2,.h2{font-size:calc(1.325rem + .9vw)}@media (min-width: 1200px){h2,.h2{font-size:2rem}}h3,.h3{font-size:calc(1.3rem + .6vw)}@media (min-width: 1200px){h3,.h3{font-size:1.75rem}}h4,.h4{font-size:calc(1.275rem + .3vw)}@media (min-width: 1200px){h4,.h4{font-size:1.5rem}}h5,.h5{font-size:1.25rem}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:.875em}mark,.mark{padding:.1875em;background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.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:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em;color:RGB(var(--bs-emphasis-color-rgb, 0, 0, 0));background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.04);padding:.5rem;border:1px solid var(--bs-border-color, #dee2e6);border-radius:3px}pre code{background-color:transparent;font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.04);border-radius:3px;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);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:var(--bs-secondary-color);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 + .3vw);line-height:inherit}@media (min-width: 1200px){legend{font-size:1.5rem}}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);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-1{font-size:5rem}}.display-2{font-size:calc(1.575rem + 3.9vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-2{font-size:4.5rem}}.display-3{font-size:calc(1.525rem + 3.3vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-3{font-size:4rem}}.display-4{font-size:calc(1.475rem + 2.7vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-4{font-size:3.5rem}}.display-5{font-size:calc(1.425rem + 2.1vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-5{font-size:3rem}}.display-6{font-size:calc(1.375rem + 1.5vw);font-weight:300;line-height:1.2}@media (min-width: 1200px){.display-6{font-size:2.5rem}}.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:.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:.875em;color:#707782}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--bs-secondary-color)}.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}.row{--bs-gutter-x: 1.5rem;--bs-gutter-y: 0;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;-webkit-flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.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}}.col{flex:1 0 0%;-webkit-flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.row-cols-4>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;-webkit-flex:0 0 auto;width:8.33333%}.col-2{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-3{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.col-5{flex:0 0 auto;-webkit-flex:0 0 auto;width:41.66667%}.col-6{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;-webkit-flex:0 0 auto;width:58.33333%}.col-8{flex:0 0 auto;-webkit-flex:0 0 auto;width:66.66667%}.col-9{flex:0 0 auto;-webkit-flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;-webkit-flex:0 0 auto;width:83.33333%}.col-11{flex:0 0 auto;-webkit-flex:0 0 auto;width:91.66667%}.col-12{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333%}.offset-2{margin-left:16.66667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333%}.offset-5{margin-left:41.66667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333%}.offset-8{margin-left:66.66667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333%}.offset-11{margin-left:91.66667%}.g-0,.gx-0{--bs-gutter-x: 0}.g-0,.gy-0{--bs-gutter-y: 0}.g-1,.gx-1{--bs-gutter-x: .25rem}.g-1,.gy-1{--bs-gutter-y: .25rem}.g-2,.gx-2{--bs-gutter-x: .5rem}.g-2,.gy-2{--bs-gutter-y: .5rem}.g-3,.gx-3{--bs-gutter-x: 1rem}.g-3,.gy-3{--bs-gutter-y: 1rem}.g-4,.gx-4{--bs-gutter-x: 1.5rem}.g-4,.gy-4{--bs-gutter-y: 1.5rem}.g-5,.gx-5{--bs-gutter-x: 3rem}.g-5,.gy-5{--bs-gutter-y: 3rem}@media (min-width: 576px){.col-sm{flex:1 0 0%;-webkit-flex:1 0 0%}.row-cols-sm-auto>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.row-cols-sm-4>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-sm-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;-webkit-flex:0 0 auto;width:8.33333%}.col-sm-2{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-sm-3{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.col-sm-5{flex:0 0 auto;-webkit-flex:0 0 auto;width:41.66667%}.col-sm-6{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;-webkit-flex:0 0 auto;width:58.33333%}.col-sm-8{flex:0 0 auto;-webkit-flex:0 0 auto;width:66.66667%}.col-sm-9{flex:0 0 auto;-webkit-flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;-webkit-flex:0 0 auto;width:83.33333%}.col-sm-11{flex:0 0 auto;-webkit-flex:0 0 auto;width:91.66667%}.col-sm-12{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333%}.offset-sm-2{margin-left:16.66667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333%}.offset-sm-5{margin-left:41.66667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333%}.offset-sm-8{margin-left:66.66667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333%}.offset-sm-11{margin-left:91.66667%}.g-sm-0,.gx-sm-0{--bs-gutter-x: 0}.g-sm-0,.gy-sm-0{--bs-gutter-y: 0}.g-sm-1,.gx-sm-1{--bs-gutter-x: .25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y: .25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x: .5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y: .5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x: 1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y: 1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x: 1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y: 1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x: 3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y: 3rem}}@media (min-width: 768px){.col-md{flex:1 0 0%;-webkit-flex:1 0 0%}.row-cols-md-auto>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.row-cols-md-4>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-md-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;-webkit-flex:0 0 auto;width:8.33333%}.col-md-2{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-md-3{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.col-md-5{flex:0 0 auto;-webkit-flex:0 0 auto;width:41.66667%}.col-md-6{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;-webkit-flex:0 0 auto;width:58.33333%}.col-md-8{flex:0 0 auto;-webkit-flex:0 0 auto;width:66.66667%}.col-md-9{flex:0 0 auto;-webkit-flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;-webkit-flex:0 0 auto;width:83.33333%}.col-md-11{flex:0 0 auto;-webkit-flex:0 0 auto;width:91.66667%}.col-md-12{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333%}.offset-md-2{margin-left:16.66667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333%}.offset-md-5{margin-left:41.66667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333%}.offset-md-8{margin-left:66.66667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333%}.offset-md-11{margin-left:91.66667%}.g-md-0,.gx-md-0{--bs-gutter-x: 0}.g-md-0,.gy-md-0{--bs-gutter-y: 0}.g-md-1,.gx-md-1{--bs-gutter-x: .25rem}.g-md-1,.gy-md-1{--bs-gutter-y: .25rem}.g-md-2,.gx-md-2{--bs-gutter-x: .5rem}.g-md-2,.gy-md-2{--bs-gutter-y: .5rem}.g-md-3,.gx-md-3{--bs-gutter-x: 1rem}.g-md-3,.gy-md-3{--bs-gutter-y: 1rem}.g-md-4,.gx-md-4{--bs-gutter-x: 1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y: 1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x: 3rem}.g-md-5,.gy-md-5{--bs-gutter-y: 3rem}}@media (min-width: 992px){.col-lg{flex:1 0 0%;-webkit-flex:1 0 0%}.row-cols-lg-auto>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.row-cols-lg-4>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-lg-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;-webkit-flex:0 0 auto;width:8.33333%}.col-lg-2{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-lg-3{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.col-lg-5{flex:0 0 auto;-webkit-flex:0 0 auto;width:41.66667%}.col-lg-6{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;-webkit-flex:0 0 auto;width:58.33333%}.col-lg-8{flex:0 0 auto;-webkit-flex:0 0 auto;width:66.66667%}.col-lg-9{flex:0 0 auto;-webkit-flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;-webkit-flex:0 0 auto;width:83.33333%}.col-lg-11{flex:0 0 auto;-webkit-flex:0 0 auto;width:91.66667%}.col-lg-12{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333%}.offset-lg-2{margin-left:16.66667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333%}.offset-lg-5{margin-left:41.66667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333%}.offset-lg-8{margin-left:66.66667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333%}.offset-lg-11{margin-left:91.66667%}.g-lg-0,.gx-lg-0{--bs-gutter-x: 0}.g-lg-0,.gy-lg-0{--bs-gutter-y: 0}.g-lg-1,.gx-lg-1{--bs-gutter-x: .25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y: .25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x: .5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y: .5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x: 1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y: 1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x: 1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y: 1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x: 3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y: 3rem}}@media (min-width: 1200px){.col-xl{flex:1 0 0%;-webkit-flex:1 0 0%}.row-cols-xl-auto>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.row-cols-xl-4>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-xl-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;-webkit-flex:0 0 auto;width:8.33333%}.col-xl-2{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-xl-3{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.col-xl-5{flex:0 0 auto;-webkit-flex:0 0 auto;width:41.66667%}.col-xl-6{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;-webkit-flex:0 0 auto;width:58.33333%}.col-xl-8{flex:0 0 auto;-webkit-flex:0 0 auto;width:66.66667%}.col-xl-9{flex:0 0 auto;-webkit-flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;-webkit-flex:0 0 auto;width:83.33333%}.col-xl-11{flex:0 0 auto;-webkit-flex:0 0 auto;width:91.66667%}.col-xl-12{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333%}.offset-xl-2{margin-left:16.66667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333%}.offset-xl-5{margin-left:41.66667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333%}.offset-xl-8{margin-left:66.66667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333%}.offset-xl-11{margin-left:91.66667%}.g-xl-0,.gx-xl-0{--bs-gutter-x: 0}.g-xl-0,.gy-xl-0{--bs-gutter-y: 0}.g-xl-1,.gx-xl-1{--bs-gutter-x: .25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y: .25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x: .5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y: .5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x: 1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y: 1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x: 1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y: 1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x: 3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y: 3rem}}@media (min-width: 1400px){.col-xxl{flex:1 0 0%;-webkit-flex:1 0 0%}.row-cols-xxl-auto>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.row-cols-xxl-4>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-xxl-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;-webkit-flex:0 0 auto;width:8.33333%}.col-xxl-2{flex:0 0 auto;-webkit-flex:0 0 auto;width:16.66667%}.col-xxl-3{flex:0 0 auto;-webkit-flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;-webkit-flex:0 0 auto;width:33.33333%}.col-xxl-5{flex:0 0 auto;-webkit-flex:0 0 auto;width:41.66667%}.col-xxl-6{flex:0 0 auto;-webkit-flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;-webkit-flex:0 0 auto;width:58.33333%}.col-xxl-8{flex:0 0 auto;-webkit-flex:0 0 auto;width:66.66667%}.col-xxl-9{flex:0 0 auto;-webkit-flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;-webkit-flex:0 0 auto;width:83.33333%}.col-xxl-11{flex:0 0 auto;-webkit-flex:0 0 auto;width:91.66667%}.col-xxl-12{flex:0 0 auto;-webkit-flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333%}.offset-xxl-2{margin-left:16.66667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333%}.offset-xxl-5{margin-left:41.66667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333%}.offset-xxl-8{margin-left:66.66667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333%}.offset-xxl-11{margin-left:91.66667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x: 0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y: 0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x: .25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y: .25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x: .5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y: .5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x: 1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y: 1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x: 1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y: 1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x: 3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y: 3rem}}.table{--bs-table-color-type: initial;--bs-table-bg-type: initial;--bs-table-color-state: initial;--bs-table-bg-state: initial;--bs-table-color: var(--bs-body-color);--bs-table-bg: var(--bs-body-bg);--bs-table-border-color: var(--bs-border-color);--bs-table-accent-bg: rgba(0,0,0,0);--bs-table-striped-color: var(--bs-body-color);--bs-table-striped-bg: rgba(0,123,194,0.06);--bs-table-active-color: var(--bs-body-color);--bs-table-active-bg: rgba(0,0,0,0.1);--bs-table-hover-color: var(--bs-body-color);--bs-table-hover-bg: rgba(0,123,194,0.1);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:var(--bs-border-width);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(var(--bs-border-width) * 2) solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:var(--bs-border-width) 0}.table-bordered>:not(caption)>*>*{border-width:0 var(--bs-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(even)>*{--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: #cce5f3;--bs-table-border-color: #b8cedb;--bs-table-striped-bg: #c2dae7;--bs-table-striped-color: #000;--bs-table-active-bg: #b8cedb;--bs-table-active-color: #000;--bs-table-hover-bg: #bdd4e1;--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: #d9d9d9;--bs-table-border-color: #c3c3c3;--bs-table-striped-bg: #cecece;--bs-table-striped-color: #000;--bs-table-active-bg: #c3c3c3;--bs-table-active-color: #000;--bs-table-hover-bg: #c9c9c9;--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: #cce7d1;--bs-table-border-color: #b8d0bc;--bs-table-striped-bg: #c2dbc7;--bs-table-striped-color: #000;--bs-table-active-bg: #b8d0bc;--bs-table-active-color: #000;--bs-table-hover-bg: #bdd6c1;--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: #cdf4fa;--bs-table-border-color: #b9dce1;--bs-table-striped-bg: #c3e8ee;--bs-table-striped-color: #000;--bs-table-active-bg: #b9dce1;--bs-table-active-color: #000;--bs-table-hover-bg: #bee2e7;--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: #fef1d4;--bs-table-border-color: #e5d9bf;--bs-table-striped-bg: #f1e5c9;--bs-table-striped-color: #000;--bs-table-active-bg: #e5d9bf;--bs-table-active-color: #000;--bs-table-hover-bg: #ebdfc4;--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: #f3cccc;--bs-table-border-color: #dbb8b8;--bs-table-striped-bg: #e7c2c2;--bs-table-striped-color: #000;--bs-table-active-bg: #dbb8b8;--bs-table-active-color: #000;--bs-table-hover-bg: #e1bdbd;--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: #f8f8f8;--bs-table-border-color: #dfdfdf;--bs-table-striped-bg: #ececec;--bs-table-striped-color: #000;--bs-table-active-bg: #dfdfdf;--bs-table-active-color: #000;--bs-table-hover-bg: #e5e5e5;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color: #fff;--bs-table-bg: #202020;--bs-table-border-color: #363636;--bs-table-striped-bg: #2b2b2b;--bs-table-striped-color: #fff;--bs-table-active-bg: #363636;--bs-table-active-color: #fff;--bs-table-hover-bg: #313131;--bs-table-hover-color: #fff;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(.375rem + var(--bs-border-width));padding-bottom:calc(.375rem + var(--bs-border-width));margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + var(--bs-border-width));padding-bottom:calc(.5rem + var(--bs-border-width));font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + var(--bs-border-width));padding-bottom:calc(.25rem + var(--bs-border-width));font-size:.875rem}.form-text,.help-text,.help-block{margin-top:.25rem;font-size:.875em;color:#707782}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:.9375rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid #8D959E;border-radius:var(--bs-border-radius);transition:border-color 0.15s ease-in-out,box-shadow 0.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:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#80bde1;outline:0;box-shadow:0 0 0 .25rem rgba(0,123,194,0.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:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;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}@media (prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:var(--bs-body-color);background-color:transparent;border:solid transparent;border-width:var(--bs-border-width) 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 + .5rem + calc(var(--bs-border-width) * 2));padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0 !important;border-radius:var(--bs-border-radius)}.form-control-color::-webkit-color-swatch{border:0 !important;border-radius:var(--bs-border-radius)}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 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='%23343A46' 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:.9375rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:var(--bs-body-bg);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:var(--bs-border-width) solid #8D959E;border-radius:var(--bs-border-radius);transition:border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-select{transition:none}}.form-select:focus{border-color:#80bde1;outline:0;box-shadow:0 0 0 .25rem rgba(0,123,194,0.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:var(--bs-secondary-bg)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--bs-body-color)}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}[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:.25rem}.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: var(--bs-body-bg);width:1.2em;height:1.2em;margin-top:.15em;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:var(--bs-border-width) solid #8D959E;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:2px}.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:#80bde1;outline:0;box-shadow:0 0 0 .25rem rgba(0,123,194,0.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:#007bc2;border-color:#007bc2}.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='%23fff' 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='%23fff'/%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:#007bc2;border-color:#007bc2;--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='%23fff' 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 0.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='%2380bde1'/%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='%23fff'/%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:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(0,123,194,0.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(0,123,194,0.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none;background-color:#007bc2;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b3d7ed}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-tertiary-bg);border-color:transparent;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:#007bc2;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#b3d7ed}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-tertiary-bg);border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--bs-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--bs-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--bs-border-width) * 2));min-height:calc(3.5rem + calc(var(--bs-border-width) * 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:var(--bs-border-width) solid transparent;transform-origin:0 0;transition:opacity 0.1s ease-in-out,transform 0.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:transparent}.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), .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:var(--bs-body-bg);border-radius:var(--bs-border-radius)}.form-floating>.form-control:-webkit-autofill~label{color:rgba(var(--bs-body-color-rgb), .65);transform:scale(0.85) translateY(-0.5rem) translateX(0.15rem)}.form-floating>.form-control-plaintext~label{border-width:var(--bs-border-width) 0}.form-floating>:disabled~label,.form-floating>.form-control:disabled~label{color:#707782}.form-floating>:disabled~label::after,.form-floating>.form-control:disabled~label::after{background-color:var(--bs-secondary-bg)}.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:.9375rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);text-align:center;white-space:nowrap;background-color:var(--bs-tertiary-bg);border:var(--bs-border-width) solid #8D959E;border-radius:var(--bs-border-radius)}.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:var(--bs-border-radius-lg)}.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:.875rem;border-radius:var(--bs-border-radius-sm)}.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(var(--bs-border-width) * -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:.875em;color:var(--bs-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-success);border-radius:var(--bs-border-radius)}.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:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2300891a' 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(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb), 0.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:valid,.form-select.is-valid{border-color:var(--bs-form-valid-border-color)}.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='%2300891a' 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(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:valid:focus,.form-select.is-valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb), 0.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:calc(3rem + calc(1.5em + .75rem))}.was-validated .form-check-input:valid,.form-check-input.is-valid{border-color:var(--bs-form-valid-border-color)}.was-validated .form-check-input:valid:checked,.form-check-input.is-valid:checked{background-color:var(--bs-form-valid-color)}.was-validated .form-check-input:valid:focus,.form-check-input.is-valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb), 0.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:var(--bs-form-valid-color)}.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:.875em;color:var(--bs-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-danger);border-radius:var(--bs-border-radius)}.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:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .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='%23c10000'%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='%23c10000' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb), 0.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .form-select:invalid,.form-select.is-invalid{border-color:var(--bs-form-invalid-border-color)}.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='%23c10000'%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='%23c10000' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-select:invalid:focus,.form-select.is-invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb), 0.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid{width:calc(3rem + calc(1.5em + .75rem))}.was-validated .form-check-input:invalid,.form-check-input.is-invalid{border-color:var(--bs-form-invalid-border-color)}.was-validated .form-check-input:invalid:checked,.form-check-input.is-invalid:checked{background-color:var(--bs-form-invalid-color)}.was-validated .form-check-input:invalid:focus,.form-check-input.is-invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb), 0.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:var(--bs-form-invalid-color)}.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: 2em;--bs-btn-padding-y: .75em;--bs-btn-font-family: ;--bs-btn-font-size:.9375rem;--bs-btn-font-weight: 500;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--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: .65;--bs-btn-focus-box-shadow: 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 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}@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,.btn.in{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,.btn.in: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: #e3e6ea;--bs-btn-hover-border-color: #e1e5e9;--bs-btn-focus-shadow-rgb: 189,192,196;--bs-btn-active-color: #000;--bs-btn-active-bg: #e5e8eb;--bs-btn-active-border-color: #e1e5e9;--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: #fff;--bs-btn-bg: #007bc2;--bs-btn-border-color: #007bc2;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0069a5;--bs-btn-hover-border-color: #00629b;--bs-btn-focus-shadow-rgb: 38,143,203;--bs-btn-active-color: #fff;--bs-btn-active-bg: #00629b;--bs-btn-active-border-color: #005c92;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #007bc2;--bs-btn-disabled-border-color: #007bc2}.btn-secondary{--bs-btn-color: #fff;--bs-btn-bg: #404040;--bs-btn-border-color: #404040;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #363636;--bs-btn-hover-border-color: #333;--bs-btn-focus-shadow-rgb: 93,93,93;--bs-btn-active-color: #fff;--bs-btn-active-bg: #333;--bs-btn-active-border-color: #303030;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #404040;--bs-btn-disabled-border-color: #404040}.btn-success{--bs-btn-color: #fff;--bs-btn-bg: #00891a;--bs-btn-border-color: #00891a;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #007416;--bs-btn-hover-border-color: #006e15;--bs-btn-focus-shadow-rgb: 38,155,60;--bs-btn-active-color: #fff;--bs-btn-active-bg: #006e15;--bs-btn-active-border-color: #006714;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #00891a;--bs-btn-disabled-border-color: #00891a}.btn-info{--bs-btn-color: #000;--bs-btn-bg: #03c7e8;--bs-btn-border-color: #03c7e8;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #29cfeb;--bs-btn-hover-border-color: #1ccdea;--bs-btn-focus-shadow-rgb: 3,169,197;--bs-btn-active-color: #000;--bs-btn-active-bg: #35d2ed;--bs-btn-active-border-color: #1ccdea;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #03c7e8;--bs-btn-disabled-border-color: #03c7e8}.btn-warning{--bs-btn-color: #000;--bs-btn-bg: #f9b928;--bs-btn-border-color: #f9b928;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #fac448;--bs-btn-hover-border-color: #fac03e;--bs-btn-focus-shadow-rgb: 212,157,34;--bs-btn-active-color: #000;--bs-btn-active-bg: #fac753;--bs-btn-active-border-color: #fac03e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f9b928;--bs-btn-disabled-border-color: #f9b928}.btn-danger{--bs-btn-color: #fff;--bs-btn-bg: #c10000;--bs-btn-border-color: #c10000;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #a40000;--bs-btn-hover-border-color: #9a0000;--bs-btn-focus-shadow-rgb: 202,38,38;--bs-btn-active-color: #fff;--bs-btn-active-bg: #9a0000;--bs-btn-active-border-color: #910000;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #c10000;--bs-btn-disabled-border-color: #c10000}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f8f8;--bs-btn-border-color: #f8f8f8;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d3d3;--bs-btn-hover-border-color: #c6c6c6;--bs-btn-focus-shadow-rgb: 211,211,211;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c6c6;--bs-btn-active-border-color: #bababa;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f8f8;--bs-btn-disabled-border-color: #f8f8f8}.btn-dark{--bs-btn-color: #fff;--bs-btn-bg: #202020;--bs-btn-border-color: #202020;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #414141;--bs-btn-hover-border-color: #363636;--bs-btn-focus-shadow-rgb: 65,65,65;--bs-btn-active-color: #fff;--bs-btn-active-bg: #4d4d4d;--bs-btn-active-border-color: #363636;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #202020;--bs-btn-disabled-border-color: #202020}.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: #007bc2;--bs-btn-border-color: #007bc2;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #007bc2;--bs-btn-hover-border-color: #007bc2;--bs-btn-focus-shadow-rgb: 0,123,194;--bs-btn-active-color: #fff;--bs-btn-active-bg: #007bc2;--bs-btn-active-border-color: #007bc2;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #007bc2;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #007bc2;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-secondary{--bs-btn-color: #404040;--bs-btn-border-color: #404040;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #404040;--bs-btn-hover-border-color: #404040;--bs-btn-focus-shadow-rgb: 64,64,64;--bs-btn-active-color: #fff;--bs-btn-active-bg: #404040;--bs-btn-active-border-color: #404040;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #404040;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #404040;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-success{--bs-btn-color: #00891a;--bs-btn-border-color: #00891a;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #00891a;--bs-btn-hover-border-color: #00891a;--bs-btn-focus-shadow-rgb: 0,137,26;--bs-btn-active-color: #fff;--bs-btn-active-bg: #00891a;--bs-btn-active-border-color: #00891a;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #00891a;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #00891a;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-info{--bs-btn-color: #03c7e8;--bs-btn-border-color: #03c7e8;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #03c7e8;--bs-btn-hover-border-color: #03c7e8;--bs-btn-focus-shadow-rgb: 3,199,232;--bs-btn-active-color: #000;--bs-btn-active-bg: #03c7e8;--bs-btn-active-border-color: #03c7e8;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #03c7e8;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #03c7e8;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-warning{--bs-btn-color: #f9b928;--bs-btn-border-color: #f9b928;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #f9b928;--bs-btn-hover-border-color: #f9b928;--bs-btn-focus-shadow-rgb: 249,185,40;--bs-btn-active-color: #000;--bs-btn-active-bg: #f9b928;--bs-btn-active-border-color: #f9b928;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #f9b928;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #f9b928;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-danger{--bs-btn-color: #c10000;--bs-btn-border-color: #c10000;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #c10000;--bs-btn-hover-border-color: #c10000;--bs-btn-focus-shadow-rgb: 193,0,0;--bs-btn-active-color: #fff;--bs-btn-active-bg: #c10000;--bs-btn-active-border-color: #c10000;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #c10000;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #c10000;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-light{--bs-btn-color: #f8f8f8;--bs-btn-border-color: #f8f8f8;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #f8f8f8;--bs-btn-hover-border-color: #f8f8f8;--bs-btn-focus-shadow-rgb: 248,248,248;--bs-btn-active-color: #000;--bs-btn-active-bg: #f8f8f8;--bs-btn-active-border-color: #f8f8f8;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #f8f8f8;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #f8f8f8;--bs-btn-bg: transparent;--bs-gradient: none}.btn-outline-dark{--bs-btn-color: #202020;--bs-btn-border-color: #202020;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #202020;--bs-btn-hover-border-color: #202020;--bs-btn-focus-shadow-rgb: 32,32,32;--bs-btn-active-color: #fff;--bs-btn-active-bg: #202020;--bs-btn-active-border-color: #202020;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #202020;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #202020;--bs-btn-bg: transparent;--bs-gradient: none}.btn-link{--bs-btn-font-weight: 400;--bs-btn-color: var(--bs-link-color);--bs-btn-bg: transparent;--bs-btn-border-color: transparent;--bs-btn-hover-color: var(--bs-link-hover-color);--bs-btn-hover-border-color: transparent;--bs-btn-active-color: var(--bs-link-hover-color);--bs-btn-active-border-color: transparent;--bs-btn-disabled-color: #707782;--bs-btn-disabled-border-color: transparent;--bs-btn-box-shadow: 0 0 0 #000;--bs-btn-focus-shadow-rgb: 38,143,203;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: .5rem;--bs-btn-padding-x: 1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius: var(--bs-border-radius-lg)}.btn-sm,.btn-group-sm>.btn{--bs-btn-padding-y: .25rem;--bs-btn-padding-x: .5rem;--bs-btn-font-size:.875rem;--bs-btn-border-radius: var(--bs-border-radius-sm)}.fade{transition:opacity 0.15s linear}@media (prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show):not(.in){opacity:0}.collapse:not(.show):not(.in){display:none}.collapsing{height:0;overflow:hidden;transition:height 0.35s ease}@media (prefers-reduced-motion: reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width 0.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 transparent;border-bottom:0;border-left:.3em solid transparent}.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: .5rem;--bs-dropdown-spacer: .125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color: var(--bs-body-color);--bs-dropdown-bg: var(--bs-body-bg);--bs-dropdown-border-color: var(--bs-border-color-translucent);--bs-dropdown-border-radius: var(--bs-border-radius);--bs-dropdown-border-width: var(--bs-border-width);--bs-dropdown-inner-border-radius: calc(var(--bs-border-radius) - var(--bs-border-width));--bs-dropdown-divider-bg: var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y: .5rem;--bs-dropdown-box-shadow: 0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08);--bs-dropdown-link-color: var(--bs-body-color);--bs-dropdown-link-hover-color: var(--bs-body-color);--bs-dropdown-link-hover-bg: var(--bs-tertiary-bg);--bs-dropdown-link-active-color: #fff;--bs-dropdown-link-active-bg: #007bc2;--bs-dropdown-link-disabled-color: var(--bs-tertiary-color);--bs-dropdown-item-padding-x: 1rem;--bs-dropdown-item-padding-y: .25rem;--bs-dropdown-header-color: #707782;--bs-dropdown-header-padding-x: 1rem;--bs-dropdown-header-padding-y: .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 transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.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 transparent;border-right:0;border-bottom:.3em solid transparent;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 transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider,.dropdown-menu>li.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,.dropdown-menu>li>a{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:transparent;border:0;border-radius:var(--bs-dropdown-item-border-radius, 0)}.dropdown-item:hover,.dropdown-menu>li>a:hover,.dropdown-item:focus,.dropdown-menu>li>a:focus{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-menu>li>a.active,.dropdown-item:active,.dropdown-menu>li>a:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-menu>li>a.disabled,.dropdown-item:disabled,.dropdown-menu>li>a:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show,.dropdown-menu.in{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.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: #343A46;--bs-dropdown-border-color: var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color: #dee2e6;--bs-dropdown-link-hover-color: #fff;--bs-dropdown-divider-bg: var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg: rgba(255,255,255,0.15);--bs-dropdown-link-active-color: #fff;--bs-dropdown-link-active-bg: #007bc2;--bs-dropdown-link-disabled-color: #8D959E;--bs-dropdown-header-color: #8D959E}.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:var(--bs-border-radius)}.btn-group>:not(.btn-check:first-child)+.btn,.btn-group>.btn-group:not(:first-child){margin-left:calc(var(--bs-border-width) * -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:1.5em;padding-left:1.5em}.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(var(--bs-border-width) * -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: .5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color: var(--bs-link-color);--bs-nav-link-hover-color: var(--bs-link-hover-color);--bs-nav-link-disabled-color: var(--bs-secondary-color);display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link,.nav-tabs>li>a,.nav-pills>li>a,:where(ul.nav.navbar-nav > li)>a{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 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.nav-link,.nav-tabs>li>a,.nav-pills>li>a,:where(ul.nav.navbar-nav > li)>a{transition:none}}.nav-link:hover,.nav-tabs>li>a:hover,.nav-pills>li>a:hover,:where(ul.nav.navbar-nav > li)>a:hover,.nav-link:focus,.nav-tabs>li>a:focus,.nav-pills>li>a:focus,:where(ul.nav.navbar-nav > li)>a:focus{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible,.nav-tabs>li>a:focus-visible,.nav-pills>li>a:focus-visible,:where(ul.nav.navbar-nav > li)>a:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(0,123,194,0.25)}.nav-link.disabled,.nav-tabs>li>a.disabled,.nav-pills>li>a.disabled,:where(ul.nav.navbar-nav > li)>a.disabled,.nav-link:disabled,.nav-tabs>li>a:disabled,.nav-pills>li>a:disabled,:where(ul.nav.navbar-nav > li)>a:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width: var(--bs-border-width);--bs-nav-tabs-border-color: var(--bs-border-color);--bs-nav-tabs-border-radius: var(--bs-border-radius);--bs-nav-tabs-link-hover-border-color: var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color);--bs-nav-tabs-link-active-color: var(--bs-emphasis-color);--bs-nav-tabs-link-active-bg: var(--bs-body-bg);--bs-nav-tabs-link-active-border-color: var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg);border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link,.nav-tabs>li>a,.nav-tabs .nav-pills>li>a,.nav-tabs :where(ul.nav.navbar-nav > li)>a{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid transparent;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>li>a:hover,.nav-tabs .nav-pills>li>a:hover,.nav-tabs :where(ul.nav.navbar-nav > li)>a:hover,.nav-tabs .nav-link:focus,.nav-tabs>li>a:focus,.nav-tabs .nav-pills>li>a:focus,.nav-tabs :where(ul.nav.navbar-nav > li)>a:focus{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.active,.nav-tabs>li>a.active,.nav-tabs .nav-pills>li>a.active,.nav-tabs :where(ul.nav.navbar-nav > li)>a.active,.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-item.in .nav-link,.nav-tabs .nav-item.show .nav-tabs>li>a,.nav-tabs .nav-item.in .nav-tabs>li>a,.nav-tabs .nav-item.show .nav-pills>li>a,.nav-tabs .nav-item.in .nav-pills>li>a,.nav-tabs>li.show .nav-link,.nav-tabs>li.in .nav-link,.nav-tabs>li.show .nav-tabs>li>a,.nav-tabs>li.in .nav-tabs>li>a,.nav-tabs>li.show .nav-pills>li>a,.nav-tabs>li.in .nav-pills>li>a,.nav-tabs .nav-pills>li.show .nav-link,.nav-tabs .nav-pills>li.in .nav-link,.nav-tabs .nav-pills>li.show .nav-tabs>li>a,.nav-tabs .nav-pills>li.in .nav-tabs>li>a,.nav-tabs .nav-pills>li.show .nav-pills>li>a,.nav-tabs .nav-pills>li.in .nav-pills>li>a,.nav-tabs .nav-item.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-item.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs>li.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs>li.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-pills>li.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-pills>li.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-tabs>li>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-tabs>li>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-pills>li>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-pills>li>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a{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: var(--bs-border-radius);--bs-nav-pills-link-active-color: #fff;--bs-nav-pills-link-active-bg: #007bc2}.nav-pills .nav-link,.nav-pills .nav-tabs>li>a,.nav-pills>li>a,.nav-pills :where(ul.nav.navbar-nav > li)>a{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .nav-tabs>li>a.active,.nav-pills>li>a.active,.nav-pills :where(ul.nav.navbar-nav > li)>a.active,.nav-pills .show>.nav-link,.nav-pills .in>.nav-link,.nav-pills .nav-tabs>li.show>a,.nav-pills .nav-tabs>li.in>a,.nav-pills>li.show>a,.nav-pills>li.in>a,.nav-pills .show:where(ul.nav.navbar-nav > li)>a,.nav-pills .in:where(ul.nav.navbar-nav > li)>a{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: .125rem;--bs-nav-underline-link-active-color: var(--bs-emphasis-color);gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link,.nav-underline .nav-tabs>li>a,.nav-underline .nav-pills>li>a,.nav-underline :where(ul.nav.navbar-nav > li)>a{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid transparent}.nav-underline .nav-link:hover,.nav-underline .nav-tabs>li>a:hover,.nav-underline .nav-pills>li>a:hover,.nav-underline :where(ul.nav.navbar-nav > li)>a:hover,.nav-underline .nav-link:focus,.nav-underline .nav-tabs>li>a:focus,.nav-underline .nav-pills>li>a:focus,.nav-underline :where(ul.nav.navbar-nav > li)>a:focus{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .nav-tabs>li>a.active,.nav-underline .nav-pills>li>a.active,.nav-underline :where(ul.nav.navbar-nav > li)>a.active,.nav-underline .show>.nav-link,.nav-underline .in>.nav-link,.nav-underline .nav-tabs>li.show>a,.nav-underline .nav-tabs>li.in>a,.nav-underline .nav-pills>li.show>a,.nav-underline .nav-pills>li.in>a,.nav-underline .show:where(ul.nav.navbar-nav > li)>a,.nav-underline .in:where(ul.nav.navbar-nav > li)>a{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill>.nav-link,.nav-tabs>li.nav-fill>a,.nav-pills>li.nav-fill>a,.nav-fill:where(ul.nav.navbar-nav > li)>a,.nav-fill .nav-item,.nav-fill .nav-tabs>li,.nav-fill .nav-pills>li,.nav-fill :where(ul.nav.navbar-nav > li):not(.dropdown){flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-tabs>li.nav-justified>a,.nav-pills>li.nav-justified>a,.nav-justified:where(ul.nav.navbar-nav > li)>a,.nav-justified .nav-item,.nav-justified .nav-tabs>li,.nav-justified .nav-pills>li,.nav-justified :where(ul.nav.navbar-nav > li):not(.dropdown){flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-fill .nav-tabs>li .nav-link,.nav-fill .nav-tabs>li>a,.nav-fill .nav-pills>li .nav-link,.nav-fill .nav-pills>li>a,.nav-fill .nav-item :where(ul.nav.navbar-nav > li)>a,.nav-fill .nav-tabs>li :where(ul.nav.navbar-nav > li)>a,.nav-fill .nav-pills>li :where(ul.nav.navbar-nav > li)>a,.nav-fill :where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-fill :where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a,.nav-justified .nav-item .nav-link,.nav-justified .nav-tabs>li .nav-link,.nav-justified .nav-tabs>li>a,.nav-justified .nav-pills>li .nav-link,.nav-justified .nav-pills>li>a,.nav-justified .nav-item :where(ul.nav.navbar-nav > li)>a,.nav-justified .nav-tabs>li :where(ul.nav.navbar-nav > li)>a,.nav-justified .nav-pills>li :where(ul.nav.navbar-nav > li)>a,.nav-justified :where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-justified :where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x: .66rem;--bs-navbar-padding-y: .5rem;--bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), 0.65);--bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), 0.8);--bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), 0.3);--bs-navbar-active-color: rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-padding-y: .3125rem;--bs-navbar-brand-margin-end: 1rem;--bs-navbar-brand-font-size: 1.25rem;--bs-navbar-brand-color: rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color: rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-nav-link-padding-x: .5rem;--bs-navbar-toggler-padding-y: .25rem;--bs-navbar-toggler-padding-x: .75rem;--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='rgba%2829,31,33,0.75%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(var(--bs-emphasis-color-rgb), 0.15);--bs-navbar-toggler-border-radius: var(--bs-border-radius);--bs-navbar-toggler-focus-width: .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: .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-tabs>li>a.active,.navbar-nav .nav-pills>li>a.active,.navbar-nav :where(ul.nav.navbar-nav > li)>a.active,.navbar-nav .nav-link.show,.navbar-nav .nav-link.in,.navbar-nav .nav-tabs>li>a.show,.navbar-nav .nav-tabs>li>a.in,.navbar-nav .nav-pills>li>a.show,.navbar-nav .nav-pills>li>a.in,.navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar-nav :where(ul.nav.navbar-nav > li)>a.in{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,.navbar-toggle{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:transparent;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,.navbar-toggle{transition:none}}.navbar-toggler:hover,.navbar-toggle:hover{text-decoration:none}.navbar-toggler:focus,.navbar-toggle:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon,.navbar-toggle>.icon-bar:last-child{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,.navbar-expand-sm .navbar-nav .nav-tabs>li>a,.navbar-expand-sm .navbar-nav .nav-pills>li>a,.navbar-expand-sm .navbar-nav :where(ul.nav.navbar-nav > li)>a{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,.navbar-expand-sm .navbar-toggle{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:transparent !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,.navbar-expand-md .navbar-nav .nav-tabs>li>a,.navbar-expand-md .navbar-nav .nav-pills>li>a,.navbar-expand-md .navbar-nav :where(ul.nav.navbar-nav > li)>a{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,.navbar-expand-md .navbar-toggle{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:transparent !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,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl){flex-wrap:nowrap;-webkit-flex-wrap:nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link,.navbar-expand-lg .navbar-nav .nav-tabs>li>a,.navbar-expand-lg .navbar-nav .nav-pills>li>a,.navbar-expand-lg .navbar-nav :where(ul.nav.navbar-nav > li)>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-link,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-tabs>li>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-pills>li>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler,.navbar-expand-lg .navbar-toggle,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-toggler,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-toggle{display:none}.navbar-expand-lg .offcanvas,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.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:transparent !important;border:0 !important;transform:none !important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.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: 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,.navbar-expand-xl .navbar-nav .nav-tabs>li>a,.navbar-expand-xl .navbar-nav .nav-pills>li>a,.navbar-expand-xl .navbar-nav :where(ul.nav.navbar-nav > li)>a{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,.navbar-expand-xl .navbar-toggle{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:transparent !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,.navbar-expand-xxl .navbar-nav .nav-tabs>li>a,.navbar-expand-xxl .navbar-nav .nav-pills>li>a,.navbar-expand-xxl .navbar-nav :where(ul.nav.navbar-nav > li)>a{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,.navbar-expand-xxl .navbar-toggle{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:transparent !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,.navbar-expand .navbar-nav .nav-tabs>li>a,.navbar-expand .navbar-nav .nav-pills>li>a,.navbar-expand .navbar-nav :where(ul.nav.navbar-nav > li)>a{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,.navbar-expand .navbar-toggle{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:transparent !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.navbar-inverse,.navbar[data-bs-theme="dark"]{--bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), 0.55);--bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), 0.75);--bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), 0.25);--bs-navbar-active-color: rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-color: rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color: rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-toggler-border-color: rgba(var(--bs-emphasis-color-rgb), 0.1);--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='rgba%28255,255,255,0.75%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,[data-bs-theme="dark"] .navbar-toggle>.icon-bar:last-child{--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='rgba%28255,255,255,0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card,.well{--bs-card-spacer-y: 1rem;--bs-card-spacer-x: 1rem;--bs-card-title-spacer-y: .5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width: var(--bs-border-width);--bs-card-border-color: var(--bs-border-color-translucent);--bs-card-border-radius: 8px;--bs-card-box-shadow: ;--bs-card-inner-border-radius: calc(8px - (var(--bs-border-width)));--bs-card-cap-padding-y: .5rem;--bs-card-cap-padding-x: 1rem;--bs-card-cap-bg: rgba(var(--bs-body-color-rgb), 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg: var(--bs-body-bg);--bs-card-img-overlay-padding: 1rem;--bs-card-group-margin: .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,.well>hr{margin-right:0;margin-left:0}.card>.list-group,.well>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child,.well>.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,.well>.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,.well>.card-header+.list-group,.card>.list-group+.card-footer,.well>.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(-.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(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active,.card-header-tabs .nav-tabs>li>a.active,.card-header-tabs .nav-pills>li>a.active,.card-header-tabs :where(ul.nav.navbar-nav > li)>a.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.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,.card-group>.well{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,.card-group>.well{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card,.card-group>.well+.card,.card-group>.card+.well,.card-group>.well+.well{margin-left:0;border-left:0}.card-group>.card:not(:last-child),.card-group>.well:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.well:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header,.card-group>.well:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.well:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer,.card-group>.well:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child),.card-group>.well:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.well:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header,.card-group>.well:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.well:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer,.card-group>.well:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion{--bs-accordion-color: var(--bs-body-color);--bs-accordion-bg: var(--bs-body-bg);--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: var(--bs-border-color);--bs-accordion-border-width: var(--bs-border-width);--bs-accordion-border-radius: var(--bs-border-radius);--bs-accordion-inner-border-radius: calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-accordion-btn-padding-x: 1.25rem;--bs-accordion-btn-padding-y: 1rem;--bs-accordion-btn-color: var(--bs-body-color);--bs-accordion-btn-bg: var(--bs-accordion-bg);--bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%231D1F21'%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='%2300314e'%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: #80bde1;--bs-accordion-btn-focus-box-shadow: 0 0 0 .25rem rgba(0,123,194,0.25);--bs-accordion-body-padding-x: 1.25rem;--bs-accordion-body-padding-y: 1rem;--bs-accordion-active-color: ;--bs-accordion-active-bg: }.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='%2366b0da'%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='%2366b0da'%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: var(--bs-secondary-color);--bs-breadcrumb-item-padding-x: .5rem;--bs-breadcrumb-item-active-color: var(--bs-secondary-color);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: .75rem;--bs-pagination-padding-y: .375rem;--bs-pagination-font-size:1rem;--bs-pagination-color: var(--bs-link-color);--bs-pagination-bg: var(--bs-body-bg);--bs-pagination-border-width: var(--bs-border-width);--bs-pagination-border-color: var(--bs-border-color);--bs-pagination-border-radius: var(--bs-border-radius);--bs-pagination-hover-color: var(--bs-link-hover-color);--bs-pagination-hover-bg: var(--bs-tertiary-bg);--bs-pagination-hover-border-color: var(--bs-border-color);--bs-pagination-focus-color: var(--bs-link-hover-color);--bs-pagination-focus-bg: var(--bs-secondary-bg);--bs-pagination-focus-box-shadow: 0 0 0 .25rem rgba(0,123,194,0.25);--bs-pagination-active-color: #fff;--bs-pagination-active-bg: #007bc2;--bs-pagination-active-border-color: #007bc2;--bs-pagination-disabled-color: var(--bs-secondary-color);--bs-pagination-disabled-bg: var(--bs-secondary-bg);--bs-pagination-disabled-border-color: var(--bs-border-color);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 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}@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(var(--bs-border-width) * -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: .75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius: var(--bs-border-radius-lg)}.pagination-sm{--bs-pagination-padding-x: .5rem;--bs-pagination-padding-y: .25rem;--bs-pagination-font-size:.875rem;--bs-pagination-border-radius: var(--bs-border-radius-sm)}.badge{--bs-badge-padding-x: .65em;--bs-badge-padding-y: .35em;--bs-badge-font-size:.75em;--bs-badge-font-weight: 700;--bs-badge-color: #fff;--bs-badge-border-radius: var(--bs-border-radius);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: var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius: var(--bs-border-radius);--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:.75rem;--bs-progress-bg: var(--bs-secondary-bg);--bs-progress-border-radius: var(--bs-border-radius);--bs-progress-box-shadow: var(--bs-box-shadow-inset);--bs-progress-bar-color: #fff;--bs-progress-bar-bg: #007bc2;--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: var(--bs-body-color);--bs-list-group-bg: var(--bs-body-bg);--bs-list-group-border-color: var(--bs-border-color);--bs-list-group-border-width: var(--bs-border-width);--bs-list-group-border-radius: var(--bs-border-radius);--bs-list-group-item-padding-x: 1rem;--bs-list-group-item-padding-y: .5rem;--bs-list-group-action-color: var(--bs-secondary-color);--bs-list-group-action-hover-color: var(--bs-emphasis-color);--bs-list-group-action-hover-bg: var(--bs-tertiary-bg);--bs-list-group-action-active-color: var(--bs-body-color);--bs-list-group-action-active-bg: var(--bs-secondary-bg);--bs-list-group-disabled-color: var(--bs-secondary-color);--bs-list-group-disabled-bg: var(--bs-body-bg);--bs-list-group-active-color: #fff;--bs-list-group-active-bg: #007bc2;--bs-list-group-active-border-color: #007bc2;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: .5;--bs-btn-close-hover-opacity: .75;--bs-btn-close-focus-shadow: 0 0 0 .25rem rgba(0,123,194,0.25);--bs-btn-close-focus-opacity: 1;--bs-btn-close-disabled-opacity: .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:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:3px;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: .75rem;--bs-toast-padding-y: .5rem;--bs-toast-spacing: 1.5rem;--bs-toast-max-width: 350px;--bs-toast-font-size:.875rem;--bs-toast-color: ;--bs-toast-bg: rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-border-width: var(--bs-border-width);--bs-toast-border-color: var(--bs-border-color-translucent);--bs-toast-border-radius: var(--bs-border-radius);--bs-toast-box-shadow: var(--bs-box-shadow);--bs-toast-header-color: var(--bs-secondary-color);--bs-toast-header-bg: rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-header-border-color: var(--bs-border-color-translucent);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):not(.in){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(-.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: .5rem;--bs-modal-color: ;--bs-modal-bg: var(--bs-body-bg);--bs-modal-border-color: var(--bs-border-color-translucent);--bs-modal-border-width: var(--bs-border-width);--bs-modal-border-radius: var(--bs-border-radius-lg);--bs-modal-box-shadow: 0px 0px 2px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.14),0px 2px 4px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.16);--bs-modal-inner-border-radius: calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));--bs-modal-header-padding-x: 1rem;--bs-modal-header-padding-y: 1rem;--bs-modal-header-padding: 1.5rem;--bs-modal-header-border-color: var(--bs-border-color);--bs-modal-header-border-width: none;--bs-modal-title-line-height: 1.5;--bs-modal-footer-gap: .5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color: var(--bs-border-color);--bs-modal-footer-border-width: none;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 0.3s ease-out;transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog,.modal.in .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: #464646;--bs-backdrop-opacity: .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,.modal-backdrop.in{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(-.5 * var(--bs-modal-header-padding-y)) calc(-.5 * var(--bs-modal-header-padding-x)) calc(-.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: 10%;--bs-modal-box-shadow: 0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08)}.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: .5rem;--bs-tooltip-padding-y: .25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:.875rem;--bs-tooltip-color: var(--bs-body-bg);--bs-tooltip-bg: var(--bs-emphasis-color);--bs-tooltip-border-radius: var(--bs-border-radius);--bs-tooltip-opacity: .9;--bs-tooltip-arrow-width: .8rem;--bs-tooltip-arrow-height: .4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:"Open Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;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,.tooltip.in{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:transparent;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:.875rem;--bs-popover-bg: var(--bs-body-bg);--bs-popover-border-width: var(--bs-border-width);--bs-popover-border-color: var(--bs-border-color-translucent);--bs-popover-border-radius: var(--bs-border-radius-lg);--bs-popover-inner-border-radius: calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-popover-box-shadow: 0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08);--bs-popover-header-padding-x: 1rem;--bs-popover-header-padding-y: .5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color: inherit;--bs-popover-header-bg: var(--bs-secondary-bg);--bs-popover-body-padding-x: 1rem;--bs-popover-body-padding-y: 1rem;--bs-popover-body-color: var(--bs-body-color);--bs-popover-arrow-width: 1rem;--bs-popover-arrow-height: .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:"Open Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;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:transparent;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(-.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 0.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='%23fff'%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='%23fff'%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 transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity 0.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: -.125em;--bs-spinner-border-width: .25em;--bs-spinner-animation-speed: .75s;--bs-spinner-animation-name: spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width: 1rem;--bs-spinner-height: 1rem;--bs-spinner-border-width: .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: -.125em;--bs-spinner-animation-speed: .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: var(--bs-body-color);--bs-offcanvas-bg: var(--bs-body-bg);--bs-offcanvas-border-width: var(--bs-border-width);--bs-offcanvas-border-color: var(--bs-border-color-translucent);--bs-offcanvas-box-shadow: 0px 0px 2px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.14),0px 2px 4px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.16);--bs-offcanvas-transition: transform .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),.offcanvas-sm.in:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.in{visibility:visible}}@media (min-width: 576px){.offcanvas-sm{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent !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:transparent !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),.offcanvas-md.in:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.in{visibility:visible}}@media (min-width: 768px){.offcanvas-md{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent !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:transparent !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),.offcanvas-lg.in:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.in{visibility:visible}}@media (min-width: 992px){.offcanvas-lg{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent !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:transparent !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),.offcanvas-xl.in:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.in{visibility:visible}}@media (min-width: 1200px){.offcanvas-xl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent !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:transparent !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),.offcanvas-xxl.in:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.in{visibility:visible}}@media (min-width: 1400px){.offcanvas-xxl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent !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:transparent !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),.offcanvas.in:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show,.offcanvas.in{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#464646}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show,.offcanvas-backdrop.in{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(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.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(0,98,155, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(0,98,155, 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(51,51,51, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(51,51,51, 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(0,110,21, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(0,110,21, 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(53,210,237, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(53,210,237, 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(250,199,83, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(250,199,83, 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(154,0,0, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(154,0,0, 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,249,249, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(249,249,249, 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,26,26, var(--bs-link-opacity, 1)) !important;text-decoration-color:RGBA(26,26,26, 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:0.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: calc(3 / 4 * 100%)}.ratio-16x9{--bs-aspect-ratio: calc(9 / 16 * 100%)}.ratio-21x9{--bs-aspect-ratio: calc(9 / 21 * 100%)}.fixed-top,.navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom,.navbar-fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top,.navbar-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:var(--bs-border-width);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{float:left !important}.float-end,.float-right{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:0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08) !important}.shadow-sm{box-shadow:0px 0px 2px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.14),0px 2px 4px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.16) !important}.shadow-lg{box-shadow:0px 4px 10px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.17) !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: .1}.border-opacity-25{--bs-border-opacity: .25}.border-opacity-50{--bs-border-opacity: .5}.border-opacity-75{--bs-border-opacity: .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.335rem + 1.02vw) !important}.fs-2{font-size:calc(1.325rem + .9vw) !important}.fs-3{font-size:calc(1.3rem + .6vw) !important}.fs-4{font-size:calc(1.275rem + .3vw) !important}.fs-5{font-size:1.25rem !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,.help-text,.help-block{--bs-text-opacity: 1;color:var(--bs-secondary-color) !important}.text-black-50{--bs-text-opacity: 1;color:rgba(0,0,0,0.5) !important}.text-white-50{--bs-text-opacity: 1;color:rgba(255,255,255,0.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: .25}.text-opacity-50{--bs-text-opacity: .5}.text-opacity-75{--bs-text-opacity: .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: .1}.link-opacity-10-hover:hover{--bs-link-opacity: .1}.link-opacity-25{--bs-link-opacity: .25}.link-opacity-25-hover:hover{--bs-link-opacity: .25}.link-opacity-50{--bs-link-opacity: .5}.link-opacity-50-hover:hover{--bs-link-opacity: .5}.link-opacity-75{--bs-link-opacity: .75}.link-opacity-75-hover:hover{--bs-link-opacity: .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: .1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity: .1}.link-underline-opacity-25{--bs-link-underline-opacity: .25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity: .25}.link-underline-opacity-50{--bs-link-underline-opacity: .5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity: .5}.link-underline-opacity-75{--bs-link-underline-opacity: .75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity: .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: .1}.bg-opacity-25{--bs-bg-opacity: .25}.bg-opacity-50{--bs-bg-opacity: .5}.bg-opacity-75{--bs-bg-opacity: .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:2.1rem !important}.fs-2{font-size:2rem !important}.fs-3{font-size:1.75rem !important}.fs-4{font-size:1.5rem !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}}.table th[align=left]{text-align:left}.table th[align=right]{text-align:right}.table th[align=center]{text-align:center}.well{display:block;background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.03);color:RGB(var(--bs-emphasis-color-rgb, 0, 0, 0));padding:1rem;border-radius:3px}.well-lg{padding:1.5rem;border-radius:.5rem}.well-sm{padding:0.5rem;border-radius:.25rem}.dropdown-menu>li.active>a{color:#fff;text-decoration:none;background-color:#007bc2}.navbar .nav.nav-underline{--bs-navbar-nav-link-padding-x: 0}.navbar:not(.fixed-bottom):not(.navbar-fixed-bottom):not(.navbar-fixed-bottom)+div>.tab-content>.tab-pane{--bslib-navbar-margin: 20px;margin-top:var(--bslib-navbar-margin)}ul.nav.navbar-nav{flex:1;-webkit-flex:1}ul.nav.navbar-nav.navbar-right{flex:unset;-webkit-flex:unset;display:flex;display:-webkit-flex;justify-content:flex-end;-webkit-justify-content:flex-end}:where(ul.nav.navbar-nav > li).active>a,:where(ul.nav.navbar-nav > li).show>a,.in:where(ul.nav.navbar-nav > li)>a{color:var(--bs-navbar-active-color)}:where(ul.nav.navbar-nav > li).bslib-nav-item{color:var(--bs-navbar-active-color)}.navbar.navbar-default{background-color:var(--bslib-navbar-default-bg, var(--bs-light)) !important}.navbar.navbar-inverse{background-color:var(--bslib-navbar-inverse-bg, var(--bs-dark)) !important;--bs-emphasis-color: white;--bs-emphasis-color-rgb: 255, 255, 255}[data-bs-theme="dark"] .navbar.navbar-default{background-color:var(--bslib-navbar-default-bg, var(--bs-dark)) !important}.navbar-toggle>.icon-bar{display:none}@media (max-width: 991.98px){.navbar-header{width:100%;display:flex;flex-direction:row;align-items:center;justify-content:space-between}.navbar-header .navbar-toggle{order:2}}.nav-tabs>li.active>a{color:var(--bs-emphasis-color);background-color:var(--bs-body-bg);border-color:var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg)}.nav-pills>li.active>a{color:#fff;background-color:#007bc2}.nav-stacked{flex-direction:column;-webkit-flex-direction:column}.progress-bar-default{background-color:#dee2e6;color:#000}.progress-bar-primary{background-color:#007bc2;color:#fff}.progress-bar-secondary{background-color:#404040;color:#fff}.progress-bar-success{background-color:#00891a;color:#fff}.progress-bar-info{background-color:#03c7e8;color:#000}.progress-bar-warning{background-color:#f9b928;color:#000}.progress-bar-danger{background-color:#c10000;color:#fff}.progress-bar-light{background-color:#f8f8f8;color:#000}.progress-bar-dark{background-color:#202020;color:#fff}.datatables thead .form-group.has-feedback+div{background-color:var(--bs-body-bg) !important;color:var(--bs-body-color) !important;border-color:var(--bs-border-color) !important;border-width:var(--bs-border-width);border-radius:var(--bs-border-radius);border-style:var(--bs-border-style)}@font-face{font-family:'Glyphicons Halflings';src:url("fonts/bootstrap/glyphicons-halflings-regular.eot");src:url("fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("fonts/bootstrap/glyphicons-halflings-regular.woff2") format("woff2"),url("fonts/bootstrap/glyphicons-halflings-regular.woff") format("woff"),url("fonts/bootstrap/glyphicons-halflings-regular.ttf") format("truetype"),url("fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}.form-group{margin-bottom:1rem}.input-daterange .input-group-addon.input-group-prepend.input-group-append{padding:inherit;line-height:inherit;text-shadow:inherit;border-width:0}.input-daterange .input-group-addon.input-group-prepend.input-group-append .input-group-text{border-radius:0}.shiny-input-checkboxgroup .checkbox-inline,.shiny-input-radiogroup .radio-inline{cursor:pointer}.shiny-input-checkboxgroup label~.shiny-options-group,.shiny-input-radiogroup label~.shiny-options-group{margin-top:calc(-.15em - var(--bs-border-width))}pre.shiny-code{padding:0.5rem}:where(.section.level1, section.level1){margin-top:1.5rem}:where(.section.level2, section.level2){margin-top:1.5rem}:where(.section.level3, section.level3){margin-top:1.5rem}:where(.section.level4, section.level4){margin-top:1rem}:where(.section.level5, section.level5){margin-top:1rem}:where(.section.level6, section.level6){margin-top:1rem}:root{--bslib-spacer: 1.5rem;--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,.bslib-gap-spacing>.shiny-html-output>.bslib-mb-spacing,.bslib-gap-spacing>.shiny-html-output>.form-group,.bslib-gap-spacing>.shiny-html-output>p,.bslib-gap-spacing>.shiny-html-output>pre,.bslib-gap-spacing>.shiny-panel-conditional>.bslib-mb-spacing,.bslib-gap-spacing>.shiny-panel-conditional>.form-group,.bslib-gap-spacing>.shiny-panel-conditional>p,.bslib-gap-spacing>.shiny-panel-conditional>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: #007bc2;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-blue{--bslib-color-fg: #007bc2;color:var(--bslib-color-fg)}.bg-indigo{--bslib-color-bg: #4b00c1;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-indigo{--bslib-color-fg: #4b00c1;color:var(--bslib-color-fg)}.bg-purple{--bslib-color-bg: #74149c;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-purple{--bslib-color-fg: #74149c;color:var(--bslib-color-fg)}.bg-pink{--bslib-color-bg: #bf007f;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-pink{--bslib-color-fg: #bf007f;color:var(--bslib-color-fg)}.bg-red{--bslib-color-bg: #c10000;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-red{--bslib-color-fg: #c10000;color:var(--bslib-color-fg)}.bg-orange{--bslib-color-bg: #f45100;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-orange{--bslib-color-fg: #f45100;color:var(--bslib-color-fg)}.bg-yellow{--bslib-color-bg: #f9b928;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-yellow{--bslib-color-fg: #f9b928;color:var(--bslib-color-fg)}.bg-green{--bslib-color-bg: #00891a;--bslib-color-fg: #fff;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-green{--bslib-color-fg: #00891a;color:var(--bslib-color-fg)}.bg-teal{--bslib-color-bg: #00bf7f;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-teal{--bslib-color-fg: #00bf7f;color:var(--bslib-color-fg)}.bg-cyan{--bslib-color-bg: #03c7e8;--bslib-color-fg: #000;background-color:var(--bslib-color-bg);color:var(--bslib-color-fg)}.text-cyan{--bslib-color-fg: #03c7e8;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: #007bc2}.bg-primary{--bslib-color-bg: #007bc2;--bslib-color-fg: #fff}.text-secondary{--bslib-color-fg: #404040}.bg-secondary{--bslib-color-bg: #404040;--bslib-color-fg: #fff}.text-success{--bslib-color-fg: #00891a}.bg-success{--bslib-color-bg: #00891a;--bslib-color-fg: #fff}.text-info{--bslib-color-fg: #03c7e8}.bg-info{--bslib-color-bg: #03c7e8;--bslib-color-fg: #000}.text-warning{--bslib-color-fg: #f9b928}.bg-warning{--bslib-color-bg: #f9b928;--bslib-color-fg: #000}.text-danger{--bslib-color-fg: #c10000}.bg-danger{--bslib-color-bg: #c10000;--bslib-color-fg: #fff}.text-light{--bslib-color-fg: #f8f8f8}.bg-light{--bslib-color-bg: #f8f8f8;--bslib-color-fg: #000}.text-dark{--bslib-color-fg: #202020}.bg-dark{--bslib-color-bg: #202020;--bslib-color-fg: #fff}.bg-gradient-blue-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #1e4ac2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #1e4ac2;color:#fff}.bg-gradient-blue-purple{--bslib-color-fg: #fff;--bslib-color-bg: #2e52b3;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #2e52b3;color:#fff}.bg-gradient-blue-pink{--bslib-color-fg: #fff;--bslib-color-bg: #4c4aa7;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #4c4aa7;color:#fff}.bg-gradient-blue-red{--bslib-color-fg: #fff;--bslib-color-bg: #4d4a74;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #4d4a74;color:#fff}.bg-gradient-blue-orange{--bslib-color-fg: #fff;--bslib-color-bg: #626a74;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #626a74;color:#fff}.bg-gradient-blue-yellow{--bslib-color-fg: #000;--bslib-color-bg: #649484;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #649484;color:#000}.bg-gradient-blue-green{--bslib-color-fg: #fff;--bslib-color-bg: #00817f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #00817f;color:#fff}.bg-gradient-blue-teal{--bslib-color-fg: #000;--bslib-color-bg: #0096a7;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #0096a7;color:#000}.bg-gradient-blue-cyan{--bslib-color-fg: #000;--bslib-color-bg: #0199d1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #007bc2 var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #0199d1;color:#000}.bg-gradient-indigo-blue{--bslib-color-fg: #fff;--bslib-color-bg: #2d31c1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #2d31c1;color:#fff}.bg-gradient-indigo-purple{--bslib-color-fg: #fff;--bslib-color-bg: #5b08b2;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #5b08b2;color:#fff}.bg-gradient-indigo-pink{--bslib-color-fg: #fff;--bslib-color-bg: #7900a7;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #7900a7;color:#fff}.bg-gradient-indigo-red{--bslib-color-fg: #fff;--bslib-color-bg: #7a0074;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #7a0074;color:#fff}.bg-gradient-indigo-orange{--bslib-color-fg: #fff;--bslib-color-bg: #8f2074;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #8f2074;color:#fff}.bg-gradient-indigo-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #914a84;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #914a84;color:#fff}.bg-gradient-indigo-green{--bslib-color-fg: #fff;--bslib-color-bg: #2d377e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #2d377e;color:#fff}.bg-gradient-indigo-teal{--bslib-color-fg: #fff;--bslib-color-bg: #2d4ca7;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #2d4ca7;color:#fff}.bg-gradient-indigo-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #2e50d1;background:linear-gradient(var(--bg-gradient-deg, 140deg), #4b00c1 var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #2e50d1;color:#fff}.bg-gradient-purple-blue{--bslib-color-fg: #fff;--bslib-color-bg: #463dab;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #463dab;color:#fff}.bg-gradient-purple-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #640cab;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #640cab;color:#fff}.bg-gradient-purple-pink{--bslib-color-fg: #fff;--bslib-color-bg: #920c90;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #920c90;color:#fff}.bg-gradient-purple-red{--bslib-color-fg: #fff;--bslib-color-bg: #930c5e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #930c5e;color:#fff}.bg-gradient-purple-orange{--bslib-color-fg: #fff;--bslib-color-bg: #a72c5e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #a72c5e;color:#fff}.bg-gradient-purple-yellow{--bslib-color-fg: #fff;--bslib-color-bg: #a9566e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #a9566e;color:#fff}.bg-gradient-purple-green{--bslib-color-fg: #fff;--bslib-color-bg: #464368;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #464368;color:#fff}.bg-gradient-purple-teal{--bslib-color-fg: #fff;--bslib-color-bg: #465890;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #465890;color:#fff}.bg-gradient-purple-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #475cba;background:linear-gradient(var(--bg-gradient-deg, 140deg), #74149c var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #475cba;color:#fff}.bg-gradient-pink-blue{--bslib-color-fg: #fff;--bslib-color-bg: #73319a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #73319a;color:#fff}.bg-gradient-pink-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #910099;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #910099;color:#fff}.bg-gradient-pink-purple{--bslib-color-fg: #fff;--bslib-color-bg: #a1088b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #a1088b;color:#fff}.bg-gradient-pink-red{--bslib-color-fg: #fff;--bslib-color-bg: #c0004c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #c0004c;color:#fff}.bg-gradient-pink-orange{--bslib-color-fg: #fff;--bslib-color-bg: #d4204c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #d4204c;color:#fff}.bg-gradient-pink-yellow{--bslib-color-fg: #000;--bslib-color-bg: #d64a5c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #d64a5c;color:#000}.bg-gradient-pink-green{--bslib-color-fg: #fff;--bslib-color-bg: #733757;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #733757;color:#fff}.bg-gradient-pink-teal{--bslib-color-fg: #fff;--bslib-color-bg: #734c7f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #734c7f;color:#fff}.bg-gradient-pink-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #7450a9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #bf007f var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #7450a9;color:#fff}.bg-gradient-red-blue{--bslib-color-fg: #fff;--bslib-color-bg: #74314e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #74314e;color:#fff}.bg-gradient-red-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #92004d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #92004d;color:#fff}.bg-gradient-red-purple{--bslib-color-fg: #fff;--bslib-color-bg: #a2083e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #a2083e;color:#fff}.bg-gradient-red-pink{--bslib-color-fg: #fff;--bslib-color-bg: #c00033;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #c00033;color:#fff}.bg-gradient-red-orange{--bslib-color-fg: #fff;--bslib-color-bg: #d52000;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #d52000;color:#fff}.bg-gradient-red-yellow{--bslib-color-fg: #000;--bslib-color-bg: #d74a10;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #d74a10;color:#000}.bg-gradient-red-green{--bslib-color-fg: #fff;--bslib-color-bg: #74370a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #74370a;color:#fff}.bg-gradient-red-teal{--bslib-color-fg: #fff;--bslib-color-bg: #744c33;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #744c33;color:#fff}.bg-gradient-red-cyan{--bslib-color-fg: #fff;--bslib-color-bg: #75505d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #c10000 var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #75505d;color:#fff}.bg-gradient-orange-blue{--bslib-color-fg: #fff;--bslib-color-bg: #92624e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #92624e;color:#fff}.bg-gradient-orange-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #b0314d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #b0314d;color:#fff}.bg-gradient-orange-purple{--bslib-color-fg: #fff;--bslib-color-bg: #c1393e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #c1393e;color:#fff}.bg-gradient-orange-pink{--bslib-color-fg: #fff;--bslib-color-bg: #df3133;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #df3133;color:#fff}.bg-gradient-orange-red{--bslib-color-fg: #fff;--bslib-color-bg: #e03100;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #e03100;color:#fff}.bg-gradient-orange-yellow{--bslib-color-fg: #000;--bslib-color-bg: #f67b10;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #f67b10;color:#000}.bg-gradient-orange-green{--bslib-color-fg: #fff;--bslib-color-bg: #92670a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #92670a;color:#fff}.bg-gradient-orange-teal{--bslib-color-fg: #000;--bslib-color-bg: #927d33;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #927d33;color:#000}.bg-gradient-orange-cyan{--bslib-color-fg: #000;--bslib-color-bg: #94805d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f45100 var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #94805d;color:#000}.bg-gradient-yellow-blue{--bslib-color-fg: #000;--bslib-color-bg: #95a066;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #95a066;color:#000}.bg-gradient-yellow-indigo{--bslib-color-fg: #000;--bslib-color-bg: #b36f65;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #b36f65;color:#000}.bg-gradient-yellow-purple{--bslib-color-fg: #000;--bslib-color-bg: #c47756;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #c47756;color:#000}.bg-gradient-yellow-pink{--bslib-color-fg: #000;--bslib-color-bg: #e26f4b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #e26f4b;color:#000}.bg-gradient-yellow-red{--bslib-color-fg: #000;--bslib-color-bg: #e36f18;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #e36f18;color:#000}.bg-gradient-yellow-orange{--bslib-color-fg: #000;--bslib-color-bg: #f78f18;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #f78f18;color:#000}.bg-gradient-yellow-green{--bslib-color-fg: #000;--bslib-color-bg: #95a622;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #95a622;color:#000}.bg-gradient-yellow-teal{--bslib-color-fg: #000;--bslib-color-bg: #95bb4b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #95bb4b;color:#000}.bg-gradient-yellow-cyan{--bslib-color-fg: #000;--bslib-color-bg: #97bf75;background:linear-gradient(var(--bg-gradient-deg, 140deg), #f9b928 var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #97bf75;color:#000}.bg-gradient-green-blue{--bslib-color-fg: #fff;--bslib-color-bg: #00835d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #00835d;color:#fff}.bg-gradient-green-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #1e525d;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #1e525d;color:#fff}.bg-gradient-green-purple{--bslib-color-fg: #fff;--bslib-color-bg: #2e5a4e;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #2e5a4e;color:#fff}.bg-gradient-green-pink{--bslib-color-fg: #fff;--bslib-color-bg: #4c5242;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #4c5242;color:#fff}.bg-gradient-green-red{--bslib-color-fg: #fff;--bslib-color-bg: #4d5210;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #4d5210;color:#fff}.bg-gradient-green-orange{--bslib-color-fg: #fff;--bslib-color-bg: #627310;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #627310;color:#fff}.bg-gradient-green-yellow{--bslib-color-fg: #000;--bslib-color-bg: #649c20;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #649c20;color:#000}.bg-gradient-green-teal{--bslib-color-fg: #000;--bslib-color-bg: #009f42;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #009f42;color:#000}.bg-gradient-green-cyan{--bslib-color-fg: #000;--bslib-color-bg: #01a26c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00891a var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #01a26c;color:#000}.bg-gradient-teal-blue{--bslib-color-fg: #000;--bslib-color-bg: #00a49a;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #00a49a;color:#000}.bg-gradient-teal-indigo{--bslib-color-fg: #fff;--bslib-color-bg: #1e7399;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #1e7399;color:#fff}.bg-gradient-teal-purple{--bslib-color-fg: #fff;--bslib-color-bg: #2e7b8b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #2e7b8b;color:#fff}.bg-gradient-teal-pink{--bslib-color-fg: #fff;--bslib-color-bg: #4c737f;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #4c737f;color:#fff}.bg-gradient-teal-red{--bslib-color-fg: #fff;--bslib-color-bg: #4d734c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #4d734c;color:#fff}.bg-gradient-teal-orange{--bslib-color-fg: #000;--bslib-color-bg: #62934c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #62934c;color:#000}.bg-gradient-teal-yellow{--bslib-color-fg: #000;--bslib-color-bg: #64bd5c;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #64bd5c;color:#000}.bg-gradient-teal-green{--bslib-color-fg: #000;--bslib-color-bg: #00a957;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #00a957;color:#000}.bg-gradient-teal-cyan{--bslib-color-fg: #000;--bslib-color-bg: #01c2a9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #00bf7f var(--bg-gradient-start, 36%), #03c7e8 var(--bg-gradient-end, 180%)) #01c2a9;color:#000}.bg-gradient-cyan-blue{--bslib-color-fg: #000;--bslib-color-bg: #02a9d9;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #007bc2 var(--bg-gradient-end, 180%)) #02a9d9;color:#000}.bg-gradient-cyan-indigo{--bslib-color-fg: #000;--bslib-color-bg: #2077d8;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #4b00c1 var(--bg-gradient-end, 180%)) #2077d8;color:#000}.bg-gradient-cyan-purple{--bslib-color-fg: #000;--bslib-color-bg: #307fca;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #74149c var(--bg-gradient-end, 180%)) #307fca;color:#000}.bg-gradient-cyan-pink{--bslib-color-fg: #000;--bslib-color-bg: #4e77be;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #bf007f var(--bg-gradient-end, 180%)) #4e77be;color:#000}.bg-gradient-cyan-red{--bslib-color-fg: #fff;--bslib-color-bg: #4f778b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #c10000 var(--bg-gradient-end, 180%)) #4f778b;color:#fff}.bg-gradient-cyan-orange{--bslib-color-fg: #000;--bslib-color-bg: #63988b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #f45100 var(--bg-gradient-end, 180%)) #63988b;color:#000}.bg-gradient-cyan-yellow{--bslib-color-fg: #000;--bslib-color-bg: #65c19b;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #f9b928 var(--bg-gradient-end, 180%)) #65c19b;color:#000}.bg-gradient-cyan-green{--bslib-color-fg: #000;--bslib-color-bg: #02ae96;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #00891a var(--bg-gradient-end, 180%)) #02ae96;color:#000}.bg-gradient-cyan-teal{--bslib-color-fg: #000;--bslib-color-bg: #02c4be;background:linear-gradient(var(--bg-gradient-deg, 140deg), #03c7e8 var(--bg-gradient-start, 36%), #00bf7f var(--bg-gradient-end, 180%)) #02c4be;color:#000}.irs.irs--shiny{margin-top:3px}.irs.irs--shiny .irs-min,.irs.irs--shiny .irs-max,.irs.irs--shiny .irs-from,.irs.irs--shiny .irs-to,.irs.irs--shiny .irs-single{padding:3px 6px;top:-3px}.irs.irs--shiny .irs-handle{top:23px}.irs.irs--shiny .irs-bar{top:31px;height:3px;border:none}.irs.irs--shiny .irs-line{border-radius:8px}.irs.irs--shiny .irs-grid-pol{height:6px}.irs.irs--shiny .irs-grid-text{bottom:8px}.irs.irs--shiny .irs-handle:focus-visible,.irs.irs--shiny .irs-handle:active{color:#005688;background-color:#005688;border-color:#005688;outline:0;box-shadow:0 0 0 .25rem rgba(0,123,194,0.25)}.irs.irs--shiny~.slider-animate-container{text-align:left}.irs.irs--shiny~.slider-animate-container .slider-animate-button{opacity:1}.irs.irs--shiny.irs-with-grid~.slider-animate-container{margin-top:-5px}.irs.irs--shiny:not(.irs-with-grid)~.slider-animate-container{margin-top:5px}.table.dataTable{--dt-row-selected: var(--bs-primary-rgb, "0,123,194");--dt-row-selected-text: var(--bs-white-rgb, "255,255,255");--dt-row-selected-link: var(--bs-light-rgh, "248,248,248")}.table.dataTable.dataTable.table-striped>tbody>tr.odd:not(.selected)>*{box-shadow:none}.table.dataTable.dataTable.table-striped>tbody>tr.even:not(.selected)>*{box-shadow:inset 0 0 0 9999px var(--bs-table-striped-bg)}.table.dataTable.dataTable tbody td.active,.table.dataTable.dataTable tbody tr.active td{background-color:var(--bs-table-active-bg)}.table.dataTable.dataTable.table-hover>tbody>tr:hover:not(.selected)>*{box-shadow:inset 0 0 0 9999px var(--bs-table-hover-bg)}thead,tbody,tfoot,tr,td,th{border:none}.table>thead{border-bottom:1px solid var(--bs-table-color)}th{font-weight:600}.datatables .dataTables_wrapper div.dataTables_info{padding-top:1.65rem;font-size:.95rem}.datatables .dataTables_paginate{padding-top:1rem}.datatables .paginate_button a{font-size:.95rem}.datatables .dataTables_length,.datatables .dataTables_filter{padding-bottom:1rem}.datatables .dataTables_wrapper .dt-row{max-width:100%;overflow:auto}.datatables .dataTables_wrapper .dataTables_length select,.datatables .dataTables_wrapper .dataTables_filter input{border:none;border-bottom:1px solid var(--bs-body-color);border-radius:0}.bslib-card-table-sm.bslib-card[data-full-screen="false"] .datatables .dataTables_wrapper{font-size:85%}.bslib-card-table-sm.bslib-card[data-full-screen="false"] .datatables .dataTables_wrapper .dataTables_length,.bslib-card-table-sm.bslib-card[data-full-screen="false"] .datatables .dataTables_wrapper .dataTables_filter,.bslib-card-table-sm.bslib-card[data-full-screen="false"] .datatables .dataTables_wrapper .dataTables_paginate{display:none}:root{--bslib-box-shadow-color-rgb: 29,31,33}[data-bs-theme="dark"]{--bslib-box-shadow-color-rgb: 0,0,0}.checkbox input,.radio input{margin-right:.35em}.shiny-input-container-inline .shiny-options-group{display:flex;flex-wrap:wrap;flex-direction:row;column-gap:1em}.shiny-input-container-inline .shiny-options-group .checkbox-inline,.shiny-input-container-inline .shiny-options-group .radio-inline{position:relative;padding-left:calc(1.2em + .35em * 2)}.shiny-input-container-inline .shiny-options-group .checkbox-inline input,.shiny-input-container-inline .shiny-options-group .radio-inline input{position:absolute;margin-top:0;left:0;top:calc(.15em + var(--bs-border-width))}.shiny-date-range-input .input-daterange .input-group-addon{margin-right:-1px}.btn-outline-default,.btn-default:not(.btn-primary,.btn-secondary,.btn-info,.btn-success,.btn-danger,.btn-warning,.btn-light,.btn-dark,.btn-link,[class*="btn-outline-"]){--bs-btn-color: #404040;--bs-btn-border-color: #404040;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #404040;--bs-btn-hover-border-color: #404040;--bs-btn-focus-shadow-rgb: 64,64,64;--bs-btn-active-color: #fff;--bs-btn-active-bg: #404040;--bs-btn-active-border-color: #404040;--bs-btn-active-shadow: inset 0 3px 5px rgba(0,0,0,0.125);--bs-btn-disabled-color: #404040;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #404040;--bs-btn-bg: transparent;--bs-gradient: none}[data-bs-theme="dark"] .btn-outline-default,[data-bs-theme="dark"] .btn-default:not(.btn-primary,.btn-secondary,.btn-info,.btn-success,.btn-danger,.btn-warning,.btn-light,.btn-dark,.btn-link,[class*="btn-outline-"]){--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}.selectize-control.plugin-remove_button .item{align-items:flex-start !important}.selectize-control.plugin-remove_button .item .remove{border-left:none !important}.bslib-card{box-shadow:var(--bslib-card-box-shadow, 0px 0px 2px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.14),0px 2px 4px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.16));border-color:var(--bslib-card-border-color, transparent)}.bslib-card.bslib-value-box.default{--bslib-value-box-border-color-default: var(--bslib-card-border-color, transparent)}.bslib-card .bslib-card{--bslib-card-box-shadow: ;--bslib-card-border-color: var(--bs-card-border-color)}.bslib-card .bslib-card.bslib-value-box.default{--bslib-value-box-border-color-default: var(--bs-card-border-color, var(--bs-border-color-translucent))}.bslib-card-box-shadow-sm{--bslib-card-box-shadow: var(--bslib-card-box-shadow-sm, 0px 0px 2px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.14),0px 2px 4px 0px RGBA(var(--bslib-box-shadow-color-rgb), 0.16))}.bslib-card-box-shadow-md{--bslib-card-box-shadow: var(--bslib-card-box-shadow-md, 0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08))}.bslib-card-box-shadow-lg{--bslib-card-box-shadow: var(--bslib-card-box-shadow-lg, 0px 4px 10px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.17))}.bslib-card-box-shadow-none{--bslib-card-box-shadow: none;--bslib-card-border-color: var(--bs-card-border-color)}.popover{--bs-popover-shadow: 0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08);box-shadow:var(--bs-popover-shadow)}:root{--bslib-dashboard-sidebar-bg: var(--bs-body-bg);--bslib-dashboard-sidebar-main-bg: var(--bs-body-bg);--bslib-dashboard-main-bg: rgb(247, 247, 247);--bs-card-border-color: var(--bslib-dashboard-border-color-translucent, var(--bs-border-color-translucent));--bslib-dashboard-card-header-font-weight: 600;--bslib-sidebar-bg: RGBA(var(--bs-body-bg-rgb), 0.05)}[data-bs-theme="dark"]{--bslib-dashboard-main-bg: rgb(20, 20, 24)}.bslib-card{--bs-card-cap-bg: }.bslib-card .card-header,.bslib-card .card-footer{font-size:0.9rem}.bslib-card .card-header{font-weight:var(--bslib-dashboard-card-header-font-weight);line-height:1.375rem}.bslib-sidebar-layout:has(>.bslib-page-dashboard),.bslib-sidebar-layout:has(.tab-content>.bslib-page-dashboard.active){--_main-bg: var(--bslib-dashboard-main-bg)}.bslib-page-navbar .tab-content>.bslib-page-dashboard.active{background-color:var(--bslib-dashboard-main-bg)}.bslib-page-navbar>.navbar,.bslib-page-dashboard>.navbar{--bslib-navbar-default-bg: var(--bs-body-bg);--bslib-navbar-inverse-bg: var(--bs-body-color)}.bslib-page-navbar>.navbar+div,.bslib-page-dashboard>.navbar+div{border-top:var(--bs-border-width) solid var(--bs-border-color-translucent)}.bslib-page-navbar>.navbar+div>.bslib-sidebar-layout,.bslib-page-navbar>.navbar+div>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout.html-fill-item,.bslib-page-dashboard>.navbar+div>.bslib-sidebar-layout,.bslib-page-dashboard>.navbar+div>.tab-content>.tab-pane.active.html-fill-container>.bslib-sidebar-layout.html-fill-item{border-top:none !important}.bslib-page-sidebar{--bslib-page-sidebar-title-bg: var(--bs-body-bg);--bslib-page-sidebar-title-color: var(--bs-body-color)}.bslib-page-sidebar .bslib-page-title{border-color:var(--bs-border-color-translucent)}.nav-underline{--bs-link-color: rgba(var(--bs-body-color-rgb), 0.65);--bs-link-hover-color: rgba(var(--bs-body-color-rgb), 0.8);--bs-nav-link-font-size: 0.875rem}.nav-underline .nav-link,.nav-underline :where(ul.nav.navbar-nav > li)>a,.nav-underline .nav-tabs>li>a,.nav-underline .nav-pills>li>a{padding-left:5px !important;padding-right:5px !important}.nav-underline .nav-link.active,.nav-underline :where(ul.nav.navbar-nav > li)>a.active,.nav-underline .nav-tabs>li>a.active,.nav-underline .nav-pills>li>a.active{font-weight:500}.navbar-collapse.show .nav-underline,.navbar-collapse.in .nav-underline,.navbar-collapse.collapsing .nav-underline{--bs-nav-underline-border-width: 0;--bs-nav-underline-gap: 0}.navbar .nav-underline .nav-link,.navbar .nav-underline :where(ul.nav.navbar-nav > li)>a,.navbar .nav-underline .nav-tabs>li>a,.navbar .nav-underline .nav-pills>li>a{padding-bottom:calc(var(--bs-navbar-padding-y, .5rem) * 2);margin-bottom:calc(var(--bs-navbar-padding-y, .5rem) * -1)}.bslib-value-box.default .value-box-showcase>i.bi{background:linear-gradient(140deg, #007bc2 36%, #74149c 180%) #007bc2;-webkit-background-clip:text;-webkit-text-fill-color:transparent}.bslib-value-box.default .value-box-showcase>i.fa{background:linear-gradient(140deg, #007bc2 36%, #74149c 180%) #007bc2;-webkit-background-clip:text;-webkit-text-fill-color:transparent}.bslib-value-box.default .value-box-showcase>i.fas{background:linear-gradient(140deg, #007bc2 36%, #74149c 180%) #007bc2;-webkit-background-clip:text;-webkit-text-fill-color:transparent}.bslib-value-box.default .value-box-showcase>i.far{background:linear-gradient(140deg, #007bc2 36%, #74149c 180%) #007bc2;-webkit-background-clip:text;-webkit-text-fill-color:transparent}.bslib-value-box.default .value-box-showcase>i.fab{background:linear-gradient(140deg, #007bc2 36%, #74149c 180%) #007bc2;-webkit-background-clip:text;-webkit-text-fill-color:transparent}.bslib-value-box.default .value-box-showcase>i.material-icons{background:linear-gradient(140deg, #007bc2 36%, #74149c 180%) #007bc2;-webkit-background-clip:text;-webkit-text-fill-color:transparent}.bslib-value-box.default .value-box-showcase>svg.bi{fill:url("#bslib---icon-gradient") #007bc2 !important}.bslib-value-box.default .value-box-showcase>svg.fa{fill:url("#bslib---icon-gradient") #007bc2 !important}.bslib-value-box.default .value-box-showcase>svg.fas{fill:url("#bslib---icon-gradient") #007bc2 !important}.bslib-value-box.default .value-box-showcase>svg.far{fill:url("#bslib---icon-gradient") #007bc2 !important}.bslib-value-box.default .value-box-showcase>svg.fab{fill:url("#bslib---icon-gradient") #007bc2 !important}.bslib-value-box.default .value-box-showcase>svg.material-icons{fill:url("#bslib---icon-gradient") #007bc2 !important}.bslib-value-box.text-info{color:#028097 !important}.bslib-value-box.text-info,.bslib-value-box.text-info.text-cyan{--bslib-color-fg: $cyan !important}.bslib-value-box.text-light{--bslib-color-fg: $gray-600 !important}.bslib-value-box.text-warning{color:#A87600 !important}.bslib-value-box.text-warning,.bslib-value-box.text-warning.text-yellow{--bslib-color-fg: $warning !important}.bslib-value-box.text-teal.text-teal{--bslib-color-fg: #008558}.modal-body,.modal-footer{padding:1.5rem}.modal-header .btn-close{align-self:start;display:flex}#shiny-modal-wrapper:has(~.modal-backdrop) .modal{backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}#shiny-notification-panel#shiny-notification-panel{position:fixed;bottom:calc(var(--bslib-spacer, 1rem) / 2);right:calc(var(--bslib-spacer, 1rem) / 2);width:450px;z-index:1090}.progress-message{margin-right:.6rem}.shiny-notification.shiny-notification{position:relative;opacity:0.96;padding:2rem;margin:var(--bslib-spacer, 1rem);border:1px solid var(--bs-border-color-translucent);border-radius:8px;box-shadow:0px 1px 2px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 3px 7px RGBA(var(--bslib-box-shadow-color-rgb), 0.1),0px 12px 30px RGBA(var(--bslib-box-shadow-color-rgb), 0.08)}.shiny-notification.shiny-notification .shiny-notification-close{position:absolute;font-size:1.5em;width:2rem;height:2rem;top:0;right:0;bottom:unset;display:flex;align-items:center;justify-content:center;padding:0.25rem;cursor:pointer;font-weight:200;color:currentColor}.shiny-notification.shiny-notification .shiny-notification-close:hover{font-weight:normal}.shiny-notification.shiny-notification .shiny-notification-content-text :last-child{margin-bottom:0}.accordion .accordion-header{font-size:calc(1.325rem + .9vw);margin-top:0;margin-bottom:.5rem;font-weight:400;line-height:1.2;color:var(--bs-heading-color);margin-bottom:0}@media (min-width: 1200px){.accordion .accordion-header{font-size:2rem}}.accordion .accordion-icon:not(:empty){margin-right:0.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)}.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}.bslib-card[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{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,0.15);margin:0.2rem 0.4rem;padding:0.55rem !important;font-size:.8rem;cursor:pointer;opacity:0;z-index:1070}.card:hover>*>.bslib-full-screen-enter,.well:hover>*>.bslib-full-screen-enter,.card:focus-within>*>.bslib-full-screen-enter,.well:focus-within>*>.bslib-full-screen-enter{opacity:0.6}.card:hover>*>.bslib-full-screen-enter:hover,.well:hover>*>.bslib-full-screen-enter:hover,.card:hover>*>.bslib-full-screen-enter:focus,.well:hover>*>.bslib-full-screen-enter:focus,.card:focus-within>*>.bslib-full-screen-enter:hover,.well:focus-within>*>.bslib-full-screen-enter:hover,.card:focus-within>*>.bslib-full-screen-enter:focus,.well:focus-within>*>.bslib-full-screen-enter:focus{opacity:1}.card[data-full-screen="false"]:hover>*>.bslib-full-screen-enter,[data-full-screen="false"].well:hover>*>.bslib-full-screen-enter{display:block}.bslib-has-full-screen .bslib-full-screen-enter{display:none !important}.bslib-full-screen-exit{position:relative;top:1.35rem;font-size:0.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:0.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}}@media (max-width: 575.98px){.bslib-card[data-full-screen="true"]{inset:2.5rem 0.5rem 0.5rem}.bslib-full-screen-exit{top:0.75rem;margin-right:1.25rem}}.bslib-grid{--_item-column-span: 1;display:grid !important;gap:var(--bslib-spacer, 1rem);height:var(--bslib-grid-height)}.bslib-grid>*{grid-column:auto/span var(--_item-column-span, 1)}.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--row-heights--sm: unset;--bslib-grid--row-heights--md: unset;--bslib-grid--row-heights--lg: unset;--bslib-grid--row-heights--xl: unset;--bslib-grid--row-heights--xxl: unset}.bslib-grid.grid.bslib-grid--row-heights--xs{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xs)}@media (min-width: 576px){.bslib-grid.grid.bslib-grid--row-heights--sm{--bslib-grid--row-heights: var(--bslib-grid--row-heights--sm)}}@media (min-width: 768px){.bslib-grid.grid.bslib-grid--row-heights--md{--bslib-grid--row-heights: var(--bslib-grid--row-heights--md)}}@media (min-width: 992px){.bslib-grid.grid.bslib-grid--row-heights--lg{--bslib-grid--row-heights: var(--bslib-grid--row-heights--lg)}}@media (min-width: 1200px){.bslib-grid.grid.bslib-grid--row-heights--xl{--bslib-grid--row-heights: var(--bslib-grid--row-heights--xl)}}@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-layout-columns.bslib-grid{--_item-column-span: 6}bslib-layout-columns[hidden-until-init]>*{display:none}@media (max-width: 767.98px){bslib-layout-columns:where(.bslib-grid)>*{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}}@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-page-fill{width:100%;height:100%;margin:0;padding:var(--bslib-spacer, 1rem);gap:var(--bslib-spacer, 1rem)}@media (max-width: 575.98px){.bslib-flow-mobile>.html-fill-item{flex:0 0 auto}.bslib-flow-mobile.bslib-page-sidebar>.html-fill-item,.bslib-flow-mobile.bslib-page-navbar.has-page-sidebar>.html-fill-item{flex:1 1 auto}.bslib-flow-mobile.bslib-page-sidebar>.bslib-sidebar-layout>.main>.html-fill-item,.bslib-flow-mobile.bslib-page-navbar.has-page-sidebar>.html-fill-container>.bslib-sidebar-layout>.main>.html-fill-item{flex:0 0 auto}}.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)}:root{--bslib-page-sidebar-title-bg: #202020;--bslib-page-sidebar-title-color: #fff}.bslib-page-sidebar>.navbar{--bs-navbar-brand-color: var(--bslib-page-sidebar-title-color);border-bottom:var(--bs-border-width) solid var(--bs-border-color-translucent);background-color:var(--bslib-page-sidebar-title-bg);color:var(--bslib-page-sidebar-title-color)}.bslib-page-sidebar .bslib-page-title{margin-bottom:0;line-height:var(--bs-body-line-height)}@media (max-width: 991.98px){.bslib-page-sidebar>.bslib-sidebar-layout.sidebar-collapsed:not(.sidebar-right)>.main,.bslib-page-navbar>div>.bslib-sidebar-layout.sidebar-collapsed:not(.sidebar-right)>.main{padding-right:var(--_padding)}.bslib-page-sidebar>.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.main,.bslib-page-navbar>div>.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.main{padding-left:var(--_padding)}}@media (min-width: 576px){.bslib-sidebar-layout .bslib-page-main{min-height:var(--bslib-page-main-min-height, 576px)}.bslib-sidebar-layout:not(.sidebar-collapsed) .bslib-page-main,.bslib-sidebar-layout.transitioning .bslib-page-main{min-width:var(--bslib-page-main-min-width, 576px)}}.bslib-sidebar-layout{--_transition-duration: 0;--_transition-easing-x: var(--bslib-sidebar-transition-easing-x, cubic-bezier(0.8, 0.78, 0.22, 1.07));--_border: var(--bslib-sidebar-border, var(--bs-card-border-width, var(--bs-border-width)) solid var(--bs-card-border-color, var(--bs-border-color-translucent)));--_border-radius: var(--bslib-sidebar-border-radius, var(--bs-border-radius));--_vert-border: var(--bslib-sidebar-vert-border, var(--_border));--_sidebar-width: var(--bslib-sidebar-width, 250px);--_sidebar-bg: var(--bslib-sidebar-bg, rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.05));--_sidebar-fg: var(--bslib-sidebar-fg, var(--_main-fg));--_main-fg: var(--bslib-sidebar-main-fg, var(--bs-card-color, var(--bs-body-color)));--_main-bg: var(--bslib-sidebar-main-bg, transparent);--_toggle-bg: var(--bslib-sidebar-toggle-bg, rgba(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.1));--_padding: var(--bslib-sidebar-padding, var(--bslib-spacer, 1.5rem));--_icon-size: var(--bslib-sidebar-icon-size, 1rem);--_icon-button-size: var(--bslib-sidebar-icon-button-size, calc(var(--_icon-size, 1rem) * 2));--_padding-icon: calc(var(--_icon-button-size, 2rem) * 1.5);--_toggle-border-radius: var(--bslib-collapse-toggle-border-radius, var(--bs-border-radius, 3px));--_toggle-transform: var(--bslib-collapse-toggle-transform, 0deg);--_toggle-transition-easing: var(--bslib-sidebar-toggle-transition-easing, cubic-bezier(1, 0, 0, 1));--_toggle-right-transform: var(--bslib-collapse-toggle-right-transform, 180deg);--_toggle-position-y: calc(var(--_js-toggle-count-this-side, 0) * calc(var(--_icon-size) + var(--_padding)) + var(--_icon-size, 1rem) / 2);--_toggle-position-x: calc(-2.5 * var(--_icon-size) - var(--bs-card-border-width, 1px));--_mobile-max-height: var(--bslib-sidebar-mobile-max-height, var(--bslib-sidebar-max-height-mobile));--_sidebar-mobile-opacity: var(--bslib-sidebar-mobile-opacity);--_main-mobile-expanded-opacity: var(--bslib-sidebar-main-mobile-expanded-opacity, 0);--_sidebar-mobile-max-width: var(--bslib-sidebar-mobile-max-width);--_sidebar-mobile-box-shadow: var(--bslib-sidebar-mobile-box-shadow);--_column-main: minmax(0, 1fr);--_toggle-collective-height: calc(calc(var(--_icon-button-size) + 0.5em) * var(--_js-toggle-count-max-side, 1));display:grid !important;grid-template-columns:Min(calc(100% - var(--_padding-icon)), var(--_sidebar-width)) var(--_column-main);position:relative;transition:grid-template-columns ease-in-out var(--_transition-duration),background-color linear var(--_transition-duration);border:var(--_border);border-radius:var(--_border-radius)}.bslib-sidebar-layout.transitioning{--_transition-duration: max(var(--bslib-sidebar-transition-duration, 300ms), 5ms)}@media (prefers-reduced-motion: reduce){.bslib-sidebar-layout{transition:none}}.bslib-sidebar-layout,.html-fill-container>.bslib-sidebar-layout.html-fill-item{min-height:var(--_toggle-collective-height)}.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(--_padding);transition:padding var(--_transition-easing-x) var(--_transition-duration);color:var(--_main-fg);background-color:var(--_main-bg)}.bslib-sidebar-layout>.sidebar{grid-column:1 / 2;width:100%;border-right:var(--_vert-border);border-top-right-radius:0;border-bottom-right-radius:0;color:var(--_sidebar-fg);background-color:var(--_sidebar-bg)}.bslib-sidebar-layout>.sidebar>.sidebar-content{display:flex;flex-direction:column;gap:var(--bslib-spacer, 1rem);padding:var(--_padding);padding-top:var(--_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(--_padding));margin-right:calc(-1 * var(--_padding))}.bslib-sidebar-layout>.sidebar>.sidebar-content>.accordion:last-child{margin-bottom:calc(-1 * var(--_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>.collapse-toggle{grid-row:1 / 2;grid-column:1 / 2;z-index:1000;display:inline-flex;align-items:center;position:absolute;right:calc(var(--_icon-size));top:calc(var(--_icon-size, 1rem) / 2);border:none;border-radius:var(--_toggle-border-radius);height:var(--_icon-button-size, 2rem);width:var(--_icon-button-size, 2rem);display:flex;align-items:center;justify-content:center;padding:0;color:var(--_sidebar-fg);background-color:unset;transition:color var(--_transition-easing-x) var(--_transition-duration),top var(--_transition-easing-x) var(--_transition-duration),right var(--_transition-easing-x) var(--_transition-duration),left var(--_transition-easing-x) var(--_transition-duration)}.bslib-sidebar-layout>.collapse-toggle:hover{background-color:var(--_toggle-bg)}.bslib-sidebar-layout>.collapse-toggle>.collapse-icon{opacity:0.8;width:var(--_icon-size);height:var(--_icon-size);transform:rotateY(var(--_toggle-transform));transition:transform var(--_toggle-transition-easing) var(--_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(--_border)}.bslib-sidebar-layout.sidebar-right{grid-template-columns:var(--_column-main) Min(calc(100% - var(--_padding-icon)), var(--_sidebar-width))}.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(--_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(--_icon-size);right:unset;border:var(--bslib-collapse-toggle-border)}.bslib-sidebar-layout.sidebar-right>.collapse-toggle>.collapse-icon{transform:rotateY(var(--_toggle-right-transform))}.bslib-sidebar-layout.transitioning>.sidebar>.sidebar-content{display:none}.bslib-sidebar-layout.sidebar-collapsed{--_toggle-transform: 180deg;--_toggle-right-transform: 0deg;--_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;padding-left:var(--_padding-icon);padding-right:var(--_padding-icon)}.bslib-sidebar-layout.sidebar-collapsed>.collapse-toggle{color:var(--_main-fg);top:var(--_toggle-position-y);right:var(--_toggle-position-x)}.bslib-sidebar-layout.sidebar-collapsed.sidebar-right>.collapse-toggle{left:var(--_toggle-position-x);right:unset}.bslib-sidebar-layout{--bslib-sidebar-js-window-size: desktop}@media (max-width: 575.98px){.bslib-sidebar-layout{--bslib-sidebar-js-window-size: mobile}}@media (min-width: 576px){.bslib-sidebar-layout[data-collapsible-desktop="false"]{--_padding-icon: var(--_padding)}.bslib-sidebar-layout[data-collapsible-desktop="false"]>.collapse-toggle{display:none}.bslib-sidebar-layout[data-collapsible-desktop="false"]>.sidebar[hidden]{display:block !important}.bslib-sidebar-layout[data-collapsible-desktop="false"]>.sidebar[hidden]>.sidebar-content{display:flex !important}}@media (max-width: 575.98px){.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-collapsible-mobile="true"]{grid-template-rows:calc(var(--_icon-button-size) + var(--_padding)) 1fr;grid-template-columns:100% 0}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.collapse-toggle{grid-row:1 / 2}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.main{grid-row:2 / 3}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.sidebar{grid-row:1 / 3}.bslib-sidebar-layout[data-collapsible-mobile="true"]:not(.sidebar-collapsed)>.sidebar,.bslib-sidebar-layout[data-collapsible-mobile="true"].transitioning>.sidebar{z-index:1045}.bslib-sidebar-layout[data-collapsible-mobile="true"]:not(.sidebar-collapsed)>.collapse-toggle,.bslib-sidebar-layout[data-collapsible-mobile="true"].transitioning>.collapse-toggle{z-index:1045}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.collapse-toggle{top:unset;position:relative;align-self:center}.bslib-sidebar-layout[data-collapsible-mobile="true"]:not(.sidebar-right)>.collapse-toggle{left:var(--_icon-size);right:unset;justify-self:left}.bslib-sidebar-layout[data-collapsible-mobile="true"].sidebar-right>.collapse-toggle{right:var(--_icon-size);left:unset;justify-self:right}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.sidebar{opacity:var(--_sidebar-mobile-opacity, 1);max-width:var(--_sidebar-mobile-max-width, 100%);box-shadow:var(--_sidebar-mobile-box-shadow)}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.sidebar{margin:0;padding-top:var(--_padding-icon)}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.sidebar>.sidebar-content{padding-top:0;height:100%;overflow-y:auto}.bslib-sidebar-layout[data-collapsible-mobile="true"]:not(.sidebar-right)>.sidebar{margin-right:auto}.bslib-sidebar-layout[data-collapsible-mobile="true"].sidebar-right>.sidebar{margin-left:auto}.bslib-sidebar-layout[data-collapsible-mobile="true"].sidebar-right{grid-template-columns:0 100%}.bslib-sidebar-layout[data-collapsible-mobile="true"].sidebar-collapsed{grid-template-columns:0 100%}.bslib-sidebar-layout[data-collapsible-mobile="true"].sidebar-collapsed.sidebar-right{grid-template-columns:100% 0}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.main{padding-top:1px;padding-left:var(--_padding);padding-right:var(--_padding)}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.main{opacity:var(--_main-mobile-expanded-opacity);transition:opacity var(--_transition-easing-x) var(--_transition-duration)}.bslib-sidebar-layout[data-collapsible-mobile="true"].sidebar-collapsed>.main{opacity:1}.bslib-sidebar-layout[data-collapsible-mobile="true"]>.main{background-color:none}.bslib-sidebar-layout[data-collapsible-mobile="true"],.bslib-sidebar-layout[data-collapsible-mobile="true"].sidebar-collapsed{background-color:var(--_main-bg)}}@media (max-width: 575.98px){.bslib-sidebar-layout[data-collapsible-mobile="false"]{display:block !important;--_padding-icon: var(--_padding);--_vert-border: var(--_border)}.bslib-sidebar-layout[data-collapsible-mobile="false"]>.sidebar[hidden]{display:block !important}.bslib-sidebar-layout[data-collapsible-mobile="false"]>.sidebar[hidden]>.sidebar-content{display:flex !important}.bslib-sidebar-layout[data-collapsible-mobile="false"]>.sidebar{max-height:var(--_mobile-max-height);overflow-y:auto}.bslib-sidebar-layout[data-collapsible-mobile="false"][data-open-mobile="always"]>.sidebar{border-top:var(--_vert-border)}.bslib-sidebar-layout[data-collapsible-mobile="false"][data-open-mobile="always-above"]>.sidebar{border-bottom:var(--_vert-border)}.bslib-sidebar-layout[data-collapsible-mobile="false"]>.collapse-toggle{display:none}}.bslib-value-box{container-name:bslib-value-box;container-type:inline-size}.bslib-value-box.default{--bslib-value-box-bg-default: var(--bs-card-bg, #fff);--bslib-value-box-border-color-default: var(--bs-card-border-color, var(--bs-border-color-translucent));color:var(--bslib-value-box-color, var(--bs-body-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 .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:400;line-height:1.2}.bslib-value-box .value-box-title:empty::after{content:'\00a0 '}.bslib-value-box .value-box-value{font-size:calc(1.325rem + .9vw);margin-top:0;margin-bottom:.5rem;font-weight:400;line-height:1.2}@media (min-width: 1200px){.bslib-value-box .value-box-value{font-size:2rem}}.bslib-value-box .value-box-value:empty::after{content:'\00a0 '}.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}.shiny-panel-conditional:has(>*),div:where(.shiny-html-output):has(>*){display:contents}.shiny-panel-conditional:has(>*).recalculating>*,div:where(.shiny-html-output):has(>*).recalculating>*{opacity:0.3}pre.shiny-text-output:empty::before{content:" "}pre.shiny-text-output.noplaceholder:empty{margin:0;padding:0;border-width:0;height:0}pre.shiny-text-output{word-wrap:normal;border-radius:3px}.shiny-image-output img.shiny-scalable,.shiny-plot-output img.shiny-scalable{max-width:100%;max-height:100%}#shiny-disconnected-overlay{position:fixed;inset:0;background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.42);opacity:0.5;overflow:hidden;z-index:99998;pointer-events:none}html.autoreload-enabled #shiny-disconnected-overlay.reloading{opacity:0;animation:fadeIn 250ms forwards;animation-delay:1s}@keyframes fadeIn{to{opacity:0.1}}.table.shiny-table>thead>tr>th,.table.shiny-table>thead>tr>td,.table.shiny-table>tbody>tr>th,.table.shiny-table>tbody>tr>td,.table.shiny-table>tfoot>tr>th,.table.shiny-table>tfoot>tr>td{padding-right:12px;padding-left:12px}.shiny-table.spacing-xs>thead>tr>th,.shiny-table.spacing-xs>thead>tr>td,.shiny-table.spacing-xs>tbody>tr>th,.shiny-table.spacing-xs>tbody>tr>td,.shiny-table.spacing-xs>tfoot>tr>th,.shiny-table.spacing-xs>tfoot>tr>td{padding-top:3px;padding-bottom:3px}.shiny-table.spacing-s>thead>tr>th,.shiny-table.spacing-s>thead>tr>td,.shiny-table.spacing-s>tbody>tr>th,.shiny-table.spacing-s>tbody>tr>td,.shiny-table.spacing-s>tfoot>tr>th,.shiny-table.spacing-s>tfoot>tr>td{padding-top:5px;padding-bottom:5px}.shiny-table.spacing-m>thead>tr>th,.shiny-table.spacing-m>thead>tr>td,.shiny-table.spacing-m>tbody>tr>th,.shiny-table.spacing-m>tbody>tr>td,.shiny-table.spacing-m>tfoot>tr>th,.shiny-table.spacing-m>tfoot>tr>td{padding-top:8px;padding-bottom:8px}.shiny-table.spacing-l>thead>tr>th,.shiny-table.spacing-l>thead>tr>td,.shiny-table.spacing-l>tbody>tr>th,.shiny-table.spacing-l>tbody>tr>td,.shiny-table.spacing-l>tfoot>tr>th,.shiny-table.spacing-l>tfoot>tr>td{padding-top:10px;padding-bottom:10px}.shiny-table .NA{color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.46)}.shiny-output-error{color:var(--bs-danger);white-space:pre-wrap}.shiny-output-error:before{content:'Error: ';font-weight:bold}.shiny-output-error-validation{color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.5)}.shiny-output-error-validation:before{content:'';font-weight:inherit}@supports (-ms-ime-align: auto){.shiny-bound-output{transition:0}}.recalculating{opacity:0.3;transition:opacity 250ms ease 500ms}.slider-animate-container{text-align:right;margin-top:-9px}.slider-animate-button{position:relative;z-index:1;opacity:0.5}.slider-animate-button .pause{display:none}.slider-animate-button.playing .pause{display:inline}.slider-animate-button .play{display:inline}.slider-animate-button.playing .play{display:none}.progress.shiny-file-input-progress{visibility:hidden}.progress.shiny-file-input-progress .progress-bar.bar-danger{transition:none}.btn-file{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.shiny-input-container input[type=file]{overflow:hidden;max-width:100%}.shiny-progress-container{position:fixed;top:0px;width:100%;z-index:2000}.shiny-progress .progress{position:absolute;width:100%;top:0px;height:3px;margin:0px}.shiny-progress .bar{opacity:0.6;transition-duration:250ms}.shiny-progress .progress-text{position:absolute;right:10px;width:240px;background-color:RGBA(var(--bs-primary-rgb, 0,123,194), 0.05);margin:0px;padding:2px 3px;opacity:0.85}.shiny-progress .progress-text .progress-message{padding:0px 3px;font-weight:bold;font-size:90%}.shiny-progress .progress-text .progress-detail{padding:0px 3px;font-size:80%}.shiny-progress-notification .progress{margin-bottom:5px;height:10px}.shiny-progress-notification .progress-text .progress-message{font-weight:bold;font-size:90%}.shiny-progress-notification .progress-text .progress-detail{font-size:80%}.shiny-label-null{display:none}.crosshair{cursor:crosshair}.grabbable{cursor:grab;cursor:-moz-grab;cursor:-webkit-grab}.grabbing{cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}.ns-resize{cursor:ns-resize}.ew-resize{cursor:ew-resize}.nesw-resize{cursor:nesw-resize}.nwse-resize{cursor:nwse-resize}.qt pre,.qt code{font-family:monospace !important}.qt5 .radio input[type="radio"],.qt5 .checkbox input[type="checkbox"]{margin-top:0px}.qtmac input[type="radio"],.qtmac input[type="checkbox"]{zoom:1.0000001}.shiny-frame{border:none}.shiny-flow-layout>div{display:inline-block;vertical-align:top;padding-right:12px;width:220px}.shiny-split-layout{width:100%;white-space:nowrap}.shiny-split-layout>div{display:inline-block;vertical-align:top;box-sizing:border-box;overflow:auto}.shiny-input-panel{padding:6px 8px;margin-top:6px;margin-bottom:6px;background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.04);border:1px solid var(--bs-border-color, #dee2e6);border-radius:3px}.shiny-input-checkboxgroup label~.shiny-options-group,.shiny-input-radiogroup label~.shiny-options-group{margin-top:-10px}.shiny-input-checkboxgroup.shiny-input-container-inline label~.shiny-options-group,.shiny-input-radiogroup.shiny-input-container-inline label~.shiny-options-group{margin-top:-1px}.shiny-input-container:not(.shiny-input-container-inline){width:300px;max-width:100%}.well .shiny-input-container{width:auto}.shiny-input-container>div>select:not(.selectized){width:100%}#shiny-notification-panel{position:fixed;bottom:0;right:0;background-color:rgba(0,0,0,0);padding:2px;width:300px;max-width:100%;z-index:99999}.shiny-notification{position:relative;background-color:var(--bs-body-bg, #fff);color:var(--bs-emphasis-color, #000);border:1px solid var(--bs-border-color, #dee2e6);border-radius:3px;opacity:0.85;padding:10px 2rem 10px 10px;margin:5px}.shiny-notification-message{color:var(--bs-info-text-emphasis);background-color:var(--bs-info-bg-subtle);border:1px solid var(--bs-info-border-subtle)}.shiny-notification-warning{color:var(--bs-warning-text-emphasis);background-color:var(--bs-warning-bg-subtle);border:1px solid var(--bs-warning-border-subtle)}.shiny-notification-error{color:var(--bs-danger-text-emphasis);background-color:var(--bs-danger-bg-subtle);border:1px solid var(--bs-danger-border-subtle)}.shiny-notification-close{position:absolute;width:2rem;height:2rem;top:0;right:0;display:flex;align-items:center;justify-content:center;font-weight:normal;font-size:1.125em;padding:0.25rem;color:currentColor;cursor:pointer}.shiny-notification-close:hover{color:RGB(var(--bs-emphasis-color-rgb, 0, 0, 0));font-weight:bold}.shiny-notification-content-action a{color:RGB(var(--bs-primary-rgb, 0,123,194));text-decoration:underline;font-weight:bold}.shiny-file-input-active{box-shadow:0 0 0 .25rem rgba(0,123,194,0.25)}.shiny-file-input-over{box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(76,174,76,0.6)}.datepicker table tbody tr td.disabled,.datepicker table tbody tr td.disabled:hover,.datepicker table tbody tr td span.disabled,.datepicker table tbody tr td span.disabled:hover{color:var(--bs-tertiary-color);cursor:not-allowed}.nav-hidden{display:none !important}@use "sass:math";.selectize-control.plugin-drag_drop.multi>.selectize-input.dragging{overflow:visible}.selectize-control.plugin-drag_drop.multi>.selectize-input>div.ui-sortable-placeholder{visibility:visible !important;background:#f2f2f2 !important;background:rgba(0,0,0,0.06) !important;border:0 none !important;box-shadow:inset 0 0 12px 4px #fff}.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after{content:"!";visibility:hidden}.selectize-control.plugin-drag_drop .ui-sortable-helper{box-shadow:0 2px 5px rgba(0,0,0,0.2)}.selectize-dropdown.plugin-dropdown_header .selectize-dropdown-header{position:relative;padding:6px .75rem;border-bottom:1px solid #d0d0d0;background:RGBA(var(--bs-body-bg), 0.15);border-radius:var(--bs-border-radius) var(--bs-border-radius) 0 0}.selectize-dropdown.plugin-dropdown_header .selectize-dropdown-header-close{position:absolute;right:.75rem;top:50%;color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.83);opacity:0.4;margin-top:-12px;line-height:20px;font-size:20px !important;text-decoration:none}.selectize-dropdown.plugin-dropdown_header .selectize-dropdown-header-close:hover{color:RGB(var(--bs-emphasis-color-rgb, 0, 0, 0))}.selectize-dropdown.plugin-optgroup_columns .selectize-dropdown-content{display:flex}.selectize-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;flex-grow:1;flex-basis:0;min-width:0}.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.selectize-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.selectize-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.selectize-control.plugin-remove_button .item{display:inline-flex;align-items:center;padding-right:0 !important}.selectize-control.plugin-remove_button .item .remove{color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:1px 5px;border-left:1px solid #dee2e6;border-radius:0 2px 2px 0;box-sizing:border-box;margin-left:5px}.selectize-control.plugin-remove_button .item .remove:hover{background:rgba(0,0,0,0.05)}.selectize-control.plugin-remove_button .item.active .remove{border-left-color:rgba(0,0,0,0)}.selectize-control.plugin-remove_button .disabled .item .remove:hover{background:none}.selectize-control.plugin-remove_button .disabled .item .remove{border-left-color:#fff}.selectize-control.plugin-clear_button .clear{text-decoration:none;display:flex;position:absolute;height:100%;width:25px;top:0;right:calc(.75rem - 5px);color:var(--bs-body-color, black);opacity:0.4;font-weight:bold;border:none;cursor:pointer;z-index:1;font-size:21px;justify-content:center;align-items:center}.selectize-control.plugin-clear_button .clear:hover{opacity:1}.selectize-control.plugin-clear_button.single .clear{right:calc(.75rem - 5px + 1.5rem)}.selectize-dropdown.plugin-auto_position.selectize-position-top{border-top:1px solid #d0d0d0;border-bottom:0 none;border-radius:3px 3px 0 0;box-shadow:0 -6px 12px rgba(var(--bs-body-color-rgb, 0, 0, 0), 0.18)}.selectize-control.plugin-auto_position .selectize-input.selectize-position-top.dropdown-active{border-radius:0 0 3px 3px;border-top:0 none}.selectize-control.plugin-auto_position .selectize-input.selectize-position-top.dropdown-active::before{top:0;bottom:unset}.selectize-control{position:relative}.selectize-dropdown,.selectize-input,.selectize-input input{color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.83);font-family:inherit;font-size:15px;line-height:1.5;font-smoothing:inherit}.selectize-input,.selectize-control.single .selectize-input.input-active{background:var(--bs-body-bg);cursor:text;display:inline-block}.selectize-input{border:1px solid #8D959E;padding:.375rem .75rem;display:inline-block;width:100%;position:relative;z-index:1;box-sizing:border-box;box-shadow:none;border-radius:var(--bs-border-radius)}.selectize-control.multi .selectize-input.has-items{padding:calc( .375rem - 1px - 0px) .75rem calc( .375rem - 1px - 3px - 0px)}.selectize-input.full{background-color:var(--bs-body-bg)}.selectize-input.disabled,.selectize-input.disabled *{cursor:default !important}.selectize-input.focus{box-shadow:inset 0 1px 2px rgba(0,0,0,0.15)}.selectize-input.dropdown-active{border-radius:var(--bs-border-radius) var(--bs-border-radius) 0 0}.selectize-input>*{vertical-align:baseline;display:inline-block;zoom:1}.selectize-control.multi .selectize-input>div{cursor:pointer;margin:0 3px 3px 0;padding:1px 5px;background:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.05);color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.83);border:0px solid #dee2e6}.selectize-control.multi .selectize-input>div.active{background:#007bc2;color:#fff;border:0px solid rgba(0,0,0,0)}.selectize-control.multi .selectize-input.disabled>div,.selectize-control.multi .selectize-input.disabled>div.active{color:#cdcdcd;background:#cdcdcd;border:0px solid #cdcdcd}.selectize-input>input{display:inline-block !important;padding:0 !important;min-height:0 !important;max-height:none !important;max-width:100% !important;margin:0 !important;text-indent:0 !important;border:0 none !important;background:none !important;line-height:inherit !important;user-select:auto !important;box-shadow:none !important}.selectize-input>input::-ms-clear{display:none}.selectize-input>input:focus{outline:none !important}.selectize-input>input[placeholder]{box-sizing:initial}.selectize-input.has-items>input{margin:0 0px !important}.selectize-input::after{content:" ";display:block;clear:left}.selectize-input.dropdown-active::before{content:" ";display:block;position:absolute;background:rgba(141,149,158,0.8);height:1px;bottom:0;left:0;right:0}.selectize-dropdown{position:absolute;top:100%;left:0;width:100%;z-index:10;border:1px solid #d0d0d0;background:var(--bs-body-bg);margin:-1px 0 0 0;border-top:0 none;box-sizing:border-box;box-shadow:0 1px 3px rgba(0,0,0,0.1);border-radius:0 0 var(--bs-border-radius) var(--bs-border-radius)}.selectize-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.selectize-dropdown [data-selectable] .highlight{background:rgba(255,237,40,0.4);border-radius:1px}.selectize-dropdown .option,.selectize-dropdown .optgroup-header,.selectize-dropdown .no-results,.selectize-dropdown .create{padding:3px .75rem}.selectize-dropdown .option,.selectize-dropdown [data-disabled],.selectize-dropdown [data-disabled] [data-selectable].option{cursor:inherit;opacity:0.5}.selectize-dropdown [data-selectable].option{opacity:1;cursor:pointer}.selectize-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.selectize-dropdown .optgroup-header{color:#707782;background:var(--bs-body-bg);cursor:default}.selectize-dropdown .active{background-color:#007bc2;color:#fff}.selectize-dropdown .active.create{color:var(--bs-body-color)}.selectize-dropdown .selected{background-color:#007bc2;color:#fff}.selectize-dropdown .create{color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.5)}.selectize-dropdown .active:not(.selected){background:var(--bs-tertiary-bg);color:var(--bs-body-color)}.selectize-dropdown-content{overflow-y:auto;overflow-x:hidden;max-height:200px;overflow-scrolling:touch}.selectize-dropdown-emptyoptionlabel{text-align:center}.selectize-dropdown .spinner{display:inline-block;width:30px;height:30px;margin:3px .75rem}.selectize-dropdown .spinner:after{content:" ";display:block;width:24px;height:24px;margin:3px;border-radius:50%;border:5px solid #d0d0d0;border-color:#d0d0d0 transparent #d0d0d0 transparent;animation:lds-dual-ring 1.2s linear infinite}@keyframes lds-dual-ring{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.selectize-control.single .selectize-input,.selectize-control.single .selectize-input input{cursor:pointer}.selectize-control.single .selectize-input.input-active,.selectize-control.single .selectize-input.input-active input:not(:read-only){cursor:text}.selectize-control.single .selectize-input:not(.no-arrow):after{content:" ";display:block;position:absolute;top:50%;right:calc(.75rem + 5px);margin-top:-3px;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.83) transparent transparent transparent}.selectize-control.single .selectize-input:not(.no-arrow).dropdown-active:after{margin-top:-4px;border-width:0 5px 5px 5px;border-color:transparent transparent RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.83) transparent}.selectize-control.rtl{text-align:right}.selectize-control.rtl.single .selectize-input:after{left:calc(.75rem + 5px);right:auto}.selectize-control.rtl .selectize-input>input{margin:0 4px 0 -2px !important}.selectize-control .selectize-input.disabled{opacity:.5;background-color:var(--bs-body-bg)}.selectize-dropdown,.selectize-dropdown.form-control{height:auto;padding:0;margin:2px 0 0 0;z-index:1000;background:var(--bs-body-bg);border:1px solid var(--bs-border-color-translucent);border-radius:3px;box-shadow:0 6px 12px rgba(0,0,0,0.175)}.selectize-dropdown .optgroup-header{font-size:.875rem;line-height:1.5}.selectize-dropdown .optgroup:first-child:before{display:none}.selectize-dropdown .optgroup:before{content:" ";display:block;height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid var(--bs-border-color-translucent);margin-left:-.75rem;margin-right:-.75rem}.selectize-dropdown .create{padding-left:.75rem}.selectize-dropdown-content{padding:5px 0}.selectize-dropdown-emptyoptionlabel{text-align:center}.selectize-input{min-height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));transition:border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.selectize-input{transition:none}}.selectize-input.dropdown-active{border-radius:var(--bs-border-radius)}.selectize-input.dropdown-active::before{display:none}.selectize-input.focus{border-color:#80bde1;outline:0;box-shadow:0 0 0 .25rem rgba(0,123,194,0.25)}.is-invalid .selectize-input{border-color:#c10000;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.is-invalid .selectize-input:focus{border-color:#8e0000;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ff2828}.selectize-control.form-control-sm .selectize-input{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2)) !important;height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2));padding:.25rem .5rem !important;font-size:.875rem;line-height:1.25}.selectize-control.multi .selectize-input{height:auto;padding-left:calc(.75rem - 5px);padding-right:calc(.75rem - 5px)}.selectize-control.multi .selectize-input>div{border-radius:calc(var(--bs-border-radius) - 1px)}.form-select.selectize-control,.form-control.selectize-control{padding:0;height:auto;border:none;background:none;box-shadow:none;border-radius:0}.input-group>.input-group-append>.btn,.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.input-group-prepend>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group .selectize-control:not(:last-child) .selectize-input{overflow:unset;border-top-right-radius:0;border-bottom-right-radius:0}.input-group .selectize-control:not(:first-child) .selectize-input{overflow:unset;border-top-left-radius:0;border-bottom-left-radius:0}.selectize-dropdown.plugin-auto_position.selectize-position-top{border-top:1px solid #8D959E !important;border-bottom:1px solid #8D959E !important;border-radius:var(--bs-border-radius) !important}.selectize-control.plugin-auto_position .selectize-input.selectize-position-top.dropdown-active{border-radius:var(--bs-border-radius) !important;border-top:1px solid #8D959E !important}.irs{position:relative;display:block;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box}.irs *,.irs *:before,.irs *:after{box-sizing:inherit}.irs-line{position:relative;display:block;overflow:hidden;outline:none !important}.irs-bar{position:absolute;display:block;left:0;width:0}.irs-shadow{position:absolute;display:none;left:0;width:0}.irs-handle{position:absolute;display:block;box-sizing:border-box;cursor:pointer;z-index:1}.irs-handle.type_last{z-index:2}.irs-min,.irs-max{position:absolute;display:block;cursor:default}.irs-min{left:0}.irs-max{right:0}.irs-from,.irs-to,.irs-single{position:absolute;display:block;top:0;left:0;cursor:default;white-space:nowrap}.irs-grid{position:absolute;display:none;bottom:0;left:0;width:100%;height:20px}.irs-with-grid .irs-grid{display:block}.irs-grid-pol{position:absolute;top:0;left:0;width:1px;height:8px}.irs-grid-pol.small{height:4px}.irs-grid-text{position:absolute;bottom:0;left:0;white-space:nowrap;text-align:center;font-size:9px;line-height:9px;padding:0 3px}.irs-disable-mask{position:absolute;display:block;top:0;left:-1%;width:102%;height:100%;cursor:default;background:rgba(0,0,0,0);z-index:2}.lt-ie9 .irs-disable-mask{background:#000;filter:alpha(opacity=0);cursor:not-allowed}.irs-disabled{opacity:0.4}.irs-hidden-input{position:absolute !important;display:block !important;top:0 !important;left:0 !important;width:0 !important;height:0 !important;font-size:0 !important;line-height:0 !important;padding:0 !important;margin:0 !important;overflow:hidden;outline:none !important;z-index:-9999 !important;background:none !important;border-style:solid !important;border-color:transparent !important}.irs{font-family:"Open Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.irs--shiny{height:40px}.irs--shiny.irs-with-grid{height:60px}.irs--shiny .irs-line{top:32px;height:1px;background:none;background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.65);border:none;border-radius:1px;overflow:visible}.irs--shiny .irs-line::before{content:"";display:block;position:relative;cursor:s-resize;width:100%;height:19px;top:-9.25px;z-index:1}.irs--shiny .irs-bar{top:32px;height:1px;border-top:1px solid #007bc2;border-bottom:1px solid #007bc2;background:#007bc2;cursor:s-resize;z-index:2}.irs--shiny .irs-bar--single{border-radius:1px 0 0 1px}.irs--shiny .irs-bar::before{content:"";display:block;position:relative;width:100%;height:19px;top:-9.25px;z-index:2}.irs--shiny .irs-shadow{top:38px;height:2px;background:rgba(0,0,0,0.3);border-radius:5px}.irs--shiny .lt-ie9 .irs-shadow{filter:alpha(opacity=30)}.irs--shiny .irs-handle{top:17px;width:19px;height:19px;border:none;background-color:#007bc2;box-shadow:none;border-radius:19px;z-index:2}.irs--shiny .irs-handle.state_hover,.irs--shiny .irs-handle:hover{background:#268fcb}.irs--shiny .irs-min,.irs--shiny .irs-max{top:0;padding:1px 3px;text-shadow:none;background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.1);border-radius:3px;font-size:10px;line-height:1.333}.irs--shiny .lt-ie9 .irs-min,.irs--shiny .lt-ie9 .irs-max{background:#ccc}.irs--shiny .irs-from,.irs--shiny .irs-to,.irs--shiny .irs-single{color:#fff;text-shadow:none;padding:1px 3px;background-color:#007bc2;border-radius:3px;font-size:11px;line-height:1.333}.irs--shiny .lt-ie9 .irs-from,.irs--shiny .lt-ie9 .irs-to,.irs--shiny .lt-ie9 .irs-single{background:#999}.irs--shiny .irs-grid{height:27px}.irs--shiny .irs-grid-pol{background-color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.65)}.irs--shiny .irs-grid-text{bottom:5px;color:RGBA(var(--bs-emphasis-color-rgb, 0, 0, 0), 0.85)}.irs--shiny .irs-grid-pol.small{background-color:rgba(0,0,0,0)}.datepicker{border-radius:3px;direction:ltr}.datepicker-inline{width:220px}.datepicker-rtl{direction:rtl}.datepicker-rtl.dropdown-menu{left:auto}.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0;padding:4px}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid var(--bs-border-color-translucent);border-top:0;border-bottom-color:rgba(0,0,0,0.2);position:absolute}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid var(--bs-body-bg);border-top:0;position:absolute}.datepicker-dropdown.datepicker-orient-left:before{left:6px}.datepicker-dropdown.datepicker-orient-left:after{left:7px}.datepicker-dropdown.datepicker-orient-right:before{right:6px}.datepicker-dropdown.datepicker-orient-right:after{right:7px}.datepicker-dropdown.datepicker-orient-bottom:before{top:-7px}.datepicker-dropdown.datepicker-orient-bottom:after{top:-6px}.datepicker-dropdown.datepicker-orient-top:before{bottom:-7px;border-bottom:0;border-top:7px solid var(--bs-border-color-translucent)}.datepicker-dropdown.datepicker-orient-top:after{bottom:-6px;border-bottom:0;border-top:6px solid var(--bs-body-bg)}.datepicker table{margin:0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker table tr td,.datepicker table tr th{text-align:center;width:30px;height:30px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.old,.datepicker table tr td.new{color:#707782}.datepicker table tr td.day:hover,.datepicker table tr td.focused{color:#000;background:#e8e9e9;cursor:pointer}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:none;color:#707782;cursor:default}.datepicker table tr td.highlighted{color:#000;background-color:#cdf4fa;border-color:#70e0f1;border-radius:0}.datepicker table tr td.highlighted:focus,.datepicker table tr td.highlighted.focus{color:#000;background-color:#b9dce1;border-color:#54a8b5}.datepicker table tr td.highlighted:hover{color:#000;background-color:#677a7d;border-color:#63c5d4}.datepicker table tr td.highlighted:active,.datepicker table tr td.highlighted.active{color:#000;background-color:#b9dce1;border-color:#63c5d4}.datepicker table tr td.highlighted:active:hover,.datepicker table tr td.highlighted:active:focus,.datepicker table tr td.highlighted:active.focus,.datepicker table tr td.highlighted.active:hover,.datepicker table tr td.highlighted.active:focus,.datepicker table tr td.highlighted.active.focus{color:#000;background-color:#aacbd0;border-color:#54a8b5}.datepicker table tr td.highlighted.disabled:hover,.datepicker table tr td.highlighted.disabled:focus,.datepicker table tr td.highlighted.disabled.focus,.datepicker table tr td.highlighted[disabled]:hover,.datepicker table tr td.highlighted[disabled]:focus,.datepicker table tr td.highlighted[disabled].focus,fieldset[disabled] .datepicker table tr td.highlighted:hover,fieldset[disabled] .datepicker table tr td.highlighted:focus,fieldset[disabled] .datepicker table tr td.highlighted.focus{background-color:#cdf4fa;border-color:#70e0f1}.datepicker table tr td.highlighted.focused{background:#9feaf5}.datepicker table tr td.highlighted.disabled,.datepicker table tr td.highlighted.disabled:active{background:#cdf4fa;color:#707782}.datepicker table tr td.today{color:#000;background-color:#ffdb99;border-color:#ffb733}.datepicker table tr td.today:focus,.datepicker table tr td.today.focus{color:#000;background-color:#e6c58a;border-color:#bf8926}.datepicker table tr td.today:hover{color:#000;background-color:#806e4d;border-color:#e0a12d}.datepicker table tr td.today:active,.datepicker table tr td.today.active{color:#000;background-color:#e6c58a;border-color:#e0a12d}.datepicker table tr td.today:active:hover,.datepicker table tr td.today:active:focus,.datepicker table tr td.today:active.focus,.datepicker table tr td.today.active:hover,.datepicker table tr td.today.active:focus,.datepicker table tr td.today.active.focus{color:#000;background-color:#d4b67f;border-color:#bf8926}.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:focus,.datepicker table tr td.today.disabled.focus,.datepicker table tr td.today[disabled]:hover,.datepicker table tr td.today[disabled]:focus,.datepicker table tr td.today[disabled].focus,fieldset[disabled] .datepicker table tr td.today:hover,fieldset[disabled] .datepicker table tr td.today:focus,fieldset[disabled] .datepicker table tr td.today.focus{background-color:#ffdb99;border-color:#ffb733}.datepicker table tr td.today.focused{background:#ffc966}.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:active{background:#ffdb99;color:#707782}.datepicker table tr td.range{color:#000;background-color:#e8e9e9;border-color:#b4b7b7;border-radius:0}.datepicker table tr td.range:focus,.datepicker table tr td.range.focus{color:#000;background-color:#d1d2d2;border-color:#878989}.datepicker table tr td.range:hover{color:#000;background-color:#747575;border-color:#9ea1a1}.datepicker table tr td.range:active,.datepicker table tr td.range.active{color:#000;background-color:#d1d2d2;border-color:#9ea1a1}.datepicker table tr td.range:active:hover,.datepicker table tr td.range:active:focus,.datepicker table tr td.range:active.focus,.datepicker table tr td.range.active:hover,.datepicker table tr td.range.active:focus,.datepicker table tr td.range.active.focus{color:#000;background-color:#c1c1c1;border-color:#878989}.datepicker table tr td.range.disabled:hover,.datepicker table tr td.range.disabled:focus,.datepicker table tr td.range.disabled.focus,.datepicker table tr td.range[disabled]:hover,.datepicker table tr td.range[disabled]:focus,.datepicker table tr td.range[disabled].focus,fieldset[disabled] .datepicker table tr td.range:hover,fieldset[disabled] .datepicker table tr td.range:focus,fieldset[disabled] .datepicker table tr td.range.focus{background-color:#e8e9e9;border-color:#b4b7b7}.datepicker table tr td.range.focused{background:#ced0d0}.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:active{background:#e8e9e9;color:#707782}.datepicker table tr td.range.highlighted{color:#000;background-color:#dbeff2;border-color:#90ced7}.datepicker table tr td.range.highlighted:focus,.datepicker table tr td.range.highlighted.focus{color:#000;background-color:#c5d7da;border-color:#6c9aa1}.datepicker table tr td.range.highlighted:hover{color:#000;background-color:#6e7879;border-color:#7fb5bd}.datepicker table tr td.range.highlighted:active,.datepicker table tr td.range.highlighted.active{color:#000;background-color:#c5d7da;border-color:#7fb5bd}.datepicker table tr td.range.highlighted:active:hover,.datepicker table tr td.range.highlighted:active:focus,.datepicker table tr td.range.highlighted:active.focus,.datepicker table tr td.range.highlighted.active:hover,.datepicker table tr td.range.highlighted.active:focus,.datepicker table tr td.range.highlighted.active.focus{color:#000;background-color:#b6c6c9;border-color:#6c9aa1}.datepicker table tr td.range.highlighted.disabled:hover,.datepicker table tr td.range.highlighted.disabled:focus,.datepicker table tr td.range.highlighted.disabled.focus,.datepicker table tr td.range.highlighted[disabled]:hover,.datepicker table tr td.range.highlighted[disabled]:focus,.datepicker table tr td.range.highlighted[disabled].focus,fieldset[disabled] .datepicker table tr td.range.highlighted:hover,fieldset[disabled] .datepicker table tr td.range.highlighted:focus,fieldset[disabled] .datepicker table tr td.range.highlighted.focus{background-color:#dbeff2;border-color:#90ced7}.datepicker table tr td.range.highlighted.focused{background:#b6dee4}.datepicker table tr td.range.highlighted.disabled,.datepicker table tr td.range.highlighted.disabled:active{background:#dbeff2;color:#707782}.datepicker table tr td.range.today{color:#000;background-color:#f4c775;border-color:#eca117}.datepicker table tr td.range.today:focus,.datepicker table tr td.range.today.focus{color:#000;background-color:#dcb369;border-color:#b17811}.datepicker table tr td.range.today:hover{color:#000;background-color:#7a643b;border-color:#d08d14}.datepicker table tr td.range.today:active,.datepicker table tr td.range.today.active{color:#000;background-color:#dcb369;border-color:#d08d14}.datepicker table tr td.range.today:active:hover,.datepicker table tr td.range.today:active:focus,.datepicker table tr td.range.today:active.focus,.datepicker table tr td.range.today.active:hover,.datepicker table tr td.range.today.active:focus,.datepicker table tr td.range.today.active.focus{color:#000;background-color:#cba561;border-color:#b17811}.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:focus,.datepicker table tr td.range.today.disabled.focus,.datepicker table tr td.range.today[disabled]:hover,.datepicker table tr td.range.today[disabled]:focus,.datepicker table tr td.range.today[disabled].focus,fieldset[disabled] .datepicker table tr td.range.today:hover,fieldset[disabled] .datepicker table tr td.range.today:focus,fieldset[disabled] .datepicker table tr td.range.today.focus{background-color:#f4c775;border-color:#eca117}.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:active{background:#f4c775;color:#707782}.datepicker table tr td.selected,.datepicker table tr td.selected.highlighted{color:#000;background-color:#878889;border-color:#606060;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.selected:focus,.datepicker table tr td.selected.focus,.datepicker table tr td.selected.highlighted:focus,.datepicker table tr td.selected.highlighted.focus{color:#000;background-color:#7a7a7b;border-color:#484848}.datepicker table tr td.selected:hover,.datepicker table tr td.selected.highlighted:hover{color:#000;background-color:#444445;border-color:#545454}.datepicker table tr td.selected:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected.highlighted:active,.datepicker table tr td.selected.highlighted.active{color:#000;background-color:#7a7a7b;border-color:#545454}.datepicker table tr td.selected:active:hover,.datepicker table tr td.selected:active:focus,.datepicker table tr td.selected:active.focus,.datepicker table tr td.selected.active:hover,.datepicker table tr td.selected.active:focus,.datepicker table tr td.selected.active.focus,.datepicker table tr td.selected.highlighted:active:hover,.datepicker table tr td.selected.highlighted:active:focus,.datepicker table tr td.selected.highlighted:active.focus,.datepicker table tr td.selected.highlighted.active:hover,.datepicker table tr td.selected.highlighted.active:focus,.datepicker table tr td.selected.highlighted.active.focus{color:#000;background-color:#707172;border-color:#484848}.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:focus,.datepicker table tr td.selected.disabled.focus,.datepicker table tr td.selected[disabled]:hover,.datepicker table tr td.selected[disabled]:focus,.datepicker table tr td.selected[disabled].focus,fieldset[disabled] .datepicker table tr td.selected:hover,fieldset[disabled] .datepicker table tr td.selected:focus,fieldset[disabled] .datepicker table tr td.selected.focus,.datepicker table tr td.selected.highlighted.disabled:hover,.datepicker table tr td.selected.highlighted.disabled:focus,.datepicker table tr td.selected.highlighted.disabled.focus,.datepicker table tr td.selected.highlighted[disabled]:hover,.datepicker table tr td.selected.highlighted[disabled]:focus,.datepicker table tr td.selected.highlighted[disabled].focus,fieldset[disabled] .datepicker table tr td.selected.highlighted:hover,fieldset[disabled] .datepicker table tr td.selected.highlighted:focus,fieldset[disabled] .datepicker table tr td.selected.highlighted.focus{background-color:#878889;border-color:#606060}.datepicker table tr td.active,.datepicker table tr td.active.highlighted{color:#fff;background-color:#007bc2;border-color:#0176ba;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.active:focus,.datepicker table tr td.active.focus,.datepicker table tr td.active.highlighted:focus,.datepicker table tr td.active.highlighted.focus{color:#fff;background-color:#1a88c8;border-color:#4198cb}.datepicker table tr td.active:hover,.datepicker table tr td.active.highlighted:hover{color:#fff;background-color:#80bde1;border-color:#1f86c2}.datepicker table tr td.active:active,.datepicker table tr td.active.active,.datepicker table tr td.active.highlighted:active,.datepicker table tr td.active.highlighted.active{color:#fff;background-color:#1a88c8;border-color:#1f86c2}.datepicker table tr td.active:active:hover,.datepicker table tr td.active:active:focus,.datepicker table tr td.active:active.focus,.datepicker table tr td.active.active:hover,.datepicker table tr td.active.active:focus,.datepicker table tr td.active.active.focus,.datepicker table tr td.active.highlighted:active:hover,.datepicker table tr td.active.highlighted:active:focus,.datepicker table tr td.active.highlighted:active.focus,.datepicker table tr td.active.highlighted.active:hover,.datepicker table tr td.active.highlighted.active:focus,.datepicker table tr td.active.highlighted.active.focus{color:#fff;background-color:#2b91cc;border-color:#4198cb}.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:focus,.datepicker table tr td.active.disabled.focus,.datepicker table tr td.active[disabled]:hover,.datepicker table tr td.active[disabled]:focus,.datepicker table tr td.active[disabled].focus,fieldset[disabled] .datepicker table tr td.active:hover,fieldset[disabled] .datepicker table tr td.active:focus,fieldset[disabled] .datepicker table tr td.active.focus,.datepicker table tr td.active.highlighted.disabled:hover,.datepicker table tr td.active.highlighted.disabled:focus,.datepicker table tr td.active.highlighted.disabled.focus,.datepicker table tr td.active.highlighted[disabled]:hover,.datepicker table tr td.active.highlighted[disabled]:focus,.datepicker table tr td.active.highlighted[disabled].focus,fieldset[disabled] .datepicker table tr td.active.highlighted:hover,fieldset[disabled] .datepicker table tr td.active.highlighted:focus,fieldset[disabled] .datepicker table tr td.active.highlighted.focus{background-color:#007bc2;border-color:#0176ba}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;border-radius:4px}.datepicker table tr td span:hover,.datepicker table tr td span.focused{color:#000;background:#e8e9e9}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:none;color:#707782;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover{color:#fff;background-color:#007bc2;border-color:#0176ba;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td span.active:focus,.datepicker table tr td span.active.focus,.datepicker table tr td span.active:hover:focus,.datepicker table tr td span.active:hover.focus,.datepicker table tr td span.active.disabled:focus,.datepicker table tr td span.active.disabled.focus,.datepicker table tr td span.active.disabled:hover:focus,.datepicker table tr td span.active.disabled:hover.focus{color:#fff;background-color:#1a88c8;border-color:#4198cb}.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover:hover{color:#fff;background-color:#80bde1;border-color:#1f86c2}.datepicker table tr td span.active:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.disabled:hover.active{color:#fff;background-color:#1a88c8;border-color:#1f86c2}.datepicker table tr td span.active:active:hover,.datepicker table tr td span.active:active:focus,.datepicker table tr td span.active:active.focus,.datepicker table tr td span.active.active:hover,.datepicker table tr td span.active.active:focus,.datepicker table tr td span.active.active.focus,.datepicker table tr td span.active:hover:active:hover,.datepicker table tr td span.active:hover:active:focus,.datepicker table tr td span.active:hover:active.focus,.datepicker table tr td span.active:hover.active:hover,.datepicker table tr td span.active:hover.active:focus,.datepicker table tr td span.active:hover.active.focus,.datepicker table tr td span.active.disabled:active:hover,.datepicker table tr td span.active.disabled:active:focus,.datepicker table tr td span.active.disabled:active.focus,.datepicker table tr td span.active.disabled.active:hover,.datepicker table tr td span.active.disabled.active:focus,.datepicker table tr td span.active.disabled.active.focus,.datepicker table tr td span.active.disabled:hover:active:hover,.datepicker table tr td span.active.disabled:hover:active:focus,.datepicker table tr td span.active.disabled:hover:active.focus,.datepicker table tr td span.active.disabled:hover.active:hover,.datepicker table tr td span.active.disabled:hover.active:focus,.datepicker table tr td span.active.disabled:hover.active.focus{color:#fff;background-color:#2b91cc;border-color:#4198cb}.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:focus,.datepicker table tr td span.active.disabled.focus,.datepicker table tr td span.active[disabled]:hover,.datepicker table tr td span.active[disabled]:focus,.datepicker table tr td span.active[disabled].focus,fieldset[disabled] .datepicker table tr td span.active:hover,fieldset[disabled] .datepicker table tr td span.active:focus,fieldset[disabled] .datepicker table tr td span.active.focus,.datepicker table tr td span.active:hover.disabled:hover,.datepicker table tr td span.active:hover.disabled:focus,.datepicker table tr td span.active:hover.disabled.focus,.datepicker table tr td span.active:hover[disabled]:hover,.datepicker table tr td span.active:hover[disabled]:focus,.datepicker table tr td span.active:hover[disabled].focus,fieldset[disabled] .datepicker table tr td span.active:hover:hover,fieldset[disabled] .datepicker table tr td span.active:hover:focus,fieldset[disabled] .datepicker table tr td span.active:hover.focus,.datepicker table tr td span.active.disabled.disabled:hover,.datepicker table tr td span.active.disabled.disabled:focus,.datepicker table tr td span.active.disabled.disabled.focus,.datepicker table tr td span.active.disabled[disabled]:hover,.datepicker table tr td span.active.disabled[disabled]:focus,.datepicker table tr td span.active.disabled[disabled].focus,fieldset[disabled] .datepicker table tr td span.active.disabled:hover,fieldset[disabled] .datepicker table tr td span.active.disabled:focus,fieldset[disabled] .datepicker table tr td span.active.disabled.focus,.datepicker table tr td span.active.disabled:hover.disabled:hover,.datepicker table tr td span.active.disabled:hover.disabled:focus,.datepicker table tr td span.active.disabled:hover.disabled.focus,.datepicker table tr td span.active.disabled:hover[disabled]:hover,.datepicker table tr td span.active.disabled:hover[disabled]:focus,.datepicker table tr td span.active.disabled:hover[disabled].focus,fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover,fieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus,fieldset[disabled] .datepicker table tr td span.active.disabled:hover.focus{background-color:#007bc2;border-color:#0176ba}.datepicker table tr td span.old,.datepicker table tr td span.new{color:#707782}.datepicker .datepicker-switch{width:145px}.datepicker .datepicker-switch,.datepicker .prev,.datepicker .next,.datepicker tfoot tr th{cursor:pointer}.datepicker .datepicker-switch:hover,.datepicker .prev:hover,.datepicker .next:hover,.datepicker tfoot tr th:hover{color:#000;background:#e8e9e9}.datepicker .prev.disabled,.datepicker .next.disabled{visibility:hidden}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.input-group.date .input-group-addon{cursor:pointer}.input-daterange{width:100%}.input-daterange input{text-align:center}.input-daterange input:first-child{border-radius:3px 0 0 3px}.input-daterange input:last-child{border-radius:0 3px 3px 0}.input-daterange .input-group-addon{width:auto;min-width:16px;padding:4px 5px;line-height:1.5;border-width:1px 0;margin-left:-5px;margin-right:-5px}#run_pandeia{font-weight:bold;background-color:#EEBA0B;color:#FFFFFF;border-color:#CC9C00}#run_pandeia:hover{color:#000000;background-color:#ffc60a;border-color:#EEBA0B}.warning{color:#ffa500;font-weight:bold}.danger{color:red;font-weight:bold}
diff --git a/gen_tso/data/style.css b/gen_tso/data/style.css
deleted file mode 100644
index 8b6845c..0000000
--- a/gen_tso/data/style.css
+++ /dev/null
@@ -1,23 +0,0 @@
-#run_pandeia{
-    font-weight:bold;
-    background-color:#eeba0b;
-    color:#FFFFFF;
-    border-color:#cc9c00;
-}
-
-#run_pandeia:hover{
-    color:#000000;
-    background-color:#ffc60a;
-    border-color:#eeba0b;
-}
-
-.warning {
-    color: #ffa500;
-    font-weight: bold;
-}
-
-.danger {
-    color: red;
-    font-weight: bold;
-}
-
diff --git a/gen_tso/gen_tso_app.py b/gen_tso/gen_tso_app.py
index 1f3681a..7ec95ae 100644
--- a/gen_tso/gen_tso_app.py
+++ b/gen_tso/gen_tso_app.py
@@ -1,18 +1,19 @@
 # Copyright (c) 2024 Patricio Cubillos
 # Gen TSO is open-source software under the GPL-2.0 license (see LICENSE)
 
-from collections.abc import Iterable
+import json
 import os
-import sys
-import pickle
 from pathlib import Path
+import pickle
+import sys
 import textwrap
+from datetime import timedelta, datetime
+
 
 import numpy as np
 import scipy.interpolate as si
-
+import pandas as pd
 import faicons as fa
-from htmltools import HTML
 import plotly.graph_objects as go
 from shiny import ui, render, reactive, req, App
 from shinywidgets import output_widget, render_plotly
@@ -25,7 +26,11 @@
     ROOT, collect_spectra, read_spectrum_file, pretty_print_target,
 )
 import gen_tso.catalogs.utils as u
-
+from gen_tso.pandeia_io.pandeia_defaults import (
+    get_detector,
+    make_obs_label,
+    make_saturation_label,
+)
 
 # Catalog of known exoplanets (and candidate planets)
 catalog = cat.Catalog()
@@ -39,54 +44,85 @@
 p_keys, p_models, p_teff, p_logg = jwst.load_sed_list('phoenix')
 k_keys, k_models, k_teff, k_logg = jwst.load_sed_list('k93models')
 
-phoenix_dict = {model:key for key,model in zip(p_keys, p_models)}
-kurucz_dict = {model:key for key,model in zip(k_keys, k_models)}
+phoenix_dict = {key:model for key,model in zip(p_keys, p_models)}
+kurucz_dict = {key:model for key,model in zip(k_keys, k_models)}
 sed_dict = {
     'phoenix': phoenix_dict,
     'kurucz': kurucz_dict,
 }
 
 bands_dict = {
-    'J mag': '2mass,j',
-    'H mag': '2mass,h',
-    'Ks mag': '2mass,ks',
-    'Gaia mag': 'gaia,g',
-    'V mag': 'johnson,v',
+    '2mass,j': 'J mag',
+    '2mass,h': 'H mag',
+    '2mass,ks': 'Ks mag',
+    'gaia,g': 'Gaia mag',
+    'johnson,v': 'V mag',
 }
-
-inst_names = [
-    'MIRI',
-    'NIRCam',
-    'NIRISS',
-    'NIRSpec',
-]
-
 detectors = jwst.generate_all_instruments()
 instruments = np.unique([det.instrument for det in detectors])
-
-def get_detector(mode=None, instrument=None):
-    if mode is not None:
-        for det in detectors:
-            if det.mode == mode:
-                if instrument is None or det.instrument==instrument:
-                    return det
-        return None
-
 filter_throughputs = jwst.filter_throughputs()
 
-tso_runs = {}
-tso_labels = {}
-tso_labels['Transit'] = {}
-tso_labels['Eclipse'] = {}
-tso_labels['Acquisition'] = {}
+modes = {}
+for inst in instruments:
+    spec_modes = {}
+    for det in detectors:
+        if det.instrument == inst and det.obs_type=='spectroscopy':
+            spec_modes[det.mode] = det.mode_label
+    choices = {}
+    choices['Spectroscopy'] = spec_modes
+    #choices['Photometry'] = photo_modes  TBD
+    acq_modes = {}
+    for det in detectors:
+        if det.instrument == inst and det.obs_type=='acquisition':
+            acq_modes[det.mode] = 'Target Acquisition'
+    choices['Acquisition'] = acq_modes
+    modes[inst] = choices
+
+
+depth_choices = {
+    'transit': ['Flat', 'Input'],
+    'eclipse': ['Blackbody', 'Input']
+}
+
+tso_runs = {
+    'Transit': {},
+    'Eclipse': {},
+    'Acquisition': {},
+}
 
+def make_tso_labels(tso_runs):
+    tso_labels = {
+        'Transit': {},
+        'Eclipse': {},
+        'Acquisition': {},
+    }
+    for key, runs in tso_runs.items():
+        for tso_label, tso_run in runs.items():
+            tso_key = f'{key}_{tso_label}'
+            tso_labels[key][tso_key] = tso_run['label']
+    return tso_labels
+
+
+cache_target = {}
+cache_acquisition = {}
 cache_saturation = {}
-spectrum_choices = {
+
+# Planet and stellar spectra
+spectra = {
+    'transit': {},
+    'eclipse': {},
+    'sed': {},
+}
+bookmarked_spectra = {
+    'transit': [],
+    'eclipse': [],
+    'sed': [],
+}
+user_spectra = {
     'transit': [],
     'eclipse': [],
     'sed': [],
 }
-spectra = {}
 
 # Load spectra from user-defined folder and/or from default folder
 loading_folders = []
@@ -99,21 +135,20 @@ def get_detector(mode=None, instrument=None):
 for location in loading_folders:
     t_models, e_models, sed_models = collect_spectra(location)
     for label, model in t_models.items():
-        spectra[label] = model
-        spectrum_choices['transit'].append(label)
+        spectra['transit'][label] = model
+        user_spectra['transit'].append(label)
     for label, model in e_models.items():
-        spectra[label] = model
-        spectrum_choices['eclipse'].append(label)
+        spectra['eclipse'][label] = model
+        user_spectra['eclipse'].append(label)
     # for label, model in sed_models.items():
         # 'depth' --> 'flux'
-        #spectra[label] = {'wl': wl, 'depth': depth}
-        #spectrum_choices['sed'].append(label)
+        #spectra['sed'][label] = {'wl': wl, 'depth': depth}
+        #user_spectra['sed'].append(label)
 
 
 nasa_url = 'https://exoplanetarchive.ipac.caltech.edu/overview'
 trexolists_url = 'https://www.stsci.edu/~nnikolov/TrExoLiSTS/JWST/trexolists.html'
-
-css_file = f'{ROOT}data/style.css'
+stsci_url = 'https://www.stsci.edu/cgi-bin/get-proposal-info?id=PID&observatory=JWST'
 
 depth_units = [
     "none",
@@ -127,26 +162,64 @@ def get_detector(mode=None, instrument=None):
     "mJy",
 ]
 
+layout_kwargs = dict(
+    width=1/2,
+    fixed_width=False,
+    heights_equal='all',
+    gap='7px',
+    fill=False,
+    fillable=True,
+    class_="pb-2 pt-0 m-0",
+)
+
 
 app_ui = ui.page_fluid(
-    ui.markdown("## **Gen TSO**: A general ETC for time-series observations"),
-    ui.include_css(css_file),
-    #ui.markdown("""
-    #    This app is based on [shiny][0].
-    #    [0]: https://shiny.posit.co/py/api/core
-    #    """),
+    ui.layout_columns(
+        ui.span(
+            ui.HTML("<b>Gen TSO</b>: A general exoplanet ETC for JWST "
+            "time-series observations ("),
+            ui.tooltip(
+                ui.tags.a(
+                    fa.icon_svg("book", fill='black'),
+                    href='https://pcubillos.github.io/gen_tso',
+                    target="_blank",
+                ),
+                "documentation",
+                placement='bottom',
+            ),
+            ')',
+            style="font-size: 28px;",
+        ),
+        ui.output_image("tso_logo", height='50px', inline=True),
+        col_widths=(11,1),
+        fixed_width=False,
+        fill=False,
+        fillable=True,
+    ),
+    ui.tags.script(
+        """
+        $(function() {
+            Shiny.addCustomMessageHandler("update_esasky", function(message) {
+                var esaskyFrame = document.getElementById("esasky");
+                esaskyFrame.contentWindow.postMessage(
+                    JSON.parse(message.command), 'https://sky.esa.int'
+                );
+            });
+        });
+        """
+    ),
 
     # Instrument and detector modes:
     ui.layout_columns(
         cs.navset_card_tab_jwst(
-            inst_names,
-            id="select_instrument",
+            instruments,
+            id="instrument",
             selected='NIRCam',
             header="Select an instrument and detector",
             footer=ui.input_select(
-                "select_mode",
+                "mode",
                 "",
-                choices = {},
+                choices=modes['NIRCam'],
                 width='425px',
             ),
         ),
@@ -161,9 +234,9 @@ def get_detector(mode=None, instrument=None):
                         "TSO runs will show here after a 'Run Pandeia' call",
                         placement='right',
                     ),
-                    choices=tso_labels,
+                    choices=make_tso_labels(tso_runs),
                     selected=[''],
-                    #width='450px',
+                    width='100%',
                 ),
                 # TBD: Set disabled based on existing TSOs
                 ui.layout_column_wrap(
@@ -189,10 +262,28 @@ def get_detector(mode=None, instrument=None):
                 fill=True,
                 fillable=True,
             ),
-            ui.input_task_button(
-                id="run_pandeia",
-                label="Run Pandeia",
-                label_busy="processing...",
+            ui.layout_columns(
+                ui.input_task_button(
+                    id="run_pandeia",
+                    label="Run Pandeia",
+                    label_busy="processing...",
+                    width='100%',
+                ),
+                ui.panel_conditional(
+                    "input.mode == 'target_acq'",
+                    ui.input_radio_buttons(
+                        id='target_focus',
+                        label='',
+                        choices={
+                            'science': 'sci target',
+                            'acquisition': 'acq target',
+                        },
+                        selected='science',
+                    ),
+                ),
+                col_widths=(9,3),
+                gap='10px',
+                class_="px-0 py-0 mx-0 my-0",
             ),
         ),
         col_widths=[6,6],
@@ -236,16 +327,16 @@ def get_detector(mode=None, instrument=None):
                 ui.layout_column_wrap(
                     # Row 1
                     ui.p("T_eff (K):"),
-                    ui.input_text("teff", "", value='1400.0'),
+                    ui.input_text("t_eff", "", value='1400.0'),
                     # Row 2
                     ui.p("log(g):"),
-                    ui.input_text("logg", "", value='4.5'),
+                    ui.input_text("log_g", "", value='4.5'),
                     # Row 3
                     ui.input_select(
                         id='magnitude_band',
                         label='',
-                        choices=list(bands_dict.keys()),
-                        selected='Ks mag',
+                        choices=bands_dict,
+                        selected='2mass,ks',
                     ),
                     ui.input_text(
                         id="magnitude",
@@ -269,8 +360,14 @@ def get_detector(mode=None, instrument=None):
                         "blackbody",
                         "input",
                     ],
+                    selected='phoenix',
+                ),
+                ui.input_select(
+                    id="sed",
+                    label="",
+                    choices=sed_dict['phoenix'],
+                    selected='g0v',
                 ),
-                ui.output_ui('choose_sed'),
                 class_="px-2 pt-2 pb-0 m-0",
             ),
             # The planet
@@ -315,14 +412,17 @@ def get_detector(mode=None, instrument=None):
                     placement="right",
                     id="obs_popover",
                 ),
-                "Observation",
+                ui.markdown("Observation"),
                 ui.layout_column_wrap(
                     # Row 1
                     ui.p("Type:"),
                     ui.input_select(
-                        id='geometry',
+                        id='obs_geometry',
                         label='',
-                        choices=['Transit', 'Eclipse'],
+                        choices={
+                            'transit': 'Transit',
+                            'eclipse': 'Eclipse',
+                        }
                     ),
                     # Row 2
                     ui.output_text('transit_dur_label'),
@@ -342,7 +442,52 @@ def get_detector(mode=None, instrument=None):
                     label=ui.output_ui('depth_label_text'),
                     choices=["Input"],
                 ),
-                ui.output_ui('choose_depth'),
+                ui.panel_conditional(
+                    "input.planet_model_type == 'Input'",
+                    ui.tooltip(
+                        ui.input_select(
+                            id="depth",
+                            label="",
+                            choices=user_spectra['transit'],
+                        ),
+                        '',
+                        id='depth_tooltip',
+                        placement='right',
+                    ),
+                ),
+                ui.panel_conditional(
+                    "input.planet_model_type == 'Flat'",
+                    ui.layout_column_wrap(
+                        ui.p("Depth (%):"),
+                        ui.input_numeric(
+                            id="transit_depth",
+                            label="",
+                            value=0.5,
+                            step=0.1,
+                        ),
+                        **layout_kwargs,
+                    ),
+                ),
+                ui.panel_conditional(
+                    "input.planet_model_type == 'Blackbody'",
+                    ui.layout_column_wrap(
+                        ui.HTML("<p>(Rp/Rs)<sup>2</sup> (%):</p>"),
+                        ui.input_numeric(
+                            id="eclipse_depth",
+                            label="",
+                            value=0.05,
+                            step=0.1,
+                        ),
+                        ui.p("Temp (K):"),
+                        ui.input_numeric(
+                            id="teq_planet",
+                            label="",
+                            value=2000.0,
+                            step=100,
+                        ),
+                        **layout_kwargs,
+                    ),
+                ),
                 class_="px-2 pt-2 pb-0 m-0",
             ),
             body_args=dict(class_="p-2 m-0"),
@@ -382,9 +527,18 @@ def get_detector(mode=None, instrument=None):
                     choices=[''],
                     selected='',
                 ),
+                ui.panel_conditional(
+                    "input.mode == 'soss' && input.filter == 'clear'",
+                    ui.input_select(
+                        id="order",
+                        label="Order",
+                        choices=['1'],
+                        selected='1',
+                    ),
+                ),
                 class_="px-2 pt-2 pb-0 m-0",
             ),
-            # groups / integs
+            # groups and integrations
             ui.panel_well(
                 cs.label_tooltip_button(
                     label='Groups per integration ',
@@ -394,10 +548,59 @@ def get_detector(mode=None, instrument=None):
                     class_='pb-1',
                 ),
                 ui.output_ui('groups_input'),
-                ui.output_ui('integration_input'),
-                ui.input_switch("integs_switch", "Match obs. duration", False),
+                ui.panel_conditional(
+                    "input.mode != 'target_acq'",
+                    ui.input_numeric(
+                        id="integrations",
+                        label="Integrations",
+                        value=1,
+                        min=1, max=100000,
+                    ),
+                    ui.input_switch(
+                        "integs_switch",
+                        "Match obs. duration",
+                        False,
+                    ),
+                ),
                 class_="px-2 pt-2 pb-0 m-0",
             ),
+            # Search nearby Gaia targets for acquisition
+            ui.panel_conditional(
+                "input.mode == 'target_acq'",
+                ui.panel_well(
+                    ui.tooltip(
+                        ui.markdown('Acquisition targets'),
+                        'Gaia targets within 80" of science target',
+                        id="gaia_tooltip",
+                        placement="top",
+                    ),
+                    ui.layout_column_wrap(
+                        ui.input_task_button(
+                            id="search_gaia_ta",
+                            label="Search nearby targets",
+                            label_busy="processing...",
+                            class_='btn btn-outline-secondary btn-sm',
+                        ),
+                        ui.p("Select TA's SED:"),
+                        ui.input_select(
+                            id="ta_sed",
+                            label="",
+                            choices=[],
+                            selected='',
+                        ),
+                        ui.input_action_button(
+                            id="get_acquisition_target",
+                            label="Print acq. target data",
+                            class_='btn btn-outline-secondary btn-sm',
+                        ),
+                        width=1,
+                        heights_equal='row',
+                        gap='7px',
+                        class_="px-0 py-0 mx-0 my-0",
+                    ),
+                    class_="px-2 pt-2 pb-2 m-0",
+                ),
+            ),
             body_args=dict(class_="p-2 m-0"),
         ),
 
@@ -432,7 +635,20 @@ def get_detector(mode=None, instrument=None):
                 ),
                 ui.nav_panel(
                     "Sky view",
-                    ui.output_ui('esasky_card'),
+                    cs.custom_card(
+                        ui.HTML(
+                            '<iframe id="esasky" '
+                            'height="100%" '
+                            'width="100%" '
+                            'style="overflow" '
+                            'src="https://sky.esa.int/esasky/?target=0.0%200.0'
+                            '&fov=0.2&sci=true&hide_welcome=true" '
+                            'frameborder="0" allowfullscreen></iframe>',
+                        ),
+                        body_args=dict(class_='m-0 p-0'),
+                        full_screen=True,
+                        height='350px',
+                    )
                 ),
                 ui.nav_panel(
                     "Stellar SED",
@@ -554,18 +770,18 @@ def get_detector(mode=None, instrument=None):
             ui.navset_card_tab(
                 ui.nav_panel(
                     "Results",
-                    cs.custom_card(
-                        ui.span(
-                            ui.output_ui(id="exp_time"),
-                            style="font-family: monospace; font-size:medium;",
-                        ),
-                        body_args=dict(padding='8px'),
-                        style="background: #F2F2F2!important; border-radius: 3px;",
+                    ui.span(
+                        ui.output_ui(id="results"),
+                        style="font-family: monospace; font-size:medium;",
                     ),
                 ),
                 ui.nav_panel(
-                    ui.output_ui('warnings_label'),
-                    ui.output_text_verbatim(id="warnings")
+                    ui.output_ui(id='warnings_label'),
+                    ui.output_text_verbatim(id="warnings"),
+                ),
+                ui.nav_panel(
+                    "Acquisition targets",
+                    ui.output_data_frame(id="acquisition_targets"),
                 ),
             ),
             col_widths=[12, 12],
@@ -573,9 +789,26 @@ def get_detector(mode=None, instrument=None):
         ),
         col_widths=[3, 3, 6],
     ),
+    title='Gen TSO',
+    theme=f'{ROOT}/data/base_theme.css',
 )
 
 
+def parse_obs(input):
+    planet_model_type = input.planet_model_type.get()
+    depth_model = None
+    rprs_sq = None
+    teq_planet = None
+    if planet_model_type == 'Input':
+        depth_model = input.depth.get()
+    elif planet_model_type == 'Flat':
+        rprs_sq = input.transit_depth.get()
+    elif planet_model_type == 'Blackbody':
+        rprs_sq = input.eclipse_depth.get()
+        teq_planet = input.teq_planet.get()
+    return planet_model_type, depth_model, rprs_sq, teq_planet
+
+
 def planet_model_name(input):
     """
     Get the planet model name based on the transit/eclipse depth values.
@@ -585,21 +818,21 @@ def planet_model_name(input):
     depth_label: String
         A string representation of the depth model.
     """
-    model_type = input.planet_model_type.get()
-    if model_type == 'Input':
+    planet_model_type = input.planet_model_type.get()
+    if planet_model_type == 'Input':
         return input.depth.get()
-    transit_depth = input.depth.get()
-    if model_type == 'Flat':
+    elif planet_model_type == 'Flat':
+        transit_depth = input.transit_depth.get()
         return f'Flat transit ({transit_depth:.3f}%)'
-    elif model_type == 'Blackbody':
-        t_planet = input.tplanet.get()
-        return f'Blackbody({t_planet:.0f}K, rprs\u00b2={transit_depth:.3f}%)'
-    raise ValueError('Invalid model type')
+    elif planet_model_type == 'Blackbody':
+        eclipse_depth = input.eclipse_depth.get()
+        t_planet = input.teq_planet.get()
+        return f'Blackbody({t_planet:.0f}K, rprs\u00b2={eclipse_depth:.3f}%)'
 
 
 def get_throughput(input):
-    inst = req(input.select_instrument).get().lower()
-    mode = req(input.select_mode).get()
+    inst = req(input.instrument).get().lower()
+    mode = req(input.mode).get()
     if mode == 'target_acq':
         obs_type = 'acquisition'
     else:
@@ -622,51 +855,58 @@ def get_throughput(input):
 
 
 def get_auto_sed(input):
+    """
+    Guess the model closest to the available options given a T_eff
+    and log_g pair.
+    """
     sed_type = input.sed_type()
+    sed_models = sed_dict[sed_type]
     if sed_type == 'kurucz':
-        m_models, m_teff, m_logg = k_models, k_teff, k_logg
+        m_teff, m_logg = k_teff, k_logg
     elif sed_type == 'phoenix':
-        m_models, m_teff, m_logg = p_models, p_teff, p_logg
+        m_teff, m_logg = p_teff, p_logg
 
     try:
-        teff = float(input.teff())
-        logg = float(input.logg())
+        t_eff = float(input.t_eff.get())
+        log_g = float(input.log_g.get())
     except ValueError:
-        return m_models, None
-    idx = jwst.find_closest_sed(m_teff, m_logg, teff, logg)
-    chosen_sed = m_models[idx]
-    return m_models, chosen_sed
+        return sed_models, None
+    idx = jwst.find_closest_sed(m_teff, m_logg, t_eff, log_g)
+    chosen_sed = list(sed_models)[idx]
+    return sed_models, chosen_sed
 
 
-def parse_sed(input):
+def parse_sed(input, target_acq_mag=None):
     """Extract SED parameters"""
-    # Safety to prevent hanging when initalizing the app:
-    if not input.sed.is_set():
-        return None, None, None, None, None
+    if target_acq_mag is None:
+        sed_type = input.sed_type()
+        norm_band = input.magnitude_band.get()
+        norm_magnitude = float(input.magnitude.get())
+    else:
+        sed_type = 'phoenix'
+        norm_band = 'gaia,g'
+        norm_magnitude = target_acq_mag
 
-    sed_type = input.sed_type()
     if sed_type in ['phoenix', 'kurucz']:
-        sed = input.sed.get()
-        if sed not in sed_dict[sed_type]:
+        if target_acq_mag is None:
+            sed_model = input.sed.get()
+        else:
+            sed_model = input.ta_sed.get()
+        if sed_model not in sed_dict[sed_type]:
             return None, None, None, None, None
-        sed_model = sed_dict[sed_type][sed]
         model_label = f'{sed_type}_{sed_model}'
     elif sed_type == 'blackbody':
-        sed_model = float(input.teff.get())
-        model_label = f'{sed_type}_{sed_model:.0f}K'
+        sed_model = float(input.t_eff.get())
+        model_label = f'bb_{sed_model:.0f}K'
     elif sed_type == 'input':
         model_label = sed_model
 
-    norm_band = bands_dict[input.magnitude_band()]
-    norm_magnitude = float(input.magnitude())
-
     if sed_type == 'kurucz':
         sed_type = 'k93models'
 
     # Make a label
-    for name,band in bands_dict.items():
-        if band == norm_band:
-            band_label = f'{norm_magnitude}_{name.split()[0]}'
+    band_name = bands_dict[norm_band].split()[0]
+    band_label = f'{norm_magnitude:.2f}_{band_name}'
     sed_label = f'{model_label}_{band_label}'
 
     return sed_type, sed_model, norm_band, norm_magnitude, sed_label
@@ -679,27 +919,26 @@ def parse_depth_model(input):
     """
     model_type = input.planet_model_type.get()
     depth_label = planet_model_name(input)
+    obs_geometry = input.obs_geometry.get()
 
     if model_type == 'Input':
         if depth_label is None:
             wl, depth = None, None
         else:
-            wl = spectra[depth_label]['wl']
-            depth = spectra[depth_label]['depth']
+            wl = spectra[obs_geometry][depth_label]['wl']
+            depth = spectra[obs_geometry][depth_label]['depth']
     elif model_type == 'Flat':
         nwave = 1000
-        transit_depth = input.depth.get() * 0.01
+        transit_depth = input.transit_depth.get() * 0.01
         wl = np.linspace(0.6, 50.0, nwave)
         depth = np.tile(transit_depth, nwave)
     elif model_type == 'Blackbody':
-        transit_depth = input.depth.get() * 0.01
-        t_planet = input.tplanet.get()
+        transit_depth = input.eclipse_depth.get() * 0.01
+        t_planet = input.teq_planet.get()
         # Un-normalized planet and star SEDs
         sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(input)
         star_scene = jwst.make_scene(sed_type, sed_model, norm_band='none')
-        planet_scene = jwst.make_scene(
-            'blackbody', t_planet, norm_band='none',
-        )
+        planet_scene = jwst.make_scene('blackbody', t_planet, norm_band='none')
         wl, f_star = jwst.extract_sed(star_scene)
         wl_planet, f_planet = jwst.extract_sed(planet_scene)
         # Interpolate black body at wl_star
@@ -713,22 +952,24 @@ def parse_depth_model(input):
     return depth_label, wl, depth
 
 
-def make_saturation_label(mode, disperser, filter, subarray, sed_label):
+def is_consistent(inst, mode, disperser=None, filter=None, subarray=None):
     """
-    Make a label of unique saturation setups to identify when and
-    when not the saturation level can be estimated.
+    Check that detector configuration settings are consistent
+    between them.
     """
-    sat_label = f'{mode}_{filter}'
-    if mode == 'bots':
-        sat_label = f'{sat_label}_{subarray}'
-    elif mode == 'mrs_ts':
-        sat_label = f'{sat_label}_{disperser}'
-    sat_label = f'{sat_label}_{sed_label}'
-    return sat_label
+    detector = get_detector(inst, mode, detectors)
+    if detector is None:
+        return False
+    if disperser is not None and disperser not in detector.dispersers:
+        return False
+    if filter is not None and filter not in detector.filters:
+        return False
+    if subarray is not None and subarray not in detector.subarrays:
+        return False
+    return True
 
 
 def server(input, output, session):
-    sky_view_src = reactive.Value('')
     bookmarked_sed = reactive.Value(False)
     bookmarked_depth = reactive.Value(False)
     saturation_label = reactive.Value(None)
@@ -736,284 +977,578 @@ def server(input, output, session):
     uploaded_units = reactive.Value(None)
     warning_text = reactive.Value('')
     machine_readable_info = reactive.Value(False)
-
-    # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-    # Instrument and detector modes
-    @reactive.Effect
-    @reactive.event(input.select_instrument)
-    def _():
-        inst_name = input.select_instrument.get()
-        print(f"You selected me: {inst_name}")
-        spec_modes = {}
-        for det in detectors:
-            if det.instrument == inst_name and det.obs_type=='spectroscopy':
-                spec_modes[det.mode] = det.mode_label
-        choices = {}
-        choices['Spectroscopy'] = spec_modes
-
-        #choices['Photometry'] = photo_modes  TBD
-
-        acq_modes = {}
-        for det in detectors:
-            if det.instrument == inst_name and det.obs_type=='acquisition':
-                acq_modes[det.mode] = 'Target Acquisition'
-        choices['Acquisition'] = acq_modes
-
-        ui.update_select(
-            'select_mode',
-            choices=choices,
-        )
-
-
-    @reactive.Effect
-    @reactive.event(input.select_mode)
-    def _():
-        instrument = req(input.select_instrument).get()
-        mode = input.select_mode.get()
-        det = get_detector(mode, instrument)
-
-        ui.update_select(
-            'disperser',
-            label=det.disperser_label,
-            choices=det.dispersers,
-            selected=det.default_disperser,
-        )
-        ui.update_select(
-            'filter',
-            label=det.filter_label,
-            choices=det.filters,
-            selected=det.default_filter,
-        )
-
-        selected = input.filter_filter.get()
-        if det.obs_type == 'acquisition':
-            choices = [det.instrument]
-        else:
-            choices = [det.instrument, 'all']
-
-        if selected != 'all' or det.obs_type=='acquisition':
-            selected = None
-        ui.update_radio_buttons(
-            "filter_filter",
-            choices=choices,
-            selected=selected,
-        )
-
-    @reactive.Effect
-    @reactive.event(input.disperser, input.filter)
-    def update_subarray():
-        instrument = req(input.select_instrument).get()
-        mode = input.select_mode.get()
-        det = get_detector(mode, instrument)
-
-        if mode == 'bots':
-            disperser = input.filter.get().split('/')[0]
-        else:
-            disperser = input.disperser.get()
-        choices = det.get_constrained_val('subarrays', disperser=disperser)
-
-        subarray = input.subarray.get()
-        if subarray not in choices:
-            subarray = det.default_subarray
-
-        ui.update_select(
-            'subarray',
-            choices=choices,
-            selected=subarray,
-        )
-
-    @reactive.Effect
-    @reactive.event(input.disperser)
-    def update_readout():
-        instrument = req(input.select_instrument).get()
-        mode = input.select_mode.get()
-        det = get_detector(mode, instrument)
-
-        disperser = input.disperser.get()
-        choices = det.get_constrained_val('readouts', disperser=disperser)
-
-        readout = input.readout.get()
-        if readout not in choices:
-            readout = det.default_readout
-
-        ui.update_select(
-            'readout',
-            choices=choices,
-            selected=readout,
-        )
-
-    @reactive.Effect
-    @reactive.event(input.run_pandeia)
-    def _():
-        inst_name = input.select_instrument.get()
-        inst = inst_name.lower()
-        mode = input.select_mode.get()
+    acq_target_list = reactive.Value(None)
+    current_acq_science_target = reactive.Value(None)
+    preset_ngroup = reactive.Value(None)
+    preset_sed = reactive.Value(None)
+    preset_obs_dur = reactive.Value(None)
+    esasky_command = reactive.Value(None)
+    trexo_info = reactive.Value(None)
+
+    def run_pandeia(input):
+        """
+        Perform a pandeia calculation on  science or acquisition target.
+        This might be a transit/eclipse TSO or a Pandeia perform_calculation
+        call.
+        """
+        # Instrumental setup:
+        inst = input.instrument.get().lower()
+        mode = input.mode.get()
         disperser = input.disperser.get()
         filter = input.filter.get()
         subarray = input.subarray.get()
         readout = input.readout.get()
-        ngroup = int(input.groups.get())
-        nint = int(input.integrations.get())
+        order = input.order.get()
+        ngroup = int(input.ngroup.get())
+        nint = input.integrations.get()
         aperture = None
 
-        detector = get_detector(mode, inst_name)
-        inst_label = jwst.instrument_label(detector, disperser, filter)
+        detector = get_detector(inst, mode, detectors)
+        inst_label = detector.instrument_label(disperser, filter)
 
-        # "Exceptions":
+        run_is_tso = True
+        # Front-end to back-end exceptions:
         if mode == 'bots':
             disperser, filter = filter.split('/')
+        if mode == 'soss':
+            if filter == 'f277w':
+                order = [1]
+            else:
+                order = [int(val) for val in order.split()]
+        else:
+            order = None
         if mode == 'mrs_ts':
             aperture = ['ch1', 'ch2', 'ch3', 'ch4']
         if mode == 'target_acq':
             aperture = input.disperser.get()
             disperser = None
-
-
-        obs_geometry = input.geometry.get()
+            nint = 1
+            run_is_tso = False
+            run_type = 'Acquisition'
+
+        # Target setup:
+        target_focus = input.target_focus.get()
+        target_name = input.target.get()
+        t_eff = input.t_eff.get()
+        log_g = input.log_g.get()
+        obs_geometry = input.obs_geometry.get()
         transit_dur = float(input.t_dur.get())
         obs_dur = float(input.obs_dur.get())
-        exp_time = jwst.exposure_time(
-            inst, subarray, readout, ngroup, nint,
+        planet_model_type, depth_label, rprs_sq, teq_planet = parse_obs(input)
+
+        if target_focus == 'acquisition':
+            selected = acquisition_targets.cell_selection()['rows'][0]
+            target_list = acq_target_list.get()
+            target_acq_mag = np.round(target_list[1][selected], 3)
+        elif target_focus == 'science':
+            exp_time = jwst.exposure_time(
+                inst, subarray, readout, ngroup, nint,
+            )
+            in_transit_integs, in_transit_time = jwst.bin_search_exposure_time(
+                inst, subarray, readout, ngroup, transit_dur,
+            )
+            target_acq_mag = None
+
+        sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(
+            input, target_acq_mag=target_acq_mag,
         )
-        # TBD: if exp_time << obs_dur, raise warning
 
-        #print(
-        #    repr(inst), repr(mode), repr(disperser), repr(filter),
-        #    repr(subarray), repr(readout), repr(aperture),
-        #)
+        if run_is_tso and in_transit_integs > nint:
+            error_msg = ui.markdown(
+                f"**Warning:**<br>observation time for **{nint} integration"
+                f"(s)** is less than the {obs_geometry} time.  Running "
+                "a perform_calculation()"
+            )
+            ui.notification_show(error_msg, type="warning", duration=5)
+            run_is_tso = False
+            run_type = 'Pandeia_SNR'
 
-        sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(input)
-        print(sed_type, sed_model, norm_band, repr(norm_mag))
         pando = jwst.PandeiaCalculation(inst, mode)
         pando.set_scene(sed_type, sed_model, norm_band, norm_mag)
 
-        if mode == 'target_acq':
-            nint = 1
+        if not run_is_tso:
+            depth_label = ''
             tso = pando.perform_calculation(
-                ngroup, nint, disperser, filter, subarray, readout, aperture,
+                ngroup, nint,
+                disperser, filter, subarray, readout, aperture, order,
             )
-            obs_geometry = 'Acquisition'
-            depth_label = ''
         else:
             depth_label, wl, depth = parse_depth_model(input)
             if depth_label is None:
-                ui.notification_show(
-                    f"No {obs_geometry.lower()} depth model to simulate",
-                    type="error",
-                    duration=5,
+                error_msg = ui.markdown(
+                    f"**Error:**<br>no {obs_geometry} depth model "
+                    "to simulate"
                 )
+                ui.notification_show(error_msg, type="error", duration=5)
                 return
+            run_type = obs_geometry.capitalize()
             if depth_label not in spectra:
-                spectrum_choices[obs_geometry.lower()].append(depth_label)
-                spectra[depth_label] = {'wl': wl, 'depth': depth}
+                spectra[obs_geometry][depth_label] = {'wl': wl, 'depth': depth}
+                bookmarked_spectra[obs_geometry].append(depth_label)
             depth_model = [wl, depth]
 
+            observation_dur = exp_time / 3600.0
             tso = pando.tso_calculation(
-                obs_geometry.lower(), transit_dur, exp_time, depth_model,
-                ngroup, disperser, filter, subarray, readout, aperture,
+                obs_geometry, transit_dur, observation_dur, depth_model,
+                ngroup, disperser, filter, subarray, readout, aperture, order,
             )
 
-        detector_label = jwst.detector_label(
-            inst, mode, disperser, filter, subarray, readout,
-        )
-
-        ui.notification_show(
-            "TSO model simulated!",
-            type="message",
-            duration=2,
-        )
-        group_ints = f'({ngroup} G, {nint} I)'
-        pretty_label = (
-            f'{detector_label} {group_ints} / {sed_label} / {depth_label}'
+        if run_is_tso:
+            success = "TSO model simulated!"
+        else:
+            success = "Pandeia calculation done!"
+        ui.notification_show(success, type="message", duration=2)
+        tso_label = make_obs_label(
+            inst, mode, aperture, disperser, filter, subarray, readout, order,
+            ngroup, nint, run_type, sed_label, depth_label,
         )
-        tso_label = f'{obs_geometry} {pretty_label}'
-        tso_labels[obs_geometry][tso_label] = pretty_label
-        ui.update_select('display_tso_run', choices=tso_labels)
 
-        tso_runs[tso_label] = dict(
+        tso_run = dict(
             # The detector
             inst=inst,
             mode=mode,
             inst_label=inst_label,
+            label=tso_label,
             # The SED
+            target=target_name,
+            t_eff=t_eff,
+            log_g=log_g,
+            transit_dur=transit_dur,
             sed_type=sed_type,
             sed_model=sed_model,
             norm_band=norm_band,
             norm_mag=norm_mag,
-            obs_type=obs_geometry,
+            obs_geometry=obs_geometry,
+            obs_dur=obs_dur,
+            planet_model_type=planet_model_type,
+            depth_label=depth_label,
+            rprs_sq=rprs_sq,
+            teq_planet=teq_planet,
+            target_focus=target_focus,
             # The instrumental setting
             aperture=aperture,
             disperser=disperser,
             filter=filter,
             subarray=subarray,
             readout=readout,
+            order=order,
             ngroup=ngroup,
+            nint=nint,
             # The outputs
             tso=tso,
-            #pandeia_results=pandeia_results,
         )
-        if mode != 'target_acq':
+
+        if run_is_tso:
             # The planet
-            tso_runs[tso_label]['t_dur'] = transit_dur
-            tso_runs[tso_label]['obs_dur'] = obs_dur
-            tso_runs[tso_label]['depth_model_name'] = depth_label
-            tso_runs[tso_label]['depth_model'] = depth_model
-            # Take report with more flux in it:
-            rep_label = 'report_out' if obs_geometry=='Transit' else 'report_in'
-            report = tso[rep_label]
+            #tso_run['depth_model_name'] = depth_label
+            tso_run['depth_model'] = depth_model
+            if isinstance(tso, list):
+                reports = (
+                    [report['report_in']['scalar'] for report in tso],
+                    [report['report_out']['scalar'] for report in tso],
+                )
+                warnings = tso[0]['report_out']['warnings']
+            else:
+                reports = (
+                    tso['report_in']['scalar'],
+                    tso['report_out']['scalar'],
+                )
+                warnings = tso['report_out']['warnings']
         else:
-            report = tso
+            reports = tso['scalar'], None
+            warnings = tso['warnings']
+        tso_run['stats'] = jwst._print_pandeia_stats(
+            inst, mode, reports[0], reports[1], format='html',
+        )
+        tso_run['warnings'] = warnings
+
+        if run_is_tso or mode=='target_acq':
+            tso_runs[run_type][tso_label] = tso_run
+            tso_labels = make_tso_labels(tso_runs)
+            ui.update_select(
+                'display_tso_run',
+                choices=tso_labels,
+                selected=f'{run_type}_{tso_label}',
+            )
 
-        if len(report['warnings']) > 0:
-            warning_text.set(report['warnings'])
-        else:
-            warning_text.set('')
+        # Update report
+        sat_label = make_saturation_label(
+            inst, mode, aperture, disperser, filter, subarray, order, sed_label,
+        )
+        pixel_rate, full_well = jwst.saturation_level(tso, get_max=True)
+        cache_saturation[sat_label] = dict(
+            brightest_pixel_rate=pixel_rate,
+            full_well=full_well,
+            warnings=warnings,
+        )
+        saturation_label.set(sat_label)
+        warning_text.set(warnings)
 
-        print(inst, mode, disperser, filter, subarray, readout)
+        print(inst, mode, aperture, disperser, filter, subarray, readout, order)
         print(sed_type, sed_model, norm_band, repr(norm_mag))
         print('~~ TSO done! ~~')
 
-    @reactive.effect
-    @reactive.event(input.save_button)
-    def _():
-        # Make a filename from current TSO
-        tso_label = input.display_tso_run.get()
-        tso = tso_runs[tso_label]
+
+    @reactive.Effect
+    @reactive.event(input.display_tso_run)
+    def update_full_state():
+        """
+        When a user chooses a run from display_tso_run, update the entire
+        front end to match the run setup.
+        """
+        tso_key = input.display_tso_run.get()
+        if tso_key is None:
+            return
+        key, tso_label = tso_key.split('_', maxsplit=1)
+        tso = tso_runs[key][tso_label]
+
         inst = tso['inst']
-        filename = f'tso_{inst}.pickle'
+        mode = tso['mode']
+        detector = get_detector(inst, mode, detectors)
+        instrument = detector.instrument
 
-        m = ui.modal(
-            ui.input_text(
-                id='tso_save_file',
-                label='Save TSO run to file:',
-                value=filename,
-                placeholder=tso_label,
-                width='100%',
-            ),
-            ui.HTML(f"Located in current folder:<br>'{current_dir}/'<br>"),
-            # TBD: I wish this could be used to browse a folder :(
-            #ui.input_file(
-            #    id="save_file_x",
-            #    label="Into this folder:",
-            #    button_label="Browse",
-            #    multiple=True,
-            #    width='100%',
-            #),
-            ui.input_action_button(
-                id='tso_save_button',
-                label='Save to file',
-            ),
-            title="Download TSO run",
-            easy_close=True,
-            size='l',
+        # The instrumental setting
+        if mode == 'bots':
+            filter = f"{tso['disperser']}/{tso['filter']}"
+            disperser = None
+        elif mode == 'target_acq':
+            filter = tso['filter']
+            disperser = tso['aperture']
+        else:
+            filter = tso['filter']
+            disperser = tso['disperser']
+        subarray = tso['subarray']
+        readout = tso['readout']
+        order = tso['order']
+        ngroup = tso['ngroup']
+
+        # Schedule preset values for invalidation:
+        if mode != input.mode.get() or subarray != input.subarray.get():
+            preset_ngroup.set(
+                {'mode':mode, 'subarray':subarray, 'ngroup':ngroup}
+            )
+
+        ui.update_navs('instrument', selected=instrument)
+        mode_choices = modes[instrument]
+        ui.update_select('mode', choices=mode_choices, selected=mode)
+        ui.update_select(
+            'disperser',
+            label=detector.disperser_label,
+            choices=detector.dispersers,
+            selected=disperser,
         )
-        ui.modal_show(m)
+        ui.update_select(
+            'filter',
+            label=detector.filter_label,
+            choices=detector.filters,
+            selected=filter,
+        )
+        choices = detector.get_constrained_val('subarrays', disperser=disperser)
+        ui.update_select('subarray', choices=choices, selected=subarray)
+        choices = detector.get_constrained_val('readouts', disperser=disperser)
+        ui.update_select('readout', choices=choices, selected=readout)
+        if mode == 'soss':
+            choices = detector.get_constrained_val('orders', subarray=subarray)
+            order = ' '.join([str(val) for val in order])
+            ui.update_select('order', choices=choices, selected=order)
+        if ngroup != input.ngroup.get():
+            if mode == 'target_acq':
+                ui.update_select('ngroup', selected=ngroup)
+            else:
+                ui.update_numeric('ngroup', value=ngroup)
+
+        # The target:
+        current_target = input.target.get()
+        current_tdur = input.t_dur.get()
+
+        target_focus = tso['target_focus']
+        ui.update_radio_buttons('target_focus', selected=target_focus)
+
+        name = tso['target']
+        t_dur = str(tso['transit_dur'])
+        planet_model_type = tso['planet_model_type']
+        ui.update_selectize('target', selected=name)
+        norm_band = tso['norm_band']
+        norm_mag = str(tso['norm_mag'])
+        sed_type = tso['sed_type']
+        if sed_type == 'k93models':
+            sed_type = 'kurucz'
+        ui.update_select('sed_type', selected=sed_type)
+
+        if name != current_target:
+            if name not in cache_target:
+                cache_target[name] = {}
+            cache_target[name]['t_eff'] = tso['t_eff']
+            cache_target[name]['log_g'] = tso['log_g']
+            cache_target[name]['t_dur'] = t_dur
+            cache_target[name]['depth_label'] = tso['depth_label']
+            cache_target[name]['rprs_sq'] = tso['rprs_sq']
+            cache_target[name]['teq_planet'] = tso['teq_planet']
+            cache_target[name]['norm_band'] = norm_band
+            cache_target[name]['norm_mag'] = norm_mag
+        else:
+            ui.update_text('t_eff', value=tso['t_eff'])
+            ui.update_text('log_g', value=tso['log_g'])
+            ui.update_text('t_dur', value=t_dur)
+            ui.update_select('magnitude_band', selected=norm_band)
+            ui.update_text('magnitude', value=norm_mag)
+
+        reset_sed = (
+            sed_type != input.sed_type.get() or
+            tso['t_eff']!=input.t_eff.get() or
+            tso['log_g'] != input.log_g.get()
+        )
+        if sed_type in ['kurucz', 'phoenix']:
+            if reset_sed:
+                preset_sed.set(tso['sed_model'])
+            else:
+                choices = sed_dict[sed_type]
+                selected = tso['sed_model']
+                ui.update_select("sed", choices=choices, selected=selected)
+
+        if target_focus == 'acquisition':
+            selected = tso['sed_model']
+            ui.update_select('ta_sed', choices=phoenix_dict, selected=selected)
+            target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+            selected = cache_acquisition[target.host]['selected']
+        # The observation
+        warning_text.set(tso['warnings'])
+        obs_geometry = tso['obs_geometry']
+        ui.update_select('obs_geometry', selected=obs_geometry)
+        if t_dur != current_tdur:
+            preset_obs_dur.set(tso['obs_dur'])
+        else:
+            ui.update_text('obs_dur', value=tso['obs_dur'])
 
-    @reactive.effect
-    @reactive.event(input.tso_save_button)
-    def _():
-        tso_label = input.display_tso_run.get()
-        tso_run = tso_runs[tso_label]
+        choices = depth_choices[obs_geometry]
+        ui.update_select(
+            "planet_model_type", choices=choices, selected=planet_model_type,
+        )
+        if planet_model_type == 'Input':
+            choices = user_spectra[obs_geometry]
+            selected = tso['depth_label']
+            ui.update_select("depth", choices=choices, selected=selected)
+        elif planet_model_type == 'Flat':
+            ui.update_numeric("transit_depth", value=tso['rprs_sq'])
+        elif planet_model_type == 'Blackbody':
+            ui.update_numeric("eclipse_depth", value=tso['rprs_sq'])
+            ui.update_numeric("teq_planet", value=tso['teq_planet'])
+
+
+    @render.image
+    def tso_logo():
+        dir = Path(__file__).resolve().parent.parent
+        img = {
+            "src": str(dir / "docs/images/gen_tso_logo.png"),
+            "height": "50px",
+        }
+        return img
+
+
+    # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+    # Instrument and detector modes
+    @reactive.Effect(priority=3)
+    @reactive.event(input.instrument)
+    def _():
+        inst = input.instrument.get()
+        print(f"You selected me: {inst}")
+        mode_choices = modes[inst]
+        choices = []
+        for m in mode_choices.values():
+            choices += list(m)
+
+        mode = input.mode.get()
+        selected = mode if mode in choices else choices[0]
+        ui.update_select('mode', choices=mode_choices, selected=selected)
+
+
+    @reactive.Effect(priority=2)
+    @reactive.event(input.instrument, input.mode)
+    def _():
+        inst = input.instrument.get()
+        mode = input.mode.get()
+        if not is_consistent(inst, mode):
+            return
+        detector = get_detector(inst, mode, detectors)
+
+        focus = 'science' if mode!='target_acq' else input.target_focus.get()
+        ui.update_radio_buttons('target_focus', selected=focus)
+
+        # The disperser
+        choices = detector.dispersers
+        disperser = input.disperser.get()
+        if disperser not in choices:
+            disperser = detector.default_disperser
+        ui.update_select(
+            'disperser',
+            label=detector.disperser_label,
+            choices=choices,
+            selected=disperser,
+        )
+
+        # The filter
+        choices = detector.filters
+        filter = input.filter.get()
+        if filter not in choices:
+            filter = detector.default_filter
+        ui.update_select(
+            'filter',
+            label=detector.filter_label,
+            choices=choices,
+            selected=filter,
+        )
+
+        selected = input.filter_filter.get()
+        if detector.obs_type == 'acquisition':
+            choices = [detector.instrument]
+        else:
+            choices = [detector.instrument, 'all']
+
+        if selected != 'all' or detector.obs_type=='acquisition':
+            selected = None
+        ui.update_radio_buttons(
+            "filter_filter",
+            choices=choices,
+            selected=selected,
+        )
+
+
+    @reactive.Effect(priority=1)
+    @reactive.event(input.instrument, input.mode, input.disperser, input.filter)
+    def update_subarray():
+        inst = input.instrument.get()
+        mode = input.mode.get()
+        disperser = input.disperser.get()
+        filter = input.filter.get()
+        if not is_consistent(inst, mode, disperser, filter):
+            return
+        detector = get_detector(inst, mode, detectors)
+
+        if mode == 'bots':
+            disperser = input.filter.get().split('/')[0]
+        else:
+            disperser = input.disperser.get()
+        choices = detector.get_constrained_val('subarrays', disperser=disperser)
+
+        subarray = input.subarray.get()
+        if subarray not in choices:
+            subarray = detector.default_subarray
+        ui.update_select(
+            'subarray',
+            choices=choices,
+            selected=subarray,
+        )
+
+
+    @reactive.Effect(priority=1)
+    @reactive.event(input.instrument, input.mode, input.disperser)
+    def update_readout():
+        inst = input.instrument.get()
+        mode = input.mode.get()
+        disperser = input.disperser.get()
+        if not is_consistent(inst, mode, disperser):
+            return
+        detector = get_detector(inst, mode, detectors)
+
+        choices = detector.get_constrained_val('readouts', disperser=disperser)
+        readout = input.readout.get()
+        if readout not in choices:
+            readout = detector.default_readout
+        ui.update_select(
+            'readout',
+            choices=choices,
+            selected=readout,
+        )
+
+    @reactive.Effect
+    @reactive.event(input.run_pandeia)
+    def _():
+        target_focus = input.target_focus.get()
+        name = input.target.get()
+        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+
+        error_msg = None
+        if target_focus=='acquisition':
+            if target is None:
+                error_msg = ui.markdown(
+                    "Need to select a valid **Science target** before searching "
+                    "for nearby acquisition targets"
+                )
+            elif target.host not in cache_acquisition:
+                error_msg = ui.markdown(
+                    "First click the '**Search nearby targets**' button, then "
+                    "select a target from the '**Acquisition targets**' tab"
+                )
+            elif input.ta_sed.get() is None:
+                error_msg = ui.markdown(
+                    "First select a target from the '**Acquisition targets**' tab"
+                )
+
+        if error_msg is None:
+            run_pandeia(input)
+        else:
+            ui.notification_show(error_msg, type="warning", duration=5)
+
+
+    @reactive.effect
+    @reactive.event(input.delete_button)
+    def _():
+        tso_key = input.display_tso_run.get()
+        if tso_key is None:
+            return
+        key, tso_label = tso_key.split('_', maxsplit=1)
+        del tso_runs[key][tso_label]
+        tso_labels = make_tso_labels(tso_runs)
+        ui.update_select('display_tso_run', choices=tso_labels)
+
+
+    @reactive.effect
+    @reactive.event(input.save_button)
+    def _():
+        # Make a filename from current TSO
+        tso_key = input.display_tso_run.get()
+        if tso_key is None:
+            return
+        key, tso_label = tso_key.split('_', maxsplit=1)
+        tso = tso_runs[key][tso_label]
+        inst = tso['inst']
+        filename = f'tso_{inst}.pickle'
+
+        m = ui.modal(
+            ui.input_text(
+                id='tso_save_file',
+                label='Save TSO run to file:',
+                value=filename,
+                placeholder=tso_label,
+                width='100%',
+            ),
+            ui.HTML(f"Located in current folder:<br>'{current_dir}/'<br>"),
+            # TBD: I wish this could be used to browse a folder :(
+            #ui.input_file(
+            #    id="save_file_x",
+            #    label="Into this folder:",
+            #    button_label="Browse",
+            #    multiple=True,
+            #    width='100%',
+            #),
+            ui.input_action_button(
+                id='tso_save_button',
+                label='Save to file',
+            ),
+            title="Download TSO run",
+            easy_close=True,
+            size='l',
+        )
+        ui.modal_show(m)
+
+    @reactive.effect
+    @reactive.event(input.tso_save_button)
+    def _():
+        tso_key = input.display_tso_run.get()
+        if tso_key is None:
+            return
+        key, tso_label = tso_key.split('_', maxsplit=1)
+        tso_run = tso_runs[key][tso_label]
 
         filename = input.tso_save_file.get()
         if filename.strip() == '':
@@ -1072,6 +1607,9 @@ def _():
     @reactive.effect
     @reactive.event(input.show_info)
     def _():
+        """
+        Display system parameters
+        """
         name = input.target.get()
         target = catalog.get_target(name, is_transit=None, is_confirmed=None)
         planet_info, star_info, aliases = pretty_print_target(target)
@@ -1098,6 +1636,127 @@ def _():
         ui.modal_show(m)
 
 
+    @reactive.effect
+    @reactive.event(input.show_observations)
+    def _():
+        """
+        Display JWST observations
+        """
+        name = input.target.get()
+        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+
+        trexo_info.set(target.trexo_data)
+
+        keys = ui.HTML(
+            'Keys:<br>'
+            '<span style="color:#0B980D">Observed, no proprietary period.</span>'
+            '<br><span>Observed, in proprietary period.</span><br>'
+            '<span style="color:#FFa500">To be observed, planned window.</span>'
+            '<br><span style="color:red">Failed, withdrawn, or skipped.</span>'
+        )
+
+        m = ui.modal(
+            ui.output_data_frame('trexo_df'),
+            ui.hr(),
+            keys,
+            title=ui.markdown(f'JWST programs for: **{target.host}**'),
+            size='xl',
+            easy_close=True,
+        )
+        ui.modal_show(m)
+
+
+    @render.data_frame
+    @reactive.event(trexo_info)
+    def trexo_df():
+        data = trexo_info.get()
+        nobs = len(data['program'])
+
+        today = datetime.today()
+        status = data['status']
+        date_obs = data['date_start']
+        plan_obs = data['plan_window']
+        propriety = data['proprietary_period']
+        warnings = [
+            i for i in range(nobs)
+            if status[i] in ['Skipped', 'Failed', 'Withdrawn']
+        ]
+        available = []
+        dates = []
+        tbd_dates = []
+        for i in range(nobs):
+            if isinstance(date_obs[i], datetime):
+                release = date_obs[i] + timedelta(days=365.0*propriety[i]/12)
+                if release < today:
+                    available.append(i)
+                dates.append(
+                    date_obs[i].strftime('%Y-%m-%d') +
+                    f' ({propriety[i]} m)'
+                )
+            else:
+                if isinstance(plan_obs[i], datetime):
+                    dates.append(
+                        plan_obs[i].strftime('%Y-%m-%d') +
+                        f' ({propriety[i]} m)'
+                    )
+                else:
+                    dates.append('---')
+                if i not in warnings:
+                    tbd_dates.append(i)
+
+        styles = [
+            {
+                'rows': available,
+                'style': {"color": "#0B980D"},
+            },
+            {
+                'rows': warnings,
+                'style': {"color": "red"},
+            },
+            {
+                'rows': tbd_dates,
+                'cols': [10],
+                'style': {"color": "#FFa500"},
+            },
+        ]
+        programs = [
+            ' '.join(program.split()[0:2])
+            for program in data['program']
+        ]
+        pi = [
+            ' '.join(program.split()[2:])
+            for program in data['program']
+        ]
+        hrefs = [stsci_url.replace('PID', pid.split()[1]) for pid in programs]
+        programs = [
+            ui.tags.a(programs[i], href=hrefs[i], target="_blank")
+            for i in range(nobs)
+        ]
+
+        data_df = {
+            'Program ID': programs,
+            'PI': pi,
+            'Target name': data['trexo_name'],
+            # TBD: fetch which planet(s)
+            #'planet': ['b' for _ in pi],
+            'Event': data['event'],
+            'Status': data['status'],
+            'Instrument / Mode': data['mode'],
+            'Subarray': data['subarray'],
+            'Readout': data['readout'],
+            'Groups': data['groups'],
+            'Duration (h)': data['duration'],
+            'Obs date (prop. period)': dates,
+        }
+        df = pd.DataFrame(data=data_df)
+
+        return render.DataGrid(
+            df,
+            styles=styles,
+            width='100%',
+        )
+
+
     @reactive.Effect
     @reactive.event(input.re_text)
     def _():
@@ -1161,13 +1820,11 @@ def target_label():
         )
 
         if target.is_jwst:
-            ra, dec = target.trexo_ra_dec
-            url = f'{trexolists_url}?ra={ra}&dec={dec}'
             trexolists_tooltip = ui.tooltip(
-                ui.tags.a(
-                    fa.icon_svg("circle-info", fill='goldenrod'),
-                    href=url,
-                    target="_blank",
+                ui.input_action_link(
+                    id='show_observations',
+                    label='',
+                    icon=fa.icon_svg("circle-info", fill='goldenrod'),
                 ),
                 "This target's host is on TrExoLiSTS",
                 placement='top',
@@ -1189,7 +1846,7 @@ def target_label():
             )
 
         return ui.span(
-            'Known target? ',
+            'Science target ',
             info_tooltip,
             ui.tooltip(
                 ui.tags.a(
@@ -1204,10 +1861,11 @@ def target_label():
             candidate_tooltip,
         )
 
-    @reactive.Effect
+
+    @reactive.effect
     @reactive.event(input.target)
     def _():
-        """Set known-target properties"""
+        """Update target properties"""
         name = input.target.get()
         target = catalog.get_target(name, is_transit=None, is_confirmed=None)
         if target is None:
@@ -1215,56 +1873,94 @@ def _():
         if name in target.aliases:
             ui.update_selectize('target', selected=target.planet)
 
-        teff = u.as_str(target.teff, '.1f', '')
-        log_g = u.as_str(target.logg_star, '.2f', '')
-        t_dur = u.as_str(target.transit_dur, '.3f', '')
-
-        ui.update_text('teff', value=teff)
-        ui.update_text('logg', value=log_g)
-        ui.update_select('magnitude_band', selected='Ks mag')
-        ui.update_text('magnitude', value=f'{target.ks_mag:.3f}')
+        # Physical properties:
+        if target.planet in cache_target:
+            t_eff  = cache_target[target.planet]['t_eff']
+            log_g = cache_target[target.planet]['log_g']
+            t_dur = cache_target[target.planet]['t_dur']
+            band = cache_target[target.planet]['norm_band']
+            magnitude = cache_target[target.planet]['norm_mag']
+        else:
+            t_eff = u.as_str(target.teff, '.1f', '')
+            log_g = u.as_str(target.logg_star, '.2f', '')
+            t_dur = u.as_str(target.transit_dur, '.3f', '')
+            band = '2mass,ks'
+            magnitude = f'{target.ks_mag:.3f}'
+
+        ui.update_text('t_eff', value=t_eff)
+        ui.update_text('log_g', value=log_g)
+        ui.update_select('magnitude_band', selected=band)
+        ui.update_text('magnitude', value=magnitude)
         ui.update_text('t_dur', value=t_dur)
 
-        sky_view_src.set(
-            f'https://sky.esa.int/esasky/?target={target.ra}%20{target.dec}'
-            '&fov=0.2&sci=true'
-        )
+        delete_catalog = {
+            "event": 'deleteCatalogue',
+            "content": { 'overlayName': 'Nearby Gaia sources'}
+        }
+        delete_footprint = {
+            "event": 'deleteFootprintsOverlay',
+            "content": {'overlayName': 'visit splitting distance'}
+        }
+        goto = {
+            "event": "goToRaDec",
+            "content":{"ra": f"{target.ra}", "dec": f"{target.dec}"}
+        }
+        esasky_command.set([delete_catalog, delete_footprint, goto])
+
+        # Observing properties:
+        if name in cache_target and cache_target[name]['rprs_sq'] is not None:
+            rprs_square_percent = cache_target[name]['rprs_sq']
+            teq_planet = cache_target[name]['teq_planet']
+            cache_target[name]['rprs_sq'] = None
+            cache_target[name]['teq_planet'] = None
+        else:
+            teq_planet = np.round(target.eq_temp, decimals=1)
+            if np.isnan(teq_planet):
+                teq_planet = 0.0
+            rprs_square = target.rprs**2.0
+            if np.isnan(rprs_square):
+                rprs_square = 0.0
+            rprs_square_percent = np.round(100*rprs_square, decimals=4)
 
-    @render.ui
-    @reactive.event(input.sed_type, input.teff, input.logg)
+        if rprs_square_percent is not None:
+            ui.update_numeric("transit_depth", value=rprs_square_percent)
+            ui.update_numeric("eclipse_depth", value=rprs_square_percent)
+        if teq_planet is not None:
+            ui.update_numeric('teq_planet', value=teq_planet)
+
+
+    @reactive.Effect
+    @reactive.event(input.sed_type, input.t_eff, input.log_g)
     def choose_sed():
         sed_type = input.sed_type.get()
         if sed_type in ['phoenix', 'kurucz']:
-            m_models, chosen_sed = get_auto_sed(input)
-            choices = list(m_models)
-            selected = chosen_sed
+            choices, selected = get_auto_sed(input)
+            if preset_sed.get() is not None:
+                selected = preset_sed.get()
+                preset_sed.set(None)
         elif sed_type == 'blackbody':
-            if input.teff.get() == '':
-                teff = 0.0
+            if input.t_eff.get() == '':
+                t_eff = 0.0
             else:
-                teff = float(input.teff.get())
-            selected = f' Blackbody (Teff={teff:.0f} K)'
+                t_eff = float(input.t_eff.get())
+            selected = f' Blackbody (Teff={t_eff:.0f} K)'
             choices = [selected]
         elif sed_type == 'input':
-            choices=spectrum_choices['sed']
+            choices = list(spectra['sed'])
             selected = None
 
-        return ui.input_select(
-            id="sed",
-            label="",
-            choices=choices,
-            selected=selected,
-        )
+        ui.update_select("sed", choices=choices, selected=selected)
+
 
     @render.ui
     @reactive.event(
         bookmarked_sed, input.sed,
-        input.teff, input.magnitude_band, input.magnitude,
+        input.t_eff, input.magnitude_band, input.magnitude,
     )
     def stellar_sed_label():
         """Check current SED is bookmarked"""
-        sed_type, sed_model, norm_band, norm_mag, label = parse_sed(input)
-        is_bookmarked = label in spectrum_choices['sed']
+        sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(input)
+        is_bookmarked = sed_label in bookmarked_spectra['sed']
         bookmarked_sed.set(is_bookmarked)
         if is_bookmarked:
             sed_icon = fa.icon_svg("star", style='solid', fill='gold')
@@ -1292,34 +1988,32 @@ def _():
         """Toggle bookmarked SED"""
         is_bookmarked = not bookmarked_sed.get()
         bookmarked_sed.set(is_bookmarked)
-        sed_type, sed_model, norm_band, norm_mag, sed_file = parse_sed(input)
+        sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(input)
         if is_bookmarked:
             scene = jwst.make_scene(sed_type, sed_model, norm_band, norm_mag)
             wl, flux = jwst.extract_sed(scene, wl_range=[0.3,30.0])
-            spectrum_choices['sed'].append(sed_file)
-            spectra[sed_file] = {'wl': wl, 'flux': flux}
+            spectra['sed'][sed_label] = {'wl': wl, 'flux': flux}
+            bookmarked_spectra['sed'].append(sed_label)
         else:
-            spectrum_choices['sed'].remove(sed_file)
-            spectra.pop(sed_file)
+            bookmarked_spectra['sed'].remove(sed_label)
+            if sed_label not in user_spectra['sed']:
+                spectra['sed'].pop(sed_label)
 
 
-    # This breaks because tplanet is not always defined
-    #@reactive.event(
-    #    bookmarked_depth, input.geometry,
-    #    input.planet_model_type, input.depth, input.tplanet,
-    #)
     @render.ui
+    @reactive.event(
+        bookmarked_depth, input.obs_geometry, input.planet_model_type,
+        input.depth, input.transit_depth, input.eclipse_depth, input.teq_planet,
+    )
     def depth_label_text():
         """Set depth model label"""
-        obs_geometry = str(input.geometry.get()).lower()
+        obs_geometry = input.obs_geometry.get()
         depth_label = planet_model_name(input)
-        is_bookmarked = not bookmarked_depth.get()
-        is_bookmarked = depth_label in spectrum_choices[obs_geometry]
+
+        is_bookmarked = depth_label in bookmarked_spectra[obs_geometry]
         bookmarked_depth.set(is_bookmarked)
-        if is_bookmarked:
-            depth_icon = fa.icon_svg("earth-americas", style='solid', fill='royalblue')
-        else:
-            depth_icon = fa.icon_svg("earth-americas", style='solid', fill='gray')
+        fill = 'royalblue' if is_bookmarked else 'gray'
+        depth_icon = fa.icon_svg("earth-americas", style='solid', fill=fill)
         icons = [
             depth_icon,
             fa.icon_svg("file-arrow-up", fill='black'),
@@ -1332,18 +2026,19 @@ def depth_label_text():
             label=f"{obs_geometry.capitalize()} depth spectrum: ",
             icons=icons,
             tooltips=texts,
-            button_ids=['bookmark_depth', 'upload_depth']
+            button_ids=['bookmark_depth', 'upload_depth'],
         )
 
+
     @reactive.Effect
     @reactive.event(input.bookmark_depth)
     def _():
         """Toggle bookmarked depth model"""
-        obs_geometry = input.geometry.get().lower()
+        obs_geometry = input.obs_geometry.get()
         depth_label = planet_model_name(input)
         if depth_label is None:
             ui.notification_show(
-                f"No {obs_geometry.lower()} depth model to bookmark",
+                f"No {obs_geometry} depth model to bookmark",
                 type="error",
                 duration=5,
             )
@@ -1351,49 +2046,68 @@ def _():
         is_bookmarked = not bookmarked_depth.get()
         bookmarked_depth.set(is_bookmarked)
         if is_bookmarked:
+            bookmarked_spectra[obs_geometry].append(depth_label)
             depth_label, wl, depth = parse_depth_model(input)
-            spectrum_choices[obs_geometry].append(depth_label)
-            spectra[depth_label] = {'wl': wl, 'depth': depth}
+            spectra[obs_geometry][depth_label] = {'wl': wl, 'depth': depth}
         else:
-            spectrum_choices[obs_geometry].remove(depth_label)
-            spectra.pop(depth_label)
+            bookmarked_spectra[obs_geometry].remove(depth_label)
+            if depth_label not in user_spectra[obs_geometry]:
+                spectra[obs_geometry].pop(depth_label)
 
 
     @reactive.effect
-    @reactive.event(input.geometry)
+    @reactive.event(input.obs_geometry, update_depth_flag)
     def _():
-        obs_geometry = input.geometry.get()
-        selected = input.planet_model_type.get()
-        if obs_geometry == 'Transit':
-            choices = ['Flat', 'Input']
-        elif obs_geometry == 'Eclipse':
-            choices = ['Blackbody', 'Input']
-        if selected not in choices:
-            selected = choices[0]
-
+        obs_geometry = input.obs_geometry.get()
+        choices = depth_choices[obs_geometry]
+        model_type = input.planet_model_type.get()
+        if model_type not in choices:
+            model_type = choices[0]
         ui.update_select(
-            id="planet_model_type",
-            choices=choices,
-            selected=selected,
+            "planet_model_type", choices=choices, selected=model_type,
         )
 
+        spectra = user_spectra[obs_geometry]
+        name = input.target.get()
+        cached = (
+            name in cache_target and
+            cache_target[name]['depth_label'] is not None
+        )
+        selected = input.depth.get()
+        if cached:
+            selected = cache_target[name]['depth_label']
+            cache_target[name]['depth_label'] = None
+        elif selected not in spectra:
+            selected = None if len(spectra) == 0 else spectra[0]
+        #print(f'Updating input [cached={cached}]: {repr(selected)}')
+        ui.update_select("depth", choices=spectra, selected=selected)
+
+        if len(spectra) > 0:
+            tooltip_text = ''
+        elif obs_geometry == 'transit':
+            tooltip_text = f'Upload a {obs_geometry} depth spectrum'
+        elif obs_geometry == 'eclipse':
+            tooltip_text = f'Upload an {obs_geometry} depth spectrum'
+        ui.update_tooltip('depth_tooltip', tooltip_text)
+
+
     @render.text
-    @reactive.event(input.geometry)
+    @reactive.event(input.obs_geometry)
     def transit_dur_label():
-        obs_geometry = input.geometry.get()
+        obs_geometry = input.obs_geometry.get().capitalize()
         return f"{obs_geometry[0]}_dur (h):"
 
     @render.text
-    @reactive.event(input.geometry)
+    @reactive.event(input.obs_geometry)
     def transit_depth_label():
-        obs_geometry = input.geometry.get()
+        obs_geometry = input.obs_geometry.get().capitalize()
         return f"{obs_geometry} depth"
 
     @render.ui
     @reactive.event(warning_text)
     def warnings_label():
         warnings = warning_text.get()
-        if warnings == '':
+        if len(warnings) == 0:
             return "Warnings"
         n_warn = len(warnings)
         return ui.HTML(f'<div style="color:red;">Warnings ({n_warn})</div>')
@@ -1405,9 +2119,14 @@ def warnings_label():
     )
     def _():
         """Set observation time based on transit dur and popover settings"""
+        if preset_obs_dur.get() is not None:
+            obs_dur = preset_obs_dur.get()
+            preset_obs_dur.set(None)
+            ui.update_text('obs_dur', value=f'{obs_dur:.2f}')
+            return
         t_dur = req(input.t_dur).get()
         if t_dur == '':
-            ui.update_text('obs_dur', value='')
+            ui.update_text('obs_dur', value='0.0')
             return
         transit_dur = float(t_dur)
         settling = req(input.settling_time).get()
@@ -1415,91 +2134,8 @@ def _():
         min_baseline = req(input.min_baseline_time).get()
         baseline = np.clip(baseline*transit_dur, min_baseline, np.inf)
         # Tdwell = T_start + T_settle + T14 + 2*max(1, T14/2)
-        t_total = 1.0 + settling + transit_dur + 2.0*baseline
-        ui.update_text('obs_dur', value=f'{t_total:.2f}')
-
-
-    @render.ui
-    @reactive.event(
-        input.target, input.geometry, input.planet_model_type,
-        update_depth_flag,
-    )
-    def choose_depth():
-        obs_geometry = input.geometry.get()
-        model_type = input.planet_model_type.get()
-
-        name = input.target.get()
-        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
-        if target is None:
-            rprs_square = 1.0
-            teq_planet = 1000.0
-        else:
-            teq_planet = target.eq_temp
-            rprs_square = target.rprs**2.0
-            if np.isnan(rprs_square):
-                rprs_square = 0.0
-        rprs_square_percent = np.round(100*rprs_square, decimals=4)
-
-        layout_kwargs = dict(
-            width=1/2,
-            fixed_width=False,
-            heights_equal='all',
-            gap='7px',
-            fill=False,
-            fillable=True,
-            class_="pb-2 pt-0 m-0",
-        )
-
-        if model_type == 'Flat':
-            return ui.layout_column_wrap(
-                ui.p("Depth (%):"),
-                ui.input_numeric(
-                    id="depth",
-                    label="",
-                    value=rprs_square_percent,
-                    step=0.1,
-                ),
-                **layout_kwargs,
-            )
-        elif model_type == 'Blackbody':
-            return ui.layout_column_wrap(
-                ui.HTML("<p>(Rp/Rs)<sup>2</sup> (%):</p>"),
-                ui.input_numeric(
-                    id="depth",
-                    label="",
-                    value=rprs_square_percent,
-                    step=0.1,
-                ),
-                ui.p("Temp (K):"),
-                ui.input_numeric(
-                    id="tplanet",
-                    label="",
-                    value=teq_planet,
-                    step=100,
-                ),
-                **layout_kwargs,
-            )
-
-        if model_type == 'Input':
-            choices = spectrum_choices[obs_geometry.lower()]
-            input_select = ui.input_select(
-                id="depth",
-                label="",
-                choices=choices,
-                #selected=selected,
-            )
-            if len(choices) > 0:
-                return input_select
-
-            if obs_geometry == 'Transit':
-                tooltip_text = f"a {obs_geometry.lower()}"
-            elif obs_geometry == 'Eclipse':
-                tooltip_text = f"an {obs_geometry.lower()}"
-            return ui.tooltip(
-                input_select,
-                f'Upload {tooltip_text} depth spectrum',
-                placement='right',
-            )
+        obs_dur = 1.0 + settling + transit_dur + 2.0*baseline
+        ui.update_text('obs_dur', value=f'{obs_dur:.2f}')
 
 
     @reactive.effect
@@ -1534,7 +2170,7 @@ def _():
     @reactive.effect
     @reactive.event(input.upload_depth)
     def _():
-        obs_geometry = input.geometry.get().lower()
+        obs_geometry = input.obs_geometry.get()
         m = ui.modal(
             ui.input_file(
                 id="upload_file",
@@ -1571,7 +2207,6 @@ def _():
     def _():
         new_model = input.upload_file.get()
         if not new_model:
-            print('No new model!')
             return
 
         # The units tell this function SED or depth spectrum:
@@ -1588,10 +2223,11 @@ def _():
             label = label[0:-4]
 
         if units in depth_units:
-            obs_geometry = input.geometry.get().lower()
-            spectrum_choices[obs_geometry].append(label)
+            obs_geometry = input.obs_geometry.get()
             # TBD: convert depth units
-            spectra[label] = {'wl': wl, 'depth': depth}
+            spectra[obs_geometry][label] = {'wl': wl, 'depth': depth}
+            user_spectra[obs_geometry].append(label)
+            bookmarked_spectra[obs_geometry].append(label)
             if input.planet_model_type.get() != 'Input':
                 return
             # Trigger update choose_depth
@@ -1602,100 +2238,113 @@ def _():
 
     # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
     # Detector setup
+    @reactive.Effect
+    @reactive.event(input.subarray)
+    def set_soss_orders():
+        inst = input.instrument.get()
+        mode = input.mode.get()
+        subarray = input.subarray.get()
+        if not is_consistent(inst, mode, subarray=subarray):
+            return
+        if mode != 'soss':
+            return
+        detector = get_detector(inst, mode, detectors)
+        choices = detector.get_constrained_val('orders', subarray=subarray)
+        order = input.order.get()
+        if order not in choices:
+            order = list(choices)[0]
+        ui.update_select(id='order', choices=choices, selected=order)
+
+
     @render.ui
-    @reactive.event(input.select_mode, input.subarray)
+    @reactive.event(input.mode, input.subarray)
     def groups_input():
-        mode = input.select_mode.get()
+        inst = input.instrument.get()
+        mode = input.mode.get()
+        subarray = input.subarray.get()
+        preset = preset_ngroup.get()
+        has_preset = (
+            preset is not None and
+            preset['mode'] == mode and
+            preset['subarray'] == subarray
+        )
+        if has_preset:
+            value = preset['ngroup']
+            preset_ngroup.set(None)
+        else:
+            value = 2
         if mode == 'target_acq':
-            instrument = req(input.select_instrument).get()
-            det = get_detector(mode, instrument)
-            subarray = input.subarray.get()
-            choices = det.get_constrained_val('groups', subarray=subarray)
+            detector = get_detector(inst, mode, detectors)
+            choices = detector.get_constrained_val('groups', subarray=subarray)
 
             return ui.input_select(
-                id="groups",
+                id="ngroup",
                 label="",
                 choices=choices,
+                selected=value,
             )
         else:
             return ui.input_numeric(
-                id="groups",
+                id="ngroup",
                 label='',
-                value=2,
+                value=value,
                 min=2, max=10000,
             )
 
-    @render.ui
-    @reactive.event(input.select_mode)
-    def integration_input():
-        mode = input.select_mode.get()
-        if mode == 'target_acq':
-            return ui.input_select(
-                id="integrations",
-                label="Integrations",
-                choices=[1],
-            )
-        else:
-            return ui.input_numeric(
-                id="integrations",
-                label="Integrations",
-                value=1,
-                min=1, max=10000,
-            )
-
     @reactive.Effect
     @reactive.event(input.calc_saturation)
     def calculate_saturation_level():
-        inst = input.select_instrument.get().lower()
-        mode = input.select_mode.get()
+        inst = input.instrument.get().lower()
+        mode = input.mode.get()
         disperser = input.disperser.get()
         filter = input.filter.get()
         subarray = input.subarray.get()
         readout = input.readout.get()
+        order = input.order.get()
         aperture = None
         sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(input)
-        sat_label = make_saturation_label(
-            mode, disperser, filter, subarray, sed_label,
-        )
 
+        # Front-end to back-end exceptions:
         if mode == 'bots':
             disperser, filter = filter.split('/')
+        if mode == 'soss':
+            order = [int(val) for val in order.split()]
         if mode == 'mrs_ts':
             aperture = ['ch1', 'ch2', 'ch3', 'ch4']
         if mode == 'target_acq':
-            ngroup = int(input.groups.get())
+            ngroup = int(input.ngroup.get())
             aperture = input.disperser.get()
             disperser = None
         else:
             ngroup = 2
 
+        sat_label = make_saturation_label(
+            inst, mode, aperture, disperser, filter, subarray, order, sed_label,
+        )
+
         pando = jwst.PandeiaCalculation(inst, mode)
         pando.set_scene(sed_type, sed_model, norm_band, norm_mag)
-        flux_rate, full_well = pando.get_saturation_values(
-            disperser, filter, subarray, readout, ngroup,
-            aperture,
+        pixel_rate, full_well = pando.get_saturation_values(
+            disperser, filter, subarray, readout, ngroup, aperture, order,
+            get_max=True,
         )
-        if isinstance(flux_rate, Iterable):
-            idx = np.argmax(flux_rate*full_well)
-            flux_rate = flux_rate[idx]
-            full_well = full_well[idx]
 
         cache_saturation[sat_label] = dict(
-            brightest_pixel_rate = flux_rate,
-            full_well = full_well,
+            brightest_pixel_rate=pixel_rate,
+            full_well=full_well,
         )
-        # This reactive variable enforces a re-rendering of exp_time
+        # This reactive variable enforces a re-rendering of results
         saturation_label.set(sat_label)
 
 
     @reactive.Effect
     @reactive.event(
-        input.integs_switch, input.obs_dur, input.select_mode,
-        input.select_instrument, input.groups, input.readout, input.subarray,
+        input.integs_switch, input.obs_dur, input.mode,
+        input.instrument, input.ngroup, input.readout, input.subarray,
     )
     def _():
         """Switch to make the integrations match observation duration"""
-        if input.select_mode.get() == 'target_acq':
+        if input.mode.get() == 'target_acq':
             return
         match_dur = input.integs_switch.get()
         if not match_dur:
@@ -1703,30 +2352,28 @@ def _():
             return
 
         obs_dur = float(req(input.obs_dur).get())
-        inst = input.select_instrument.get().lower()
-        nint = 1
-        ngroup = input.groups.get()
+        inst = input.instrument.get().lower()
+        ngroup = input.ngroup.get()
         readout = input.readout.get()
         subarray = input.subarray.get()
         if ngroup is None:
             return
-        single_exp_time = jwst.exposure_time(
-            inst, subarray, readout, int(ngroup), int(nint),
+        integs, exp_time = jwst.bin_search_exposure_time(
+            inst, subarray, readout, int(ngroup), obs_dur,
         )
-        if single_exp_time == 0.0:
+        if exp_time == 0.0:
             return
-        integs = int(np.round(obs_dur*3600.0/single_exp_time))
         ui.update_numeric('integrations', value=integs)
 
 
     # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-    # Viewer
+    # Viewers
     @render_plotly
     def plotly_filters():
         show_all = req(input.filter_filter).get() == 'all'
 
-        inst = req(input.select_instrument).get().lower()
-        mode = input.select_mode.get()
+        inst = input.instrument.get().lower()
+        mode = input.mode.get()
         filter = input.filter.get()
         subarray = input.subarray.get()
 
@@ -1746,35 +2393,16 @@ def plotly_filters():
         return fig
 
 
-    @render.ui
-    @reactive.event(sky_view_src)
-    def esasky_card():
-        src = sky_view_src.get()
-        return cs.custom_card(
-            HTML(
-                '<iframe '
-                'height="100%" '
-                'width="100%" '
-                'style="overflow" '
-                f'src="{src}" '
-                'frameborder="0" allowfullscreen></iframe>',
-                #id=resolve_id(id),
-            ),
-            body_args=dict(class_='m-0 p-0', id='esasky'),
-            full_screen=True,
-            height='350px',
-        )
-
     @render_plotly
     def plotly_sed():
         # Gather bookmarked SEDs
         input.sed_bookmark.get()  # (make panel reactive to sed_bookmark)
-        model_names = spectrum_choices['sed']
+        model_names = bookmarked_spectra['sed']
         if len(model_names) == 0:
             fig = go.Figure()
             fig.update_layout(title='Bookmark some SEDs to show them here')
             return fig
-        sed_models = [spectra[model] for model in model_names]
+        sed_models = [spectra['sed'][model] for model in model_names]
 
         # Get current SED:
         sed_type, sed_model, norm_band, norm_mag, current_model = parse_sed(input)
@@ -1794,8 +2422,8 @@ def plotly_sed():
     @render_plotly
     def plotly_depth():
         input.bookmark_depth.get()  # (make panel reactive to bookmark_depth)
-        obs_geometry = input.geometry.get()
-        model_names = spectrum_choices[obs_geometry.lower()]
+        obs_geometry = input.obs_geometry.get()
+        model_names = bookmarked_spectra[obs_geometry]
         nmodels = len(model_names)
         if nmodels == 0:
             return go.Figure()
@@ -1806,7 +2434,7 @@ def plotly_depth():
         wl_scale = input.plot_depth_xscale.get()
         resolution = input.depth_resolution.get()
 
-        depth_models = [spectra[model] for model in model_names]
+        depth_models = [spectra[obs_geometry][model] for model in model_names]
         fig = tplots.plotly_depth_spectra(
             depth_models, model_names, current_model,
             units=units, wl_scale=wl_scale, resolution=resolution,
@@ -1817,7 +2445,10 @@ def plotly_depth():
 
     @render_plotly
     def plotly_tso():
-        tso_label = input.display_tso_run.get()
+        tso_key = input.display_tso_run.get()
+        if tso_key is None:
+            return go.Figure()
+        key, tso_label = tso_key.split('_', maxsplit=1)
         n_obs = input.n_obs.get()
         resolution = input.tso_resolution.get()
         units = input.plot_tso_units.get()
@@ -1828,96 +2459,130 @@ def plotly_tso():
         else:
             wl_range = [0.6, 13.0]
 
-        if tso_label in tso_runs:
-            tso_run = tso_runs[tso_label]
-            planet = tso_run['depth_model_name']
-            fig = tplots.plotly_tso_spectra(
-                tso_run['tso'], resolution, n_obs,
-                model_label=planet,
-                instrument_label=tso_run['inst_label'],
-                bin_widths=None,
-                units=units, wl_range=wl_range, wl_scale=wl_scale,
-                obs_geometry='Transit',
-            )
-        else:
-            fig = go.Figure()
+        tso_run = tso_runs[key][tso_label]
+        planet = tso_run['depth_label']
+        fig = tplots.plotly_tso_spectra(
+            tso_run['tso'], resolution, n_obs,
+            model_label=planet,
+            instrument_label=tso_run['inst_label'],
+            bin_widths=None,
+            units=units, wl_range=wl_range, wl_scale=wl_scale,
+            obs_geometry='transit',
+        )
         return fig
 
     # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
     # Results
     @render.ui
-    def exp_time():
-        instrument = req(input.select_instrument).get()
-        mode = input.select_mode.get()
-        detector = get_detector(mode=mode, instrument=instrument)
-        inst = instrument.lower()
+    def results():
+        warnings = {}
+        # Only read for reactivity reasons:
+        saturation_label.get()
+        input.ta_sed.get()
+
+        inst = input.instrument.get().lower()
+        mode = input.mode.get()
         disperser = input.disperser.get()
         filter = input.filter.get()
         subarray = input.subarray.get()
         readout = input.readout.get()
-        ngroup = input.groups.get()
+        order = input.order.get()
+        ngroup = input.ngroup.get()
         nint = input.integrations.get()
         sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(input)
 
-        if ngroup is None or detector is None or sed_label is None:
-            return ui.HTML(' ')
+        name = input.target.get()
+        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+        depth_label = parse_obs(input)[1]
+        transit_dur = float(input.t_dur.get())
+
+        consistent = is_consistent(inst, mode, disperser, filter, subarray)
+        if ngroup is None or not consistent or sed_label is None:
+            warning_text.set(warnings)
+            return ui.HTML('<pre> </pre>')
+
+        obs_geometry = input.obs_geometry.get()
+        run_type = obs_geometry.capitalize()
+        # Front-end to back-end exceptions:
+        aperture = None
+        if mode == 'bots' and '/' in filter:
+            disperser, filter = filter.split('/')
+        if mode == 'mrs_ts':
+            aperture = ['ch1', 'ch2', 'ch3', 'ch4']
+        if mode == 'target_acq':
+            aperture = input.disperser.get()
+            disperser = None
+            nint = 1
+            run_type = 'Acquisition'
+            depth_label = ''
 
         ngroup = int(ngroup)
-        sat_label = make_saturation_label(
-            mode, disperser, filter, subarray, sed_label,
+        report_text = jwst._print_pandeia_exposure(
+            inst, subarray, readout, ngroup, nint,
         )
+        target_focus = input.target_focus.get().capitalize()
 
-        exp_time = jwst.exposure_time(
-            inst, subarray, readout, ngroup, int(nint),
+        if target_focus == 'Science':
+            target_acq_mag = None
+            target_name = f': {target.planet}' if target is not None else ''
+        else:
+            no_target = (
+                target is None or
+                target.host not in cache_acquisition or
+                cache_acquisition[target.host]['selected'] is None
+            )
+            if no_target:
+                report_text = f'<b>{target_focus} target</b><br>{report_text}'
+                warning_text.set(warnings)
+                return ui.HTML(f'<pre>{report_text}</pre>')
+            target_list = cache_acquisition[target.host]['targets']
+            selected = cache_acquisition[target.host]['selected']
+            target_acq_mag = np.round(target_list[1][selected], 3)
+            target_name = f': {target_list[0][selected]}'
+        report_text = f'<b>{target_focus} target{target_name}</b><br>{report_text}'
+
+        sed_type, sed_model, norm_band, norm_mag, sed_label = parse_sed(
+            input, target_acq_mag=target_acq_mag,
         )
-        exposure_hours = exp_time / 3600.0
-        exp_text = ui.HTML(
-            f'Exposure time: {exp_time:.2f} s ({exposure_hours:.2f} h)'
+        sat_label = make_saturation_label(
+            inst, mode, aperture, disperser, filter, subarray, order, sed_label,
         )
-
-        saturation_label.get()  # enforce calc_saturation renders exp_time
-        if sat_label not in cache_saturation:
-            return exp_text
-
-        pixel_rate = cache_saturation[sat_label]['brightest_pixel_rate']
-        full_well = cache_saturation[sat_label]['full_well']
-        sat_time = jwst.saturation_time(detector, ngroup, readout, subarray)
-        sat_fraction = pixel_rate * sat_time / full_well
-        ngroup_80 = int(0.8*ngroup/sat_fraction)
-        ngroup_max = int(ngroup/sat_fraction)
-        saturation = f'{100.0*sat_fraction:.1f}%'
-        ngroup_80_sat = f'ngroup below 80% saturation: {ngroup_80:d}'
-        ngroup_max_sat = f'ngroup below 100% saturation: {ngroup_max:d}'
-
-        if sat_fraction >= 1.0:
-            saturation = f'<span class="danger">{saturation}</span>'
-        elif sat_fraction > 0.81:
-            saturation = f'<span class="warning">{saturation}</span>'
-
-        if ngroup_80 < 2:
-            ngroup_80_sat = f'<span class="danger">{ngroup_80_sat}</span>'
-        elif ngroup_80 == 2:
-            ngroup_80_sat = f'<span class="warning">{ngroup_80_sat}</span>'
-
-        if ngroup_max < 2:
-            ngroup_max_sat = f'<span class="danger">{ngroup_max_sat}</span>'
-        elif ngroup_max == 2:
-            ngroup_max_sat = f'<span class="warning">{ngroup_max_sat}</span>'
-        return ui.HTML(
-            f'{exp_text}<br>'
-            f'Max. fraction of saturation: {saturation}<br>'
-            f'{ngroup_80_sat}<br>'
-            f'{ngroup_max_sat}<br>'
+        tso_label = make_obs_label(
+            inst, mode, aperture, disperser, filter, subarray, readout, order,
+            ngroup, nint, run_type, sed_label, depth_label,
         )
 
+        if sat_label in cache_saturation:
+            pixel_rate = cache_saturation[sat_label]['brightest_pixel_rate']
+            full_well = cache_saturation[sat_label]['full_well']
+            saturation_text = jwst._print_pandeia_saturation(
+                inst, subarray, readout, ngroup, pixel_rate, full_well,
+                format='html',
+            )
+            report_text += f'<br>{saturation_text}'
+
+
+        if tso_label in tso_runs[run_type]:
+            tso_run = tso_runs[run_type][tso_label]
+            warnings = tso_run['warnings']
+            if transit_dur == tso_run['transit_dur']:
+                report_text += f'<br><br>{tso_run["stats"]}'
+        warning_text.set(warnings)
+        return ui.HTML(f'<pre>{report_text}</pre>')
+
+
     @render.text
     @reactive.event(warning_text)
     def warnings():
         warnings = warning_text.get()
-        if warnings == '':
+        if len(warnings) == 0:
             return 'No warnings'
         text = ''
         for warn_label, warn_text in warnings.items():
+            warn_text = warn_text.replace(
+                '<font color=red><b>TA MAY FAIL</b></font>',
+                'TA MAY FAIL',
+            )
             warn = textwrap.fill(
                 f'- {warn_text}',
                 subsequent_indent='  ',
@@ -1926,5 +2591,174 @@ def warnings():
             text += warn + '\n\n'
         return text
 
+
+    @reactive.effect
+    @reactive.event(esasky_command)
+    async def _():
+        commands = esasky_command.get()
+        if commands is None:
+            return
+        if not isinstance(commands, list):
+            commands = [commands]
+        for command in commands:
+            command = json.dumps(command)
+            await session.send_custom_message(
+                "update_esasky",
+                {"command": command},
+            )
+
+
+    @reactive.Effect
+    @reactive.event(input.search_gaia_ta)
+    def _():
+        name = input.target.get()
+        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+        if target is None:
+            return
+
+        query = cat.fetch_gaia_targets(
+            target.ra, target.dec, max_separation=80.0, raise_errors=False,
+        )
+        if isinstance(query, str):
+            msg = ui.HTML(
+                "The Gaia astroquery request failed :(<br>"
+                "Check the terminal for more info"
+            )
+            ui.notification_show(msg, type="error", duration=5)
+            return
+
+        cache_acquisition[target.host] = {'targets': query, 'selected': None}
+        acq_target_list.set(query)
+        current_acq_science_target.set(name)
+        success = "Nearby targets found!  Open the '*Acquisition targets*' tab"
+        ui.notification_show(ui.markdown(success), type="message", duration=5)
+
+        circle = u.esasky_js_circle(target.ra, target.dec, radius=80.0)
+        ta_catalog = u.esasky_js_catalog(query)
+        esasky_command.set([ta_catalog, circle])
+
+
+    @render.data_frame
+    @reactive.event(acq_target_list, input.target)
+    def acquisition_targets():
+        """
+        Display TA list, gets triggered only when tab is shown
+        """
+        name = input.target.get()
+        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+        if target is None:
+            return render.DataGrid(pd.DataFrame([]))
+        if target.host not in cache_acquisition:
+            # Do I need to? gets wiped anyway
+            ui.update_select('ta_sed', choices=[])
+            return render.DataGrid(pd.DataFrame([]))
+
+        ta_list = cache_acquisition[target.host]['targets']
+        acq_target_list.set(ta_list)
+        names, G_mag, t_eff, log_g, ra, dec, separation = ta_list
+        data_df = {
+            'Gaia DR3 target': [name[9:] for name in names],
+            'G_mag': [f'{mag:5.2f}' for mag in G_mag],
+            'separation (")': [f'{sep:.3f}' for sep in separation],
+            'T_eff (K)': [f'{temp:.1f}' for temp in t_eff],
+            'log(g)': [f'{grav:.2f}' for grav in log_g],
+            'RA (deg)': [f'{r:.4f}' for r in ra],
+            'dec (deg)': [f'{d:.4f}' for d in dec],
+        }
+        acquisition_df = pd.DataFrame(data=data_df)
+        return render.DataGrid(
+            acquisition_df,
+            selection_mode="row",
+            height='370px',
+            summary=True,
+        )
+
+
+    @reactive.effect
+    def select_ta_row():
+        """
+        Gets triggrered all the time. Can I limit it to true unser-interactions
+        with acquisition_targets
+        """
+        acq_target_list.get()
+        name = input.target.get()
+        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+
+        if target is None or target.host not in cache_acquisition:
+            ui.update_select('ta_sed', choices=[])
+            return
+        target_list = cache_acquisition[target.host]['targets']
+
+        # TBD: if acquisition_targets changed, a previous non-zero cell_selection()
+        # will leak into the new dataframe, which will de-synchronize
+        # cache_acquisition[target.host]['selected']
+        df = acquisition_targets.cell_selection()
+        if df is None or len(df['rows'])==0:
+            return
+
+        df_data = acquisition_targets.data()
+        current_data = [f'Gaia DR3 {id}' for id in df_data["Gaia DR3 target"]]
+        if current_data[0] != target_list[0][0]:
+            acquisition_targets._reset_reactives()
+            return
+
+        cache_acquisition[target.host]['selected'] = idx = df['rows'][0]
+        target_name = target_list[0][idx]
+        t_eff = target_list[2][idx]
+        log_g = target_list[3][idx]
+        i = jwst.find_closest_sed(p_teff, p_logg, t_eff, log_g)
+        chosen_sed = p_keys[i]
+        ui.update_select('ta_sed', choices=phoenix_dict, selected=chosen_sed)
+
+        deselect_targets = {'event': 'deselectAllShapes'}
+        select_acq_target = {
+            'event': 'selectShape',
+            'content': {
+                'overlayName': 'Nearby Gaia sources',
+                'shapeName': target_name
+            }
+        }
+        esasky_command.set([deselect_targets, select_acq_target])
+
+
+    # TBD: rename
+    @reactive.effect
+    @reactive.event(input.get_acquisition_target)
+    def _():
+        return
+        name = input.target.get()
+        target = catalog.get_target(name, is_transit=None, is_confirmed=None)
+        if target is None:
+            return
+        if target.host not in cache_acquisition:
+            error_msg = ui.markdown(
+                "First click the '*Search nearby targets*' button, then select "
+                "a target from the '*Acquisition targets*' tab"
+            )
+            ui.notification_show(error_msg, type="warning", duration=5)
+            return
+
+        selected = acquisition_targets.cell_selection()['rows']
+        if len(selected) == 0:
+            error_msg = ui.markdown(
+                "First select a target from the '*Acquisition targets*' tab"
+            )
+            ui.notification_show(error_msg, type="warning", duration=5)
+            return
+        target_list = cache_acquisition[target.host]['targets']
+        names, G_mag, t_eff, log_g, ra, dec, separation = target_list
+        idx = selected[0]
+        text = (
+            f"\nacq_target = {repr(names[idx])}\n"
+            f"gaia_mag = {G_mag[idx]}\n"
+            f"separation = {separation[idx]}\n"
+            f"t_eff = {t_eff[idx]}\n"
+            f"log_g = {log_g[idx]}\n"
+            f"ra = {ra[idx]}\n"
+            f"dec = {dec[idx]}"
+        )
+        print(text)
+
+
 app = App(app_ui, server)
 
diff --git a/gen_tso/pandeia_io/__init__.py b/gen_tso/pandeia_io/__init__.py
index 0227fa3..e242578 100644
--- a/gen_tso/pandeia_io/__init__.py
+++ b/gen_tso/pandeia_io/__init__.py
@@ -2,10 +2,12 @@
 # Gen TSO is open-source software under the GPL-2.0 license (see LICENSE)
 
 from .pandeia_interface import *
+from .pandeia_calculation import *
 from .pandeia_defaults import *
 
 __all__ = (
     pandeia_interface.__all__
+    + pandeia_calculation.__all__
     + pandeia_defaults.__all__
 )
 
diff --git a/gen_tso/pandeia_io/pandeia_calculation.py b/gen_tso/pandeia_io/pandeia_calculation.py
new file mode 100644
index 0000000..35d6c54
--- /dev/null
+++ b/gen_tso/pandeia_io/pandeia_calculation.py
@@ -0,0 +1,787 @@
+# Copyright (c) 2024 Patricio Cubillos
+# Gen TSO is open-source software under the GPL-2.0 license (see LICENSE)
+
+__all__ = [
+    'PandeiaCalculation',
+]
+
+from collections.abc import Iterable
+from itertools import product
+
+import numpy as np
+from pandeia.engine.calc_utils import (
+    build_default_calc,
+    get_instrument_config,
+)
+from pandeia.engine.perform_calculation import perform_calculation
+
+from ..plotly_io.plots import band_boundaries
+from .pandeia_interface import (
+    read_noise_variance,
+    bin_search_exposure_time,
+    saturation_level,
+    make_scene,
+    set_depth_scene,
+    simulate_tso,
+    tso_print,
+)
+from .pandeia_defaults import (
+    generate_all_instruments,
+    filter_throughputs,
+    get_detector,
+)
+detectors = generate_all_instruments()
+throughputs = filter_throughputs()
+
+
+class PandeiaCalculation():
+    """
+    A class to interface with the pandeia.engine package.
+
+    Parameters
+    ----------
+    instrument: string
+        The JWST instrument: nircam, niriss, nirspec, miri.
+    mode: string
+        Observing mode. If not set, default to the first item for
+        each instrument from this list below:
+          instrument   mode          comments
+          ----------   ----          --------
+          nircam:      ssgrism       spectroscopy
+                       target_acq    aquisition
+          niriss:      soss          spectroscopy
+                       target_acq    aquisition
+          nirspec:     bots          spectroscopy
+                       target_acq    aquisition
+          miri:        lrsslitless   spectroscopy
+                       mrs_ts        spectroscopy
+                       target_acq    aquisition
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+
+    >>> pando = jwst.PandeiaCalculation('nircam')
+    >>> pando = jwst.PandeiaCalculation('nirspec')
+    >>> pando = jwst.PandeiaCalculation('nircam', 'target_acq')
+    """
+    def __init__(self, instrument, mode=None):
+        if mode is None:
+            # Default to the most popular spectroscopic mode
+            for detector in detectors:
+                if detector.instrument.lower() == instrument:
+                    mode = detector.mode
+                    break
+        if mode == 'acquisition':
+            mode = 'target_acq'
+
+        self.telescope = 'jwst'
+        self.instrument = instrument
+        self.mode = mode
+        self.calc = build_default_calc(
+            self.telescope, self.instrument, self.mode,
+        )
+        # Set default config for TSO:
+        detector = get_detector(self.instrument, self.mode, detectors)
+        disperser = detector.default_disperser
+        filter = detector.default_filter
+        subarray = detector.default_subarray
+        readout = detector.default_readout
+        if self.mode == 'bots':
+            disperser, filter = filter.split('/')
+
+        if self.mode == 'target_acq':
+            self.calc['configuration']['instrument']['aperture'] = disperser
+        else:
+            self.calc['configuration']['instrument']['disperser'] = disperser
+        self.calc['configuration']['instrument']['filter'] = filter
+        self.calc['configuration']['detector']['subarray'] = subarray
+        self.calc['configuration']['detector']['readout_pattern'] = readout
+        self._ensure_wl_reference_in_range()
+
+
+    def get_configs(self, output=None):
+        """
+        Print out or return the list of available configurations.
+
+        Parameters
+        ----------
+        output: String
+            The configuration variable to list. Select from:
+            readouts, subarrays, filters, or dispersers.
+
+        Returns
+        -------
+            outputs: 1D list of strings
+            The list of available inputs for the requested variable.
+        """
+        ins_config = get_instrument_config(self.telescope, self.instrument)
+        config = ins_config['mode_config'][self.mode]
+
+        screen_output = ''
+        if self.instrument == 'nirspec':
+            gratings_dict = ins_config['config_constraints']['dispersers']
+            gratings = filters = dispersers = []
+            for grating, filter_list in gratings_dict.items():
+                for filter in filter_list['filters']:
+                    gratings.append(f'{grating}/{filter}')
+            screen_output += f'grating/filter pairs: {gratings}\n'
+        else:
+            dispersers = [disperser for disperser in config['dispersers']]
+            filters = config['filters']
+            screen_output += f'dispersers: {dispersers}\n'
+            screen_output += f'filters: {filters}\n'
+
+        subarrays = config['subarrays']
+        screen_output += f'subarrays: {subarrays}\n'
+
+        if self.instrument == 'niriss':
+            readouts = ins_config['readout_patterns']
+        else:
+            readouts = config['readout_patterns']
+        screen_output += f'readout patterns: {readouts}\n'
+
+        if output is None:
+            print(screen_output)
+        elif output == 'readouts':
+            return readouts
+        elif output == 'subarrays':
+            return subarrays
+        elif output == 'filters':
+            return filters
+        elif output == 'dispersers':
+            return dispersers
+        elif self.instrument=='nirspec' and output=='gratings':
+            return gratings
+        else:
+            raise ValueError(f"Invalid config output: '{output}'")
+
+    def wl_ranges(self):
+        """
+        Get wavelength range covered by the instrument/mode
+        """
+        aperture = self.calc['configuration']['instrument']['aperture']
+        disperser = self.calc['configuration']['instrument']['disperser']
+        filter = self.calc['configuration']['instrument']['filter']
+        conf = get_instrument_config('jwst', self.instrument)
+
+        if self.mode == 'bots':
+            subarray = self.calc['configuration']['detector']['subarray']
+            filter = f'{disperser}/{filter}'
+            throughput = throughputs['spectroscopy'][self.instrument][subarray][filter]
+            band_bounds = band_boundaries(throughput, threshold=0.03)
+            bounds = [tuple(np.round(bounds, 3)) for bounds in band_bounds]
+            if len(bounds) == 1:
+                bounds = bounds[0]
+            return bounds
+
+        if self.mode in ['ssgrism', 'target_acq']:
+            config = conf['range'][aperture][filter]
+        elif self.mode in ['lrsslitless', 'mrs_ts']:
+            config = conf['range'][aperture][disperser]
+        elif self.mode == 'soss':
+            order = 1
+            disperser = f'{disperser}_{order}'
+            config = conf['range'][aperture][disperser][filter]
+
+        wl_min = config['wmin']
+        wl_max = config['wmax']
+        return (wl_min, wl_max)
+
+    def _ensure_wl_reference_in_range(self):
+        """
+        Make sure that reference wavelength is in the range of the detector
+        """
+        if self.mode == 'target_acq':
+            return
+        if 'reference_wavelength' not in self.calc['strategy']:
+            self.calc['strategy']['reference_wavelength'] = -1.0
+
+        ref_wl = self.calc['strategy']['reference_wavelength']
+        wl_ranges = self.wl_ranges()
+        if isinstance(wl_ranges, tuple):
+            wl_ranges = [wl_ranges]
+        in_range = np.any([
+            ran[0]<ref_wl and ref_wl<ran[1]
+            for ran in wl_ranges
+        ])
+        if in_range:
+            return
+
+        subarray = self.calc['configuration']['detector']['subarray']
+        if self.mode == 'bots' and subarray != 'sub2048':
+            ref_wl = np.mean(wl_ranges[0])
+        else:
+            ref_wl = 0.5*(np.amax(wl_ranges) + np.amin(wl_ranges))
+        self.calc['strategy']['reference_wavelength'] = np.round(ref_wl, 2)
+
+
+    def set_scene(
+            self, sed_type, sed_model, norm_band, norm_magnitude,
+            background='ecliptic_low',
+        ):
+        """
+        Set the stellar point-source scene to observe.
+
+        Parameters
+        ----------
+        sed_type: String
+            Type of model: 'phoenix', 'k93models', 'blackbody', or 'flat'
+        sed_model:
+            The SED model required for each sed_type:
+            - phoenix or k93models: the model key (see load_sed_list)
+            - blackbody: the effective temperature (K)
+            - flat: the unit ('flam' or 'fnu')
+        norm_band: String
+            Band over which to normalize the spectrum.
+        norm_magnitude: float
+            Magnitude of the star at norm_band.
+        background: String
+            Set the background flux. Select from:
+            'ecliptic_low', 'ecliptic_medium', 'ecliptic_high',
+            'minzodi_low',  'minzodi_medium',  'minzodi_high'
+
+        Examples
+        --------
+        >>> import pandeia_interface as jwst
+
+        >>> instrument = 'nircam'
+        >>> mode = 'ssgrism'
+        >>> pando = jwst.PandeiaCalculation(instrument, mode)
+        >>> pando.set_scene(
+        >>>     sed_type='phoenix', sed_model='k5v',
+        >>>     norm_band='2mass,ks', norm_magnitude=8.637,
+        >>> )
+        """
+        scene = make_scene(sed_type, sed_model, norm_band, norm_magnitude)
+        self.calc['scene'] = [scene]
+        bkg, bkg_level = background.strip().split('_')
+        self.calc['background'] = bkg
+        self.calc['background_level'] = bkg_level
+
+
+    def get_saturation_values(
+            self, disperser, filter, subarray, readout, ngroup=2,
+            aperture=None, order=None, get_max=False,
+        ):
+        """
+        Calculate the brightest-pixel rate (e-/s) and full_well (e-)
+        for the current instrument and scene configuration, which once known,
+        are sufficient to calculate the saturation level once the
+        saturation  time is known.
+
+        Examples
+        --------
+        >>> import gen_tso.pandeia_io as jwst
+
+        >>> instrument = 'nircam'
+        >>> mode = 'ssgrism'
+        >>> pando = jwst.PandeiaCalculation(instrument, mode)
+        >>> pando.set_scene(
+        >>>     sed_type='phoenix', sed_model='k2v',
+        >>>     norm_band='2mass,ks', norm_magnitude=8.351,
+        >>> )
+        >>> brightest_pixel_rate, full_well = pando.get_saturation_values(
+        >>>     disperser='grismr', filter='f444w',
+        >>>     readout='rapid', subarray='subgrism64',
+        >>> )
+
+        >>> # Also works for Target Acquisition:
+        >>> instrument = 'nircam'
+        >>> mode = 'target_acq'
+        >>> pando = jwst.PandeiaCalculation(instrument, mode)
+        >>> pando.set_scene(
+        >>>     sed_type='phoenix', sed_model='k5v',
+        >>>     norm_band='2mass,ks', norm_magnitude=8.351,
+        >>> )
+        >>> brightest_pixel_rate, full_well = pando.get_saturation_values(
+        >>>     disperser=None, filter='f335m',
+        >>>     readout='rapid', subarray='sub32tats', ngroup=3,
+        >>> )
+        """
+        # TBD: Automate here the group setting
+        reports = self.perform_calculation(
+            ngroup=ngroup, nint=1,
+            disperser=disperser, filter=filter,
+            subarray=subarray, readout=readout,
+            aperture=aperture, order=order,
+        )
+        brightest_pixel_rate, full_well = saturation_level(reports, get_max)
+        return brightest_pixel_rate, full_well
+
+
+    def perform_calculation(
+            self, ngroup, nint,
+            disperser=None, filter=None, subarray=None, readout=None,
+            aperture=None, order=None,
+        ):
+        """
+        Run pandeia's perform_calculation() for the given configuration
+        (or set of configurations, see notes below).
+
+        Parameter
+        ----------
+        ngroup: Integer
+            Number of groups per integration.  Must be >= 2.
+        nint: Integer
+            Number of integrations.
+        disperser: String
+            Disperser/grating for the given instrument.
+        filter: String
+            Filter for the given instrument.
+        subarray: String
+            Subarray mode for the given instrument.
+        readout: String
+            Readout pattern mode for the given instrument.
+        aperture: String
+            Aperture configuration for the given instrument.
+        order: Integer
+            For NIRISS SOSS only, the spectral order.
+            Other modes will ignore this argument.
+
+        Returns
+        -------
+        report: dict
+            The Pandeia's report output for the given configuration.
+            If there's more than one requested calculation, return a
+            list of reports.
+
+        Notes
+        -----
+        - Provide a list of values for any of these arguments to
+          compute a batch of calculations.
+        - To leave a config parameter unmodified, leave the respective
+          argument as None.
+          To set a config parameter as None, set the argument to ''.
+        """
+        if not isinstance(nint, Iterable):
+            nint = [nint]
+        if not isinstance(ngroup, Iterable):
+            ngroup = [ngroup]
+        if not isinstance(disperser, Iterable) or isinstance(disperser, str):
+            disperser = [disperser]
+        if not isinstance(filter, Iterable) or isinstance(filter, str):
+            filter = [filter]
+        if not isinstance(subarray, Iterable) or isinstance(subarray, str):
+            subarray = [subarray]
+        if not isinstance(readout, Iterable) or isinstance(readout, str):
+            readout = [readout]
+        if not isinstance(aperture, Iterable) or isinstance(aperture, str):
+            aperture = [aperture]
+        if not isinstance(order, Iterable) or isinstance(order, str):
+            order = [order]
+
+        configs = product(
+            aperture, disperser, filter, subarray, readout, order, nint, ngroup,
+        )
+
+        reports = [
+            self._perform_calculation(config)
+            for config in configs
+        ]
+        if len(reports) == 1:
+            return reports[0]
+        return reports
+
+
+    def _perform_calculation(self, params):
+        """
+        (the real function that) runs pandeia.
+        """
+        # Unpack configuration parameters
+        aperture, disperser, filter, subarray, readout, order, nint, ngroup = params
+        if aperture is not None:
+            self.calc['configuration']['instrument']['aperture'] = aperture
+        if disperser is not None:
+            self.calc['configuration']['instrument']['disperser'] = disperser
+        if readout is not None:
+            self.calc['configuration']['detector']['readout_pattern'] = readout
+        if subarray is not None:
+            self.calc['configuration']['detector']['subarray'] = subarray
+        if order is not None and self.mode == 'soss':
+            self.calc['strategy']['order'] = order
+        if filter == '':
+            self.calc['configuration']['instrument']['filter'] = None
+        elif filter is not None:
+            self.calc['configuration']['instrument']['filter'] = filter
+
+        self.calc['configuration']['detector']['nexp'] = 1 # dither
+        self.calc['configuration']['detector']['nint'] = nint
+        self.calc['configuration']['detector']['ngroup'] = ngroup
+        self._ensure_wl_reference_in_range()
+
+        report = perform_calculation(self.calc)
+        self.report = report
+        return report
+
+    def calc_noise(
+            self, obs_dur=None, ngroup=None,
+            disperser=None, filter=None, subarray=None, readout=None,
+            aperture=None, nint=None,
+        ):
+        """
+        Run a Pandeia calculation and extract the observed wavelength,
+        flux, and variances.
+
+        Parameters
+        ----------
+        obs_dur: Float
+            Duration of the observation.
+        ngroup: Integer
+            Number of groups per integrations
+        disperser: String
+        filter: String
+        subarray: String
+        readout: String
+        aperture: String
+
+        Returns
+        -------
+        TBD
+
+        Examples
+        --------
+        >>> import gen_tso.pandeia_io as jwst
+
+        >>> instrument = 'nircam'
+        >>> mode = 'ssgrism'
+        >>> pando = jwst.PandeiaCalculation(instrument, mode)
+        >>> pando.set_scene(
+        >>>     sed_type='phoenix', sed_model='k5v',
+        >>>     norm_band='2mass,ks', norm_magnitude=8.637,
+        >>> )
+        >>> # Example TBD
+        """
+        if aperture is None:
+            aperture = self.calc['configuration']['instrument']['aperture']
+        if disperser is None:
+            disperser = self.calc['configuration']['instrument']['disperser']
+        if readout is None:
+            readout = self.calc['configuration']['detector']['readout_pattern']
+        if subarray is None:
+            subarray = self.calc['configuration']['detector']['subarray']
+        if filter is None:
+            filter = self.calc['configuration']['instrument']['filter']
+
+        if ngroup is None:
+            raise TypeError("Missing required argument: 'ngroup'")
+        # Check timing inputs are properly defined:
+        if obs_dur is None and nint is None:
+            raise ValueError(
+                'Neither of obs_dur nor nint were provided'
+            )
+        if obs_dur is not None and nint is not None:
+            raise ValueError(
+                'Either provide obs_dur or nint, but not both'
+            )
+        if obs_dur is not None:
+            nint, _ = bin_search_exposure_time(
+                self.instrument, subarray, readout, ngroup, obs_dur,
+            )
+        if nint == 0:
+            nint = 1
+            # TBD: and raise a warning
+
+        report = self.perform_calculation(
+            ngroup, nint, disperser, filter, subarray, readout, aperture,
+        )
+
+        # Flux:
+        measurement_time = report['scalar']['measurement_time']
+        flux = report['1d']['extracted_flux'][1] * measurement_time
+        wl = report['1d']['extracted_flux'][0]
+
+        # Background variance:
+        background_var = report['1d']['extracted_bg_only'][1] * measurement_time
+        # Read noise variance:
+        ins_config = get_instrument_config(self.telescope, self.instrument)
+        read_noise = read_noise_variance(report, ins_config)
+        npix = report['scalar']['extraction_area']
+        read_noise_var = 2.0 * read_noise**2.0 * nint * npix
+        # Pandeia (multiaccum) noise:
+        shot_var = (report['1d']['extracted_noise'][1] * measurement_time)**2.0
+        # Last-minus-first (LMF) noise:
+        lmf_var = np.abs(flux) + background_var + read_noise_var
+
+        variances = lmf_var, shot_var, background_var, read_noise_var
+
+        return report, wl, flux, variances, measurement_time
+
+
+    def tso_calculation(
+            self, obs_type, transit_dur, obs_dur, depth_model,
+            ngroup=None, disperser=None, filter=None,
+            subarray=None, readout=None, aperture=None, order=None,
+        ):
+        """
+        Run pandeia to simulate a transit/eclipse time-series observation
+
+        Parameters
+        ----------
+        obs_type: String
+            The observing geometry 'transit' or 'eclipse'.
+        transit_dur: Float
+            Duration of the transit or eclipse event in hours.
+        obs_dur: Float
+            Total duration of the observation (baseline plus transit
+            or eclipse event) in hours.
+        depth_model: list of two 1D array or a 2D array
+            The transit or eclipse depth spectrum where the first item is
+            the wavelength (um) and the second is the depth.
+        ngroup: Integer
+            Number of groups per integrations
+        disperser: String
+        filter: String
+        subarray: String
+        readout: String
+        aperture: String
+        order: String
+
+        Returns
+        -------
+        tso: dict
+            A dictionary containing the time-series observation data:
+            - wl: instrumental wavelength sampling (microns)
+            - depth_spectrum: Transit/eclipse depth spectrum at instrumental wl
+            - time_in: In-transit/eclipse measuring time (seconds)
+            - flux_in: In-transit/eclipse flux (e-)
+            - var_in:  In-transit/eclipse variance
+            - time_out: Out-of-transit/eclipse measuring time (seconds)
+            - flux_out: Out-of-transit/eclipse flux (e-)
+            - var_out:  Out-of-transit/eclipse
+            - report_in:  In-transit/eclipse pandeia output report
+            - report_out:  Out-of-transit/eclipse pandeia output report
+
+        Examples
+        --------
+        >>> import pandeia_interface as jwst
+        >>> from pandeia_interface import set_depth_scene
+
+        >>> # Set the stellar scene and transit:
+        >>> scene = jwst.make_scene(
+        >>>     sed_type='phoenix', sed_model='k5v',
+        >>>     norm_band='2mass,ks', norm_magnitude=8.637,
+        >>> )
+        >>> transit_dur = 2.753
+        >>> obs_dur = 7.1
+        >>> obs_type = 'transit'
+        >>> depth_model = np.loadtxt(
+        >>>     '../planet_spectra/WASP80b_transit.dat', unpack=True)
+
+        >>> # Set a NIRSpec observation
+        >>> pando = jwst.PandeiaCalculation('nirspec', 'bots')
+        >>> pando.calc['scene'] = [scene]
+        >>> disperser = 'g395h'
+        >>> filter = 'f290lp'
+        >>> readout = 'nrsrapid'
+        >>> subarray = 'sub2048'
+        >>> ngroup = 16
+
+        >>> tso = pando.tso_calculation(
+        >>>     obs_type, transit_dur, obs_dur, depth_model,
+        >>>     ngroup, disperser, filter, subarray, readout,
+        >>> )
+
+        >>> # Fluxes and Flux rates
+        >>> col1, col2 = plt.cm.viridis(0.8), plt.cm.viridis(0.25)
+        >>> plt.figure(0, (8.5, 4))
+        >>> plt.clf()
+        >>> plt.subplot(121)
+        >>> plt.plot(tso['wl'], tso['flux_out'], c=col2, label='out of transit')
+        >>> plt.plot(tso['wl'], tso['flux_in'], c=col1, label='in transit')
+        >>> plt.legend(loc='best')
+        >>> plt.xlabel('Wavelength (um)')
+        >>> plt.ylabel('Collected flux (e-)')
+        >>> plt.subplot(122)
+        >>> plt.plot(tso['wl'], tso['flux_out']/tso['time_out'], c=col2, label='out of transit')
+        >>> plt.plot(tso['wl'], tso['flux_in']/tso['time_in'], c=col1, label='in transit')
+        >>> plt.legend(loc='best')
+        >>> plt.xlabel('Wavelength (um)')
+        >>> plt.ylabel('Flux rate (e-/s)')
+        >>> plt.tight_layout()
+
+        >>> # Model and instrument-observed transit depth spectrum
+        >>> wl_depth, depth = depth_model
+        >>> plt.figure(4)
+        >>> plt.clf()
+        >>> plt.plot(wl_depth, 100*depth, c='orange', label='model depth')
+        >>> plt.plot(tso['wl'], 100*tso['depth_spectrum'], c='b', label='obs depth')
+        >>> plt.legend(loc='best')
+        >>> plt.xlim(2.75, 5.25)
+        >>> plt.xlabel('Wavelength (um)')
+        >>> plt.ylabel('Transit depth (%)')
+        """
+        if transit_dur >= obs_dur:
+            raise ValueError(
+                f'{obs_type} duration is longer than the observation duration'
+            )
+        # Scale in or out transit flux rates
+        scene = self.calc['scene'][0]
+        star_scene, depth_scene = set_depth_scene(scene, obs_type, depth_model)
+        if obs_type == 'eclipse':
+            scene_in = star_scene
+            scene_out = depth_scene
+        elif obs_type == 'transit':
+            scene_in = depth_scene
+            scene_out = star_scene
+
+        if not isinstance(ngroup, Iterable):
+            ngroup = [ngroup]
+        if not isinstance(disperser, Iterable) or isinstance(disperser, str):
+            disperser = [disperser]
+        if not isinstance(filter, Iterable) or isinstance(filter, str):
+            filter = [filter]
+        if not isinstance(subarray, Iterable) or isinstance(subarray, str):
+            subarray = [subarray]
+        if not isinstance(readout, Iterable) or isinstance(readout, str):
+            readout = [readout]
+        if not isinstance(aperture, Iterable) or isinstance(aperture, str):
+            aperture = [aperture]
+        if not isinstance(order, Iterable) or isinstance(order, str):
+            order = [order]
+
+        configs = product(
+            aperture, disperser, filter, subarray, readout, order, ngroup,
+        )
+        tso = [
+            self._tso_calculation(
+                config, scene_in, scene_out, transit_dur, obs_dur,
+            )
+            for config in configs
+        ]
+        if len(tso) == 1:
+             tso = tso[0]
+        self.tso = tso
+        # Return scene to its previous state
+        self.calc['scene'][0] = scene
+        return tso
+
+
+    def _tso_calculation(
+            self, config, scene_in, scene_out, transit_dur, obs_dur,
+        ):
+        """
+        (the real function that) runs a TSO calculation.
+        """
+        aperture, disperser, filter, subarray, readout, order, ngroup = config
+        if aperture is not None:
+            self.calc['configuration']['instrument']['aperture'] = aperture
+        if disperser is not None:
+            self.calc['configuration']['instrument']['disperser'] = disperser
+        if readout is not None:
+            self.calc['configuration']['detector']['readout_pattern'] = readout
+        if subarray is not None:
+            self.calc['configuration']['detector']['subarray'] = subarray
+        if order is not None and self.mode == 'soss':
+            self.calc['strategy']['order'] = order
+        if filter == '':
+            self.calc['configuration']['instrument']['filter'] = None
+        elif filter is not None:
+            self.calc['configuration']['instrument']['filter'] = filter
+
+        # Now that everything is defined I can turn durations into integs:
+        inst = self.instrument
+        subarray = self.calc['configuration']['detector']['subarray']
+        readout = self.calc['configuration']['detector']['readout_pattern']
+        if transit_dur is not None:
+            transit_integs, _ = bin_search_exposure_time(
+                inst, subarray, readout, ngroup, transit_dur,
+            )
+        if obs_dur is not None:
+            obs_integs, _ = bin_search_exposure_time(
+                inst, subarray, readout, ngroup, obs_dur,
+            )
+        if obs_integs <= transit_integs:
+            raise ValueError(
+                "Number of integrations for the total observation duration "
+                "is <= in-transit integrations"
+            )
+
+        # Compute observed fluxes and noises:
+        self.calc['scene'][0] = scene_in
+        report_in, wl, flux_in, variances_in, time_in = self.calc_noise(
+            nint=transit_integs, ngroup=ngroup,
+        )
+        var_lmf_in = variances_in[0]
+
+        out_transit_integs = obs_integs - transit_integs
+        self.calc['scene'][0] = scene_out
+        report_out, wl, flux_out, variances_out, time_out = self.calc_noise(
+            nint=out_transit_integs, ngroup=ngroup,
+        )
+        var_lmf_out = variances_out[0]
+
+        # Mask out un-illumnated wavelengths (looking at you, G395H)
+        mask = flux_in > 1e-6 * np.median(flux_in)
+        wl = wl[mask]
+        flux_in = flux_in[mask]
+        flux_out = flux_out[mask]
+        var_in = var_lmf_in[mask]
+        var_out = var_lmf_out[mask]
+        obs_depth = 1 - (flux_in/time_in) / (flux_out/time_out)
+
+        tso = {
+            'wl': wl,
+            'depth_spectrum': obs_depth,
+            'time_in': time_in,
+            'flux_in': flux_in,
+            'var_in': var_in,
+            'time_out': time_out,
+            'flux_out': flux_out,
+            'var_out': var_out,
+            'report_in': report_in,
+            'report_out': report_out,
+        }
+        return tso
+
+
+    def tso_print(self, format='rich'):
+        """
+        Print to screen a summary of the latest tso_calculation() ran.
+
+        Parameters
+        ----------
+        format: String
+            If 'rich' print with colourful text when there are warnings
+            or errors in values.
+            If None, print as plain text.
+
+        Examples
+        --------
+        >>> import gen_tso.pandeia_io as jwst
+        >>> import numpy as np
+
+        >>> wl = np.logspace(0, 2, 1000)
+        >>> depth = [wl, np.tile(0.03, len(wl))]
+        >>> pando = jwst.PandeiaCalculation('nircam', 'ssgrism')
+        >>> pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+        >>> tso = pando.tso_calculation(
+        >>>     'transit', transit_dur=2.1, obs_dur=6.0, depth_model=depth,
+        >>>     ngroup=130, readout='rapid', filter='f444w',
+        >>> )
+        >>> pando.tso_print()
+        """
+        tso_print(self.tso, format)
+
+
+    def simulate_tso(
+            self, n_obs=1, resolution=None, bins=None, noiseless=False,
+        ):
+        """
+        Simulate a time-series observation spectrum with noise
+        for the given number of observations and spectral sampling.
+
+        Parameters
+        ----------
+        TBD
+
+        Returns
+        -------
+        TBD
+
+        Examples
+        --------
+        >>> TBD
+        """
+        return simulate_tso(self.tso, n_obs, resolution, bins, noiseless)
+
diff --git a/gen_tso/pandeia_io/pandeia_defaults.py b/gen_tso/pandeia_io/pandeia_defaults.py
index 9a7ef34..53d03fb 100644
--- a/gen_tso/pandeia_io/pandeia_defaults.py
+++ b/gen_tso/pandeia_io/pandeia_defaults.py
@@ -6,8 +6,6 @@
     'filter_throughputs',
     'generate_all_instruments',
     'Detector',
-    'detector_label',
-    'instrument_label',
 ]
 
 from itertools import product
@@ -136,8 +134,8 @@ def get_configs(instrument=None, obs_type=None):
     ta_apertures = {
         'miri': ['imager'],
         'nircam': ['lw'],
-        'nirspec': ['s1600a1'],
         'niriss': ['imager', 'nrm'],
+        'nirspec': ['s1600a1'],
     }
     if instrument is None:
         instrument = 'miri nircam nirspec niriss'.split()
@@ -233,6 +231,15 @@ def get_configs(instrument=None, obs_type=None):
             for slit in slits
         }
 
+        if inst_dict['mode'] == 'soss':
+            inst_dict['orders'] = {
+                '1': '1',
+                '2': '2',
+                '1 2': '1 and 2',
+            }
+        else:
+            inst_dict['orders'] = None
+
         if obs_type == 'acquisition':
             groups = inst_config['mode_config'][mode]['enum_ngroups']
             if not isinstance(groups, list):
@@ -242,6 +249,7 @@ def get_configs(instrument=None, obs_type=None):
             #print(inst_config['mode_config'][mode]['enum_nexps'])
             #print(inst_config['mode_config'][mode]['enum_nints'])
 
+
         # Special constraints
         inst_dict['constraints'] = {}
         if mode == 'bots':
@@ -259,6 +267,14 @@ def get_configs(instrument=None, obs_type=None):
                 constraints[disperser] = subs
             inst_dict['constraints']['subarrays'] = {'dispersers': constraints}
 
+        if mode == 'soss':
+            constraints = {
+                'substrip96': ['1'],
+                'substrip256': ['1', '2', '1 2'],
+                'sossfull': ['1', '2', '1 2'],
+            }
+            inst_dict['constraints']['orders'] = {'subarrays': constraints}
+
         if inst_dict['instrument']=='MIRI' and mode=='target_acq':
             group_constraints = inst_config['mode_config'][mode]['enum_ngroups']
             constraints = {}
@@ -349,7 +365,7 @@ class Detector:
     def __init__(
             self, mode, label, instrument, obs_type,
             disperser_label, dispersers, filter_label, filters,
-            subarrays, readouts, apertures,
+            subarrays, readouts, apertures, orders=None,
             groups=None, default_indices=None,
             constraints={},
         ):
@@ -378,6 +394,8 @@ def __init__(
         self.apertures = apertures
         self.groups = groups
         self.constraints = constraints
+        if self.mode == 'soss':
+            self.orders = orders
 
         telescope = 'jwst'
         self.ins_config = get_instrument_config(telescope, instrument.lower())
@@ -398,7 +416,7 @@ def get_constrained_val(
         ):
         """
         det = generate_all_instruments()[5]
-        get_constrained_val(det, 'filters', disperser='nrm')
+        det.get_constrained_val('filters', disperser='nrm')
         get_constrained_val(det, 'readouts', disperser='nrm')
         get_constrained_val(det, 'readouts', disperser='imager')
         get_constrained_val(det, 'readouts', filter='imager')
@@ -435,7 +453,38 @@ def get_constrained_val(
                 }
         return default_vals
 
-
+    def instrument_label(self, disperser, filter):
+        """
+        Generate a pretty label with only instrument, mode,
+        and sometimes disperser or filter.
+
+        Examples
+        --------
+        >>> import gen_tso.pandeia_io as jwst
+        >>> detectors = jwst.generate_all_instruments()
+        >>> bots = detectors[4]
+        >>> print(bots.instrument_label(None, 'g395h/f290lp'))
+        """
+        inst = self.instrument
+        mode = self.mode
+        if mode == 'mrs_ts':
+            disperser_label = self.dispersers[disperser]
+            label = f'{inst} / MRS / {disperser_label}'
+        elif mode == 'lrsslitless':
+            label = f'{inst} / LRS'
+        elif mode == 'soss':
+            label = f'{inst} / SOSS'
+        elif mode == 'ssgrism':
+            filter_label = self.filters[filter]
+            label = f'{inst} / {filter_label}'
+        elif mode == 'bots':
+            disperser_label = self.filters[filter]
+            disperser_label = disperser_label[:disperser_label.index('/')]
+            label = f'{inst} / {disperser_label}'
+        elif mode == 'target_acq':
+            label = f'{inst} / acquisition'
+
+        return label
 
 
 def filter_throughputs():
@@ -494,6 +543,7 @@ def generate_all_instruments():
         subarrays = inst['subarrays']
         readouts = inst['readouts']
         apertures = inst['apertures']
+        orders = inst['orders']
         constraints = inst['constraints']
 
         if mode == 'lrsslitless':
@@ -542,11 +592,55 @@ def generate_all_instruments():
             subarrays,
             readouts,
             apertures,
+            orders=orders,
             default_indices=default_indices,
             constraints=constraints,
         )
         detectors.append(det)
 
+    # Photometry observing modes
+    photo_insts = get_configs(obs_type='photometry')
+    # TBD: enable when the front-end app is ready to take these in
+    if False:
+        for inst in photo_insts:
+            mode = inst['mode']
+            # Use pupil in place of 'disperser'
+            dispersers = inst['apertures']
+            filters = inst['filters']
+            subarrays = inst['subarrays']
+            readouts = inst['readouts']
+            apertures = inst['apertures']
+
+            disperser_label = 'Pupil'
+            filter_label = 'Filter'
+            default_indices = 0, 0, 0, 0
+            constraints = {}
+
+            if mode == 'lw_ts':
+                # Constraints for filter depends on pupil
+                pupil_constraints = {'lw': []}
+                for filter,filter_name in inst['filters'].items():
+                    if filter in inst['filter_constraints']:
+                        dispersers[filter] = filter_name
+                        pupil_constraints[filter] = [inst['filter_constraints'][filter]]
+                    else:
+                        pupil_constraints['lw'].append(filter)
+                constraints['filters'] = {'dispersers': pupil_constraints}
+            if mode == 'sw_ts':
+                # Constraints for filter depends on pupil
+                pupil_constraints = {'sw': []}
+                for filter,filter_name in inst['filters'].items():
+                    print(filter, filter_name)
+                    if filter in inst['filter_constraints']:
+                        dispersers[filter] = filter_name
+                        pupil_constraints[filter] = [inst['filter_constraints'][filter]]
+                    else:
+                        pupil_constraints['sw'].append(filter)
+                constraints['filters'] = {'dispersers': pupil_constraints}
+            if mode == 'imaging_ts':
+                disperser_label = ''
+                dispersers = {'':''}
+
     # Acquisition observing modes
     acq_insts = get_configs(obs_type='acquisition')
     for inst in acq_insts:
@@ -585,29 +679,64 @@ def generate_all_instruments():
             subarrays,
             readouts,
             apertures,
-            inst['groups'],
-            default_indices,
-            constraints,
+            groups=inst['groups'],
+            default_indices=default_indices,
+            constraints=constraints,
         )
         detectors.append(det)
 
-
     return detectors
 
 
-def detector_label(inst, mode, disperser, filter, subarray, readout):
+def get_detector(instrument=None, mode=None, detectors=None):
+    """
+    Find the detector matching instrument and mode.
+    """
+    if detectors is None:
+        detectors = generate_all_instruments()
+
+    if instrument is None and mode is None:
+        return None
+
+    if mode is None:
+        # Default to first detector for instrument (spectroscopic mode)
+        for detector in detectors:
+            if detector.instrument.lower() == instrument.lower():
+                return detector
+
+    for det in detectors:
+        if det.mode == mode:
+            if instrument is None or det.instrument.lower()==instrument.lower():
+                return det
+    return None
+
+
+def make_detector_label(
+        inst, mode, aperture, disperser, filter, subarray, readout, order,
+    ):
     """
     Generate a pretty and (as succinct as possible) label for the
     detector configuration.
     """
     if mode == 'target_acq':
-        return inst_names[inst]
+        if inst == 'miri':
+            label = f'{filter.upper()} {subarray.upper()}'
+        if inst == 'nircam':
+            label = f'{filter.upper()} {readout.upper()}'
+        if inst == 'niriss':
+            label = 'Bright' if aperture == 'nrm' else 'Faint'
+            label = f'{label} {readout.upper()}'
+        if inst == 'nirspec':
+            label = f'{filter.upper()} {subarray.upper()} {readout.upper()}'
+        return f'{inst_names[inst]} {label}'
+
     if mode == 'mrs_ts':
-        return 'MIRI MRS'
+        return f'MIRI MRS {disperser.upper()}'
     if mode == 'lrsslitless':
         return 'MIRI LRS'
     if mode == 'soss':
-        return f'NIRISS {mode.upper()} {subarray}'
+        order = f' O{order[0]}' if len(order)==1 else ''
+        return f'NIRISS {mode.upper()} {subarray}{order}'
     if mode == 'ssgrism':
         subarray = subarray.replace('grism', '')
         return f'NIRCam {filter.upper()} {subarray} {readout}'
@@ -617,29 +746,42 @@ def detector_label(inst, mode, disperser, filter, subarray, readout):
         return f'NIRSpec {disperser.upper()} {subarray} {readout}'
 
 
-def instrument_label(detector, disperser, filter):
+def make_saturation_label(
+        inst, mode, aperture, disperser, filter, subarray, order, sed_label,
+    ):
     """
-    Generate a pretty label with only instrument, mode,
-    and sometimes disperser or filter.
+    Make a label of unique saturation setups to identify when and
+    when not the saturation level can be estimated.
     """
-    inst = detector.instrument
-    mode = detector.mode
-    if mode == 'mrs_ts':
-        disperser_label = detector.dispersers[disperser]
-        label = f'{inst} / MRS / {disperser_label}'
-    if mode == 'lrsslitless':
-        label = f'{inst} / LRS'
-    if mode == 'soss':
-        label = f'{inst} / SOSS'
-    if mode == 'ssgrism':
-        filter_label = detector.filters[filter]
-        label = f'{inst} / {filter_label}'
-    elif mode == 'bots':
-        disperser_label = detector.filters[filter]
-        disperser_label = disperser_label[:disperser_label.index('/')]
-        label = f'{inst} / {disperser_label}'
-    elif mode == 'target_acq':
-        label = f'{inst} / acquisition'
-
+    sat_label = f'{mode}_{filter}'
+    if mode == 'bots':
+        sat_label = f'{sat_label}_{disperser}_{subarray}'
+    elif mode == 'soss':
+        order = f'_O{order[0]}' if len(order)==1 else ''
+        sat_label = f'{sat_label}_{sed_label}{order}'
+    elif mode == 'mrs_ts':
+        sat_label = f'{sat_label}_{disperser}'
+    elif mode == 'target_acq' and inst == 'niriss':
+        sat_label = f'{sat_label}_{aperture}'
+
+    sat_label = f'{sat_label}_{sed_label}'
+    return sat_label
+
+
+def make_obs_label(
+        inst, mode, aperture, disperser, filter, subarray, readout, order,
+        ngroup, nint, run_type, sed_label, depth_label,
+    ):
+    detector_label = make_detector_label(
+        inst, mode, aperture, disperser, filter, subarray, readout, order,
+    )
+    if run_type == 'Acquisition':
+        group_ints = f'({ngroup} G)'
+        depth_label = 'acquisition'
+    else:
+        group_ints = f'({ngroup} G, {nint} I)'
+    label = (
+        f'{detector_label} {group_ints} / {sed_label} / {depth_label}'
+    )
     return label
 
diff --git a/gen_tso/pandeia_io/pandeia_interface.py b/gen_tso/pandeia_io/pandeia_interface.py
index efd2c20..c0bf37d 100644
--- a/gen_tso/pandeia_io/pandeia_interface.py
+++ b/gen_tso/pandeia_io/pandeia_interface.py
@@ -4,19 +4,23 @@
 __all__ = [
     'read_noise_variance',
     'exposure_time',
-    'saturation_time',
+    'bin_search_exposure_time',
+    'integration_time',
+    'saturation_level',
     'load_sed_list',
     'find_closest_sed',
     'extract_sed',
     'make_scene',
     'set_depth_scene',
     'simulate_tso',
-    'PandeiaCalculation',
+    '_print_pandeia_exposure',
+    '_print_pandeia_saturation',
+    '_print_pandeia_stats',
+    '_print_pandeia_report',
+    'tso_print',
 ]
 
-from collections.abc import Iterable
 import copy
-from itertools import product
 import json
 import os
 import random
@@ -25,15 +29,12 @@
 import requests
 import scipy.interpolate as si
 import pandeia.engine.sed as sed
-from pandeia.engine.calc_utils import (
-    build_default_calc,
-    get_instrument_config,
-)
-from pandeia.engine.perform_calculation import perform_calculation
+from pandeia.engine.calc_utils import get_instrument_config
 from pandeia.engine.normalization import NormalizationFactory
+import prompt_toolkit
 from synphot.config import conf, Conf
 
-from ..utils import constant_resolution_spectrum
+from ..utils import constant_resolution_spectrum, format_text
 
 
 def check_pandeia_version():
@@ -97,13 +98,10 @@ def read_noise_variance(report, ins_config):
     return read_noise
 
 
-def exposure_time(
-        instrument, subarray, readout,
-        ngroup=None, nint=None, nexp=1,
-    ):
+def _exposure_time_function(instrument, subarray, readout, ngroup, nexp=1):
     """
-    Calculate the exposure time for the given instrumental setup.
-    Based on pandeia.engine.exposure.
+    Return a callable that evaluates the exposure time as a function
+    of nint.
 
     Parameters
     ----------
@@ -115,8 +113,6 @@ def exposure_time(
         Readout pattern mode for the given instrument.
     ngroup: Integeer
         Number of groups per integration.  Must be >= 2.
-    nint: Integer
-        Number of integrations.
     nexp: Integer
         Number of exposures.
 
@@ -125,18 +121,6 @@ def exposure_time(
     exp_time: Float
         Exposure time in seconds.
 
-    Examples
-    --------
-    >>> import gen_tso.pandeia_io as jwst
-
-    >>> inst = 'nircam'
-    >>> subarray = 'subgrism64'
-    >>> subarray = 'full'
-    >>> readout = 'rapid'
-    >>> nint = 1
-    >>> ngroup = 20
-    >>> exp_time = jwst.exposure_time(inst, subarray, readout, ngroup, nint)
-    >>> print(exp_time)
     """
     if isinstance(instrument, str):
         telescope = 'jwst'
@@ -146,9 +130,9 @@ def exposure_time(
 
     # When switching instrument, subarray and readout updates are not atomic
     if subarray not in ins_config['subarray_config']['default']:
-        return 0.0
+        return None
     if readout not in ins_config['readout_pattern_config']:
-        return 0.0
+        return None
 
     subarray_config = ins_config['subarray_config']['default'][subarray]
     readout_config = ins_config['readout_pattern_config'][readout]
@@ -165,20 +149,151 @@ def exposure_time(
     if 'nreset2' in readout_config:
         nreset2 = readout_config['nreset2']
 
-    exposure_time = nexp * (
-        tfffr * nint +
-        tframe * (
-            nreset1 + (nint-1) * nreset2 +
-            nint * (ndrop1 + (ngroup-1) * (nframe + ndrop2) + nframe + ndrop3)
+    def exp_time(nint):
+        time = nexp * (
+            tfffr * nint +
+            tframe * (
+                nreset1 + (nint-1) * nreset2 +
+                nint * (ndrop1 + (ngroup-1) * (nframe + ndrop2) + nframe + ndrop3)
+            )
         )
+        return time
+    return exp_time
+
+
+def exposure_time(instrument, subarray, readout, ngroup, nint, nexp=1):
+    """
+    Calculate the exposure time for the given instrumental setup.
+    Based on pandeia.engine.exposure.
+
+    Parameters
+    ----------
+    instrument: String
+        Which instruments (miri, nircam, niriss, or nirspec).
+    subarray: String
+        Subarray mode for the given instrument.
+    readout: String
+        Readout pattern mode for the given instrument.
+    ngroup: Integeer
+        Number of groups per integration.  Must be >= 2.
+    nint: Integer
+        Number of integrations.
+    nexp: Integer
+        Number of exposures.
+
+    Returns
+    -------
+    exp_time: Float
+        Exposure time in seconds.
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+
+    >>> inst = 'nircam'
+    >>> subarray = 'subgrism64'
+    >>> readout = 'rapid'
+    >>> nint = 1
+    >>> ngroup = 90
+    >>> exp_time = jwst.exposure_time(inst, subarray, readout, ngroup, nint)
+    >>> print(exp_time)
+    """
+    exp_time = _exposure_time_function(
+        instrument, subarray, readout, ngroup, nexp,
     )
-    return exposure_time
+    if exp_time is None:
+        return 0.0
+    return exp_time(nint)
 
 
-def saturation_time(instrument, ngroup=None, readout=None, subarray=None):
+def bin_search_exposure_time(
+        instrument, subarray, readout, ngroup, obs_time, nexp=1,
+    ):
     """
-    Compute JWST's saturation time for the given instrument configuration.
+    Binary search for nint such that exp_time(nint) > obs_time
+
+    Parameters
+    ----------
+    instrument: String
+        Which instruments (miri, nircam, niriss, or nirspec).
+    subarray: String
+        Subarray mode for the given instrument.
+    readout: String
+        Readout pattern mode for the given instrument.
+    ngroup: Integeer
+        Number of groups per integration.  Must be >= 2.
+    obs_time: Integer
+        Total observation time to aim for (in hours).
+    nexp: Integer
+        Number of exposures.
+
+    Returns
+    -------
+    nint: Integer
+        Number of integrations to reach obs_time.
+    exp_time: Float
+        Exposure time in seconds.
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+
+    >>> instrument = 'miri'
+    >>> subarray = 'slitlessprism'
+    >>> readout = 'fastr1'
+    >>> ngroup = 30
+    >>> obs_time = 6.0
+    >>> nint, exp_time = jwst.bin_search_exposure_time(
+    >>>     instrument, subarray, readout, ngroup, obs_time,
+    >>> )
+    >>> print(nint, exp_time)
+    """
+    exp_time = _exposure_time_function(
+        instrument, subarray, readout, ngroup, nexp,
+    )
+    if exp_time is None:
+        return 0, 0.0
+
+    obs_time_sec = 3600 * obs_time
+    n1 = 1
+    t1 = exp_time(n1)
+    if obs_time_sec < t1:
+        return n1, t1
+
+    n2 = int(obs_time_sec / t1)
+    t2 = exp_time(n2)
+    while t2 < obs_time_sec:
+        n1 = n2
+        n2 = n1*2
+        t2 = exp_time(n2)
+    while n2-n1 > 1:
+        n = int(0.5*(n1+n2))
+        t = exp_time(n)
+        if obs_time_sec > t:
+            n1 = n
+        else:
+            n2 = n
+
+    return n2, exp_time(n2)
+
+
+def integration_time(instrument, subarray, readout, ngroup):
+    """
+    Compute JWST's integration time for a given instrument configuration.
     Based on pandeia.engine.exposure.
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+
+    >>> # Calculate integration time for a given instrument setup:
+    >>> inst = 'nircam'
+    >>> ngroup = 90
+    >>> readout = 'rapid'
+    >>> subarray = 'subgrism64'
+    >>> integ_time = jwst.integration_time(inst, subarray, readout, ngroup)
+    >>> print(integ_time)
+    30.6549
     """
     if isinstance(instrument, str):
         telescope = 'jwst'
@@ -197,10 +312,84 @@ def saturation_time(instrument, ngroup=None, readout=None, subarray=None):
     ndrop2 = ins_config['readout_pattern_config'][readout]['ndrop2']
     ndrop1 = 0
 
-    saturation_time = tframe * (
+    integration_time = tframe * (
         ndrop1 + (ngroup - 1) * (nframe + ndrop2) + nframe
     )
-    return saturation_time
+    return integration_time
+
+
+def saturation_level(reports, get_max=False):
+    """
+    Compute saturation values for a given perform_calculation output.
+
+    Parameters
+    ----------
+    reports: Dictionary or list of dictionaries
+        One or more pandeia's perform_calculation() output dictionary
+        or a tso_calculation output dictionary.
+        If there is more than one input report, return arrays of
+        saturation values for each input.
+    get_max: Bool
+        If True and there is  more than one input report, return the
+        saturation values for the report that's quickest to saturate.
+
+    Returns
+    -------
+    brightest_pixel_rate: Float
+        e- per second rate at the brightest pixel.
+    full_well: Float
+        Number of e- counts to saturate the detector.
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+
+    >>> inst = 'nircam'
+    >>> readout = 'rapid'
+    >>> pando = jwst.PandeiaCalculation(inst, 'ssgrism')
+    >>> pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    >>> result = pando.perform_calculation(
+    >>>     ngroup=2, nint=683, readout='rapid', filter='f444w',
+    >>> )
+    >>> pixel_rate, full_well = jwst.saturation_level(result)
+
+    >>> # Now I can calculate the saturation level for any integration time:
+    >>> # (for the given filter and scene)
+    >>> subarray = 'subgrism64'
+    >>> for ngroup in [2, 97, 122]:
+    >>>     integ_time = jwst.integration_time(inst, subarray, readout, ngroup)
+    >>>     sat_level = pixel_rate * integ_time / full_well * 100
+    >>>     print(f'Sat. fraction for {ngroup:3d} groups: {sat_level:5.1f}%')
+    Sat. fraction for   2 groups:   1.6%
+    Sat. fraction for  97 groups:  79.4%
+    Sat. fraction for 122 groups:  99.9%
+    """
+    if not isinstance(reports, list):
+        reports = [reports]
+    # Unpack TSO dictionary
+    if 'report_in' in reports[0]:
+        reports = (
+            [report['report_in'] for report in reports] +
+            [report['report_out'] for report in reports]
+        )
+
+    ncalc = len(reports)
+    brightest_pixel_rate = np.zeros(ncalc)
+    full_well = np.zeros(ncalc)
+    for i,report in enumerate(reports):
+        brightest_pixel_rate[i] = report['scalar']['brightest_pixel']
+        full_well[i] = (
+            brightest_pixel_rate[i]
+            * report['scalar']['saturation_time']
+            / report['scalar']['fraction_saturation']
+        )
+
+    if len(reports) == 1:
+        return brightest_pixel_rate[0], full_well[0]
+    if get_max:
+        idx = np.argmax(brightest_pixel_rate*full_well)
+        return brightest_pixel_rate[idx], full_well[idx]
+    return brightest_pixel_rate, full_well
 
 
 def load_sed_list(source):
@@ -671,567 +860,435 @@ def simulate_tso(
     return bin_wl[mask], bin_spec[mask], bin_err[mask], bin_widths[mask]
 
 
-class PandeiaCalculation():
-    def __init__(self, instrument, mode):
-        self.telescope = 'jwst'
-        self.instrument = instrument
-        self.mode = mode
-        self.calc = build_default_calc(
-            self.telescope, self.instrument, self.mode,
-        )
+def _print_pandeia_exposure(
+        inst=None, subarray=None, readout=None, ngroup=None, nint=None,
+        config=None, format=None,
+    ):
+    """
+    Return a text showing the total exposure time in seconds and hours.
+    Either config or the set of inst, subarray, readout, ngroup, and nint
+    values must be defined.
 
-    def get_configs(self, output=None):
-        """
-        Print out or return the list of available configurations.
-
-        Parameters
-        ----------
-        output: String
-            The configuration variable to list. Select from:
-            readouts, subarrays, filters, or dispersers.
-
-        Returns
-        -------
-            outputs: 1D list of strings
-            The list of available inputs for the requested variable.
-        """
-        ins_config = get_instrument_config(self.telescope, self.instrument)
-        config = ins_config['mode_config'][self.mode]
-
-        subarrays = config['subarrays']
-        screen_output = f'subarrays: {subarrays}\n'
-
-        if self.instrument == 'niriss':
-            readouts = ins_config['readout_patterns']
-        else:
-            readouts = config['readout_patterns']
-        screen_output += f'readout patterns: {readouts}\n'
-
-        if self.instrument == 'nirspec':
-            gratings_dict = ins_config['config_constraints']['dispersers']
-            gratings = filters = dispersers = []
-            for grating, filter_list in gratings_dict.items():
-                for filter in filter_list['filters']:
-                    gratings.append(f'{grating}/{filter}')
-            screen_output += f'grating/filter pairs: {gratings}'
-        else:
-            filters = config['filters']
-            dispersers = [disperser for disperser in config['dispersers']]
-            screen_output += f'dispersers: {dispersers}\n'
-            screen_output += f'filters: {filters}'
-
-        if output is None:
-            print(screen_output)
-        elif output == 'readouts':
-            return readouts
-        elif output == 'subarrays':
-            return subarrays
-        elif output == 'filters':
-            return filters
-        elif output == 'dispersers':
-            return dispersers
-        elif self.instrument=='nirspec' and output=='gratings':
-            return gratings
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+    >>> import numy as np
+
+    >>> wl = np.logspace(0, 2, 1000)
+    >>> depth = [wl, np.tile(0.03, len(wl))]
+    >>> pando = jwst.PandeiaCalculation('nircam', 'ssgrism')
+    >>> pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    >>> tso = pando.tso_calculation(
+    >>>     'transit', transit_dur=2.1, obs_dur=6.0, depth_model=depth,
+    >>>     ngroup=190, readout='rapid', filter='f444w',
+    >>> )
+
+    >>> # Print from config dictionary:
+    >>> config = tso['report_out']['input']['configuration']
+    >>> text = jwst._print_pandeia_exposure(config=config)
+
+    >>> # Print from direct input values:
+    >>> inst = 'nircam'
+    >>> subarray = 'subgrism64'
+    >>> readout = 'rapid'
+    >>> ngroup = 90
+    >>> nint = 150
+    >>> text = jwst._print_pandeia_exposure(
+    >>>     inst, subarray, readout, ngroup, nint,
+    >>> )
+    """
+    if config is not None:
+        inst = config['instrument']['instrument']
+        subarray = config['detector']['subarray']
+        readout = config['detector']['readout_pattern']
+        nint = config['detector']['nint']
+        ngroup = config['detector']['ngroup']
+
+    exp_time = exposure_time(inst, subarray, readout, ngroup, nint)
+    exposure_hours = exp_time / 3600.0
+    exp_text = f'Exposure time: {exp_time:.2f} s ({exposure_hours:.2f} h)'
+    return exp_text
+
+
+def _print_pandeia_saturation(
+        inst=None, subarray=None, readout=None, ngroup=None,
+        pixel_rate=None, full_well=None, reports=None, format=None,
+    ):
+    """
+    >>> import gen_tso.pandeia_io as jwst
+    >>> import numy as np
+
+    >>> wl = np.logspace(0, 2, 1000)
+    >>> depth = [wl, np.tile(0.03, len(wl))]
+    >>> pando = jwst.PandeiaCalculation('nircam', 'ssgrism')
+    >>> pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    >>> tso = pando.tso_calculation(
+    >>>     'transit', transit_dur=2.1, obs_dur=6.0, depth_model=depth,
+    >>>     ngroup=190, readout='rapid', filter='f444w',
+    >>> )
+
+    >>> # Directly print from input values:
+    >>> pixel_rate, full_well = jwst.saturation_level(tso, get_max=True)
+    >>> inst = 'nircam'
+    >>> subarray = 'subgrism64'
+    >>> readout = 'rapid'
+    >>> ngroup = 90
+    >>> nint = 150
+    >>> text = jwst._print_pandeia_saturation(
+    >>>     inst, subarray, readout, ngroup, pixel_rate, full_well,
+    >>>     format='html',
+    >>> )
+
+    >>> # Print from tso_calculation() or perform_calculation() output:
+    >>> text = jwst._print_pandeia_saturation(
+    >>>     reports=[tso], format='html',
+    >>> )
+    """
+    # parse reports
+    if reports is not None:
+        pixel_rate, full_well = saturation_level(reports, get_max=True)
+        # This is a TSO dict
+        if 'report_in' in reports[0]:
+            report = reports[0]['report_in']
         else:
-            raise ValueError(f"Invalid config output: '{output}'")
-
-
-    def set_scene(
-            self, sed_type, sed_model, norm_band, norm_magnitude,
-            background='ecliptic_low',
-        ):
-        """
-        Set the stellar point-source scene to observe.
-
-        Parameters
-        ----------
-        sed_type: String
-            Type of model: 'phoenix', 'k93models', 'blackbody', or 'flat'
-        sed_model:
-            The SED model required for each sed_type:
-            - phoenix or k93models: the model key (see load_sed_list)
-            - blackbody: the effective temperature (K)
-            - flat: the unit ('flam' or 'fnu')
-        norm_band: String
-            Band over which to normalize the spectrum.
-        norm_magnitude: float
-            Magnitude of the star at norm_band.
-        background: String
-            Set the background flux. Select from:
-            'ecliptic_low', 'ecliptic_medium', 'ecliptic_high',
-            'minzodi_low',  'minzodi_medium',  'minzodi_high'
-
-        Examples
-        --------
-        >>> import pandeia_interface as jwst
-
-        >>> instrument = 'nircam'
-        >>> mode = 'ssgrism'
-        >>> pando = jwst.PandeiaCalculation(instrument, mode)
-        >>> pando.set_scene(
-        >>>     sed_type='phoenix', sed_model='k5v',
-        >>>     norm_band='2mass,ks', norm_magnitude=8.637,
-        >>> )
-        """
-        scene = make_scene(sed_type, sed_model, norm_band, norm_magnitude)
-        self.calc['scene'] = [scene]
-        bkg, bkg_level = background.strip().split('_')
-        self.calc['background'] = bkg
-        self.calc['background_level'] = bkg_level
-
-
-    def get_saturation_values(
-            self, disperser, filter, subarray, readout, ngroup=2,
-            aperture=None,
-        ):
-        """
-        Calculate the brightest-pixel rate (e-/s) and full_well (e-)
-        for the current instrument and scene configuration, which once known,
-        are sufficient to calculate the saturation level once the
-        saturation  time is known.
-
-        Examples
-        --------
-        >>> import gen_tso.pandeia_io as jwst
-
-        >>> instrument = 'nircam'
-        >>> mode = 'ssgrism'
-        >>> pando = jwst.PandeiaCalculation(instrument, mode)
-        >>> pando.set_scene(
-        >>>     sed_type='phoenix', sed_model='k2v',
-        >>>     norm_band='2mass,ks', norm_magnitude=8.351,
-        >>> )
-        >>> brightest_pixel_rate, full_well = pando.get_saturation_values(
-        >>>     disperser='grismr', filter='f444w',
-        >>>     readout='rapid', subarray='subgrism64',
-        >>> )
-
-        >>> # Also works for Target Acquisition:
-        >>> instrument = 'nircam'
-        >>> mode = 'target_acq'
-        >>> pando = jwst.PandeiaCalculation(instrument, mode)
-        >>> pando.set_scene(
-        >>>     sed_type='phoenix', sed_model='k5v',
-        >>>     norm_band='2mass,ks', norm_magnitude=8.351,
-        >>> )
-        >>> brightest_pixel_rate, full_well = pando.get_saturation_values(
-        >>>     disperser=None, filter='f335m',
-        >>>     readout='rapid', subarray='sub32tats', ngroup=3,
-        >>> )
-        """
-        # TBD: Automate here the group setting
-        reports = self.perform_calculation(
-            ngroup=ngroup, nint=1,
-            disperser=disperser, filter=filter,
-            subarray=subarray, readout=readout,
-            aperture=aperture,
-        )
-        if not isinstance(reports, list):
-            reports = [reports]
-
-        ncalc = len(reports)
-        brightest_pixel_rate = np.zeros(ncalc)
-        full_well = np.zeros(ncalc)
-        for i,report in enumerate(reports):
-            results = report['scalar']
-            brightest_pixel_rate[i] = results['brightest_pixel']
-            full_well[i] = (
-                brightest_pixel_rate[i]
-                * results['saturation_time']
-                / results['fraction_saturation']
-            )
-        if len(reports) == 1:
-            return brightest_pixel_rate[0], full_well[0]
-        return brightest_pixel_rate, full_well
-
-
-    def perform_calculation(
-            self, ngroup, nint,
-            disperser=None, filter=None, subarray=None, readout=None,
-            aperture=None,
-        ):
-        """
-        Run pandeia's perform_calculation() for the given configuration
-        (or set of configurations, see notes below).
-
-        Parameter
-        ----------
-        ngroup: Integeer
-            Number of groups per integration.  Must be >= 2.
-        nint: Integer
-            Number of integrations.
-        disperser: String
-            Disperser/grating for the given instrument.
-        filter: String
-            Filter for the given instrument.
-        subarray: String
-            Subarray mode for the given instrument.
-        readout: String
-            Readout pattern mode for the given instrument.
-        aperture: String
-            Aperture configuration for the given instrument.
-
-        Returns
-        -------
-        report: dict
-            The Pandeia's report output for the given configuration.
-            If there's more than one requested calculation, return a
-            list of reports.
-
-        Notes
-        -----
-        - Provide a list of values for any of these arguments to
-          compute a batch of calculations.
-        - To leave a config parameter unmodified, leave the respective
-          argument as None.
-          To set a config parameter as None, set the argument to ''.
-        """
-        if not isinstance(nint, Iterable):
-            nint = [nint]
-        if not isinstance(ngroup, Iterable):
-            ngroup = [ngroup]
-        if not isinstance(disperser, Iterable) or isinstance(disperser, str):
-            disperser = [disperser]
-        if not isinstance(filter, Iterable) or isinstance(filter, str):
-            filter = [filter]
-        if not isinstance(subarray, Iterable) or isinstance(subarray, str):
-            subarray = [subarray]
-        if not isinstance(readout, Iterable) or isinstance(readout, str):
-            readout = [readout]
-        if not isinstance(aperture, Iterable) or isinstance(aperture, str):
-            aperture = [aperture]
-
-        configs = product(
-            aperture, disperser, filter, subarray, readout, nint, ngroup,
-        )
+            report = reports[0]
+        config = report['input']['configuration']
+        inst = config['instrument']['instrument']
+        subarray = config['detector']['subarray']
+        readout = config['detector']['readout_pattern']
+        ngroup = config['detector']['ngroup']
+
+    sat_time = integration_time(inst, subarray, readout, ngroup)
+    sat_fraction = 100 * pixel_rate * sat_time / full_well
+    ngroup_80 = int(80*ngroup/sat_fraction)
+    ngroup_max = int(100*ngroup/sat_fraction)
+
+    saturation = format_text(
+        f"{sat_fraction:.1f}%", sat_fraction>=81, sat_fraction>=100, format,
+    )
+    ngroup_80 = format_text(
+        f"{ngroup_80:d}", ngroup_80==2, ngroup_80<2, format,
+    )
+    ngroup_max = format_text(
+        f"{ngroup_max:d}", ngroup_max==2, ngroup_max<2, format,
+    )
+    saturation = f'Max fraction of saturation: {saturation}'
+    ngroup_80_sat = f'ngroup below 80% saturation: {ngroup_80}'
+    ngroup_max_sat = f'ngroup below 100% saturation: {ngroup_max}'
+
+    sat_text = (
+        f'{saturation}\n'
+        f'{ngroup_80_sat}\n'
+        f'{ngroup_max_sat}'
+    )
+    if format == 'html':
+        sat_text = sat_text.replace('\n', '<br>')
+    return sat_text
 
-        reports = [
-            self._perform_calculation(config)
-            for config in configs
-        ]
-        if len(reports) == 1:
-            return reports[0]
-        return reports
-
-
-    def _perform_calculation(self, params):
-        """
-        (the real function that) runs pandeia.
-        """
-        # Unpack configuration parameters
-        aperture, disperser, filter, subarray, readout, nint, ngroup = params
-        if aperture is not None:
-            self.calc['configuration']['instrument']['aperture'] = aperture
-        if disperser is not None:
-            self.calc['configuration']['instrument']['disperser'] = disperser
-        if readout is not None:
-            self.calc['configuration']['detector']['readout_pattern'] = readout
-        if subarray is not None:
-            self.calc['configuration']['detector']['subarray'] = subarray
-        if filter == '':
-            self.calc['configuration']['instrument']['filter'] = None
-        elif filter is not None:
-            self.calc['configuration']['instrument']['filter'] = filter
-
-        if self.instrument == 'niriss':
-            self.calc['strategy']['order'] = 1
-            # DataError: No mask configured for SOSS order 2.
-
-        self.calc['configuration']['detector']['nexp'] = 1 # dither
-        self.calc['configuration']['detector']['nint'] = nint
-        self.calc['configuration']['detector']['ngroup'] = ngroup
-
-        report = perform_calculation(self.calc)
-        self.report = report
-        return report
-
-    def calc_noise(
-            self, obs_dur, ngroup,
-            disperser, filter, subarray, readout, aperture,
-        ):
-        """
-        Run a Pandeia calculation and extract the observed wavelength,
-        flux, and variances.
-
-        Parameters
-        ----------
-        obs_dur: Float
-            Duration of the observation.
-        ngroup: Integer
-            Number of groups per integrations
-        disperser: String
-        filter: String
-        subarray: String
-        readout: String
-        aperture: String
-
-        Returns
-        -------
-        TBD
-
-        Examples
-        --------
-        >>> import gen_tso.pandeia_io as jwst
-
-        >>> instrument = 'nircam'
-        >>> mode = 'ssgrism'
-        >>> pando = jwst.PandeiaCalculation(instrument, mode)
-        >>> pando.set_scene(
-        >>>     sed_type='phoenix', sed_model='k5v',
-        >>>     norm_band='2mass,ks', norm_magnitude=8.637,
-        >>> )
-        >>> # Example TBD
-        """
-        ins_config = get_instrument_config(self.telescope, self.instrument)
-        single_exp_time = exposure_time(
-            self.instrument, nint=1, ngroup=ngroup,
-            readout=readout, subarray=subarray,
-        )
 
-        nint = int(obs_dur*3600/single_exp_time)
-        report = self.perform_calculation(
-            ngroup, nint, disperser, filter, subarray, readout, aperture,
-        )
+def _print_pandeia_stats(inst, mode, report_in, report_out=None, format=None):
+    r"""
+    Return a text summarizing the SNR, timings, and backround info
+    from a perform_calculation() or a tso_calculation() output.
 
-        # Flux:
-        measurement_time = report['scalar']['measurement_time']
-        flux = report['1d']['extracted_flux'][1] * measurement_time
-        wl = report['1d']['extracted_flux'][0]
-
-        # Background variance:
-        background_var = report['1d']['extracted_bg_only'][1] * measurement_time
-        # Read noise variance:
-        read_noise = read_noise_variance(report, ins_config)
-        npix = report['scalar']['extraction_area']
-        read_noise_var = 2.0 * read_noise**2.0 * nint * npix
-        # Pandeia (multiaccum) noise:
-        shot_var = (report['1d']['extracted_noise'][1] * measurement_time)**2.0
-        # Last-minus-first (LMF) noise:
-        lmf_var = np.abs(flux) + background_var + read_noise_var
-
-        variances = lmf_var, shot_var, background_var, read_noise_var
-
-        return report, wl, flux, variances, measurement_time
-
-
-    def tso_calculation(
-            self, obs_type, transit_dur, obs_dur, depth_model,
-            ngroup, disperser=None, filter=None,
-            subarray=None, readout=None, aperture=None,
-        ):
-        """
-        Run pandeia to simulate a transit/eclipse time-series observation
-
-        Parameters
-        ----------
-        obs_type: String
-            The observing geometry 'transit' or 'eclipse'.
-        transit_dur: Float
-            Duration of the transit or eclipse event in hours.
-        obs_dur: Float
-            Total duration of the observation (baseline plus transit
-            or eclipse event) in hours.
-        depth_model: list of two 1D array or a 2D array
-            The transit or eclipse depth spectrum where the first item is
-            the wavelength (um) and the second is the depth.
-        ngroup: Integer
-            Number of groups per integrations
-        disperser: String
-        filter: String
-        subarray: String
-        readout: String
-        aperture: String
-
-        Returns
-        -------
-        tso: dict
-            A dictionary containing the time-series observation data:
-            - wl: instrumental wavelength sampling (microns)
-            - depth_spectrum: Transit/eclipse depth spectrum at instrumental wl
-            - time_in: In-transit/eclipse measuring time (seconds)
-            - flux_in: In-transit/eclipse flux (e-)
-            - var_in:  In-transit/eclipse variance
-            - time_out: Out-of-transit/eclipse measuring time (seconds)
-            - flux_out: Out-of-transit/eclipse flux (e-)
-            - var_out:  Out-of-transit/eclipse
-            - report_in:  In-transit/eclipse pandeia output report
-            - report_out:  Out-of-transit/eclipse pandeia output report
-
-        Examples
-        --------
-        >>> import pandeia_interface as jwst
-        >>> from pandeia_interface import set_depth_scene
-
-        >>> # Set the stellar scene and transit:
-        >>> scene = jwst.make_scene(
-        >>>     sed_type='phoenix', sed_model='k5v',
-        >>>     norm_band='2mass,ks', norm_magnitude=8.637,
-        >>> )
-        >>> transit_dur = 2.753
-        >>> obs_dur = 7.1
-        >>> obs_type = 'transit'
-        >>> depth_model = np.loadtxt(
-        >>>     '../planet_spectra/WASP80b_transit.dat', unpack=True)
-
-        >>> # Set a NIRSpec observation
-        >>> pando = jwst.PandeiaCalculation('nirspec', 'bots')
-        >>> pando.calc['scene'] = [scene]
-        >>> disperser = 'g395h'
-        >>> filter = 'f290lp'
-        >>> readout = 'nrsrapid'
-        >>> subarray = 'sub2048'
-        >>> ngroup = 16
-
-        >>> tso = pando.tso_calculation(
-        >>>     obs_type, transit_dur, obs_dur, depth_model,
-        >>>     ngroup, disperser, filter, subarray, readout,
-        >>> )
-
-        >>> # Fluxes and Flux rates
-        >>> col1, col2 = plt.cm.viridis(0.8), plt.cm.viridis(0.25)
-        >>> plt.figure(0, (8.5, 4))
-        >>> plt.clf()
-        >>> plt.subplot(121)
-        >>> plt.plot(tso['wl'], tso['flux_out'], c=col2, label='out of transit')
-        >>> plt.plot(tso['wl'], tso['flux_in'], c=col1, label='in transit')
-        >>> plt.legend(loc='best')
-        >>> plt.xlabel('Wavelength (um)')
-        >>> plt.ylabel('Collected flux (e-)')
-        >>> plt.subplot(122)
-        >>> plt.plot(tso['wl'], tso['flux_out']/tso['time_out'], c=col2, label='out of transit')
-        >>> plt.plot(tso['wl'], tso['flux_in']/tso['time_in'], c=col1, label='in transit')
-        >>> plt.legend(loc='best')
-        >>> plt.xlabel('Wavelength (um)')
-        >>> plt.ylabel('Flux rate (e-/s)')
-        >>> plt.tight_layout()
-
-        >>> # Model and instrument-observed transit depth spectrum
-        >>> wl_depth, depth = depth_model
-        >>> plt.figure(4)
-        >>> plt.clf()
-        >>> plt.plot(wl_depth, 100*depth, c='orange', label='model depth')
-        >>> plt.plot(tso['wl'], 100*tso['depth_spectrum'], c='b', label='obs depth')
-        >>> plt.legend(loc='best')
-        >>> plt.xlim(2.75, 5.25)
-        >>> plt.xlabel('Wavelength (um)')
-        >>> plt.ylabel('Transit depth (%)')
-        """
-        # Scale in or out transit flux rates
-        scene = self.calc['scene'][0]
-        star_scene, depth_scene = set_depth_scene(scene, obs_type, depth_model)
-        if obs_type == 'eclipse':
-            scene_in = star_scene
-            scene_out = depth_scene
-        elif obs_type == 'transit':
-            scene_in = depth_scene
-            scene_out = star_scene
-
-        if not isinstance(ngroup, Iterable):
-            ngroup = [ngroup]
-        if not isinstance(disperser, Iterable) or isinstance(disperser, str):
-            disperser = [disperser]
-        if not isinstance(filter, Iterable) or isinstance(filter, str):
-            filter = [filter]
-        if not isinstance(subarray, Iterable) or isinstance(subarray, str):
-            subarray = [subarray]
-        if not isinstance(readout, Iterable) or isinstance(readout, str):
-            readout = [readout]
-        if not isinstance(aperture, Iterable) or isinstance(aperture, str):
-            aperture = [aperture]
-
-        configs = product(
-            aperture, disperser, filter, subarray, readout, ngroup,
-        )
+    Parameters
+    ----------
+    inst: String
+        Instrument name.
+    mode: String
+        Instrument's mode.
+    report_in: Dictionary
+        A tso_calculation() or pandeia's perform_calculation() output.
+    report_out: Dictionary
+        A pandeia's perform_calculation() output.
+        If not None, assume that the inputs reports are an in-transit
+        and out-of-transit pair.
+    format: String
+        If None format as plain text (e.g., for print() calls)
+        If 'rich' format as rich/colorful text (e.g., for FormattedText())
+        If 'html' format as HTML text (e.g., for browser applications)
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
 
-        tso = [
-            self._tso_calculation(config, scene_in, scene_out, transit_dur, obs_dur)
-            for config in configs
-        ]
-        if len(tso) == 1:
-             tso = tso[0]
-        self.tso = tso
-        # Return scene to its previous state
-        self.calc['scene'][0] = scene
-        return tso
-
-
-    def _tso_calculation(
-            self, config, scene_in, scene_out, transit_dur, obs_dur,
-        ):
-        """
-        (the real function that) runs a TSO calculation.
-        """
-        aperture, disperser, filter, subarray, readout, ngroup = config
-        if aperture is not None:
-            self.calc['configuration']['instrument']['aperture'] = aperture
-        if disperser is not None:
-            self.calc['configuration']['instrument']['disperser'] = disperser
-        if readout is not None:
-            self.calc['configuration']['detector']['readout_pattern'] = readout
-        if subarray is not None:
-            self.calc['configuration']['detector']['subarray'] = subarray
-        if filter == '':
-            self.calc['configuration']['instrument']['filter'] = None
-        elif filter is not None:
-            self.calc['configuration']['instrument']['filter'] = filter
-
-        # Compute observed fluxes and noises:
-        self.calc['scene'][0] = scene_in
-        report_in, wl, flux_in, variances_in, time_in = self.calc_noise(
-            transit_dur, ngroup,
-            disperser, filter, subarray, readout, aperture,
+    >>> inst = 'nircam'
+    >>> readout = 'rapid'
+    >>> pando = jwst.PandeiaCalculation(inst, 'ssgrism')
+    >>> pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    >>> result = pando.perform_calculation(
+    >>>     ngroup=92, nint=683, readout='rapid', filter='f444w',
+    >>> )
+    >>> report = jwst.print_pandeia_report(inst, mode, result['scalar'])
+    >>> print(report)
+    """
+    if not isinstance(report_in, list):
+        report_in = [report_in]
+    rate_in = report_in[0]['extracted_flux']
+    if report_out == []:
+        report_out = None
+    if report_out is not None:
+        if not isinstance(report_out, list):
+           report_out = [report_out]
+        rate_out = report_out[0]['extracted_flux']
+
+    # Take report with more flux in it
+    if report_out is None or rate_in > rate_out:
+        reports = report_in
+    else:
+        reports = report_out
+
+    snr = ''
+    flux = ''
+    flux_std = ''
+    pixel_rate = ''
+    ref_wave = ''
+    extract_area = ''
+    bkg_area = ''
+    bkg_brightness = ''
+    sky = ''
+    bkg_flux = ''
+    bkg_source = ''
+    min_snr = 0.0
+    if mode == 'target_acq' and inst in ['miri', 'nirspec']:
+        min_snr = 20.0
+    if mode == 'target_acq' and inst in ['niriss', 'nircam']:
+        min_snr = 30.0
+
+    for report in report_in:
+        sn = report['sn']
+        snr += format_text(f"{sn:9.1f} ", danger=sn<min_snr, format=format)
+        flux += f"{report['extracted_flux']:9.1f} "
+        flux_std += f"{report['extracted_noise']:9.1f} "
+        pixel_rate += f"{report['brightest_pixel']:9.1f} "
+        ref_wave += f"{report['reference_wavelength']:6.2f} "
+        extract_area += f"{report['extraction_area']:6.2f} "
+        if report_in[0]['background_area'] is not None:
+            bkg_area += f"{report['background_area']:6.1f} "
+            bkg_brightness += f"{report['background']:6.1f} "
+            sky += f"{report['background_sky']:6.2f} "
+            bkg_flux += f"{report['background_total']:6.2f} "
+            bkg_source += f"{report['contamination']:6.2f} "
+
+    background_info = ''
+    if report_in[0]['background_area'] is not None:
+        background_info = (
+            f"Area of background measurement:        {bkg_area} pixels\n"
+            f"Background surface brightness:         {bkg_brightness} MJy/sr\n"
+            f"Total sky flux in background aperture: {sky} e-/s\n"
+            f"Total flux in background aperture:     {bkg_flux} e-/s\n"
+            f"Background flux fraction from scene:   {bkg_source.rstrip()}\n"
         )
-        var_lmf_in = variances_in[0]
 
-        out_transit_dur = obs_dur - transit_dur
-        self.calc['scene'][0] = scene_out
-        report_out, wl, flux_out, variances_out, time_out = self.calc_noise(
-            out_transit_dur, ngroup,
-            disperser, filter, subarray, readout, aperture,
+    cosmic_rays = f"{report_in[0]['cr_ramp_rate']:9.4f}"
+
+    integs = ''
+    duty_cycle = ''
+    total_time = ''
+    exp_time = ''
+    dt_exposure = ''
+    dt_integ = ''
+    dt_fmt = '8.1f' if report_in[0]['total_exposure_time'] > 100 else '8.3f'
+    min_duty = 0.0 if mode == 'target_acq' else 0.49
+    reports = report_in[0:1]
+    if report_out is not None:
+        reports.append(report_out[0])
+    for report in reports:
+        integs += f"{report['total_integrations']:8d} "
+        duty = report['duty_cycle']
+        duty_cycle += format_text(
+            f"{duty:8.2f} ", warning=duty<min_duty, format=format,
         )
-        var_lmf_out = variances_out[0]
-
-        # Mask out un-illumnated wavelengths (looking at you, G395H)
-        mask = flux_in > 1e-6 * np.median(flux_in)
-        wl = wl[mask]
-        flux_in = flux_in[mask]
-        flux_out = flux_out[mask]
-        var_in = var_lmf_in[mask]
-        var_out = var_lmf_out[mask]
-        obs_depth = 1 - (flux_in/time_in) / (flux_out/time_out)
-
-        tso = {
-            'wl': wl,
-            'depth_spectrum': obs_depth,
-            'time_in': time_in,
-            'flux_in': flux_in,
-            'var_in': var_in,
-            'time_out': time_out,
-            'flux_out': flux_out,
-            'var_out': var_out,
-            'report_in': report_in,
-            'report_out': report_out,
-        }
-        return tso
-
-    def simulate_tso(
-            self, n_obs=1, resolution=None, bins=None, noiseless=False,
-        ):
-        """
-        Simulate a time-series observation spectrum with noise
-        for the given number of observations and spectral sampling.
-
-        Parameters
-        ----------
-        TBD
-
-        Returns
-        -------
-        TBD
-
-        Examples
-        --------
-        >>> TBD
-        """
-        return simulate_tso(self.tso, n_obs, resolution, bins, noiseless)
+        total_time += f"{report['total_exposure_time']:{dt_fmt}} "
+        exp_time += f"{report['all_dithers_time']:{dt_fmt}} "
+        dt_exposure += f"{report['exposure_time']:{dt_fmt}} "
+        dt_integ += f"{report['measurement_time']:{dt_fmt}} "
+
+    if report_out is None:
+        tso_header = ''
+    else:
+        tso_header = f"{'in-transit':>41}  out-transit\n"
+    if mode == 'miri_ts' and len(reports)==4:
+        channels = "CH1 CH2 CH3 CH4"
+        band_header1 = f"{'':31s}{channels.replace(' ', '       ')}\n"
+        band_header2 = f"{'':42s}{channels.replace(' ', '    ')}\n"
+    else:
+        band_header1 = band_header2 = ''
+
+    summary = (
+        f"{band_header1}"
+        f"Signal-to-noise ratio    {snr.rstrip()}\n"
+        f"Extracted flux           {flux} e-/s\n"
+        f"Flux standard deviation  {flux_std} e-/s\n"
+        f"Brightest pixel rate     {pixel_rate} e-/s\n\n"
+
+        f"{tso_header}"
+        f"Integrations:                    {integs.rstrip()}\n"
+        f"Duty cycle:                      {duty_cycle.rstrip()}\n"
+        f"Total exposure time:             {total_time} s\n"
+        # Ignore exp_time since it always matches total_time (nexp=1)
+        #f"Single exposure time:            {exp_time} s\n"
+        f"First--last dt per exposure:     {dt_exposure} s\n"
+        f"Reset--last dt per integration:  {dt_integ} s\n\n"
+
+        f"{band_header2}"
+        f"Reference wavelength:                  {ref_wave} microns\n"
+        f"Area of extraction aperture:           {extract_area} pixels\n"
+        f"{background_info}"
+        f"Number of cosmic rays:   {cosmic_rays}  events/pixel/read"
+    )
+
+    if format=='html':
+        summary = summary.replace('\n', '<br>')
+    return summary
+
+
+def _print_pandeia_report(reports, format=None):
+    """
+    Get a text summarizing tso_calculation() or perform_calculation() output.
+    Similar to the results panel in the ETC.
+
+    Parameters
+    ----------
+    reports: Dictionary
+        A tso_calculation() or a perform_calculation() output.
+        Or a list of them.
+    format: String
+        If None format as plain text (e.g., for print() calls)
+        If 'rich' format as rich/colorful text (e.g., for FormattedText())
+        If 'html' format as HTML text (e.g., for browser applications)
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+
+    >>> wl = np.logspace(0, 2, 1000)
+    >>> depth = [wl, np.tile(0.03, len(wl))]
+    >>> pando = jwst.PandeiaCalculation('nircam', 'ssgrism')
+    >>> pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    >>> tso = pando.tso_calculation(
+    >>>     'transit', transit_dur=2.1, obs_dur=6.0, depth_model=depth,
+    >>>     ngroup=90, readout='rapid', filter='f444w',
+    >>> )
+
+    >>> tso_report = jwst._print_pandeia_report(tso, format=None)
+    >>> print(tso_report)
+
+    Exposure time: 21545.44 s (5.98 h)
+    Max fraction of saturation: 73.7%
+    ngroup below 80% saturation: 97
+    ngroup below 100% saturation: 122
+
+    Signal-to-noise ratio       3484.8
+    Extracted flux              2043.0  e-/s
+    Flux standard deviation        0.6  e-/s
+    Brightest pixel rate        1354.7  e-/s
+
+                                   in-transit  out-transit
+    Integrations:                         243      452
+    Duty cycle:                          0.98     0.98
+    Total exposure time:               7533.2  14012.3  s
+    First--last dt per exposure:       7533.2  14012.3  s
+    Reset--last dt per integration:    7366.4  13702.1  s
+
+    Reference wavelength:                    4.36  microns
+    Area of extraction aperture:             4.76  pixels
+    Area of background measurement:           6.3  pixels
+    Background surface brightness:            0.3  MJy/sr
+    Total sky flux in background aperture:   4.45  e-/s
+    Total flux in background aperture:      64.12  e-/s
+    Background flux fraction from scene:     0.93
+    Number of cosmic rays:      0.0072  events/pixel/read
+    """
+    if not isinstance(reports, list):
+        reports = [reports]
+    # This is a TSO dict
+    if 'report_in' in reports[0]:
+        report_in = [report['report_in'] for report in reports]
+        report_out = [report['report_out'] for report in reports]
+    # This is a perform_calculation dict
+    else:
+        report_in = reports
+        report_out = []
+
+    # Put everything into a list to make things easier to handle:
+    if not isinstance(report_in, list):
+        report_in = [report_in]
+    if not isinstance(report_out, list):
+        report_out = [report_out]
+
+    # Exposure
+    config = report_in[0]['input']['configuration']
+    inst = config['instrument']['instrument']
+    mode = config['instrument']['mode']
+    subarray = config['detector']['subarray']
+    readout = config['detector']['readout_pattern']
+    ngroup = config['detector']['ngroup']
+    nint = config['detector']['nint']
+    if report_out != []:
+        nint += report_out[0]['input']['configuration']['detector']['nint']
+    text_report = _print_pandeia_exposure(inst, subarray, readout, ngroup, nint)
+
+    # Saturation
+    reports = report_in + report_out
+    pixel_rate, full_well = saturation_level(reports, get_max=True)
+    saturation_report = _print_pandeia_saturation(
+        inst, subarray, readout, ngroup, pixel_rate, full_well,
+        format=format,
+    )
+    text_report = f'{text_report}\n{saturation_report}'
+
+    # Full report
+    scalar_in = [report['scalar'] for report in report_in]
+    scalar_out = [report['scalar'] for report in report_out]
+    stats = _print_pandeia_stats(inst, mode, scalar_in, scalar_out, format)
+    text_report = f'{text_report}\n\n{stats}'
+    if format == 'html':
+        text_report = text_report.replace('\n', '<br>')
+    return text_report
+
+
+def tso_print(calculation, format='rich'):
+    """
+    Print to screen a tso_calculation() output or a Pandeia's
+    perform_calculation() output.
+
+    Parameters
+    ----------
+    calculation: Dictionary or list of dictionaries
+        A tso_calculation() or a Pandeia's perform_calculation() output.
+    format: String
+        If 'rich' print with colourful text when there are warnings
+        or errors in values.
+        If None, print as plain text.
+
+    Examples
+    --------
+    >>> import gen_tso.pandeia_io as jwst
+    >>> import numpy as np
+
+    >>> wl = np.logspace(0, 2, 1000)
+    >>> depth = [wl, np.tile(0.03, len(wl))]
+    >>> pando = jwst.PandeiaCalculation('nircam', 'ssgrism')
+    >>> pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    >>> tso = pando.tso_calculation(
+    >>>     'transit', transit_dur=2.1, obs_dur=6.0, depth_model=depth,
+    >>>     ngroup=100, readout='rapid', filter='f444w',
+    >>> )
+    >>> # A perform_calculation() call:
+    >>> jwst.tso_print(tso)
+
+    >>> # A tso_calculation() call:
+    >>> calc = pando.perform_calculation(ngroup=130, nint=300)
+    >>> jwst.tso_print(calc)
+    """
+    # TBD: get style from style.css file?
+    style = prompt_toolkit.styles.Style.from_dict({
+        'danger': '#cb2222',
+        'warning': '#ffa500',
+    })
+    report = _print_pandeia_report(calculation, format)
+    if format == 'rich':
+        report = prompt_toolkit.HTML(report)
+    prompt_toolkit.print_formatted_text(report, style=style)
 
diff --git a/gen_tso/utils.py b/gen_tso/utils.py
index 66581d5..ebf9fbd 100644
--- a/gen_tso/utils.py
+++ b/gen_tso/utils.py
@@ -15,6 +15,7 @@
     'bin_spectrum',
     'read_spectrum_file',
     'collect_spectra',
+    'format_text',
     'pretty_print_target',
 ]
 
@@ -22,6 +23,7 @@
 import os
 
 import numpy as np
+from prompt_toolkit.formatted_text import FormattedText
 from pyratbay.tools import u
 from pyratbay.spectrum import PassBand
 from shiny import ui
@@ -352,6 +354,7 @@ def collect_spectra(folder, on_fail=None):
     on_fail: String
         if 'warning' raise a warning.
         if 'error' raise an error.
+
     Examples
     --------
     >>> import gen_tso.utils as u
@@ -394,6 +397,58 @@ def collect_spectra(folder, on_fail=None):
     return transit_spectra, eclipse_spectra, sed_spectra
 
 
+def format_text(text, warning=False, danger=False, format=None):
+    """
+    Return a colorful text depending on requested format and warning
+    or danger flags.
+
+    Parameters
+    ----------
+    text: String
+        A text to print with optional richer format.
+    warning: Bool
+        If True, format as warning text (orange color).
+    danger: Bool
+        If True, format as danger text (red color).
+        If True, overrides warning.
+    format: String
+        If None return plain text.
+        If 'html' return HTML formatted text.
+        If 'rich' return formatted text to be printed with prompt_toolkit.
+
+    See also
+    --------
+    gen_tso.pandeia_io.tso_print
+        
+    Examples
+    --------
+    >>> import gen_tso.utils as u
+    >>> text = 'WASP-80 b'
+    >>> plain = u.format_text(text, danger=True)
+    >>> normal = u.format_text(text, warning=False, danger=False, format='html')
+    >>> html = u.format_text(text, danger=True, format='html')
+    >>> rich = u.format_text(text, danger=True, format='rich')
+
+    >>> warned = u.format_text(text, warning=True, format='html')
+    >>> danger1 = u.format_text(text, danger=True, format='html')
+    >>> danger2 = u.format_text(text, warning=True, danger=True, format='html')
+    """
+    status = 'normal'
+    if danger:
+        status = 'danger'
+    elif warning:
+        status = 'warning'
+
+    if format is None or status=='normal':
+        return text
+
+    if format == 'html':
+        text_value = f'<span class="{status}">{text}</span>'
+    elif format == 'rich':
+        text_value = f'<{status}>{text}</{status}>'
+    return text_value
+
+
 def pretty_print_target(target):
     """
     Print a target's info to HTML text.
diff --git a/gen_tso/version.py b/gen_tso/version.py
index 4873257..a9b1ae4 100644
--- a/gen_tso/version.py
+++ b/gen_tso/version.py
@@ -4,7 +4,7 @@
 
 # Pyrat-Bay version:
 TSO_VER = 0  # Major version
-TSO_MIN = 2  # Minor version
+TSO_MIN = 3  # Minor version
 TSO_REV = '0'  # Revision
 
 
diff --git a/pyproject.toml b/pyproject.toml
index 0e626fe..ff25be2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,12 +16,13 @@ authors = [
   {name = "Patricio Cubillos", email = "pcubillos@fulbrightmail.org"}
 ]
 dependencies = [
-    'shiny>=0.8.1',
+    'shiny>=1.0.0',
     'pandeia.engine>=3.0.0',
     'scipy',
     'numpy>=1.15.1',
     'requests>=2.19.1',
     'grequests>=0.7.0',
+    'astropy>=5.3.0',
     'astroquery',
     'pandas',
     'plotly',
@@ -49,3 +50,7 @@ version = {attr = "gen_tso.version.__version__"}
 [tool.setuptools.package-data]
 "gen_tso.data" = ["*"]
 
+[tool.pytest.ini_options]
+filterwarnings = [
+    "ignore:datetime.datetime.utcfromtimestamp:DeprecationWarning",
+]
diff --git a/requirements.txt b/requirements.txt
index 56b41dc..3885b38 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,10 +1,11 @@
-shiny>=0.8.1
+shiny>=1.0.0
 pandeia.engine>=3.0.0
 numpy>=1.17
 scipy
 requests>=2.19.1
 grequests>=0.7.0
 astroquery
+astropy>=5.3.0
 pandas
 plotly
 shinywidgets>=0.3.0


Test patch:
diff --git a/tests/mocks/make_mocks.py b/tests/mocks/make_mocks.py
new file mode 100644
index 0000000..276ec02
--- /dev/null
+++ b/tests/mocks/make_mocks.py
@@ -0,0 +1,98 @@
+# Copyright (c) 2024 Patricio Cubillos
+# Gen TSO is open-source software under the GPL-2.0 license (see LICENSE)
+
+import pickle
+import numpy as np
+import gen_tso.pandeia_io as jwst
+
+
+def mock_perform_calculation_single():
+    pando = jwst.PandeiaCalculation('nircam', 'ssgrism')
+    pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    result = pando.perform_calculation(
+        ngroup=2, nint=683, readout='rapid', filter='f444w',
+    )
+    result['1d'] = {}
+    result['2d'] = {}
+    result['3d'] = {}
+    with open('perform_calculation_nircam_ssgrism.pkl', 'wb') as f:
+        pickle.dump(result, f)
+
+
+def mock_perform_calculation_multi():
+    pando = jwst.PandeiaCalculation('miri', 'mrs_ts')
+    pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    aperture = ['ch1', 'ch2', 'ch3', 'ch4']
+    results = pando.perform_calculation(
+        ngroup=250, nint=40, aperture=aperture,
+    )
+    for result in results:
+        result['1d'] = {}
+        result['2d'] = {}
+        result['3d'] = {}
+    with open('perform_calculation_miri_mrs_ts.pkl', 'wb') as f:
+        pickle.dump(results, f)
+
+
+def mock_tso_calculation_multi():
+    wl = np.logspace(0, 2, 1000)
+    depth = [wl, np.tile(0.03, len(wl))]
+    pando = jwst.PandeiaCalculation('nircam', 'ssgrism')
+    pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    tso = pando.tso_calculation(
+        'transit', transit_dur=2.1, obs_dur=6.0, depth_model=depth,
+        ngroup=90, readout='rapid', filter='f444w',
+    )
+
+    thin = 20
+    tso['wl'] = tso['wl'][::thin]
+    tso['depth_spectrum'] = tso['depth_spectrum'][::thin]
+    tso['flux_in'] = tso['flux_in'][::thin]
+    tso['flux_out'] = tso['flux_out'][::thin]
+    tso['var_in'] = tso['var_in'][::thin]
+    tso['var_out'] = tso['var_out'][::thin]
+
+    for result in (tso['report_in'], tso['report_out']):
+        result['1d'] = {}
+        result['2d'] = {}
+        result['3d'] = {}
+        spec = result['input']['scene'][0]['spectrum']['sed']['spectrum']
+        wl, spectrum = spec
+        spec = wl[::2000], spectrum[::2000]
+        result['input']['scene'][0]['spectrum']['sed']['spectrum'] = spec
+
+    with open('tso_calculation_nircam_ssgrism.pkl', 'wb') as f:
+        pickle.dump(tso, f)
+
+
+def mock_tso_calculation_multi():
+    wl = np.logspace(0, 2, 1000)
+    depth = [wl, np.tile(0.03, len(wl))]
+    pando = jwst.PandeiaCalculation('miri', 'mrs_ts')
+    pando.set_scene('phoenix', 'k5v', '2mass,ks', 8.351)
+    aperture = ['ch1', 'ch2', 'ch3', 'ch4']
+    tso = pando.tso_calculation(
+        'transit', transit_dur=2.1, obs_dur=6.0, depth_model=depth,
+        ngroup=250, aperture=aperture,
+    )
+    for report in tso:
+        thin = 20
+        report['wl'] = report['wl'][::thin]
+        report['depth_spectrum'] = report['depth_spectrum'][::thin]
+        report['flux_in'] = report['flux_in'][::thin]
+        report['flux_out'] = report['flux_out'][::thin]
+        report['var_in'] = report['var_in'][::thin]
+        report['var_out'] = report['var_out'][::thin]
+
+        for result in (report['report_in'], report['report_out']):
+            result['1d'] = {}
+            result['2d'] = {}
+            result['3d'] = {}
+            spec = result['input']['scene'][0]['spectrum']['sed']['spectrum']
+            wl, spectrum = spec
+            spec = wl[::2000], spectrum[::2000]
+            result['input']['scene'][0]['spectrum']['sed']['spectrum'] = spec
+
+    with open('tso_calculation_miri_mrs_ts.pkl', 'wb') as f:
+        pickle.dump(tso, f)
+
diff --git a/tests/mocks/perform_calculation_miri_mrs_ts.pkl b/tests/mocks/perform_calculation_miri_mrs_ts.pkl
new file mode 100644
index 0000000..e2674db
Binary files /dev/null and b/tests/mocks/perform_calculation_miri_mrs_ts.pkl differ
diff --git a/tests/mocks/perform_calculation_nircam_ssgrism.pkl b/tests/mocks/perform_calculation_nircam_ssgrism.pkl
new file mode 100644
index 0000000..8d5a7e8
Binary files /dev/null and b/tests/mocks/perform_calculation_nircam_ssgrism.pkl differ
diff --git a/tests/mocks/tso_calculation_miri_mrs_ts.pkl b/tests/mocks/tso_calculation_miri_mrs_ts.pkl
new file mode 100644
index 0000000..00f745d
Binary files /dev/null and b/tests/mocks/tso_calculation_miri_mrs_ts.pkl differ
diff --git a/tests/mocks/tso_calculation_nircam_ssgrism.pkl b/tests/mocks/tso_calculation_nircam_ssgrism.pkl
new file mode 100644
index 0000000..13d20cc
Binary files /dev/null and b/tests/mocks/tso_calculation_nircam_ssgrism.pkl differ
diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py
index 07c5764..8c25018 100644
--- a/tests/test_catalogs.py
+++ b/tests/test_catalogs.py
@@ -1,3 +1,4 @@
+import pytests
 import gen_tso.catalogs as cat
 import numpy as np
 from gen_tso.utils import ROOT
@@ -27,8 +28,6 @@ def test_fetch_aliases_oddballs():
     # from gen_tso.utils import ROOT
     # import gen_tso.catalogs.utils as u
     # from gen_tso.catalogs import *
-
-
     hosts = [
         'TOI-4336',
         'TOI-216',
@@ -40,3 +39,48 @@ def test_fetch_aliases_oddballs():
     host_aliases, planet_aliases = fetch_nea_aliases(hosts)
 
 
+def test_fetch_gaia_targets():
+    target_ra = 315.0260
+    target_dec = -5.0949
+    names, G_mag, teff, log_g, ra, dec, separation = cat.fetch_gaia_targets(
+        target_ra, target_dec, max_separation=80.0,
+    )
+    names = np.array([
+        'Gaia DR3 6910753016653587840', 'Gaia DR3 6910752844854895360',
+        'Gaia DR3 6910747136843460480', 'Gaia DR3 6910746934979897088',
+        'Gaia DR3 6910747141138328064', 'Gaia DR3 6910753046718453248',
+        'Gaia DR3 6910746930684973952', 'Gaia DR3 6910746866260418944',
+        'Gaia DR3 6910746934979895936',
+    ])
+    G_mag = np.array([
+         9.491504, 16.80548 , 18.476078, 16.334204, 18.974197, 17.175997,
+        18.024723, 15.700529, 16.899416,
+    ])
+    teff = np.array([
+        4729.3774, 5503.5996, 4959.2495, 5394.8145, 3979.5588, 5134.7896,
+        4528.2563, 5572.225 , 4862.2915,
+    ])
+    log_g = np.array([
+        4.5058, 4.4191, 4.7718, 4.3786, 5.018 , 4.3886, 4.6305, 3.774 ,
+        4.6665,
+    ])
+    ra = np.array([
+        315.02597081, 315.03419028, 315.01496413, 315.01522348,
+        315.00966205, 315.04041427, 315.02272526, 315.03525381,
+        315.0218094,
+    ])
+    dec = np.array([
+        -5.09487006, -5.08816924, -5.09282223, -5.10531022, -5.10264537,
+        -5.08275871, -5.11378437, -5.11325095, -5.11603216,
+    ])
+    sep = np.array([
+        4.99691642e-02, 3.80699861e+01, 4.01249572e+01, 5.38511968e+01,
+        6.48380986e+01, 6.76834547e+01, 6.91223563e+01, 7.41212133e+01,
+        7.76740049e+01,
+    ])
+
+
+@pytest.mark.skip(reason='mock requests')
+def test_fetch_gaia_targets_error():
+    pass
+
diff --git a/tests/test_pandeia_interface.py b/tests/test_pandeia_interface.py
new file mode 100644
index 0000000..1554b93
--- /dev/null
+++ b/tests/test_pandeia_interface.py
@@ -0,0 +1,448 @@
+# Copyright (c) 2024 Patricio Cubillos
+# Gen TSO is open-source software under the GPL-2.0 license (see LICENSE)
+
+import os
+import pickle
+import pytest
+
+import numpy as np
+
+import gen_tso.pandeia_io as jwst
+from gen_tso.utils import ROOT
+
+os.chdir(ROOT+'../tests')
+# See tests/make_mocks.py for mocked data setup.
+
+
+def test_saturation_level_perform_calculation_single():
+    with open('mocks/perform_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+
+    pixel_rate, full_well = jwst.saturation_level(result)
+    expected_rate = 1396.5528564453125
+    expected_well = 58100.00422843957
+    np.testing.assert_allclose(pixel_rate, expected_rate)
+    np.testing.assert_allclose(full_well, expected_well)
+
+
+def test_saturation_level_perform_calculation_multi():
+    with open('mocks/perform_calculation_miri_mrs_ts.pkl', 'rb') as f:
+        result = pickle.load(f)
+
+    pixel_rate, full_well = jwst.saturation_level(result)
+    expected_rate = [
+        204.37779236, 109.17165375,  32.75593948,   4.55676889,
+    ]
+    expected_well = [
+        193654.99564498, 193655.00540975, 193655.004117  , 193654.99798687,
+    ]
+    np.testing.assert_allclose(pixel_rate, expected_rate)
+    np.testing.assert_allclose(full_well, expected_well)
+
+
+def test_saturation_level_tso_calculation_single():
+    with open('mocks/tso_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        tso = pickle.load(f)
+
+    pixel_rate, full_well = jwst.saturation_level(tso)
+    expected_rate = [1354.6842041 , 1396.55285645]
+    expected_well = [58100.00016363, 58100.00129109]
+    np.testing.assert_allclose(pixel_rate, expected_rate)
+    np.testing.assert_allclose(full_well, expected_well)
+
+
+def test_saturation_level_tso_calculation_multi():
+    with open('mocks/tso_calculation_miri_mrs_ts.pkl', 'rb') as f:
+        tso = pickle.load(f)
+
+    pixel_rate, full_well = jwst.saturation_level(tso)
+    expected_rate = [
+        198.24740601, 105.90003204,  31.80119514,   4.46783495,
+        204.37779236, 109.17165375,  32.75593948,   4.55676889,
+    ]
+    expected_well = [
+        193654.99147199, 193654.99886718, 193654.98493823, 193654.99820043,
+        193654.99564498, 193655.00540975, 193655.004117  , 193654.99798687,
+    ]
+    np.testing.assert_allclose(pixel_rate, expected_rate)
+    np.testing.assert_allclose(full_well, expected_well)
+
+
+@pytest.mark.skip(reason='TBD')
+def test_saturation_level_tso_calculation_get_max():
+    pass
+
+
+def test_exposure_time_nircam():
+    inst = 'nircam'
+    subarray = 'subgrism64'
+    readout = 'rapid'
+    ngroup = 90
+    nint = 1
+    exp_time = jwst.exposure_time(inst, subarray, readout, ngroup, nint)
+    np.testing.assert_allclose(exp_time, 31.00063)
+
+
+def test_exposure_time_miri():
+    inst = 'miri'
+    subarray = 'slitlessprism'
+    readout = 'fastr1'
+    ngroup = 30
+    nint = 1
+    exp_time = jwst.exposure_time(inst, subarray, readout, ngroup, nint)
+    np.testing.assert_allclose(exp_time, 4.7712)
+
+
+def test_exposure_time_bad_subarray():
+    inst = 'nircam'
+    subarray = 'nope'
+    readout = 'rapid'
+    ngroup = 90
+    nint = 1
+    exp_time = jwst.exposure_time(inst, subarray, readout, ngroup, nint)
+    assert exp_time == 0.0
+
+
+def test_exposure_time_bad_readout():
+    inst = 'nircam'
+    subarray = 'subgrism64'
+    readout = 'nope'
+    ngroup = 90
+    nint = 1
+    exp_time = jwst.exposure_time(inst, subarray, readout, ngroup, nint)
+    assert exp_time == 0.0
+
+
+def test_bin_search_exposure_time_nircam():
+    inst = 'nircam'
+    subarray = 'subgrism64'
+    readout = 'rapid'
+    ngroup = 90
+    obs_time = 6.0
+    nint, exp_time = jwst.bin_search_exposure_time(
+        inst, subarray, readout, ngroup, obs_time,
+    )
+    assert nint == 697
+    np.testing.assert_allclose(exp_time, 21607.43911)
+
+
+def test_bin_search_exposure_time_miri():
+    inst = 'miri'
+    subarray = 'slitlessprism'
+    readout = 'fastr1'
+    ngroup = 30
+    obs_time = 6.0
+    nint, exp_time = jwst.bin_search_exposure_time(
+        inst, subarray, readout, ngroup, obs_time,
+    )
+    assert nint == 4382
+    np.testing.assert_allclose(exp_time, 21604.15264)
+
+
+def test_bin_search_exposure_time_bad_subarray():
+    inst = 'nircam'
+    subarray = 'nope'
+    readout = 'rapid'
+    ngroup = 90
+    obs_time = 6.0
+    nint, exp_time = jwst.bin_search_exposure_time(
+        inst, subarray, readout, ngroup, obs_time,
+    )
+    assert exp_time == 0.0
+
+
+def test_bin_search_exposure_time_bad_readout():
+    inst = 'nircam'
+    subarray = 'subgrism64'
+    readout = 'nope'
+    ngroup = 90
+    obs_time = 6.0
+    nint, exp_time = jwst.bin_search_exposure_time(
+        inst, subarray, readout, ngroup, obs_time,
+    )
+    assert exp_time == 0.0
+
+
+def test__print_pandeia_exposure_config():
+    with open('mocks/perform_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+    config = result['input']['configuration']
+    text = jwst._print_pandeia_exposure(config=config)
+    assert text == 'Exposure time: 701.41 s (0.19 h)'
+
+
+def test__print_pandeia_exposure_vals():
+    inst = 'nircam'
+    subarray = 'subgrism64'
+    readout = 'rapid'
+    ngroup = 90
+    nint = 150
+    text = jwst._print_pandeia_exposure(inst, subarray, readout, ngroup, nint)
+    assert text == 'Exposure time: 4650.09 s (1.29 h)'
+
+
+@pytest.mark.parametrize('format', [None, 'html', 'rich'])
+def test__print_pandeia_exposure_format(format):
+    with open('mocks/perform_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+    config = result['input']['configuration']
+    text = jwst._print_pandeia_exposure(config=config, format=format)
+    assert text == 'Exposure time: 701.41 s (0.19 h)'
+
+
+def test__print_pandeia_saturation_perform_calc():
+    with open('mocks/perform_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+
+    text = jwst._print_pandeia_saturation(reports=[result], format=None)
+    expected_text = """Max fraction of saturation: 1.6%
+ngroup below 80% saturation: 97
+ngroup below 100% saturation: 122"""
+    assert text == expected_text
+
+
+def test__print_pandeia_saturation_tso_calc():
+    with open('mocks/tso_calculation_miri_mrs_ts.pkl', 'rb') as f:
+        tso = pickle.load(f)
+
+    text = jwst._print_pandeia_saturation(reports=tso, format=None)
+    expected_text = """Max fraction of saturation: 73.2%
+ngroup below 80% saturation: 273
+ngroup below 100% saturation: 341"""
+    assert text == expected_text
+
+
+def test__print_pandeia_saturation_values():
+    pixel_rate, full_well = 1396.5528564453125, 58100.002280515175
+    inst = 'nircam'
+    subarray = 'subgrism64'
+    readout = 'rapid'
+    ngroup = 90
+    text = jwst._print_pandeia_saturation(
+        inst, subarray, readout, ngroup, pixel_rate, full_well,
+        format=None,
+    )
+    expected_text = """Max fraction of saturation: 73.7%
+ngroup below 80% saturation: 97
+ngroup below 100% saturation: 122"""
+    assert text == expected_text
+
+
+@pytest.mark.skip(reason='TBD')
+def test__print_pandeia_stats():
+    pass
+
+
+def test__print_pandeia_report_perform_calculation_single():
+    with open('mocks/perform_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+
+    report = jwst._print_pandeia_report([result], format=None)
+    expected_report = """Exposure time: 701.41 s (0.19 h)
+Max fraction of saturation: 1.6%
+ngroup below 80% saturation: 97
+ngroup below 100% saturation: 122
+
+Signal-to-noise ratio        410.9
+Extracted flux              2106.2  e-/s
+Flux standard deviation        5.1  e-/s
+Brightest pixel rate        1396.6  e-/s
+
+Integrations:                         683
+Duty cycle:                          0.33
+Total exposure time:                701.4  s
+First--last dt per exposure:        701.4  s
+Reset--last dt per integration:     232.6  s
+
+Reference wavelength:                    4.36  microns
+Area of extraction aperture:             4.76  pixels
+Area of background measurement:           6.3  pixels
+Background surface brightness:            0.3  MJy/sr
+Total sky flux in background aperture:   4.45  e-/s
+Total flux in background aperture:      65.97  e-/s
+Background flux fraction from scene:     0.93
+Number of cosmic rays:      0.0002  events/pixel/read"""
+    assert report == expected_report
+
+
+
+def test__print_pandeia_report_perform_calculation_multi():
+    with open('mocks/perform_calculation_miri_mrs_ts.pkl', 'rb') as f:
+        result = pickle.load(f)
+
+    report = jwst._print_pandeia_report(result, format=None)
+    expected_report = """Exposure time: 27858.63 s (7.74 h)
+Max fraction of saturation: 73.2%
+ngroup below 80% saturation: 273
+ngroup below 100% saturation: 341
+
+Signal-to-noise ratio       1334.2    1265.2     960.1     179.2
+Extracted flux               225.1     147.4      46.2       2.0  e-/s
+Flux standard deviation        0.2       0.1       0.0       0.0  e-/s
+Brightest pixel rate         204.4     109.2      32.8       4.6  e-/s
+
+Integrations:                          40
+Duty cycle:                          0.99
+Total exposure time:              27858.6  s
+First--last dt per exposure:      27858.6  s
+Reset--last dt per integration:   27639.4  s
+
+Reference wavelength:                    5.35   8.15  12.50  19.29  microns
+Area of extraction aperture:             8.20   5.21   2.98   1.61  pixels
+Area of background measurement:          79.4   50.5   28.9   15.6  pixels
+Background surface brightness:            1.0   10.9   43.0  165.5  MJy/sr
+Total sky flux in background aperture:   0.29   0.82   2.98   2.44  e-/s
+Total flux in background aperture:       0.85   1.47   3.19   2.54  e-/s
+Background flux fraction from scene:     0.66   0.45   0.06   0.04
+Number of cosmic rays:      0.3122  events/pixel/read"""
+    assert report == expected_report
+
+
+def test__print_pandeia_report_tso_calculation_single():
+    with open('mocks/tso_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+
+    report = jwst._print_pandeia_report(result, format=None)
+    expected_report = """Exposure time: 21545.44 s (5.98 h)
+Max fraction of saturation: 73.7%
+ngroup below 80% saturation: 97
+ngroup below 100% saturation: 122
+
+Signal-to-noise ratio       3484.8
+Extracted flux              2043.0  e-/s
+Flux standard deviation        0.6  e-/s
+Brightest pixel rate        1354.7  e-/s
+
+                               in-transit  out-transit
+Integrations:                         243      452
+Duty cycle:                          0.98     0.98
+Total exposure time:               7533.2  14012.3  s
+First--last dt per exposure:       7533.2  14012.3  s
+Reset--last dt per integration:    7366.4  13702.1  s
+
+Reference wavelength:                    4.36  microns
+Area of extraction aperture:             4.76  pixels
+Area of background measurement:           6.3  pixels
+Background surface brightness:            0.3  MJy/sr
+Total sky flux in background aperture:   4.45  e-/s
+Total flux in background aperture:      64.12  e-/s
+Background flux fraction from scene:     0.93
+Number of cosmic rays:      0.0072  events/pixel/read"""
+    assert report == expected_report
+
+
+def test__print_pandeia_report_tso_calculation_multi():
+    with open('mocks/tso_calculation_miri_mrs_ts.pkl', 'rb') as f:
+        tso = pickle.load(f)
+
+    report = jwst._print_pandeia_report(tso, format=None)
+    expected_report = """Exposure time: 20893.28 s (5.80 h)
+Max fraction of saturation: 73.2%
+ngroup below 80% saturation: 273
+ngroup below 100% saturation: 341
+
+Signal-to-noise ratio        657.0     623.0     472.3      87.5
+Extracted flux               218.4     142.9      44.8       1.9  e-/s
+Flux standard deviation        0.3       0.2       0.1       0.0  e-/s
+Brightest pixel rate         198.2     105.9      31.8       4.5  e-/s
+
+                               in-transit  out-transit
+Integrations:                          10       20
+Duty cycle:                          0.99     0.99
+Total exposure time:               6962.6  13927.9  s
+First--last dt per exposure:       6962.6  13927.9  s
+Reset--last dt per integration:    6909.8  13819.7  s
+
+Reference wavelength:                    5.35   8.15  12.50  19.29  microns
+Area of extraction aperture:             8.20   5.21   2.98   1.61  pixels
+Area of background measurement:          79.4   50.5   28.9   15.6  pixels
+Background surface brightness:            1.0   10.9   43.0  165.5  MJy/sr
+Total sky flux in background aperture:   0.29   0.82   2.98   2.44  e-/s
+Total flux in background aperture:       0.83   1.45   3.18   2.54  e-/s
+Background flux fraction from scene:     0.65   0.44   0.06   0.04
+Number of cosmic rays:      0.3122  events/pixel/read"""
+    assert report == expected_report
+
+
+def test_tso_print_plain(capsys):
+    with open('mocks/tso_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+    # Make some troublesome figures
+    result['report_in']['scalar']['duty_cycle'] = 0.25
+    result['report_in']['input']['configuration']['detector']['ngroup'] = 130
+    result['report_out']['scalar']['duty_cycle'] = 0.25
+    result['report_out']['input']['configuration']['detector']['ngroup'] = 130
+
+    jwst.tso_print(result, format=None)
+    captured = capsys.readouterr()
+    expected_report = (
+        "Exposure time: 31014.40 s (8.62 h)\r\n"
+        "Max fraction of saturation: 106.4%\r\n"
+        "ngroup below 80% saturation: 97\r\n"
+        "ngroup below 100% saturation: 122\r\n"
+        "\r\n"
+        "Signal-to-noise ratio       3484.8\r\n"
+        "Extracted flux              2043.0  e-/s\r\n"
+        "Flux standard deviation        0.6  e-/s\r\n"
+        "Brightest pixel rate        1354.7  e-/s\r\n"
+        "\r\n"
+        "                               in-transit  out-transit\r\n"
+        "Integrations:                         243      452\r\n"
+        "Duty cycle:                          0.25     0.25\r\n"
+        "Total exposure time:               7533.2  14012.3  s\r\n"
+        "First--last dt per exposure:       7533.2  14012.3  s\r\n"
+        "Reset--last dt per integration:    7366.4  13702.1  s\r\n"
+        "\r\n"
+        "Reference wavelength:                    4.36  microns\r\n"
+        "Area of extraction aperture:             4.76  pixels\r\n"
+        "Area of background measurement:           6.3  pixels\r\n"
+        "Background surface brightness:            0.3  MJy/sr\r\n"
+        "Total sky flux in background aperture:   4.45  e-/s\r\n"
+        "Total flux in background aperture:      64.12  e-/s\r\n"
+        "Background flux fraction from scene:     0.93\r\n"
+        "Number of cosmic rays:      0.0072  events/pixel/read\r\n"
+    )
+    assert captured.out == expected_report
+
+
+@pytest.mark.skip(reason='Having some issues with capsys IO')
+def test_tso_print_rich(capsys):
+    with open('mocks/tso_calculation_nircam_ssgrism.pkl', 'rb') as f:
+        result = pickle.load(f)
+    # Make some troublesome figures
+    result['report_in']['scalar']['duty_cycle'] = 0.25
+    result['report_in']['input']['configuration']['detector']['ngroup'] = 130
+    result['report_out']['scalar']['duty_cycle'] = 0.25
+    result['report_out']['input']['configuration']['detector']['ngroup'] = 130
+
+    jwst.tso_print(result)
+    captured = capsys.readouterr()
+    expected_report = (
+        "Exposure time: 31014.40 s (8.62 h)\r\n"
+        "Max fraction of saturation: 106.4%\r\n"
+        "ngroup below 80% saturation: 97\r\n"
+        "ngroup below 100% saturation: 122\r\n"
+        "\r\n"
+        "Signal-to-noise ratio       3484.8\r\n"
+        "Extracted flux              2043.0  e-/s\r\n"
+        "Flux standard deviation        0.6  e-/s\r\n"
+        "Brightest pixel rate        1354.7  e-/s\r\n"
+        "\r\n"
+        "                               in-transit  out-transit\r\n"
+        "Integrations:                         243      452\r\n"
+        "Duty cycle:                          0.25     0.25\r\n"
+        "Total exposure time:               7533.2  14012.3  s\r\n"
+        "First--last dt per exposure:       7533.2  14012.3  s\r\n"
+        "Reset--last dt per integration:    7366.4  13702.1  s\r\n"
+        "\r\n"
+        "Reference wavelength:                    4.36  microns\r\n"
+        "Area of extraction aperture:             4.76  pixels\r\n"
+        "Area of background measurement:           6.3  pixels\r\n"
+        "Background surface brightness:            0.3  MJy/sr\r\n"
+        "Total sky flux in background aperture:   4.45  e-/s\r\n"
+        "Total flux in background aperture:      64.12  e-/s\r\n"
+        "Background flux fraction from scene:     0.93\r\n"
+        "Number of cosmic rays:      0.0072  events/pixel/read\r\n"
+    )
+    assert captured.out == expected_report
+
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 61847d3..650a47d 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,6 +1,63 @@
 # Copyright (c) 2024 Patricio Cubillos
 # Gen TSO is open-source software under the GPL-2.0 license (see LICENSE)
  
+import gen_tso.utils as u
+from prompt_toolkit.formatted_text import FormattedText
+
+
+def test_format_text_plain():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, danger=True)
+    assert formatted == text
+
+
+def test_format_text_normal():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, warning=False, danger=False, format='html')
+    assert formatted == text
+
+
+def test_format_text_html_warning():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, warning=True, format='html')
+    assert formatted == '<span class="warning">WASP-80 b</span>'
+
+
+def test_format_text_html_danger():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, danger=True, format='html')
+    assert formatted == '<span class="danger">WASP-80 b</span>'
+
+
+def test_format_text_rich_warning():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, warning=True, format='rich')
+    assert formatted == '<warning>WASP-80 b</warning>'
+
+
+def test_format_text_rich_danger():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, danger=True, format='rich')
+    assert formatted == '<danger>WASP-80 b</danger>'
+
+
+def test_format_text_warning():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, warning=True, format='html')
+    assert formatted == '<span class="warning">WASP-80 b</span>'
+
+
+def test_format_text_danger1():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, danger=True, format='html')
+    assert formatted == '<span class="danger">WASP-80 b</span>'
+
+
+def test_format_text_danger2():
+    text = 'WASP-80 b'
+    formatted = u.format_text(text, warning=True, danger=True, format='html')
+    assert formatted == '<span class="danger">WASP-80 b</span>'
+
 
 def test_read_spectrum_file_success():
     pass