diff --git a/.github/workflows/docker-build-dev.yml b/.github/workflows/docker-build-dev.yml index e1968299ec..be32d7f22a 100644 --- a/.github/workflows/docker-build-dev.yml +++ b/.github/workflows/docker-build-dev.yml @@ -1,6 +1,4 @@ name: Dev - Build & Push docker images -permissions: - contents: read on: push: @@ -42,6 +40,8 @@ jobs: Setup: runs-on: ubuntu-latest environment: dev + permissions: + contents: read steps: - name: Get variables run: | @@ -61,6 +61,8 @@ jobs: needs: [Setup] runs-on: ubuntu-latest environment: dev + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v6 @@ -111,6 +113,8 @@ jobs: needs: [Setup,Branch,PushVariables] runs-on: ubuntu-latest environment: dev + permissions: + contents: read steps: - uses: actions/checkout@v6 - name: Build Docker images @@ -125,10 +129,10 @@ jobs: echo "$JFROG_PASSWORD" | docker login -u "$JFROG_USERNAME" --password-stdin $JFROG_SERVICE - name: Push application images to Artifactory container registry run: | - docker tag unity-grantmanager-dbmigrator $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator - docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator - docker tag unity-grantmanager-web $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web - docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web + docker tag unity-grantmanager-dbmigrator $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator:latest + docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator:latest + docker tag unity-grantmanager-web $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web:latest + docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web:latest - name: Disconnect docker from JFrog Artifactory run: | docker logout diff --git a/.github/workflows/docker-build-main.yml b/.github/workflows/docker-build-main.yml index 892ddbf95d..b146da454a 100644 --- a/.github/workflows/docker-build-main.yml +++ b/.github/workflows/docker-build-main.yml @@ -1,6 +1,4 @@ name: Main - Build & Push docker images -permissions: - contents: read on: push: @@ -42,6 +40,8 @@ jobs: Setup: runs-on: ubuntu-latest environment: main + permissions: + contents: read steps: - name: Get variables run: | @@ -61,6 +61,8 @@ jobs: needs: [Setup] runs-on: ubuntu-latest environment: main + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v6 @@ -168,6 +170,8 @@ jobs: needs: [Setup,Branch,GenerateTag,PushVariables] runs-on: ubuntu-latest environment: main + permissions: + contents: read steps: - uses: actions/checkout@v6 - name: Build Docker images diff --git a/.github/workflows/docker-build-test.yml b/.github/workflows/docker-build-test.yml index 96a43e594d..9728ee15d8 100644 --- a/.github/workflows/docker-build-test.yml +++ b/.github/workflows/docker-build-test.yml @@ -1,6 +1,4 @@ name: Test - Build & Push docker images -permissions: - contents: read on: push: @@ -42,6 +40,8 @@ jobs: Setup: runs-on: ubuntu-latest environment: test + permissions: + contents: read steps: - name: Get variables run: | @@ -61,6 +61,8 @@ jobs: needs: [Setup] runs-on: ubuntu-latest environment: test + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v6 @@ -89,6 +91,8 @@ jobs: needs: [Setup,Branch] runs-on: ubuntu-latest environment: test + permissions: + contents: write steps: - name: Checkout repository uses: actions/checkout@v6 @@ -114,6 +118,7 @@ jobs: needs: [Setup,Branch,GenerateTag] permissions: actions: write + contents: read runs-on: ubuntu-latest environment: test steps: @@ -144,6 +149,8 @@ jobs: needs: [Setup,Branch,GenerateTag,PushVariables] runs-on: ubuntu-latest environment: test + permissions: + contents: read steps: - uses: actions/checkout@v6 - name: Build Docker images @@ -158,10 +165,10 @@ jobs: echo "$JFROG_PASSWORD" | docker login -u "$JFROG_USERNAME" --password-stdin $JFROG_SERVICE - name: Push application images to Artifactory container registry run: | - docker tag unity-grantmanager-dbmigrator $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator - docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator - docker tag unity-grantmanager-web $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web - docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web + docker tag unity-grantmanager-dbmigrator $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator:latest + docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-dbmigrator:latest + docker tag unity-grantmanager-web $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web:latest + docker push $JFROG_SERVICE/$JFROG_REPO_PATH/unity-grantmanager-web:latest - name: Disconnect docker from JFrog Artifactory run: | docker logout diff --git a/.github/workflows/manual-trigger.yml b/.github/workflows/manual-trigger.yml index 8737a62c80..c34b9e697b 100644 --- a/.github/workflows/manual-trigger.yml +++ b/.github/workflows/manual-trigger.yml @@ -1,8 +1,6 @@ # This is a basic workflow that is manually triggered name: Workflow - Run manual trigger -permissions: - contents: read # Controls when the action will run. Workflow runs when manually triggered on: @@ -39,6 +37,8 @@ jobs: Setup: runs-on: ubuntu-latest environment: ${{ inputs.name }} + permissions: + contents: read steps: - name: Get variables run: | @@ -57,6 +57,8 @@ jobs: needs: [Setup] runs-on: ubuntu-latest environment: ${{ inputs.name }} + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v6 @@ -86,6 +88,7 @@ jobs: environment: ${{ inputs.name }} permissions: actions: write + contents: read steps: - name: Checkout repository uses: actions/checkout@v6 @@ -106,6 +109,8 @@ jobs: needs: [Setup,Branch,PushVariables] runs-on: ubuntu-latest environment: ${{ inputs.name }} + permissions: + contents: read steps: - uses: actions/checkout@v6 - name: Build Docker images diff --git a/.github/workflows/pr-check-dev-branch.yml b/.github/workflows/pr-check-dev-branch.yml index 80f6731abd..04ded4919b 100644 --- a/.github/workflows/pr-check-dev-branch.yml +++ b/.github/workflows/pr-check-dev-branch.yml @@ -1,9 +1,5 @@ name: Dev - Branch Protection - CI & Unit Tests -permissions: - contents: read - pull-requests: write - on: pull_request: branches: @@ -15,6 +11,8 @@ jobs: # --------------------------------------------------------------------- check-dev-branch: runs-on: ubuntu-latest + permissions: + contents: read outputs: branch-allowed: ${{ steps.branch-check.outputs.allowed }} steps: @@ -41,6 +39,8 @@ jobs: needs: check-dev-branch if: needs.check-dev-branch.outputs.branch-allowed == 'true' runs-on: ubuntu-latest + permissions: + contents: read outputs: matrix: ${{ steps.discover.outputs.matrix }} steps: @@ -60,6 +60,8 @@ jobs: test-project: needs: discover-test-projects runs-on: ubuntu-latest + permissions: + contents: read strategy: fail-fast: false @@ -69,7 +71,7 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 with: dotnet-version: "9.0.x" @@ -85,7 +87,7 @@ jobs: --logger "trx;LogFileName=${NAME}.trx" \ --results-directory TestResults - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: test-output-${{ strategy.job-index }} path: TestResults/ @@ -96,6 +98,9 @@ jobs: aggregate-results: needs: test-project runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write steps: - uses: actions/download-artifact@v4 with: @@ -133,7 +138,7 @@ jobs: echo "failed=$FAILED" >> $GITHUB_OUTPUT echo "skipped=$SKIPPED" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: merged-test-results path: merged/ diff --git a/.github/workflows/pr-check-main-branch.yml b/.github/workflows/pr-check-main-branch.yml index cbb297ba79..4b7d14bce2 100644 --- a/.github/workflows/pr-check-main-branch.yml +++ b/.github/workflows/pr-check-main-branch.yml @@ -1,8 +1,4 @@ name: Main - Branch Protection - CI & Unit Tests -permissions: - contents: read - pull-requests: write - issues: write on: pull_request: @@ -15,6 +11,8 @@ jobs: # --------------------------------------------------------------------- check-main-branch: runs-on: ubuntu-latest + permissions: + contents: read outputs: branch-allowed: ${{ steps.branch-check.outputs.allowed }} steps: @@ -37,6 +35,8 @@ jobs: needs: check-main-branch if: needs.check-main-branch.outputs.branch-allowed == 'true' runs-on: ubuntu-latest + permissions: + contents: read outputs: matrix: ${{ steps.discover.outputs.matrix }} steps: @@ -56,6 +56,8 @@ jobs: test-project: needs: discover-test-projects runs-on: ubuntu-latest + permissions: + contents: read strategy: fail-fast: false @@ -65,7 +67,7 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 with: dotnet-version: "9.0.x" @@ -81,7 +83,7 @@ jobs: --logger "trx;LogFileName=${NAME}.trx" \ --results-directory TestResults - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: test-output-${{ strategy.job-index }} path: TestResults/ @@ -92,6 +94,10 @@ jobs: aggregate-results: needs: test-project runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + issues: write steps: - uses: actions/download-artifact@v4 with: @@ -129,7 +135,7 @@ jobs: echo "failed=$FAILED" >> $GITHUB_OUTPUT echo "skipped=$SKIPPED" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: merged-test-results path: merged/ diff --git a/.github/workflows/pr-check-test-branch.yml b/.github/workflows/pr-check-test-branch.yml index 7deb972735..d823787d99 100644 --- a/.github/workflows/pr-check-test-branch.yml +++ b/.github/workflows/pr-check-test-branch.yml @@ -1,8 +1,4 @@ name: Test - Branch Protection - CI & Unit Tests -permissions: - contents: read - pull-requests: write - issues: write on: pull_request: @@ -15,6 +11,8 @@ jobs: # --------------------------------------------------------------------- check-test-branch: runs-on: ubuntu-latest + permissions: + contents: read outputs: branch-allowed: ${{ steps.branch-check.outputs.allowed }} steps: @@ -39,6 +37,8 @@ jobs: needs: check-test-branch if: needs.check-test-branch.outputs.branch-allowed == 'true' runs-on: ubuntu-latest + permissions: + contents: read outputs: matrix: ${{ steps.discover.outputs.matrix }} steps: @@ -58,6 +58,8 @@ jobs: test-project: needs: discover-test-projects runs-on: ubuntu-latest + permissions: + contents: read strategy: fail-fast: false @@ -67,7 +69,7 @@ jobs: steps: - uses: actions/checkout@v6 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v5 with: dotnet-version: "9.0.x" @@ -83,7 +85,7 @@ jobs: --logger "trx;LogFileName=${NAME}.trx" \ --results-directory TestResults - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: test-output-${{ strategy.job-index }} path: TestResults/ @@ -94,6 +96,10 @@ jobs: aggregate-results: needs: test-project runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + issues: write steps: - uses: actions/download-artifact@v4 with: @@ -131,7 +137,7 @@ jobs: echo "failed=$FAILED" >> $GITHUB_OUTPUT echo "skipped=$SKIPPED" >> $GITHUB_OUTPUT - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v5 with: name: merged-test-results path: merged/ diff --git a/.github/workflows/sonarsource-scan.yml b/.github/workflows/sonarsource-scan.yml new file mode 100644 index 0000000000..9e5ba89c6d --- /dev/null +++ b/.github/workflows/sonarsource-scan.yml @@ -0,0 +1,87 @@ +name: SonarCloud Analysis + +on: + push: + branches: + - dev2 + - dev + - test + - main + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + checks: write + security-events: write + +jobs: + sonarcloud: + name: SonarCloud + runs-on: ubuntu-latest + environment: ${{ github.ref_name == 'main' && 'main' || github.ref_name == 'test' && 'test' || 'dev' }} + steps: + - name: Set up JDK 17 + uses: actions/setup-java@v5 + with: + java-version: 17 + distribution: 'zulu' + + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '9.0.x' + + - name: Cache SonarCloud packages + uses: actions/cache@v5 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + + - name: Cache SonarCloud scanner + id: cache-sonar-scanner + uses: actions/cache@v5 + with: + path: ./.sonar/scanner + key: ${{ runner.os }}-sonar-scanner + restore-keys: ${{ runner.os }}-sonar-scanner + + - name: Install SonarCloud scanner + if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' + run: | + dotnet tool install --global dotnet-sonarscanner + + - name: Set version for SonarCloud + run: | + VERSION="${{ vars.UGM_BUILD_VERSION }}" + echo "Debug: UGM_BUILD_VERSION variable value: '$VERSION'" + if [ -z "$VERSION" ]; then + echo "BUILD_VERSION=1.0.0-dev" >> $GITHUB_ENV + echo "Using fallback version: 1.0.0-dev (UGM_BUILD_VERSION variable not set)" + else + echo "BUILD_VERSION=$VERSION" >> $GITHUB_ENV + echo "Using project version: $VERSION" + fi + + - name: Restore dependencies + working-directory: ./applications/Unity.GrantManager + run: dotnet restore Unity.GrantManager.sln + + - name: Build solution + working-directory: ./applications/Unity.GrantManager + run: dotnet build Unity.GrantManager.sln --no-restore + + - name: SonarCloud Scan + uses: SonarSource/sonarqube-scan-action@v7 + with: + projectBaseDir: applications/Unity.GrantManager + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file diff --git a/applications/Unity.AutoUI/cypress/e2e/basicEmail.cy.ts b/applications/Unity.AutoUI/cypress/e2e/basicEmail.cy.ts index 6ae85878e2..4eff6302d0 100644 --- a/applications/Unity.AutoUI/cypress/e2e/basicEmail.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/basicEmail.cy.ts @@ -1,4 +1,5 @@ // cypress/e2e/basicEmail.cy.ts +import { LoginPageInstance, NavigationPageInstance } from "../utilities"; describe("Send an email", () => { const TEST_EMAIL_TO = Cypress.env("TEST_EMAIL_TO") as string; @@ -32,123 +33,8 @@ describe("Send an email", () => { String(now.getSeconds()).padStart(2, "0"); const TEST_EMAIL_SUBJECT = `Smoke Test Email ${timestamp}`; - - function ensureLoggedInToGrantApplications() { - // Headless runs specs sequentially in the same browser process. - // Do not assume logged-out or logged-in. Detect UI state like chefsdata.cy.ts does. - cy.visit(Cypress.env("webapp.url")); - - cy.get("body", { timeout: STANDARD_TIMEOUT }).then(($body) => { - // Already authenticated - if ($body.find('button:contains("VIEW APPLICATIONS")').length > 0) { - cy.contains("VIEW APPLICATIONS", { timeout: STANDARD_TIMEOUT }).click({ - force: true, - }); - return; - } - - // Not authenticated - if ($body.find('button:contains("LOGIN")').length > 0) { - cy.contains("LOGIN", { timeout: STANDARD_TIMEOUT }) - .should("exist") - .click({ force: true }); - - cy.get("body", { timeout: STANDARD_TIMEOUT }).then(($loginBody) => { - // IDIR chooser may or may not appear - if ($loginBody.find(':contains("IDIR")').length > 0) { - cy.contains("IDIR", { timeout: STANDARD_TIMEOUT }).click({ - force: true, - }); - } - - cy.get("body", { timeout: STANDARD_TIMEOUT }).then(($authBody) => { - // Only type creds if the login form is actually present - if ($authBody.find("#user").length > 0) { - cy.get("#user", { timeout: STANDARD_TIMEOUT }).type( - Cypress.env("test1username"), - ); - cy.get("#password", { timeout: STANDARD_TIMEOUT }).type( - Cypress.env("test1password"), - ); - cy.contains("Continue", { timeout: STANDARD_TIMEOUT }).click({ - force: true, - }); - } else { - cy.log("Already authenticated"); - } - }); - }); - - return; - } - - throw new Error("Unable to determine authentication state"); - }); - - cy.location("pathname", { timeout: 30000 }).should( - "include", - "/GrantApplications", - ); - } - - function switchToDefaultGrantsProgramIfAvailable() { - cy.get("body").then(($body) => { - const hasUserInitials = $body.find(".unity-user-initials").length > 0; - - if (!hasUserInitials) { - cy.log("Skipping tenant: no user initials menu found"); - return; - } - - cy.get(".unity-user-initials").click(); - - cy.get("body").then(($body2) => { - const switchLink = $body2 - .find("#user-dropdown a.dropdown-item") - .filter((_, el) => { - return (el.textContent || "").trim() === "Switch Grant Programs"; - }); - - if (switchLink.length === 0) { - cy.log( - 'Skipping tenant: "Switch Grant Programs" not present for this user/session', - ); - cy.get("body").click(0, 0); - return; - } - - cy.wrap(switchLink.first()).click(); - - cy.url({ timeout: STANDARD_TIMEOUT }).should( - "include", - "/GrantPrograms", - ); - - cy.get("#search-grant-programs", { timeout: STANDARD_TIMEOUT }) - .should("be.visible") - .clear() - .type("Default Grants Program"); - - cy.get("#UserGrantProgramsTable", { timeout: STANDARD_TIMEOUT }) - .should("be.visible") - .within(() => { - cy.contains("tbody tr", "Default Grants Program", { - timeout: STANDARD_TIMEOUT, - }) - .should("exist") - .within(() => { - cy.contains("button", "Select").should("be.enabled").click(); - }); - }); - - cy.location("pathname", { timeout: STANDARD_TIMEOUT }).should((p) => { - expect( - p.indexOf("/GrantApplications") >= 0 || p.indexOf("/auth/") >= 0, - ).to.eq(true); - }); - }); - }); - } + const loginPage = LoginPageInstance(); + const navPage = NavigationPageInstance(); function openSavedEmailFromHistoryBySubject(subject: string) { cy.get("body", { timeout: STANDARD_TIMEOUT }).then(($body) => { @@ -231,11 +117,12 @@ describe("Send an email", () => { } it("Login", () => { - ensureLoggedInToGrantApplications(); + loginPage.login(); + loginPage.verifyOnGrantApplications(); }); it("Switch to Default Grants Program if available", () => { - switchToDefaultGrantsProgramIfAvailable(); + navPage.switchToDefaultGrantsProgramIfAvailable(); }); it("Handle IDIR if required", () => { @@ -368,6 +255,7 @@ describe("Send an email", () => { it("Save the email", () => { cy.get("#btn-save", { timeout: STANDARD_TIMEOUT }) .should("exist") + .scrollIntoView() .should("be.visible") .click(); @@ -391,6 +279,7 @@ describe("Send an email", () => { it("Send the email", () => { cy.get("#btn-send", { timeout: STANDARD_TIMEOUT }) .should("exist") + .scrollIntoView() .should("be.visible") .should("not.be.disabled") .click(); diff --git a/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts b/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts index 05fe3e5a54..76f4d4154f 100644 --- a/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/chefsdata.cy.ts @@ -1,9 +1,12 @@ /// // cypress/e2e/chefsdata.cy.ts +import { LoginPageInstance, NavigationPageInstance } from "../utilities"; describe('Unity Login and check data from CHEFS', () => { const STANDARD_TIMEOUT = 20000 + const loginPage = LoginPageInstance() + const navPage = NavigationPageInstance() // TEST renders the Submission tab inside an open shadow root (Form.io). // Enabling this makes cy.get / cy.contains pierce shadow DOM consistently across envs. @@ -12,42 +15,12 @@ describe('Unity Login and check data from CHEFS', () => { }) it('Verify Login', () => { - // 1.) Always start from the base URL - cy.visit(Cypress.env('webapp.url')) - - // 2.) Decide auth path based on visible UI - cy.get('body', { timeout: STANDARD_TIMEOUT }).then(($body) => { - // Already authenticated - if ($body.find('button:contains("VIEW APPLICATIONS")').length > 0) { - cy.contains('VIEW APPLICATIONS', { timeout: STANDARD_TIMEOUT }).click({ force: true }) - return - } - - // Not authenticated - if ($body.find('button:contains("LOGIN")').length > 0) { - cy.contains('LOGIN', { timeout: STANDARD_TIMEOUT }).should('exist').click({ force: true }) - cy.contains('IDIR', { timeout: STANDARD_TIMEOUT }).should('exist').click({ force: true }) - - cy.get('body', { timeout: STANDARD_TIMEOUT }).then(($loginBody) => { - // Perform IDIR login only if prompted - if ($loginBody.find('#user').length > 0) { - cy.get('#user', { timeout: STANDARD_TIMEOUT }).type(Cypress.env('test1username')) - cy.get('#password', { timeout: STANDARD_TIMEOUT }).type(Cypress.env('test1password')) - cy.contains('Continue', { timeout: STANDARD_TIMEOUT }).should('exist').click({ force: true }) - } else { - cy.log('Already logged in') - } - }) - - return - } - - // Fail loudly if neither state is detectable - throw new Error('Unable to determine authentication state') - }) + loginPage.login() + loginPage.verifyOnGrantApplications() + }) - // 3.) Post-condition check - cy.url({ timeout: STANDARD_TIMEOUT }).should('include', '/GrantApplications') + it('Switch to Default Grants Program if available', () => { + navPage.switchToDefaultGrantsProgramIfAvailable() }) // Verify that the details panel populates with mapped data @@ -228,6 +201,6 @@ describe('Unity Login and check data from CHEFS', () => { }) it('Verify Logout', () => { - cy.logout() + loginPage.quickLogout() }) }) diff --git a/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts b/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts index 7a3869f0ca..4ef0eda373 100644 --- a/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/lists.cy.ts @@ -1,145 +1,59 @@ -describe('Grant Manager Login and List Navigation', () => { - - function switchToDefaultGrantsProgramIfAvailable() { - cy.get('body').then(($body) => { - const hasUserInitials = $body.find('.unity-user-initials').length > 0 - - if (!hasUserInitials) { - cy.log('Skipping tenant switch: no user initials menu found') - return - } - - cy.get('.unity-user-initials').click() - - cy.get('body').then(($body2) => { - const switchLink = $body2.find('#user-dropdown a.dropdown-item').filter((_, el) => { - return (el.textContent || '').trim() === 'Switch Grant Programs' - }) - - if (switchLink.length === 0) { - cy.log('Skipping tenant switch: "Switch Grant Programs" not present') - cy.get('body').click(0, 0) - return - } +import { + ApplicationsPageInstance, + LoginPageInstance, + NavigationPageInstance, +} from '../utilities' - cy.wrap(switchLink.first()).click() - cy.url({ timeout: 20000 }).should('include', '/GrantPrograms') - - cy.get('#search-grant-programs', { timeout: 20000 }) - .should('be.visible') - .clear() - .type('Default Grants Program') - - cy.get('#UserGrantProgramsTable', { timeout: 20000 }) - .should('be.visible') - .within(() => { - cy.contains('tbody tr', 'Default Grants Program', { timeout: 20000 }) - .should('exist') - .within(() => { - cy.contains('button', 'Select') - .should('be.enabled') - .click() - }) - }) - - cy.location('pathname', { timeout: 20000 }).should((p) => { - expect( - p.indexOf('/GrantApplications') >= 0 || - p.indexOf('/auth/') >= 0 - ).to.eq(true) - }) - }) - }) - } +describe('Grant Manager Login and List Navigation', () => { + const loginPage = LoginPageInstance() + const navPage = NavigationPageInstance() + const appsPage = ApplicationsPageInstance() function setDashboardIntakeToTestIfAvailable() { const btnSel = 'button[data-id="dashboardIntakeId"]' const listboxSel = '#bs-select-1[role="listbox"]' const searchSel = 'input[type="search"][aria-controls="bs-select-1"]' - cy.get('body').then(($body) => { - if ($body.find(btnSel).length === 0) { - cy.log('Skipping intake switch: selector not found') - return - } + cy.get(btnSel, { timeout: 30000 }) + .should('be.visible') + .first() + .click({ force: true }) - cy.get(btnSel).first().click({ force: true }) - cy.get(listboxSel, { timeout: 20000 }).should('exist') + cy.get(listboxSel, { timeout: 30000 }).should('be.visible') - cy.get('body').then(($b2) => { - if ($b2.find(searchSel).length > 0) { - cy.get(searchSel).clear().type('Test') - } - }) + cy.get(searchSel, { timeout: 30000 }) + .should('be.visible') + .clear() + .type('Test') - cy.get(listboxSel).within(() => { - cy.get('a.dropdown-item[role="option"]').then(($opts) => { - const match = $opts.filter((_, el) => { - const text = el.querySelector('span.text')?.textContent || '' - return text.trim() === 'Test' - }) - - if (match.length === 0) { - cy.log('Skipping intake switch: Test not found') - return - } - - const el = match.get(0) - const selected = - el.getAttribute('aria-selected') === 'true' || - el.classList.contains('selected') - - if (!selected) { - cy.wrap(el).scrollIntoView().click({ force: true }) - } - }) + cy.contains(`${listboxSel} a.dropdown-item[role="option"] span.text`, /^Test$/, { timeout: 30000 }) + .closest('a.dropdown-item') + .then(($opt) => { + const selected = + $opt.attr('aria-selected') === 'true' || + $opt.hasClass('selected') + + if (!selected) { + cy.wrap($opt).scrollIntoView().click({ force: true }) + } }) - cy.get('body').click(0, 0) + cy.get('select#dashboardIntakeId option:selected').should(($opts) => { + const texts = Array.from($opts, (opt) => (opt.textContent || '').trim()) + expect(texts).to.include('Test') }) + + cy.get(btnSel).first().click({ force: true }) + cy.get(btnSel).first().should('have.attr', 'aria-expanded', 'false') } it('Verify Login', () => { - - cy.visit(Cypress.env('webapp.url')) - - cy.get('body').then(($body) => { - - if ($body.find('button:contains("VIEW APPLICATIONS")').length > 0) { - cy.contains('VIEW APPLICATIONS').click() - return - } - - if ($body.find('button:contains("LOGIN")').length > 0) { - cy.contains('LOGIN').click() - - cy.get('body').then(($loginBody) => { - if ($loginBody.find(':contains("IDIR")').length > 0) { - cy.contains('IDIR').click() - } - - cy.get('body').then(($authBody) => { - if ($authBody.find('#user').length > 0) { - cy.get('#user').type(Cypress.env('test1username')) - cy.get('#password').type(Cypress.env('test1password')) - cy.contains('Continue').click() - } else { - cy.log('Already authenticated') - } - }) - }) - - return - } - - throw new Error('Unable to determine authentication state') - }) - - cy.location('pathname', { timeout: 30000 }).should('include', '/GrantApplications') + loginPage.login() + loginPage.verifyOnGrantApplications() }) it('Switch to Default Grants Program if available', () => { - switchToDefaultGrantsProgramIfAvailable() + navPage.switchToDefaultGrantsProgramIfAvailable() }) it('Handle IDIR if required', () => { @@ -154,37 +68,37 @@ describe('Grant Manager Login and List Navigation', () => { it('Verify Applications, Roles, Users, Intakes, Forms, Dashboard lists are populated', () => { - cy.get('.unity-user-initials').should('exist').click() - cy.get('#user-dropdown .btn-dropdown span') - .should('contain', 'Default Grants Program') + navPage.verifyCurrentTenant('Default Grants Program') - cy.contains("Applications").click() - cy.get('tbody tr').should('have.length.at.least', 1) + navPage.goToApplications() + appsPage.verifyListHasData() - cy.contains("Roles").click() + navPage.goToRoles() cy.get('tbody tr').should('have.length.at.least', 1) - cy.contains("Users").click() + navPage.goToUsers() cy.get('tbody tr').should('have.length.at.least', 1) - cy.contains("Intakes").click() + navPage.goToIntakes() cy.get('tbody tr').should('have.length.at.least', 1) - cy.contains("Forms").click() + navPage.goToForms() cy.get('tbody tr').should('have.length.at.least', 1) - cy.contains("Dashboard").click() + navPage.goToDashboard() + cy.location('pathname', { timeout: 30000 }).should('include', '/Dashboard') setDashboardIntakeToTestIfAvailable() - cy.get('#applicationStatusChart text') + cy.get('#applicationStatusChart text', { timeout: 30000 }) .first() - .invoke('text') - .then(n => expect(parseInt(n, 10)).to.be.gt(0)) + .should(($el) => { + expect(parseInt($el.text(), 10)).to.be.gt(0) + }) cy.visit(Cypress.env('webapp.url')) }) it('Verify Logout', () => { - cy.logout() + loginPage.quickLogout() }) }) diff --git a/applications/Unity.AutoUI/cypress/e2e/login.cy.ts b/applications/Unity.AutoUI/cypress/e2e/login.cy.ts index 274e68ffaf..3735041179 100644 --- a/applications/Unity.AutoUI/cypress/e2e/login.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/login.cy.ts @@ -1,55 +1,17 @@ +import { LoginPageInstance, NavigationPageInstance } from "../utilities"; + describe('Grant Manager Login and Logout', () => { + const loginPage = LoginPageInstance() + const navPage = NavigationPageInstance() it('Verify Default Grant Program tenant is selected.', () => { - - // Always start from the base URL - cy.visit(Cypress.env('webapp.url')) - - // Determine authentication state from UI - cy.get('body').then(($body) => { - - // Already authenticated - if ($body.find('button:contains("VIEW APPLICATIONS")').length > 0) { - cy.contains('VIEW APPLICATIONS').click() - return - } - - // Not authenticated - if ($body.find('button:contains("LOGIN")').length > 0) { - cy.contains('LOGIN').click() - - cy.get('body').then(($loginBody) => { - - // IDIR chooser may or may not appear - if ($loginBody.find(':contains("IDIR")').length > 0) { - cy.contains('IDIR').click() - } - - cy.get('body').then(($authBody) => { - if ($authBody.find('#user').length > 0) { - cy.get('#user').type(Cypress.env('test1username')) - cy.get('#password').type(Cypress.env('test1password')) - cy.contains('Continue').click() - } - }) - }) - - return - } - - throw new Error('Unable to determine authentication state') - }) - - // Verify we landed in the authenticated app - cy.location('pathname', { timeout: 30000 }) - .should('include', '/GrantApplications') + loginPage.login() + loginPage.verifyOnGrantApplications() // Verify Default Grant Program tenant is selected - cy.get('.unity-user-initials').should('exist').click() - cy.get('#user-dropdown .btn-dropdown span') - .should('contain', 'Default Grants Program') + navPage.verifyCurrentTenant('Default Grants Program') // Logout (terminal action) - cy.logout() + loginPage.quickLogout() }) }) diff --git a/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts b/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts index 0cb046669f..6bcf9a65df 100644 --- a/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/navigation.cy.ts @@ -1,83 +1,48 @@ +import { LoginPageInstance, NavigationPageInstance } from "../utilities"; + describe('Grant Manager Login and Top Navigation', () => { + const loginPage = LoginPageInstance() + const navPage = NavigationPageInstance() it('Verify Login', () => { - - // Always start from the base URL - cy.visit(Cypress.env('webapp.url')) - - cy.get('body').then(($body) => { - - // Already authenticated - if ($body.find('button:contains("VIEW APPLICATIONS")').length > 0) { - cy.contains('VIEW APPLICATIONS').click() - return - } - - // Not authenticated - if ($body.find('button:contains("LOGIN")').length > 0) { - cy.contains('LOGIN').click() - - cy.get('body').then(($loginBody) => { - - // IDIR chooser may or may not appear - if ($loginBody.find(':contains("IDIR")').length > 0) { - cy.contains('IDIR').click() - } - - cy.get('body').then(($authBody) => { - if ($authBody.find('#user').length > 0) { - cy.get('#user').type(Cypress.env('test1username')) - cy.get('#password').type(Cypress.env('test1password')) - cy.contains('Continue').click() - } - }) - }) - - return - } - - throw new Error('Unable to determine authentication state') - }) - - cy.location('pathname', { timeout: 30000 }) - .should('include', '/GrantApplications') + loginPage.login() + loginPage.verifyOnGrantApplications() }) it('Verify navigation options in the top banner', () => { // 3.) Verify Default Grant Program tenant is selected. - cy.get('.unity-user-initials').should('exist').click() - cy.get('#user-dropdown .btn-dropdown span') - .should('contain', 'Default Grants Program') + navPage.verifyCurrentTenant('Default Grants Program') // 4.) Ensure all expected headings are present. + navPage.verifyAllNavItemsExist() // 5.) Applications - cy.contains('Applications').should('exist').click() + navPage.goToApplications() // 6.) Roles - cy.contains('Roles').should('exist').click() + navPage.goToRoles() // 7.) Users - cy.contains('Users').should('exist').click() + navPage.goToUsers() // 8.) Intakes - cy.contains('Intakes').should('exist').click() + navPage.goToIntakes() // 9.) Forms - cy.contains('Forms').should('exist').click() + navPage.goToForms() // 10.) Dashboard - cy.contains('Dashboard').should('exist').click() + navPage.goToDashboard() // 11.) Payments - cy.contains('Payments').should('exist').click() + navPage.goToPayments() // Return to top cy.visit(Cypress.env('webapp.url')) }) it('Verify Logout', () => { - cy.logout() + loginPage.quickLogout() }) }) diff --git a/applications/Unity.AutoUI/cypress/pages/ApplicationDetailsPage.ts b/applications/Unity.AutoUI/cypress/pages/ApplicationDetailsPage.ts index 550c95ff22..14e171027c 100644 --- a/applications/Unity.AutoUI/cypress/pages/ApplicationDetailsPage.ts +++ b/applications/Unity.AutoUI/cypress/pages/ApplicationDetailsPage.ts @@ -110,11 +110,19 @@ export class ApplicationDetailsPage extends BasePage { super(); } + private activateTab(tabSelector: string): void { + cy.get(tabSelector, { timeout: 20000 }) + .scrollIntoView() + .should("be.visible") + .click({ force: true }) + .should("have.class", "active"); + } + /** * Navigate to Submission tab */ goToSubmissionTab(): this { - this.clickElement(this.tabs.submission); + this.activateTab(this.tabs.submission); return this; } @@ -123,7 +131,7 @@ export class ApplicationDetailsPage extends BasePage { */ goToReviewAssessmentTab(): this { this.dismissErrorModalIfPresent(); - this.clickElement(this.tabs.reviewAssessment); + this.activateTab(this.tabs.reviewAssessment); return this; } @@ -131,7 +139,7 @@ export class ApplicationDetailsPage extends BasePage { * Navigate to Project Info tab */ goToProjectInfoTab(): this { - this.clickElement(this.tabs.projectInfo); + this.activateTab(this.tabs.projectInfo); return this; } @@ -139,7 +147,7 @@ export class ApplicationDetailsPage extends BasePage { * Navigate to Applicant Info tab */ goToApplicantInfoTab(): this { - this.clickElement(this.tabs.applicantInfo); + this.activateTab(this.tabs.applicantInfo); return this; } @@ -147,7 +155,7 @@ export class ApplicationDetailsPage extends BasePage { * Navigate to Funding Agreement tab */ goToFundingAgreementTab(): this { - this.clickElement(this.tabs.fundingAgreement); + this.activateTab(this.tabs.fundingAgreement); return this; } @@ -155,7 +163,7 @@ export class ApplicationDetailsPage extends BasePage { * Navigate to Payment Info tab */ goToPaymentInfoTab(): this { - this.clickElement(this.tabs.paymentInfo); + this.activateTab(this.tabs.paymentInfo); return this; } @@ -597,12 +605,30 @@ export class ApplicationDetailsPage extends BasePage { */ dismissErrorModalIfPresent(): this { cy.get("body").then(($body) => { - // Only dismiss if it is specifically an error modal (swal2-error icon) - if ($body.find(".swal2-container .swal2-icon.swal2-error").length > 0) { - cy.get(".swal2-container") - .find(".swal2-confirm") - .first() - .click({ force: true }); + const hasSwalError = + $body.find(".swal2-container .swal2-icon.swal2-error").length > 0; + const hasTokenErrorText = + $body.text().includes("GetAuthTokenAsync") || + $body.text().includes("Error retrieving Token"); + + if (hasSwalError || hasTokenErrorText) { + if ($body.find(".swal2-container .swal2-confirm").length > 0) { + cy.get(".swal2-container") + .find(".swal2-confirm") + .first() + .click({ force: true }); + } else if ($body.find(".modal.show button").length > 0) { + cy.get(".modal.show") + .contains("button", /^ok$/i) + .click({ force: true }); + } + + cy.wait(500); + } + + if ($body.find(".modal.show .btn-close").length > 0) { + cy.get(".modal.show .btn-close").first().click({ force: true }); + cy.get(".swal2-container").should("not.exist"); cy.wait(500); } }); diff --git a/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts b/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts index 108d6b0cfe..52c129791a 100644 --- a/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts +++ b/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts @@ -37,7 +37,8 @@ export class ApplicationsListPage extends ApplicationsPage { private readonly extendedActionBar = { customButtons: "#app_custom_buttons", dynamicButtonContainer: "#dynamicButtonContainerId", - exportButton: "#dynamicButtonContainerId .dt-buttons button span", + exportButton: + "#dynamicButtonContainerId .dt-buttons button, #dynamicButtonContainerId .dt-buttons button span", saveViewButton: "button.grp-savedStates", }; @@ -62,6 +63,11 @@ export class ApplicationsListPage extends ApplicationsPage { cancelButton: "#payment-modal .modal-footer button", }; + private readonly blockingUi = { + bootstrapModal: ".modal.show", + swalContainer: ".swal2-container", + }; + // Grant program selectors private readonly grantProgram = { userInitials: ".unity-user-initials", @@ -94,10 +100,13 @@ export class ApplicationsListPage extends ApplicationsPage { | "last3months" | "last6months" | "alltime" - | "custom" + | "custom", ): this { + this.waitForNoBlockingOverlay(); cy.get(this.dateFilters.quickDateRange, { timeout: this.STANDARD_TIMEOUT }) + .scrollIntoView() .should("be.visible") + .and("not.be.disabled") .select(range); return this; } @@ -127,10 +136,11 @@ export class ApplicationsListPage extends ApplicationsPage { | "last3months" | "last6months" | "alltime" - | "custom" + | "custom", ): this { - cy.get(this.dateFilters.quickDateRange, { timeout: this.STANDARD_TIMEOUT }) - .should("have.value", expectedValue); + cy.get(this.dateFilters.quickDateRange, { + timeout: this.STANDARD_TIMEOUT, + }).should("have.value", expectedValue); return this; } @@ -139,12 +149,16 @@ export class ApplicationsListPage extends ApplicationsPage { * @deprecated Use selectQuickDateRange() instead. This method is for custom date ranges only. */ setSubmittedFromDate(date: string): this { - cy.get(this.dateFilters.submittedFromDate, { timeout: this.STANDARD_TIMEOUT }) - .click({ force: true }) - .clear({ force: true }) - .type(date, { force: true }) - .trigger("change", { force: true }) - .blur({ force: true }) + cy.get(this.dateFilters.submittedFromDate, { + timeout: this.STANDARD_TIMEOUT, + }) + .scrollIntoView() + .should("be.visible") + .click() + .clear() + .type(date) + .trigger("change") + .blur() .should("have.value", date); return this; } @@ -154,11 +168,13 @@ export class ApplicationsListPage extends ApplicationsPage { */ setSubmittedToDate(date: string): this { cy.get(this.dateFilters.submittedToDate, { timeout: this.STANDARD_TIMEOUT }) - .click({ force: true }) - .clear({ force: true }) - .type(date, { force: true }) - .trigger("change", { force: true }) - .blur({ force: true }) + .scrollIntoView() + .should("be.visible") + .click() + .clear() + .type(date) + .trigger("change") + .blur() .should("have.value", date); return this; } @@ -172,7 +188,7 @@ export class ApplicationsListPage extends ApplicationsPage { cy.wrap($s) .should("have.attr", "style") .and("contain", "display: none"); - } + }, ); return this; } @@ -203,9 +219,12 @@ export class ApplicationsListPage extends ApplicationsPage { * Select a row by matching text content */ selectRowByText(text: string): this { + this.waitForNoBlockingOverlay(); cy.contains("tr", text, { timeout: this.STANDARD_TIMEOUT }) + .scrollIntoView() .find(".checkbox-select") - .click({ force: true }); + .should("be.visible") + .click(); return this; } @@ -215,7 +234,8 @@ export class ApplicationsListPage extends ApplicationsPage { clickOpenButton(): this { cy.get("#externalLink", { timeout: this.STANDARD_TIMEOUT }) .should("exist") - .click({ force: true }); + .should("be.visible") + .click(); return this; } @@ -225,10 +245,59 @@ export class ApplicationsListPage extends ApplicationsPage { * Verify table has rows (using scroll body selector) */ verifyTableHasData(): this { - cy.get(this.scrollTable.tableRows, { timeout: this.STANDARD_TIMEOUT }).should( - "have.length.greaterThan", - 1 - ); + cy.get(this.scrollTable.tableRows, { + timeout: this.STANDARD_TIMEOUT, + }).should("have.length.greaterThan", 1); + return this; + } + + /** + * Dispatch a native mouse click sequence against the current target cell. + * This avoids Cypress holding a stale DOM reference while DataTables redraws. + */ + private clickRowCellNative(rowIndex: number, withCtrl = false): this { + this.waitForNoBlockingOverlay(); + + cy.window({ log: false }).then((win: Cypress.AUTWindow) => { + cy.get(this.scrollTable.tableRows, { + timeout: this.STANDARD_TIMEOUT, + }) + .should("have.length.greaterThan", rowIndex) + .eq(rowIndex) + .should("exist") + .then(($row: JQuery) => { + const $cell = $row.find("td").not(":has(a)").first(); + + expect( + $cell.length, + `row ${rowIndex} should contain at least one non-link cell`, + ).to.be.greaterThan(0); + + const cell = $cell[0] as HTMLElement; + + cell.scrollIntoView({ + block: "center", + inline: "nearest", + }); + + const eventInit: MouseEventInit = { + bubbles: true, + cancelable: true, + view: win, + ctrlKey: withCtrl, + metaKey: withCtrl, + button: 0, + buttons: 1, + }; + + cell.dispatchEvent(new win.MouseEvent("mouseover", eventInit)); + cell.dispatchEvent(new win.MouseEvent("mousemove", eventInit)); + cell.dispatchEvent(new win.MouseEvent("mousedown", eventInit)); + cell.dispatchEvent(new win.MouseEvent("mouseup", eventInit)); + cell.dispatchEvent(new win.MouseEvent("click", eventInit)); + }); + }); + return this; } @@ -236,13 +305,7 @@ export class ApplicationsListPage extends ApplicationsPage { * Select a row by index (clicks on a non-link cell) */ selectRowByIndex(rowIndex: number, withCtrl = false): this { - cy.get(this.scrollTable.tableRows, { timeout: this.STANDARD_TIMEOUT }) - .eq(rowIndex) - .find("td") - .not(":has(a)") - .first() - .click({ force: true, ctrlKey: withCtrl }); - return this; + return this.clickRowCellNative(rowIndex, withCtrl); } /** @@ -274,7 +337,9 @@ export class ApplicationsListPage extends ApplicationsPage { .then(($els: JQuery) => { const titles: string[] = Cypress.$($els) .toArray() - .map((el: HTMLElement) => (el.textContent || "").replace(/\s+/g, " ").trim()) + .map((el: HTMLElement) => + (el.textContent || "").replace(/\s+/g, " ").trim(), + ) .filter((t: string) => t.length > 0); return titles; }); @@ -287,10 +352,9 @@ export class ApplicationsListPage extends ApplicationsPage { this.getVisibleHeaderTitles().then((titles: string[]) => { const titlesLower = titles.map((t: string) => t.toLowerCase()); expected.forEach((e: string) => { - expect( - titlesLower, - `visible headers should include "${e}"` - ).to.include(e.toLowerCase()); + expect(titlesLower, `visible headers should include "${e}"`).to.include( + e.toLowerCase(), + ); }); }); return this; @@ -302,7 +366,9 @@ export class ApplicationsListPage extends ApplicationsPage { * Scroll to and verify action bar exists */ verifyActionBarExists(): this { - cy.get(this.extendedActionBar.customButtons, { timeout: this.STANDARD_TIMEOUT }) + cy.get(this.extendedActionBar.customButtons, { + timeout: this.STANDARD_TIMEOUT, + }) .should("exist") .scrollIntoView(); return this; @@ -312,10 +378,11 @@ export class ApplicationsListPage extends ApplicationsPage { * Click the Payment button (extended with visibility checks) */ clickPaymentButtonWithWait(): this { + this.waitForNoBlockingOverlay(); cy.get("#applicationPaymentRequest", { timeout: this.BUTTON_TIMEOUT }) .should("be.visible") .and("not.be.disabled") - .click({ force: true }); + .click(); return this; } @@ -325,7 +392,10 @@ export class ApplicationsListPage extends ApplicationsPage { verifyExportButtonVisible(): this { cy.contains(this.extendedActionBar.exportButton, "Export", { timeout: this.STANDARD_TIMEOUT, - }).should("be.visible"); + matchCase: false, + }) + .scrollIntoView() + .should("be.visible"); return this; } @@ -336,7 +406,7 @@ export class ApplicationsListPage extends ApplicationsPage { cy.contains( "#dynamicButtonContainerId button.grp-savedStates", "Save View", - { timeout: this.STANDARD_TIMEOUT } + { timeout: this.STANDARD_TIMEOUT }, ).should("be.visible"); return this; } @@ -346,10 +416,12 @@ export class ApplicationsListPage extends ApplicationsPage { */ verifyColumnsButtonVisible(): this { cy.contains( - "#dynamicButtonContainerId .dt-buttons button span", + "#dynamicButtonContainerId .dt-buttons button, #dynamicButtonContainerId .dt-buttons button span", "Columns", - { timeout: this.STANDARD_TIMEOUT } - ).should("be.visible"); + { timeout: this.STANDARD_TIMEOUT, matchCase: false }, + ) + .scrollIntoView() + .should("be.visible"); return this; } @@ -374,6 +446,27 @@ export class ApplicationsListPage extends ApplicationsPage { cy.get(this.paymentModal.modal, { timeout: this.STANDARD_TIMEOUT }) .should("be.visible") .and("have.class", "show"); + cy.get(this.paymentModal.backdrop, { + timeout: this.STANDARD_TIMEOUT, + }).should("exist"); + return this; + } + + /** + * Wait for blocking modal overlays to clear before interacting with list controls. + */ + waitForNoBlockingOverlay(): this { + cy.get(this.blockingUi.swalContainer, { + timeout: this.STANDARD_TIMEOUT, + }).should("not.exist"); + + cy.get(this.blockingUi.bootstrapModal, { + timeout: this.STANDARD_TIMEOUT, + }).should("not.exist"); + + cy.get(this.paymentModal.backdrop, { + timeout: this.STANDARD_TIMEOUT, + }).should("not.exist"); return this; } @@ -381,56 +474,71 @@ export class ApplicationsListPage extends ApplicationsPage { * Close payment modal using multiple strategies */ closePaymentModal(): this { - // Attempt ESC key - cy.get("body").type("{esc}", { force: true }); - - // Click backdrop if present (check existence first to avoid timeout) cy.get("body").then(($body: JQuery) => { - if ($body.find(this.paymentModal.backdrop).length > 0) { - cy.get(this.paymentModal.backdrop).click("topLeft", { force: true }); + if ($body.find(`${this.paymentModal.modal}.show`).length === 0) { + return; } - }); - // Try Cancel button if available (check existence first to avoid timeout) - cy.get("body").then(($body: JQuery) => { - const $cancelBtn = $body.find(this.paymentModal.cancelButton).filter( - (_: number, el: HTMLElement) => (el.textContent || "").includes("Cancel") - ); + const $cancelBtn = $body + .find(this.paymentModal.cancelButton) + .filter((_: number, el: HTMLElement) => + (el.textContent || "").includes("Cancel"), + ); + if ($cancelBtn.length > 0) { cy.wrap($cancelBtn.first()).scrollIntoView().click({ force: true }); - } else { - cy.log("Cancel button not present, proceeding to hard-close fallback"); } }); - // Hard close fallback using jQuery - cy.window().then((win: Cypress.AUTWindow) => { - try { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const windowWithModal = win as any; - if (typeof windowWithModal.closePaymentModal === "function") { - windowWithModal.closePaymentModal(); - } - } catch { - /* ignore */ + cy.get("body").then(($body: JQuery) => { + if ($body.find(`${this.paymentModal.modal}.show`).length > 0) { + cy.get("body").type("{esc}", { force: true }); + } + }); + + cy.get("body").then(($body: JQuery) => { + if ( + $body.find(`${this.paymentModal.modal}.show`).length > 0 && + $body.find(this.paymentModal.backdrop).length > 0 + ) { + cy.get(this.paymentModal.backdrop).first().click("topLeft", { + force: true, + }); } + }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const $ = (win as any).jQuery || (win as any).$; - if ($) { - try { - $("#payment-modal") - .removeClass("show") - .attr("aria-hidden", "true") - .css("display", "none"); - $(".modal-backdrop").remove(); - $("body").removeClass("modal-open").css("overflow", ""); - } catch { - /* ignore */ - } + cy.get("body").then(($body: JQuery) => { + if ($body.find(`${this.paymentModal.modal}.show`).length > 0) { + cy.window().then((win: Cypress.AUTWindow) => { + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const windowWithModal = win as any; + if (typeof windowWithModal.closePaymentModal === "function") { + windowWithModal.closePaymentModal(); + } + } catch { + /* ignore */ + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const $ = (win as any).jQuery || (win as any).$; + if ($) { + try { + $(this.paymentModal.modal) + .removeClass("show") + .attr("aria-hidden", "true") + .css("display", "none"); + $(this.paymentModal.backdrop).remove(); + $("body").removeClass("modal-open").css("overflow", ""); + } catch { + /* ignore */ + } + } + }); } }); - return this; + + return this.verifyPaymentModalClosed(); } /** @@ -441,16 +549,19 @@ export class ApplicationsListPage extends ApplicationsPage { ($m: JQuery) => { const isHidden = !$m.is(":visible") || !$m.hasClass("show"); expect(isHidden, "payment-modal hidden or not shown").to.eq(true); - } - ); - cy.get(this.paymentModal.backdrop, { timeout: this.STANDARD_TIMEOUT }).should( - "not.exist" + }, ); + + cy.get(this.paymentModal.backdrop, { + timeout: this.STANDARD_TIMEOUT, + }).should("not.exist"); + + cy.get(this.blockingUi.bootstrapModal, { + timeout: this.STANDARD_TIMEOUT, + }).should("not.exist"); return this; } - // ============ Columns Menu Methods ============ - /** * Close any open dropdowns or modals */ @@ -475,14 +586,13 @@ export class ApplicationsListPage extends ApplicationsPage { cy.contains(this.saveView.resetOption, "Reset to Default View", { timeout: this.STANDARD_TIMEOUT, }) - .should("exist") - .click({ force: true }); + .should("be.visible") + .click(); // Wait for table to rebuild - cy.get(this.scrollTable.columnTitles, { timeout: this.STANDARD_TIMEOUT }).should( - "have.length.gt", - 5 - ); + cy.get(this.scrollTable.columnTitles, { + timeout: this.STANDARD_TIMEOUT, + }).should("have.length.gt", 5); return this; } @@ -490,15 +600,19 @@ export class ApplicationsListPage extends ApplicationsPage { * Open the Columns menu */ openColumnsMenu(): this { - cy.contains("span", "Columns", { timeout: this.STANDARD_TIMEOUT }) + cy.contains( + "#dynamicButtonContainerId .dt-buttons button, #dynamicButtonContainerId .dt-buttons button span", + "Columns", + { timeout: this.STANDARD_TIMEOUT, matchCase: false }, + ) + .scrollIntoView() .should("be.visible") .click(); // Wait for dropdown to be fully populated - cy.get(this.columnsMenu.dropdownItem, { timeout: this.STANDARD_TIMEOUT }).should( - "have.length.gt", - 50 - ); + cy.get(this.columnsMenu.dropdownItem, { + timeout: this.STANDARD_TIMEOUT, + }).should("have.length.gt", 50); return this; } @@ -510,9 +624,16 @@ export class ApplicationsListPage extends ApplicationsPage { timeout: this.STANDARD_TIMEOUT, matchCase: false, }) - .should("exist") .scrollIntoView() - .click({ force: true }); + .should("exist") + .then(($item) => { + if (Cypress.dom.isVisible($item)) { + cy.wrap($item).click(); + } else { + // Some dropdown items are clipped by overflow containers; native click still triggers menu toggle reliably. + ($item[0] as HTMLElement).click(); + } + }); return this; } @@ -530,7 +651,9 @@ export class ApplicationsListPage extends ApplicationsPage { * Close the Columns menu */ closeColumnsMenu(): this { - cy.get(this.columnsMenu.buttonBackground, { timeout: this.STANDARD_TIMEOUT }) + cy.get(this.columnsMenu.buttonBackground, { + timeout: this.STANDARD_TIMEOUT, + }) .should("exist") .click({ force: true }); @@ -567,7 +690,7 @@ export class ApplicationsListPage extends ApplicationsPage { if (switchLink.length === 0) { cy.log( - 'Skipping tenant switch: "Switch Grant Programs" not present for this user/session' + 'Skipping tenant switch: "Switch Grant Programs" not present for this user/session', ); cy.get("body").click(0, 0); return; @@ -577,10 +700,12 @@ export class ApplicationsListPage extends ApplicationsPage { cy.url({ timeout: this.STANDARD_TIMEOUT }).should( "include", - "/GrantPrograms" + "/GrantPrograms", ); - cy.get(this.grantProgram.searchInput, { timeout: this.STANDARD_TIMEOUT }) + cy.get(this.grantProgram.searchInput, { + timeout: this.STANDARD_TIMEOUT, + }) .should("be.visible") .clear() .type(programName); @@ -596,9 +721,9 @@ export class ApplicationsListPage extends ApplicationsPage { cy.location("pathname", { timeout: this.STANDARD_TIMEOUT }).should( (p: string) => { expect( - p.indexOf("/GrantApplications") >= 0 || p.indexOf("/auth/") >= 0 + p.indexOf("/GrantApplications") >= 0 || p.indexOf("/auth/") >= 0, ).to.eq(true); - } + }, ); }); }); diff --git a/applications/Unity.AutoUI/cypress/pages/LoginPage.ts b/applications/Unity.AutoUI/cypress/pages/LoginPage.ts index 71a836e1d8..ea146d5c07 100644 --- a/applications/Unity.AutoUI/cypress/pages/LoginPage.ts +++ b/applications/Unity.AutoUI/cypress/pages/LoginPage.ts @@ -1,4 +1,5 @@ import { BasePage } from "./BasePage"; +import { loginIfNeeded } from "../support/auth"; /** * LoginPage - Page Object for Login/Authentication functionality @@ -24,27 +25,24 @@ export class LoginPage extends BasePage { * Perform login with credentials */ login(username?: string, password?: string): void { - this.visit(); - this.clickByText(this.selectors.loginButton); - this.wait(1000); - this.clickByText(this.selectors.idirButton); - this.wait(1000); - - // Check if already logged in - cy.get("body").then(($body) => { - if ($body.find(this.selectors.usernameField).length) { - const user = username || Cypress.env("test1username"); - const pass = password || Cypress.env("test1password"); - - this.typeText(this.selectors.usernameField, user); - this.typeText(this.selectors.passwordField, pass); - this.clickByText(this.selectors.continueButton); - } else { - cy.log("Already logged in"); - } + loginIfNeeded({ + username, + password, + timeout: 30000, + baseUrl: Cypress.env("webapp.url"), }); } + /** + * Verify we are on the authenticated applications page + */ + verifyOnGrantApplications(): void { + cy.location("pathname", { timeout: 30000 }).should( + "include", + "/GrantApplications", + ); + } + /** * Perform logout */ @@ -81,7 +79,7 @@ export class LoginPage extends BasePage { * Quick login using custom command (backward compatibility) */ quickLogin(): void { - cy.login(); + this.login(); } /** diff --git a/applications/Unity.AutoUI/cypress/pages/NavigationPage.ts b/applications/Unity.AutoUI/cypress/pages/NavigationPage.ts index 84da532ae6..1ea703ba93 100644 --- a/applications/Unity.AutoUI/cypress/pages/NavigationPage.ts +++ b/applications/Unity.AutoUI/cypress/pages/NavigationPage.ts @@ -31,6 +31,7 @@ export class NavigationPage extends BasePage { * Verify current tenant name */ verifyCurrentTenant(tenantName: string): void { + this.clickUserMenu(); cy.get(this.tenantDropdown).should("contain", tenantName); } @@ -101,6 +102,13 @@ export class NavigationPage extends BasePage { }); } + /** + * Switch to the default grant program if available for the current session + */ + switchToDefaultGrantsProgramIfAvailable(): void { + this.switchToTenantIfAvailable("Default Grants Program"); + } + /** * Navigate to Applications page */ diff --git a/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts b/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts index 5b480b2aab..67e9a4e6cf 100644 --- a/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts +++ b/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts @@ -35,6 +35,7 @@ const TEST_CONFIG = { submissionId: null as string | null, grantProgram: "Default Grants Program", approvedAmount: "5000", + assignOwner: "Unity User1", supplierNumber: Cypress.env("environment") === "TEST" ? "2002712" : "2009366", paymentGroup: "Cheque" as const, testComment: "Test comment from automated regression test", @@ -48,6 +49,24 @@ const TEST_CONFIG = { }, }; +const STATUS_ACTIONS = { + menuButton: "#ApplicationActionDropdown .dropdown-toggle", + menu: "#ApplicationActionDropdown .dropdown-menu", + startReview: "#Application_StartReviewButton", + completeReview: "#Application_CompleteReviewButton", + startAssessment: "#Application_StartAssessmentButton", + completeAssessment: "#Application_CompleteAssessmentButton", + approve: "#Application_ApproveButton", +}; + +const ADJUDICATION_ACTIONS = { + completeAssessment: "#AdjudicationTeamLeadActionBar #CompleteButton", +}; + +const BREADCRUMB_STATUS_SELECTOR = + ".application-details-breadcrumb .application-status"; +const APPLICATIONS_PATH = "GrantApplications"; + (isProd ? describe.skip : describe)("Approval Flow Regression Test", () => { // Page object instances reused across all tests const listPage = new ApplicationsListPage(); @@ -63,6 +82,7 @@ const TEST_CONFIG = { /** Navigate to the Payments tab and filter the table by submissionId. */ function navigateToPaymentsAndSearch(): void { + listPage.waitForNoBlockingOverlay(); cy.reload(); navPage.goToPayments(); cy.location("pathname", { timeout: 20000 }).should("include", "Payment"); @@ -73,9 +93,338 @@ const TEST_CONFIG = { cy.contains("tr", submissionId, { timeout: 20000 }).should("exist"); } + function navigateToApplicationsList(): void { + cy.location("pathname", { timeout: 20000 }).then((pathname) => { + if (!pathname.includes(`/${APPLICATIONS_PATH}`)) { + cy.visit(`${Cypress.env("webapp.url")}${APPLICATIONS_PATH}`); + } + }); + listPage.waitForNoBlockingOverlay(); + } + + /** + * Seeded submissions can take time to appear in the Grant Applications list. + * Poll the list with a refresh until the row becomes searchable. + */ + function waitForSubmissionToAppearInList( + attempt = 1, + maxAttempts = 8, + ): Cypress.Chainable { + navigateToApplicationsList(); + dismissBlockingModalIfPresent(); + + listPage + .selectQuickDateRange("alltime") + .waitForTableRefresh() + .searchForSubmission(submissionId); + + return cy.get("body").then(($body) => { + const hasRow = $body.find(`tr:contains("${submissionId}")`).length > 0; + + if (hasRow) { + cy.log( + `Submission ${submissionId} found in applications list on attempt ${attempt}`, + ); + return; + } + + if (attempt >= maxAttempts) { + throw new Error( + `Submission ${submissionId} was not visible in the applications list after ${maxAttempts} attempts`, + ); + } + + cy.log( + `Submission ${submissionId} not visible yet. Refreshing applications list (attempt ${attempt} of ${maxAttempts})`, + ); + cy.wait(5000); + cy.reload(); + return waitForSubmissionToAppearInList(attempt + 1, maxAttempts); + }); + } + + function ensureSiteInfoReady( + attempt = 1, + maxAttempts = 4, + ): Cypress.Chainable { + detailsPage.dismissErrorModalIfPresent(); + detailsPage.goToPaymentInfoTab(); + cy.wait(1000); + + return cy.get("body").then(($body) => { + const hasTokenError = + $body.text().includes("GetAuthTokenAsync") || + $body.text().includes("Error retrieving Token"); + const rows = $body.find("#SiteInfoTable tbody tr"); + const firstRowText = rows.first().text().replace(/\s+/g, " ").trim(); + const hasData = + rows.length > 0 && !/no data available/i.test(firstRowText); + + if (!hasTokenError && hasData) { + cy.log(`Site info ready on attempt ${attempt}`); + return; + } + + if (attempt >= maxAttempts) { + throw new Error( + `Site info was not ready after ${maxAttempts} attempts`, + ); + } + + cy.log( + `Site info not ready yet. Re-activating payment info content (attempt ${attempt} of ${maxAttempts})`, + ); + detailsPage.dismissErrorModalIfPresent(); + detailsPage.goToFundingAgreementTab(); + cy.wait(1000); + detailsPage.goToPaymentInfoTab(); + cy.wait(3000); + return ensureSiteInfoReady(attempt + 1, maxAttempts); + }); + } + + function waitForBlockingUiToClear(): void { + cy.get(".swal2-container", { timeout: 20000 }).should("not.exist"); + cy.get(".modal.show", { timeout: 20000 }).should("not.exist"); + cy.get(".modal-backdrop", { timeout: 20000 }).should("not.exist"); + } + + function openStatusActionsMenu(): void { + waitForBlockingUiToClear(); + detailsPage.dismissErrorModalIfPresent(); + cy.get(STATUS_ACTIONS.menuButton, { timeout: 20000 }) + .filter(":visible") + .first() + .scrollIntoView() + .should("be.visible") + .and("not.contain.text", "Processing...") + .click({ force: true }); + cy.get(STATUS_ACTIONS.menu, { timeout: 20000 }).should("be.visible"); + } + + function clickStatusAction(actionSelector: string): void { + openStatusActionsMenu(); + cy.get(actionSelector, { timeout: 20000 }) + .filter(":visible") + .first() + .should("be.visible") + .and("not.be.disabled") + .click({ force: true }); + } + + function clickStatusActionIfEnabled( + actionSelector: string, + actionName: string, + ): void { + openStatusActionsMenu(); + cy.get("body").then(($body) => { + const $action = $body.find(actionSelector).filter(":visible"); + if ($action.length === 0) { + cy.log(`${actionName} not present in dropdown; likely already progressed`); + cy.get("body").click(0, 0); // close menu + return; + } + if ($action.is(":disabled")) { + cy.log(`${actionName} is disabled; likely already progressed`); + cy.get("body").click(0, 0); // close menu + return; + } + cy.wrap($action.first()).click({ force: true }); + confirmStatusActionIfNeeded(); + }); + } + + function confirmStatusActionIfNeeded(): void { + cy.wait(500); + cy.get("body").then(($body) => { + if ($body.find(".swal2-popup .swal2-confirm").length > 0) { + cy.get(".swal2-popup .swal2-confirm", { timeout: 20000 }) + .should("be.visible") + .click({ force: true }); + cy.get(".swal2-container", { timeout: 20000 }).should("not.exist"); + return; + } + + if ( + $body.find(".modal.show .modal-content:contains('Confirm Action')") + .length > 0 + ) { + cy.get(".modal.show", { timeout: 20000 }) + .should("be.visible") + .within(() => { + cy.contains("button", /^Confirm$/i, { timeout: 20000 }) + .should("be.visible") + .click({ force: true }); + }); + cy.contains(".modal.show .modal-content", "Confirm Action", { + timeout: 20000, + }).should("not.exist"); + cy.get(".modal-backdrop", { timeout: 20000 }).should("not.exist"); + } + }); + } + + function dismissBlockingModalIfPresent(): void { + cy.get("body").then(($body) => { + if ($body.find(".swal2-container .swal2-confirm").length > 0) { + cy.get(".swal2-container .swal2-confirm", { timeout: 20000 }) + .should("be.visible") + .click({ force: true }); + cy.get(".swal2-container", { timeout: 20000 }).should("not.exist"); + } + + if ($body.find(".modal.show").length > 0) { + cy.get(".modal.show", { timeout: 20000 }).should("not.exist"); + cy.get(".modal-backdrop", { timeout: 20000 }).should("not.exist"); + } + }); + } + + function selectFirstAvailableOptionByLabel(labelText: string): void { + cy.get("body").then(($body) => { + if ($body.find(`label:contains('${labelText}'):visible`).length === 0) { + cy.log(`Label not found (skip): ${labelText}`); + return; + } + + cy.contains("label", labelText, { timeout: 10000 }) + .first() + .then(($label) => { + const fieldId = ($label.attr("for") || "").trim(); + if (!fieldId) { + cy.log(`No 'for' attribute on label (skip): ${labelText}`); + return; + } + + const selector = `#${fieldId}`; + if ($body.find(selector).length === 0) { + cy.log(`Field not found by id (skip): ${selector}`); + return; + } + + cy.get(selector, { timeout: 10000 }).then(($select) => { + const options = $select.find("option").toArray(); + const candidate = options.find((opt) => { + const value = (opt.getAttribute("value") || "").trim(); + const text = (opt.textContent || "").trim().toLowerCase(); + return value !== "" && text !== "please choose..."; + }); + + const value = candidate?.getAttribute("value"); + if (value) { + cy.wrap($select).select(value, { force: true }); + } + }); + }); + }); + } + + function populateReviewFieldsRequiredForCompleteReview(): void { + detailsPage.goToReviewAssessmentTab(); + + reviewPage.verifyFormioLoaded(); + cy.get("#ApprovalView_ApprovedAmount", { timeout: 30000 }) + .should("be.visible") + .and("not.be.disabled"); + + cy.get("body").then(($body) => { + if ($body.find("#ApprovalView_ApprovedAmount").length > 0) { + reviewPage.enterApprovedAmount(TEST_CONFIG.approvedAmount); + } else { + cy.log("Approved amount field not present yet; skipping amount entry"); + } + + if ($body.find("#ApprovalView_FinalDecisionDate").length > 0) { + reviewPage.setDecisionDateToToday(); + } else { + cy.log("Decision date field not present yet; skipping date entry"); + } + }); + + selectFirstAvailableOptionByLabel("Likelihood of Funding"); + selectFirstAvailableOptionByLabel("Due Diligence Status"); + selectFirstAvailableOptionByLabel("Assessment Result"); + reviewPage.clickSave(); + } + + function assignSubmissionFromList(ownerName: string): void { + dismissBlockingModalIfPresent(); + waitForSubmissionToAppearInList(); + + listPage + .waitForNoBlockingOverlay() + .selectQuickDateRange("alltime") + .waitForTableRefresh() + .searchForSubmission(submissionId) + .selectRowByText(submissionId); + + cy.get("#assignApplication", { timeout: 20000 }) + .should("exist") + .and("not.have.class", "action-bar-btn-unavailable") + .and("be.visible") + .click({ force: true }); + + cy.contains(".modal-title", "Assessment Users", { timeout: 20000 }).should( + "be.visible", + ); + + cy.get("#AssigneeId", { timeout: 20000 }) + .should("be.visible") + .select(ownerName); + + cy.get("#user-tags-input", { timeout: 20000 }) + .should("be.visible") + .clear() + .type(ownerName, { delay: 0 }); + + cy.get("body").then(($body) => { + if ( + $body.find(".tags-suggestion-container .tags-suggestion-element") + .length > 0 + ) { + cy.get(".tags-suggestion-container .tags-suggestion-element", { + timeout: 10000, + }) + .contains(ownerName) + .click({ force: true }); + } else { + cy.get("#user-tags-input").type("{enter}"); + } + }); + + cy.contains(".modal-footer button", "Save", { timeout: 20000 }) + .should("be.visible") + .and("not.be.disabled") + .click({ force: true }); + + cy.contains(".modal-title", "Assessment Users", { timeout: 20000 }).should( + "not.exist", + ); + listPage.waitForNoBlockingOverlay(); + } + + function clickAdjudicationActionIfEnabled(actionSelector: string): void { + cy.get("body").then(($body) => { + if ($body.find(actionSelector).length > 0) { + cy.get(actionSelector, { timeout: 20000 }).then(($button) => { + if (!$button.is(":disabled")) { + cy.wrap($button).click({ force: true }); + confirmStatusActionIfNeeded(); + } else { + cy.log(`Action is disabled: ${actionSelector}`); + } + }); + } else { + cy.log(`Action not present: ${actionSelector}`); + } + }); + } + /** Select the submissionId row and open the Approve Payments modal. */ function selectRowAndOpenApproveModal(): void { + waitForBlockingUiToClear(); cy.contains("tr", submissionId, { timeout: 20000 }) + .scrollIntoView() .find(".checkbox-select") .click({ force: true }); cy.contains("button", "Approve", { timeout: 20000 }) @@ -168,54 +517,90 @@ const TEST_CONFIG = { .searchForSubmission(submissionId); }); + it("Assign submission on application list", () => { + assignSubmissionFromList(TEST_CONFIG.assignOwner); + }); + it("Select submission and open details", () => { - listPage.selectRowByText(submissionId).clickOpenButton(); + dismissBlockingModalIfPresent(); + waitForSubmissionToAppearInList(); + listPage.waitForNoBlockingOverlay(); + + cy.location("pathname", { timeout: 20000 }).then((pathname) => { + if (pathname.includes("/GrantApplications/Details")) { + cy.log("Already on details page after assignment"); + } else { + listPage + .selectQuickDateRange("alltime") + .waitForTableRefresh() + .searchForSubmission(submissionId) + .selectRowByText(submissionId) + .clickOpenButton(); + } + }); + + cy.get(BREADCRUMB_STATUS_SELECTOR, { timeout: 20000 }) + .should("be.visible") + .invoke("text") + .then((statusText) => { + const normalized = statusText.trim().toLowerCase(); + expect( + ["submitted", "assigned"], + "Expected initial status to be Submitted or Assigned", + ).to.include(normalized); + }); }); // ============ Review & Assessment ============ - it("Navigate to Review and Assessment tab", () => { - detailsPage.goToReviewAssessmentTab().verifyActiveTab("reviewAssessment"); + it("Start review from Status Actions", () => { + clickStatusActionIfEnabled(STATUS_ACTIONS.startReview, "Start Review"); }); - it("Enter approval details and save", () => { - reviewPage - .verifyFormioLoaded() - .enterApprovedAmount(TEST_CONFIG.approvedAmount) - .setDecisionDateToToday() - .clickSave(); + it("Complete review from Status Actions", () => { + populateReviewFieldsRequiredForCompleteReview(); + clickStatusActionIfEnabled( + STATUS_ACTIONS.completeReview, + "Complete Review", + ); + }); + + it("Start assessment from Status Actions", () => { + clickStatusActionIfEnabled( + STATUS_ACTIONS.startAssessment, + "Start Assessment", + ); + }); + + it("Navigate to Review and Assessment tab", () => { + detailsPage.goToReviewAssessmentTab().verifyActiveTab("reviewAssessment"); }); - it("Create and complete assessment", () => { + it("Create assessment", () => { cy.wait(2000); // Allow assessment section to fully load reviewPage.scrollToAssessmentList(); cy.get("body").then(($body) => { if ($body.find("#CreateButton").length > 0) { cy.get("#CreateButton").click({ force: true }); - cy.wait(1000); + // Give the new assessment row time to render before subsequent actions. + cy.wait(1000); // Needed because row creation animation can delay DOM readiness. } else { cy.log("Create Assessment button not found - may already be created"); } }); + }); - cy.get("body").then(($body) => { - if ($body.find("#CompleteButton").length > 0) { - cy.get("#CompleteButton").click({ force: true }); - cy.wait(1000); - } else { - cy.log( - "Complete Assessment button not found - may already be completed", - ); - } - }); + it("Complete assessment from adjudication action bar", () => { + clickAdjudicationActionIfEnabled(ADJUDICATION_ACTIONS.completeAssessment); }); // ============ Payment Info ============ it("Configure payment info", () => { cy.reload(); // Reload to get fresh data and avoid concurrency issues - cy.wait(2000); + // Wait briefly for async payment tab dependencies to stabilize after reload. + cy.wait(2000); // Prevents save attempts before payment controls are initialized. detailsPage .goToPaymentInfoTab() .enterSupplierNumber(TEST_CONFIG.supplierNumber) @@ -224,6 +609,7 @@ const TEST_CONFIG = { }); it("Validate and edit site info", () => { + ensureSiteInfoReady(); detailsPage .verifySiteInfoTablePopulated() .verifySiteInfoTableHasData() @@ -269,18 +655,37 @@ const TEST_CONFIG = { }); }); + it("Enter approval details and save", () => { + detailsPage.goToReviewAssessmentTab().verifyActiveTab("reviewAssessment"); + reviewPage + .verifyFormioLoaded() + .enterApprovedAmount(TEST_CONFIG.approvedAmount) + .setDecisionDateToToday() + .clickSave(); + }); + // ============ Application Approval ============ it("Test approval workflow (confirm)", () => { cy.reload(); // Refresh to ensure all changes are reflected before approval detailsPage.dismissErrorModalIfPresent(); - detailsPage.clickApprove().waitForConfirmModal().clickConfirm(); + clickStatusAction(STATUS_ACTIONS.completeAssessment); + confirmStatusActionIfNeeded(); + + cy.get(STATUS_ACTIONS.menuButton, { timeout: 20000 }) + .filter(":visible") + .first() + .should("be.visible") + .and("not.contain.text", "Processing..."); + + clickStatusAction(STATUS_ACTIONS.approve); + detailsPage.waitForConfirmModal().clickConfirm(); }); // ============ Post-Approval Verification ============ it("Navigate back to applications list", () => { - cy.visit(`${Cypress.env("webapp.url")}GrantApplications`); + cy.visit(`${Cypress.env("webapp.url")}${APPLICATIONS_PATH}`); listPage.switchToGrantProgram(TEST_CONFIG.grantProgram); }); @@ -300,7 +705,10 @@ const TEST_CONFIG = { // ============ Payment Request ============ it("Select approved application and submit payment request", () => { - listPage.selectRowByText(submissionId).clickPaymentButtonWithWait(); + listPage + .waitForNoBlockingOverlay() + .selectRowByText(submissionId) + .clickPaymentButtonWithWait(); listPage.waitForPaymentModalVisible(); // Description field has a max length of 40 chars @@ -317,7 +725,7 @@ const TEST_CONFIG = { .and("not.be.disabled") .click(); - cy.get("#payment-modal", { timeout: 20000 }).should("not.be.visible"); + listPage.verifyPaymentModalClosed(); cy.log(`✅ Payment request submitted: ${paymentDescription}`); }); diff --git a/applications/Unity.GrantManager/.github/agents/feature-planner.agent.md b/applications/Unity.GrantManager/.github/agents/feature-planner.agent.md index adb12769d6..a52030b62f 100644 --- a/applications/Unity.GrantManager/.github/agents/feature-planner.agent.md +++ b/applications/Unity.GrantManager/.github/agents/feature-planner.agent.md @@ -1,16 +1,88 @@ --- name: feature-planner description: Plans feature implementation across Domain, Application, EF Core, Web, and tests. -tools: ['fetch', 'githubRepo', 'problems', 'usages', 'search', 'todos', 'runSubagent'] +argument-hint: Outline the goal or problem to research +target: vscode +disable-model-invocation: true +tools: ['search', 'read', 'web', 'vscode/memory', 'github/issue_read', 'github.vscode-pull-request-github/issue_fetch', 'github.vscode-pull-request-github/activePullRequest', 'execute/getTerminalOutput', 'execute/testFailure', 'agent', 'vscode/askQuestions'] +agents: ['Explore'] +handoffs: + - label: Start Implementation + agent: agent + prompt: 'Start implementation' + send: true + - label: Open in Editor + agent: agent + prompt: '#createFile the plan as is into an untitled file (`untitled:plan-${camelCaseName}.prompt.md` without frontmatter) for further refinement.' + send: true + showContinueOn: false --- # ABP Feature Planner Agent -You are the feature planning specialist for Unity Grant Manager. +You are the FEATURE PLANNING AGENT for Unity Grant Manager, pairing with the user to create a detailed, actionable plan. -## Mission +You research the codebase → clarify with the user → capture findings and decisions to convert a feature request into a comprehensive plan that respects ABP modular layering and delivery flow. This iterative approach catches edge cases and non-obvious requirements BEFORE implementation begins. -Convert a feature request into an implementation plan that respects ABP modular layering and delivery flow. +Your SOLE responsibility is planning. NEVER start implementation. + +**Current plan**: `/memories/session/plan.md` - update using #tool:vscode/memory. + + +- STOP if you consider running file editing tools — plans are for others to execute. The only write tool you have is #tool:vscode/memory for persisting plans. +- Use #tool:vscode/askQuestions freely to clarify requirements — don't make large assumptions +- Present a well-researched plan with loose ends tied BEFORE implementation + + + +Cycle through these phases based on user input. This is iterative, not linear. If the user task is highly ambiguous, do only *Discovery* to outline a draft plan, then move on to alignment before fleshing out the full plan. + +## 1. Discovery + +Run the *Explore* subagent to gather context, analogous existing features to use as implementation templates, and potential blockers or ambiguities. When the task spans multiple independent areas (e.g., frontend + backend, different features, separate modules), launch **2-3 *Explore* subagents in parallel** — one per area — to speed up discovery. + +Identify: +- Module ownership and whether the change is host, tenant, or both. +- Work split by ABP layer: Domain.Shared → Domain → Application.Contracts → Application → EntityFrameworkCore → HttpApi/Web → Tests. +- Dependencies and ordering constraints between layers. +- Cross-module impacts and permission/localization requirements. + +Update the plan with your findings. + +## 2. Alignment + +If research reveals major ambiguities or if you need to validate assumptions: +- Use #tool:vscode/askQuestions to clarify intent with the user. +- Surface discovered technical constraints or alternative approaches. +- If answers significantly change the scope, loop back to **Discovery**. + +## 3. Design + +Once context is clear, draft a comprehensive implementation plan structured around ABP layers. + +The plan should reflect: +- Structured concisely enough to be scannable and detailed enough for effective execution. +- Step-by-step implementation with explicit dependencies — mark which steps can run in parallel vs. which block on prior steps. +- For plans with many steps, group into named phases that are each independently verifiable. +- Verification steps for validating the implementation, both automated and manual. +- Critical architecture to reuse or use as reference — reference specific functions, types, or patterns, not just file names. +- Critical files to be modified (with full paths). +- Explicit scope boundaries — what's included and what's deliberately excluded. +- Reference decisions from the discussion. +- Leave no ambiguity. + +Save the comprehensive plan document to `/memories/session/plan.md` via #tool:vscode/memory, then show the scannable plan to the user for review. You MUST show the plan to the user, as the plan file is for persistence only, not a substitute for showing it to the user. + +## 4. Refinement + +On user input after showing the plan: +- Changes requested → revise and present updated plan. Update `/memories/session/plan.md` to keep the documented plan in sync. +- Questions asked → clarify, or use #tool:vscode/askQuestions for follow-ups. +- Alternatives wanted → loop back to **Discovery** with new subagent. +- Approval given → acknowledge, the user can now use handoff buttons. + +Keep iterating until explicit approval or handoff. + ## Inputs @@ -19,30 +91,54 @@ Convert a feature request into an implementation plan that respects ABP modular - Target module(s). - Any constraints (timeline, migration risk, tenant scope, security requirements). -## Process - -1. Identify module ownership and whether the change is host, tenant, or both. -2. Split work by layer: - - Domain.Shared - - Domain - - Application.Contracts - - Application - - EntityFrameworkCore - - HttpApi/Web - - Tests -3. List dependencies and ordering constraints. -4. Flag cross-module impacts and permission/localization requirements. - -## Output Format - -Return sections in this order: - -1. Scope summary. -2. Layer-by-layer implementation tasks. -3. Migration and data impact. -4. Test plan summary. -5. Risks and mitigations. -6. Definition of done checklist. + +```markdown +## Plan: {Title (2-10 words)} + +{TL;DR - what, why, and how (your recommended approach).} + +**Steps** + +### Phase 1 — Domain & Contracts +1. {Domain.Shared changes — enums, consts, error codes} +2. {Domain entity/aggregate changes — note dependency ("*depends on N*") or parallelism ("*parallel with step N*") when applicable} +3. {Application.Contracts — DTOs, IAppService interfaces, permissions} + +### Phase 2 — Application & Persistence +4. {Application service implementation} +5. {EntityFrameworkCore — DbContext, entity config, migration} + +### Phase 3 — API & Frontend +6. {HttpApi controller / AutoAPI} +7. {Web — Pages, JS, localization} + +### Phase 4 — Tests +8. {Unit and integration tests} + +**Relevant files** +- `{full/path/to/file}` — {what to modify or reuse, referencing specific functions/patterns} + +**Migration & Data Impact** +- {Host vs tenant migration scope, data backfill needs, breaking schema changes} + +**Verification** +1. {Verification steps for validating the implementation (**Specific** tasks, tests, commands, MCP tools, etc; not generic statements)} + +**Decisions** (if applicable) +- {Decision, assumptions, and includes/excluded scope} + +**Risks & Mitigations** (if applicable) +- {Risk and mitigation strategy} + +**Definition of Done** +- [ ] {Checklist item} +``` + +Rules: +- NO code blocks — describe changes, link to files and specific symbols/functions. +- NO blocking questions at the end — ask during workflow via #tool:vscode/askQuestions. +- The plan MUST be presented to the user, don't just mention the plan file. + ## Guardrails diff --git a/applications/Unity.GrantManager/.github/skills/abp-cli/SKILL.md b/applications/Unity.GrantManager/.github/skills/abp-cli/SKILL.md index df1fd7b055..f65cd83801 100644 --- a/applications/Unity.GrantManager/.github/skills/abp-cli/SKILL.md +++ b/applications/Unity.GrantManager/.github/skills/abp-cli/SKILL.md @@ -1,6 +1,6 @@ --- name: abp-cli -description: ABP CLI commands - generate-proxy, install-libs, add-package-ref, new-module, install-module, abp update, abp clean, abp suite generate. Use when the user asks how to run ABP CLI commands, generate proxies, install libraries, or use ABP Suite. +description: ABP CLI commands - generate-proxy, install-libs, add-package-ref, new-module, install-module, abp update, abp clean, abp suite generate. Use when the user asks how to run ABP CLI commands, generate proxies, install NPM libraries, or use ABP Suite. --- # ABP CLI Commands diff --git a/applications/Unity.GrantManager/README.md b/applications/Unity.GrantManager/README.md index 5518ac38b3..e04725a097 100644 --- a/applications/Unity.GrantManager/README.md +++ b/applications/Unity.GrantManager/README.md @@ -24,6 +24,16 @@ This is the main grant management application for the Unity platform. It include - Right click on `Unity.GrantManager.DbMigrator` and click **"Set As Startup Project"** - `Ctrl + F5` to run without debugging +## Attachment Preview + +Office file preview (DOCX, XLSX, PPTX, ODT, ODS, ODP, RTF, CSV) uses **LibreOffice** for server-side PDF conversion. LibreOffice is installed automatically in the Docker image via the Dockerfile — no manual setup is needed for deployed environments (DEV, TEST, PROD). + +**Local development (Visual Studio on Windows):** +LibreOffice conversion requires a Linux environment and is not supported when running the app directly on Windows. Clicking "Preview" on an office file will show the message *"LibreOffice is not installed on the server. File preview is unavailable."* This is expected behaviour. Use the **Download** button to open the file locally. To test the full preview feature, run the application via Docker. + +**Preview caching:** +The first preview request converts the file and caches the PDF in S3 alongside the original (e.g. `applications/{id}/preview/{filename}.pdf`). Subsequent preview requests serve the cached PDF. The cached PDF is automatically deleted when the original attachment is deleted. + ## See Also - https://docs.abp.io/en/abp/latest diff --git a/applications/Unity.GrantManager/documentation/reporting/reporting-configuration.md b/applications/Unity.GrantManager/documentation/reporting/reporting-configuration.md new file mode 100644 index 0000000000..846023fb3f --- /dev/null +++ b/applications/Unity.GrantManager/documentation/reporting/reporting-configuration.md @@ -0,0 +1,103 @@ +# Reporting Configuration + +## Overview + +The Reporting Configuration system allows administrators to define how source field data maps to PostgreSQL database columns for generated reporting views. It supports three correlation providers, each sourcing field metadata from a different system: + +| Provider | Source | Correlation ID | Description | +|----------|--------|----------------|-------------| +| `formversion` | CHEFS form submissions | Form Version ID | Immutable form schema fields | +| `worksheet` | Unity.Flex worksheets | Form Version ID | Dynamic worksheet fields | +| `scoresheet` | Unity.Flex scoresheets | Form ID | Evaluation/scoring fields | + +## Architecture + +### Layered Components + +- **`ReportMappingUtils`** (`Unity.Reporting.Application`) — Static utility methods for column name sanitization, validation, uniqueness enforcement, and mapping creation/update logic. +- **`ReportMappingService`** (`Unity.Reporting.Application`) — Application service orchestrating CRUD operations, field metadata retrieval, view generation, and provider resolution. +- **`IFieldsProvider`** (`Unity.Reporting.Application`) — Interface for correlation-specific field metadata extraction and change detection. +- **`ReportingConfigurationController`** (`Unity.Reporting.Web`) — MVC controller providing AJAX API endpoints for the UI. +- **`Default.js`** (`Unity.Reporting.Web`) — Client-side DataTable configuration, validation, and provider-aware UI logic. + +### Field Providers + +Each provider implements `IFieldsProvider`: + +- **`FormVersionFieldsProvider`** — Retrieves field metadata from immutable CHEFS form version schemas. Change detection always returns null since form versions are immutable. +- **`WorksheetFieldsProvider`** — Retrieves field metadata from Unity.Flex worksheet definitions. Supports change detection for dynamic schema evolution. +- **`ScoresheetFieldsProvider`** — Retrieves field metadata from Unity.Flex scoresheet definitions. Supports change detection for scoring structure changes. + +## Default Column Name Generation + +When a user creates or saves a report configuration for the first time (or when new fields are discovered during an update), the system auto-generates default column names for fields that don't have user-specified names. + +### Provider-Specific Column Name Source + +The source used for generating default column names differs by provider: + +| Provider | Default Column Name Source | Rationale | +|----------|---------------------------|-----------| +| `formversion` | **Key** (CHEFS Property Name, e.g., `firstName`) | CHEFS property names are stable, developer-defined identifiers that produce clean, predictable column names (e.g., `firstname`). Labels can be verbose or contain special characters. | +| `worksheet` | **Label** (e.g., `First Name`) | Worksheet labels are human-readable names configured by administrators, producing descriptive column names (e.g., `first_name`). | +| `scoresheet` | **Label** (e.g., `Score One`) | Scoresheet labels provide meaningful, user-facing descriptions that map well to reporting column names. | + +### Column Name Sanitization + +All auto-generated column names go through the same sanitization pipeline regardless of provider: + +1. Convert to lowercase +2. Replace spaces and hyphens with underscores +3. Remove all non-alphanumeric characters (except underscores) +4. Remove consecutive underscores +5. Trim leading/trailing underscores +6. Prefix with `col_` if name starts with a digit +7. Truncate to 60 characters maximum +8. Ensure uniqueness by appending numeric suffixes (`_1`, `_2`, etc.) when collisions occur + +### Implementation Details + +The column name source selection is implemented identically on server and client with no cross-field fallbacks: + +- **Server-side** — `ReportMappingUtils.GetDefaultColumnNameSource()` returns `field.Key ?? ""` for `formversion`, or `field.Label ?? ""` for all other providers. Used by `CreateNewMap()` and `UpdateExistingMap()` when auto-generating column names for unmapped or newly discovered fields. The provider comparison is case-insensitive via `StringComparison.OrdinalIgnoreCase`. +- **Client-side** — `getDefaultColumnNameSource()` in `Default.js` uses the same logic: `field.key || ''` when `currentProvider === 'formversion'`, otherwise `field.label || ''`. This is used by `transformFieldsMetadata()` to set initial column name values in the DataTable when no saved configuration exists. + +> **Important:** Neither implementation falls back from Key to Label or vice versa. If the source value is null/empty, an empty string is used, and the downstream sanitization produces `"col_1"` as a placeholder. This ensures client and server always produce identical defaults. + +### Impact on Existing Configurations + +- **Existing saved configurations are not affected.** Column names are persisted in the database; the provider-specific logic only determines defaults for new/unsaved fields. +- **Existing column names are preserved during updates.** The three-tier priority system (user-provided → existing → auto-generated) ensures established mappings are maintained. + +## Column Name Validation + +Both client-side and server-side enforce PostgreSQL column name rules: + +- Maximum 60 characters +- Must start with a letter or underscore +- Contains only letters, digits, and underscores +- Cannot be a PostgreSQL reserved word +- Must be unique within the configuration + +## View Generation + +After saving a configuration, users can generate a PostgreSQL database view: + +1. User provides a view name (validated for availability and PostgreSQL compliance) +2. A background job is queued to create/update the view in the `Reporting` schema +3. View status is tracked and displayed via a widget + +View names follow similar sanitization rules with a 63-character maximum (PostgreSQL identifier limit). + +## Configuration Lifecycle + +``` +Fields Metadata → [Save] → Configuration → [Generate View] → Database View + ↓ + [Delete] → Removes configuration and optionally the view +``` + +1. **Initial Load**: Field metadata is fetched from the appropriate provider; default column names are generated. +2. **Save**: Creates or updates the mapping configuration with user-specified and auto-generated column names. +3. **Generate View**: Creates a PostgreSQL view in the `Reporting` schema based on the saved mapping. +4. **Delete**: Removes the configuration and optionally drops the associated database view. diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Extraction/ITextExtractionService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Extraction/ITextExtractionService.cs similarity index 81% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Extraction/ITextExtractionService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Extraction/ITextExtractionService.cs index 1e68280b99..d1c4d9f992 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Extraction/ITextExtractionService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Extraction/ITextExtractionService.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; -namespace Unity.GrantManager.AI.Extraction +namespace Unity.AI.Extraction { public interface ITextExtractionService { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/IAIService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/IAIService.cs similarity index 83% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/IAIService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/IAIService.cs index d059187316..84c1e1c08b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/IAIService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/IAIService.cs @@ -1,8 +1,8 @@ using System.Threading.Tasks; -using Unity.GrantManager.AI.Requests; -using Unity.GrantManager.AI.Responses; +using Unity.AI.Requests; +using Unity.AI.Responses; -namespace Unity.GrantManager.AI +namespace Unity.AI { public interface IAIService { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/AIAttachmentItem.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/AIAttachmentItem.cs similarity index 88% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/AIAttachmentItem.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/AIAttachmentItem.cs index 58c7c1c65e..550b032916 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/AIAttachmentItem.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/AIAttachmentItem.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Unity.GrantManager.AI.Models +namespace Unity.AI.Models { public class AIAttachmentItem { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/AIJsonKeys.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/AIJsonKeys.cs similarity index 70% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/AIJsonKeys.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/AIJsonKeys.cs index fb2230cba5..6e83686ff0 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/AIJsonKeys.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/AIJsonKeys.cs @@ -1,15 +1,13 @@ -namespace Unity.GrantManager.AI.Models +namespace Unity.AI.Models { public static class AIJsonKeys { - public const string Rating = "rating"; public const string Errors = "errors"; public const string Warnings = "warnings"; public const string Summaries = "summaries"; - public const string NextSteps = "nextSteps"; - public const string Hidden = "hidden"; - public const string Recommendation = "recommendation"; + public const string Recommendations = "recommendations"; public const string Decision = "decision"; + public const string Dismissed = "dismissed"; public const string Id = "id"; public const string Title = "title"; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationAnalysisFinding.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/ApplicationAnalysisFinding.cs similarity index 74% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationAnalysisFinding.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/ApplicationAnalysisFinding.cs index 47baf9bca1..f386f45d1f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationAnalysisFinding.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/ApplicationAnalysisFinding.cs @@ -1,14 +1,14 @@ using System.Text.Json.Serialization; -namespace Unity.GrantManager.AI.Models +namespace Unity.AI.Models { public class ApplicationAnalysisFinding { [JsonPropertyName(AIJsonKeys.Id)] public string? Id { get; set; } - [JsonPropertyName(AIJsonKeys.Hidden)] - public bool Hidden { get; set; } + [JsonPropertyName(AIJsonKeys.Dismissed)] + public bool Dismissed { get; set; } [JsonPropertyName(AIJsonKeys.Title)] public string? Title { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationScoringAnswer.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/ApplicationScoringAnswer.cs similarity index 91% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationScoringAnswer.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/ApplicationScoringAnswer.cs index 7796460557..48b348164f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationScoringAnswer.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Models/ApplicationScoringAnswer.cs @@ -1,7 +1,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Unity.GrantManager.AI.Models +namespace Unity.AI.Models { public class ApplicationScoringAnswer { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/AICompletionRequest.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/AICompletionRequest.cs similarity index 90% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/AICompletionRequest.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/AICompletionRequest.cs index 56dbc6fc4d..cc134ef988 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/AICompletionRequest.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/AICompletionRequest.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Unity.GrantManager.AI.Requests +namespace Unity.AI.Requests { public class AICompletionRequest { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/ApplicationAnalysisRequest.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/ApplicationAnalysisRequest.cs similarity index 87% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/ApplicationAnalysisRequest.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/ApplicationAnalysisRequest.cs index 5366b29877..4a4eca5de1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/ApplicationAnalysisRequest.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/ApplicationAnalysisRequest.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; -using Unity.GrantManager.AI.Models; +using Unity.AI.Models; -namespace Unity.GrantManager.AI.Requests +namespace Unity.AI.Requests { public class ApplicationAnalysisRequest { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/ApplicationScoringRequest.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/ApplicationScoringRequest.cs similarity index 89% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/ApplicationScoringRequest.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/ApplicationScoringRequest.cs index 241a46a977..5a72460138 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/ApplicationScoringRequest.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/ApplicationScoringRequest.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; -using Unity.GrantManager.AI.Models; +using Unity.AI.Models; -namespace Unity.GrantManager.AI.Requests +namespace Unity.AI.Requests { public class ApplicationScoringRequest { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/AttachmentSummaryRequest.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/AttachmentSummaryRequest.cs similarity index 92% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/AttachmentSummaryRequest.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/AttachmentSummaryRequest.cs index 4f4d009e86..e1703a01ff 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Requests/AttachmentSummaryRequest.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Requests/AttachmentSummaryRequest.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Unity.GrantManager.AI.Requests +namespace Unity.AI.Requests { public class AttachmentSummaryRequest { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/AICompletionResponse.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/AICompletionResponse.cs similarity index 81% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/AICompletionResponse.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/AICompletionResponse.cs index a146c7f86a..0f0c1c8efe 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/AICompletionResponse.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/AICompletionResponse.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Unity.GrantManager.AI.Responses +namespace Unity.AI.Responses { public class AICompletionResponse { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/ApplicationAnalysisResponse.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/ApplicationAnalysisResponse.cs similarity index 54% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/ApplicationAnalysisResponse.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/ApplicationAnalysisResponse.cs index fda17e43d6..68231cd763 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/ApplicationAnalysisResponse.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/ApplicationAnalysisResponse.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Text.Json.Serialization; -using Unity.GrantManager.AI.Models; +using Unity.AI.Models; -namespace Unity.GrantManager.AI.Responses +namespace Unity.AI.Responses { public class ApplicationAnalysisResponse { - [JsonPropertyName(AIJsonKeys.Rating)] - public string? Rating { get; set; } + [JsonPropertyName(AIJsonKeys.Decision)] + public string? Decision { get; set; } [JsonPropertyName(AIJsonKeys.Errors)] public List Errors { get; set; } = new(); @@ -18,10 +18,7 @@ public class ApplicationAnalysisResponse [JsonPropertyName(AIJsonKeys.Summaries)] public List Summaries { get; set; } = new(); - [JsonPropertyName(AIJsonKeys.NextSteps)] - public List NextSteps { get; set; } = new(); - - [JsonPropertyName(AIJsonKeys.Recommendation)] - public ApplicationAnalysisRecommendation? Recommendation { get; set; } + [JsonPropertyName(AIJsonKeys.Recommendations)] + public List Recommendations { get; set; } = new(); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/ApplicationScoringResponse.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/ApplicationScoringResponse.cs similarity index 77% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/ApplicationScoringResponse.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/ApplicationScoringResponse.cs index 3a5ce46501..d838e7667e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/ApplicationScoringResponse.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/ApplicationScoringResponse.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Text.Json.Serialization; -using Unity.GrantManager.AI.Models; +using Unity.AI.Models; -namespace Unity.GrantManager.AI.Responses +namespace Unity.AI.Responses { public class ApplicationScoringResponse { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/AttachmentSummaryResponse.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/AttachmentSummaryResponse.cs similarity index 72% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/AttachmentSummaryResponse.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/AttachmentSummaryResponse.cs index 170345cad1..546e20bd0f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Responses/AttachmentSummaryResponse.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/AI/Responses/AttachmentSummaryResponse.cs @@ -1,7 +1,7 @@ using System.Text.Json.Serialization; -using Unity.GrantManager.AI.Models; +using Unity.AI.Models; -namespace Unity.GrantManager.AI.Responses +namespace Unity.AI.Responses { public class AttachmentSummaryResponse { diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Attachments/AttachmentSummaryResultDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Attachments/AttachmentSummaryResultDto.cs new file mode 100644 index 0000000000..b7100305b0 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Attachments/AttachmentSummaryResultDto.cs @@ -0,0 +1,6 @@ +namespace Unity.GrantManager.Attachments; + +public class AttachmentSummaryResultDto +{ + public bool Completed { get; set; } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Attachments/IAttachmentSummaryAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Attachments/IAttachmentSummaryAppService.cs new file mode 100644 index 0000000000..b9eb70ae3a --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Attachments/IAttachmentSummaryAppService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace Unity.GrantManager.Attachments; + +public interface IAttachmentSummaryAppService : IApplicationService +{ + Task GenerateAttachmentSummaryAsync(Guid attachmentId, string? promptVersion = null); + Task> GenerateAttachmentSummariesAsync(List attachmentIds, string? promptVersion = null); +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Automation/IApplicationAIGenerationQueue.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Automation/IApplicationAIGenerationQueue.cs new file mode 100644 index 0000000000..b9d5db8a9a --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Automation/IApplicationAIGenerationQueue.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Unity.AI.Automation; + +public interface IApplicationAIGenerationQueue +{ + Task QueueAttachmentSummariesAsync(IReadOnlyList attachmentIds, Guid? tenantId, string? promptVersion = null); + Task QueueApplicationAnalysisAsync(Guid applicationId, Guid? tenantId, string? promptVersion = null); + Task QueueApplicationScoringAsync(Guid applicationId, Guid? tenantId, string? promptVersion = null); + Task QueueApplicationPipelineAsync(Guid applicationId, Guid? tenantId, string? promptVersion = null); +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationAnalysisResultDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationAnalysisResultDto.cs new file mode 100644 index 0000000000..19c829756e --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationAnalysisResultDto.cs @@ -0,0 +1,6 @@ +namespace Unity.GrantManager.GrantApplications; + +public class ApplicationAnalysisResultDto +{ + public bool Completed { get; set; } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationContentResultDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationContentResultDto.cs new file mode 100644 index 0000000000..0349127194 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationContentResultDto.cs @@ -0,0 +1,6 @@ +namespace Unity.GrantManager.GrantApplications; + +public class ApplicationContentResultDto +{ + public bool Completed { get; set; } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationScoringResultDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationScoringResultDto.cs new file mode 100644 index 0000000000..b4e4e86214 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/ApplicationScoringResultDto.cs @@ -0,0 +1,6 @@ +namespace Unity.GrantManager.GrantApplications; + +public class ApplicationScoringResultDto +{ + public bool Completed { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationAnalysisAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationAnalysisAppService.cs similarity index 63% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationAnalysisAppService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationAnalysisAppService.cs index 493eb82c56..21bf7c7867 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationAnalysisAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationAnalysisAppService.cs @@ -6,6 +6,6 @@ namespace Unity.GrantManager.GrantApplications { public interface IApplicationAnalysisAppService : IApplicationService { - Task GenerateApplicationAnalysisAsync(Guid applicationId, string? promptVersion = null); + Task GenerateApplicationAnalysisAsync(Guid applicationId, string? promptVersion = null); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationContentAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationContentAppService.cs similarity index 64% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationContentAppService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationContentAppService.cs index c2d27129a6..1ce45e8a99 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationContentAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationContentAppService.cs @@ -6,5 +6,5 @@ namespace Unity.GrantManager.GrantApplications; public interface IApplicationContentAppService : IApplicationService { - Task GenerateContentAsync(Guid applicationId, string? promptVersion = null); + Task GenerateContentAsync(Guid applicationId, string? promptVersion = null); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationScoringAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationScoringAppService.cs similarity index 63% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationScoringAppService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationScoringAppService.cs index dae0bc4fb7..c9a7fbab08 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationScoringAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/GrantApplications/IApplicationScoringAppService.cs @@ -6,6 +6,6 @@ namespace Unity.GrantManager.GrantApplications { public interface IApplicationScoringAppService : IApplicationService { - Task GenerateApplicationScoringAsync(Guid applicationId, string? promptVersion = null); + Task GenerateApplicationScoringAsync(Guid applicationId, string? promptVersion = null); } } diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissionDefinitionProvider.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissionDefinitionProvider.cs index fb7980f037..051af67236 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissionDefinitionProvider.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissionDefinitionProvider.cs @@ -21,20 +21,39 @@ public override void Define(IPermissionDefinitionContext context) L("Permission:AI.Reporting")) .RequireFeatures("Unity.AIReporting"); - aiPermissionsGroup.AddPermission( - AIPermissions.ApplicationAnalysis.ApplicationAnalysisDefault, - L("Permission:AI.ApplicationAnalysis")) - .RequireFeatures("Unity.AI.ApplicationAnalysis"); + var analysisParent = aiPermissionsGroup.AddPermission( + AIPermissions.Analysis.AnalysisDefault, + L("Permission:AI.Analysis")); - aiPermissionsGroup.AddPermission( - AIPermissions.AttachmentSummary.AttachmentSummaryDefault , - L("Permission:AI.AttachmentSummary")) - .RequireFeatures("Unity.AI.AttachmentSummaries"); + var viewApplicationAnalysis = analysisParent.AddChild( + AIPermissions.Analysis.ViewApplicationAnalysis, + L("Permission:AI.Analysis.ViewApplicationAnalysis")) + .RequireFeatures("Unity.AI.ApplicationAnalysis"); - aiPermissionsGroup.AddPermission( - AIPermissions.ScoringAssistant.ScoringAssistantDefault, - L("Permission:AI.ScoringAssistant")) - .RequireFeatures("Unity.AI.Scoring"); + viewApplicationAnalysis.AddChild( + AIPermissions.Analysis.GenerateApplicationAnalysis, + L("Permission:AI.Analysis.GenerateApplicationAnalysis")) + .RequireFeatures("Unity.AI.ApplicationAnalysis"); + + var viewAttachmentSummary = analysisParent.AddChild( + AIPermissions.Analysis.ViewAttachmentSummary, + L("Permission:AI.Analysis.ViewAttachmentSummary")) + .RequireFeatures("Unity.AI.AttachmentSummaries"); + + viewAttachmentSummary.AddChild( + AIPermissions.Analysis.GenerateAttachmentSummaries, + L("Permission:AI.Analysis.GenerateAttachmentSummaries")) + .RequireFeatures("Unity.AI.AttachmentSummaries"); + + var viewScoringResult = analysisParent.AddChild( + AIPermissions.Analysis.ViewScoringResult, + L("Permission:AI.Analysis.ViewScoringResult")) + .RequireFeatures("Unity.AI.Scoring"); + + viewScoringResult.AddChild( + AIPermissions.Analysis.GenerateScoring, + L("Permission:AI.Analysis.GenerateScoring")) + .RequireFeatures("Unity.AI.Scoring"); var settingManagement = context.GetGroup(SettingManagementPermissions.GroupName); settingManagement.AddPermission( diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissions.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissions.cs index 8caef403c4..b119e140f9 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissions.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Permissions/AIPermissions.cs @@ -13,19 +13,17 @@ public static class Reporting public const string ReportingDefault = GroupName + ".Reporting"; } - public static class ApplicationAnalysis + public static class Analysis { - public const string ApplicationAnalysisDefault = GroupName + ".ApplicationAnalysis"; - } + public const string AnalysisDefault = GroupName + ".Analysis"; - public static class AttachmentSummary - { - public const string AttachmentSummaryDefault = GroupName + ".AttachmentSummary"; - } + public const string ViewApplicationAnalysis = GroupName + ".Analysis.ViewApplicationAnalysis"; + public const string ViewAttachmentSummary = GroupName + ".Analysis.ViewAttachmentSummary"; + public const string ViewScoringResult = GroupName + ".Analysis.ViewScoringResult"; - public static class ScoringAssistant - { - public const string ScoringAssistantDefault = GroupName + ".ScoringAssistant"; + public const string GenerateApplicationAnalysis = GroupName + ".Analysis.GenerateApplicationAnalysis"; + public const string GenerateAttachmentSummaries = GroupName + ".Analysis.GenerateAttachmentSummaries"; + public const string GenerateScoring = GroupName + ".Analysis.GenerateScoring"; } public static class Configuration diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/AIScoringSettingsDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/AIScoringSettingsDto.cs deleted file mode 100644 index 14837f27b4..0000000000 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/AIScoringSettingsDto.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Unity.AI.Settings; - -public class AIScoringSettingsDto -{ - public bool ScoringAssistantEnabled { get; set; } -} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/AITenantConfigurationDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/AITenantConfigurationDto.cs new file mode 100644 index 0000000000..10a0d84b3c --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/AITenantConfigurationDto.cs @@ -0,0 +1,7 @@ +namespace Unity.AI.Settings; + +public class AITenantConfigurationDto +{ + public bool AutomaticGenerationEnabled { get; set; } + public bool ManualGenerationEnabled { get; set; } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/IAIConfigurationAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/IAIConfigurationAppService.cs index 8a21259aa6..9919f44698 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/IAIConfigurationAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/IAIConfigurationAppService.cs @@ -5,6 +5,6 @@ namespace Unity.AI.Settings; public interface IAIConfigurationAppService : IApplicationService { - Task GetScoringSettingsAsync(); - Task UpdateScoringSettingsAsync(UpdateAIScoringSettingsDto input); + Task GetTenantConfigurationAsync(); + Task UpdateTenantConfigurationAsync(UpdateAITenantConfigurationDto input); } diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/UpdateAIScoringSettingsDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/UpdateAIScoringSettingsDto.cs deleted file mode 100644 index a6323e4a34..0000000000 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/UpdateAIScoringSettingsDto.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Unity.AI.Settings; - -public class UpdateAIScoringSettingsDto -{ - public bool ScoringAssistantEnabled { get; set; } -} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/UpdateAITenantConfigurationDto.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/UpdateAITenantConfigurationDto.cs new file mode 100644 index 0000000000..bbbed5c2f0 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Settings/UpdateAITenantConfigurationDto.cs @@ -0,0 +1,7 @@ +namespace Unity.AI.Settings; + +public class UpdateAITenantConfigurationDto +{ + public bool AutomaticGenerationEnabled { get; set; } + public bool ManualGenerationEnabled { get; set; } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Unity.AI.Application.Contracts.csproj b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Unity.AI.Application.Contracts.csproj index dcf9c1f296..a78c926a82 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Unity.AI.Application.Contracts.csproj +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application.Contracts/Unity.AI.Application.Contracts.csproj @@ -1,21 +1,18 @@ - - net9.0 enable Unity.AI - - + + - @@ -23,5 +20,4 @@ runtime; build; native; contentfiles; analyzers - - + \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Extraction/TextExtractionService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Extraction/TextExtractionService.cs similarity index 99% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Extraction/TextExtractionService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Extraction/TextExtractionService.cs index a29d4cad30..8d91759dce 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Extraction/TextExtractionService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Extraction/TextExtractionService.cs @@ -13,7 +13,7 @@ using UglyToad.PdfPig; using Volo.Abp.DependencyInjection; -namespace Unity.GrantManager.AI.Extraction +namespace Unity.AI.Extraction { public partial class TextExtractionService : ITextExtractionService, ITransientDependency { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/ApplicationAnalysisService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/ApplicationAnalysisService.cs similarity index 98% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/ApplicationAnalysisService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/ApplicationAnalysisService.cs index a06863fc8d..473a50d5b6 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/ApplicationAnalysisService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/ApplicationAnalysisService.cs @@ -5,13 +5,13 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; -using Unity.GrantManager.AI.Models; -using Unity.GrantManager.AI.Prompts; -using Unity.GrantManager.AI.Requests; +using Unity.AI.Models; +using Unity.AI.Prompts; +using Unity.AI.Requests; using Unity.GrantManager.Applications; using Volo.Abp.DependencyInjection; -namespace Unity.GrantManager.AI.Operations +namespace Unity.AI.Operations { public class ApplicationAnalysisService( IApplicationRepository applicationRepository, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/ApplicationScoringService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/ApplicationScoringService.cs similarity index 98% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/ApplicationScoringService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/ApplicationScoringService.cs index b73b76fe27..bcbf240301 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/ApplicationScoringService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/ApplicationScoringService.cs @@ -5,13 +5,13 @@ using System.Text.Json; using System.Threading.Tasks; using Unity.Flex.Domain.Scoresheets; -using Unity.GrantManager.AI.Models; -using Unity.GrantManager.AI.Prompts; -using Unity.GrantManager.AI.Requests; +using Unity.AI.Models; +using Unity.AI.Prompts; +using Unity.AI.Requests; using Unity.GrantManager.Applications; using Volo.Abp.DependencyInjection; -namespace Unity.GrantManager.AI.Operations +namespace Unity.AI.Operations { public class ApplicationScoringService( IApplicationRepository applicationRepository, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/AttachmentSummaryService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/AttachmentSummaryService.cs similarity index 98% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/AttachmentSummaryService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/AttachmentSummaryService.cs index eb8f84be83..1225970df5 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/AttachmentSummaryService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/AttachmentSummaryService.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Unity.GrantManager.AI.Requests; +using Unity.AI.Requests; using Unity.GrantManager.Applications; using Unity.GrantManager.Intakes; using Volo.Abp.DependencyInjection; -namespace Unity.GrantManager.AI.Operations; +namespace Unity.AI.Operations; public class AttachmentSummaryService( IApplicationChefsFileAttachmentRepository applicationChefsFileAttachmentRepository, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IApplicationAnalysisService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IApplicationAnalysisService.cs similarity index 82% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IApplicationAnalysisService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IApplicationAnalysisService.cs index 38eb57b046..991a9fe3c0 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IApplicationAnalysisService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IApplicationAnalysisService.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; -namespace Unity.GrantManager.AI.Operations +namespace Unity.AI.Operations { public interface IApplicationAnalysisService { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IApplicationScoringService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IApplicationScoringService.cs similarity index 82% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IApplicationScoringService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IApplicationScoringService.cs index ff76afb866..96fd5db6d1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IApplicationScoringService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IApplicationScoringService.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; -namespace Unity.GrantManager.AI.Operations +namespace Unity.AI.Operations { public interface IApplicationScoringService { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IAttachmentSummaryService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IAttachmentSummaryService.cs similarity index 90% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IAttachmentSummaryService.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IAttachmentSummaryService.cs index a4cdfd8f9f..c14ea0e01b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Operations/IAttachmentSummaryService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Operations/IAttachmentSummaryService.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Unity.GrantManager.AI.Operations; +namespace Unity.AI.Operations; public interface IAttachmentSummaryService { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/AIPromptTypes.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/AIPromptTypes.cs similarity index 85% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/AIPromptTypes.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/AIPromptTypes.cs index 47870da3f6..f908e1a388 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/AIPromptTypes.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/AIPromptTypes.cs @@ -1,4 +1,4 @@ -namespace Unity.GrantManager.AI.Prompts; +namespace Unity.AI.Prompts; public static class AIPromptTypes { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/PromptDataPayloadBuilder.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/PromptDataPayloadBuilder.cs similarity index 99% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/PromptDataPayloadBuilder.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/PromptDataPayloadBuilder.cs index c24166e354..315a26fc92 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/PromptDataPayloadBuilder.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/PromptDataPayloadBuilder.cs @@ -6,7 +6,7 @@ using System.Text.Json; using Unity.GrantManager.Applications; -namespace Unity.GrantManager.AI.Prompts +namespace Unity.AI.Prompts { internal static class PromptDataPayloadBuilder { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/README.md b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/README.md similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/README.md rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/README.md diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-analysis.system.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-analysis.system.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-analysis.system.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-analysis.system.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-analysis.user.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-analysis.user.txt similarity index 86% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-analysis.user.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-analysis.user.txt index 67a6fde997..8d7c84c90e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-analysis.user.txt +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-analysis.user.txt @@ -57,7 +57,7 @@ Analyze this grant application comprehensively across all five rubric categories OUTPUT { - "rating": "", + "decision": "", "warnings": [ { "title": "", @@ -76,23 +76,18 @@ OUTPUT "detail": "" } ], - "nextSteps": [ + "recommendations": [ { "title": "", "detail": "" } - ], - "recommendation": { - "decision": "", - "rationale": "" - } + ] } Important: - Use only APPLICATION CONTENT, ATTACHMENT SUMMARIES, FORM FIELD CONFIGURATION, and EVALUATION RUBRIC as evidence. +- decision must be PROCEED or HOLD. - Use summaries for overall application quality/readiness synthesis. -- Use nextSteps for reviewer-facing follow-up actions or considerations before scoring or decision-making. -- recommendation.decision must be PROCEED or HOLD. -- recommendation.rationale must explain the high-level recommendation in 1-2 complete sentences using provided evidence. +- Use recommendations for reviewer-facing follow-up actions or considerations before scoring or decision-making. - Use "title" and "detail" keys for all finding objects. - Return valid plain JSON only in the exact OUTPUT shape. diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-scoring.system.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-scoring.system.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-scoring.system.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-scoring.system.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-scoring.user.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-scoring.user.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/application-scoring.user.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/application-scoring.user.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/attachment-summary.system.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/attachment-summary.system.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/attachment-summary.system.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/attachment-summary.system.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/attachment-summary.user.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/attachment-summary.user.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v0/attachment-summary.user.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v0/attachment-summary.user.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.output.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.output.txt similarity index 69% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.output.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.output.txt index a80671676b..44093f50be 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.output.txt +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.output.txt @@ -1,5 +1,5 @@ { - "rating": "", + "decision": "", "errors": [ { "title": "", @@ -18,14 +18,10 @@ "detail": "" } ], - "nextSteps": [ + "recommendations": [ { "title": "", "detail": "" } - ], - "recommendation": { - "decision": "", - "rationale": "" - } + ] } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.rubric.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.rubric.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.rubric.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.rubric.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.rules.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.rules.txt similarity index 77% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.rules.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.rules.txt index a250310372..5840d215c8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.rules.txt +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.rules.txt @@ -19,17 +19,13 @@ - Use 3-6 words for title. - Summary titles should name the specific substantive reviewer conclusion, strength, or risk, not a generic evaluation label or abstract category. - Each detail must be 1-2 complete sentences. -- Summaries and nextSteps must be concrete, distinct, reviewer-relevant, and specific to this application's evidence. +- Summaries and recommendations must be concrete, distinct, reviewer-relevant, and specific to this application's evidence. - Avoid generic praise, checklist language, and repeated conclusions across lists. - Do not use a summary merely to say that supporting documents were provided; summarize the specific substantive evidence they add, or omit the finding. - If no findings exist, return empty arrays. -- Rating must be HIGH, MEDIUM, or LOW. +- Decision must be PROCEED or HOLD. - Use summaries for overall application quality/readiness synthesis. -- Use nextSteps for concrete reviewer-facing next actions based on the provided evidence. -- nextSteps may include proceeding with the normal review process when the application appears ready for that step. -- When evidence shows a meaningful gap, inconsistency, or uncertainty, use nextSteps for specific follow-up or verification actions. +- Use recommendations for concrete reviewer-facing next actions based on the provided evidence. +- Recommendations may include proceeding with the normal review process when the application appears ready for that step. +- When evidence shows a meaningful gap, inconsistency, or uncertainty, use recommendations for specific follow-up or verification actions. - Return an empty array only when no concrete next action would help the reviewer. -- recommendation.decision must be PROCEED or HOLD. -- Use HOLD only when provided evidence shows a material eligibility, feasibility, budget, or readiness concern that would reasonably block scoring or decision-making. -- recommendation.rationale must explain the high-level recommendation in 1-2 complete sentences using provided evidence. -- recommendation.rationale should name the 1-3 strongest evidence-based reasons for the recommendation. diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.score.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.score.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.score.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.score.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.system.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.system.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.system.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.system.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.user.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.user.txt similarity index 85% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.user.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.user.txt index 3b62f3cd97..b450089268 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-analysis.user.txt +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-analysis.user.txt @@ -13,8 +13,8 @@ RUBRIC SCORE {{SCORE}} -OUTPUT -{{OUTPUT}} +RESPONSE +{{RESPONSE}} RULES {{RULES}} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.output.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.output.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.output.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.output.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.rules.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.rules.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.rules.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.rules.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.system.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.system.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.system.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.system.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.user.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.user.txt similarity index 86% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.user.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.user.txt index 5b9d01b001..a8f64bc65f 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/application-scoring.user.txt +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/application-scoring.user.txt @@ -10,9 +10,6 @@ SECTION RESPONSE {{RESPONSE}} -OUTPUT -{{OUTPUT}} - RULES {{RULES}} {{COMMON_RULES}} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.output.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.output.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.output.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.output.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.rules.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.rules.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.rules.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.rules.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.system.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.system.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.system.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.system.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.user.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.user.txt similarity index 73% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.user.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.user.txt index 3247815c7b..acf4c67f3e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/attachment-summary.user.txt +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/attachment-summary.user.txt @@ -1,8 +1,8 @@ ATTACHMENT {{ATTACHMENT}} -OUTPUT -{{OUTPUT}} +RESPONSE +{{RESPONSE}} RULES {{RULES}} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/common.rules.txt b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/common.rules.txt similarity index 100% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Prompts/Versions/v1/common.rules.txt rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Prompts/Versions/v1/common.rules.txt diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIOperationResult.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIOperationResult.cs similarity index 90% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIOperationResult.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIOperationResult.cs index 12518f53e7..d0c2a2ceec 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIOperationResult.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIOperationResult.cs @@ -1,6 +1,6 @@ -namespace Unity.GrantManager.AI.Runtime +namespace Unity.AI.Runtime { - internal enum AIOperationOutcome + public enum AIOperationOutcome { Success, TransientFailure, @@ -8,7 +8,7 @@ internal enum AIOperationOutcome InvalidOutput } - internal sealed record AIOperationResult( + public sealed record AIOperationResult( AIOperationOutcome Outcome, AIProviderResult Response) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderPayloadValidator.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderPayloadValidator.cs similarity index 92% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderPayloadValidator.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderPayloadValidator.cs index 436f693d7f..f34cb95092 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderPayloadValidator.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderPayloadValidator.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Text.Json; -using Unity.GrantManager.AI.Models; +using Unity.AI.Models; -namespace Unity.GrantManager.AI.Runtime +namespace Unity.AI.Runtime { internal static class AIProviderPayloadValidator { @@ -19,16 +19,16 @@ public static bool IsValidApplicationAnalysisJson(string response) return false; } - return root.TryGetProperty(AIJsonKeys.Rating, out var rating) - && rating.ValueKind == JsonValueKind.String + return root.TryGetProperty(AIJsonKeys.Decision, out var decision) + && decision.ValueKind == JsonValueKind.String && root.TryGetProperty(AIJsonKeys.Errors, out var errors) && errors.ValueKind == JsonValueKind.Array && root.TryGetProperty(AIJsonKeys.Warnings, out var warnings) && warnings.ValueKind == JsonValueKind.Array && root.TryGetProperty(AIJsonKeys.Summaries, out var summaries) && summaries.ValueKind == JsonValueKind.Array - && root.TryGetProperty(AIJsonKeys.NextSteps, out var nextSteps) - && nextSteps.ValueKind == JsonValueKind.Array; + && root.TryGetProperty(AIJsonKeys.Recommendations, out var recommendations) + && recommendations.ValueKind == JsonValueKind.Array; } public static bool IsValidApplicationScoringJson(string response, string sectionJson) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderResponseMetadata.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderResponseMetadata.cs similarity index 64% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderResponseMetadata.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderResponseMetadata.cs index 5aa97d54c6..8144c43e4e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderResponseMetadata.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderResponseMetadata.cs @@ -1,6 +1,6 @@ -namespace Unity.GrantManager.AI.Runtime +namespace Unity.AI.Runtime { - internal sealed record AIProviderResponseMetadata( + public sealed record AIProviderResponseMetadata( string? Model, string? FinishReason, int? PromptTokens, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderResult.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderResult.cs similarity index 85% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderResult.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderResult.cs index a3b117062a..f36b165279 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIProviderResult.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIProviderResult.cs @@ -1,6 +1,6 @@ -namespace Unity.GrantManager.AI.Runtime +namespace Unity.AI.Runtime { - internal sealed record AIProviderResult( + public sealed record AIProviderResult( string Content, string RawResponse = "", string? Model = null, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIResponseJson.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIResponseJson.cs similarity index 97% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIResponseJson.cs rename to applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIResponseJson.cs index ff586c7588..7cbe184ec8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/AIResponseJson.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/AIResponseJson.cs @@ -1,6 +1,6 @@ using System; -namespace Unity.GrantManager.AI.Runtime +namespace Unity.AI.Runtime { internal static class AIResponseJson { diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIConfigurationResolver.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIConfigurationResolver.cs new file mode 100644 index 0000000000..7d999907aa --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIConfigurationResolver.cs @@ -0,0 +1,178 @@ +using Microsoft.Extensions.Configuration; +using System; +using System.Globalization; +using Volo.Abp.DependencyInjection; + +namespace Unity.AI.Runtime; + +public class OpenAIConfigurationResolver(IConfiguration configuration) : ITransientDependency +{ + private const string DefaultMaxTokensParameterName = "max_completion_tokens"; + private const string LegacyMaxTokensParameterName = "max_tokens"; + private const string DefaultProviderName = "OpenAI"; + private const string OpenAiApiKeyEnvironmentVariableName = "AZURE_OPENAI_API_KEY"; + private const string OpenAiEndpointEnvironmentVariableName = "AZURE_OPENAI_ENDPOINT"; + + private readonly IConfiguration _configuration = configuration; + + public string ResolveProviderName(string? operationName = null) + { + if (!string.IsNullOrWhiteSpace(operationName)) + { + var configuredProvider = _configuration[$"Azure:Operations:{operationName}:Provider"]; + if (!string.IsNullOrWhiteSpace(configuredProvider)) + { + return configuredProvider.Trim(); + } + } + + var defaultProvider = _configuration["Azure:Operations:Defaults:Provider"]; + return string.IsNullOrWhiteSpace(defaultProvider) ? DefaultProviderName : defaultProvider.Trim(); + } + + public string ResolveApiKey(string? operationName = null) + { + var providerName = ResolveProviderName(operationName); + if (string.Equals(providerName, DefaultProviderName, StringComparison.Ordinal)) + { + var injectedApiKey = _configuration[OpenAiApiKeyEnvironmentVariableName]; + if (!string.IsNullOrWhiteSpace(injectedApiKey)) + { + return injectedApiKey; + } + } + + return _configuration[$"Azure:{providerName}:ApiKey"] ?? string.Empty; + } + + public string ResolveMaxTokensParameterNameForOperation(string? operationName = null) + { + var providerName = ResolveProviderName(operationName); + var profileName = ResolveProfileName(operationName); + var profileParameterName = ResolveProfileSetting(providerName, profileName, "MaxTokensParameter"); + return ResolveMaxTokensParameterName(profileParameterName); + } + + public double? ResolveConfiguredTemperature(string? operationName = null) + { + var providerName = ResolveProviderName(operationName); + var profileName = ResolveProfileName(operationName); + var profileTemperature = ResolveProfileSetting(providerName, profileName, "Temperature"); + if (profileTemperature != null + && double.TryParse(profileTemperature, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedTemperature)) + { + return parsedTemperature; + } + + return null; + } + + public int ResolveCompletionTokens(string operationName, int defaultValue) + { + var configuredValue = _configuration.GetValue($"Azure:Operations:{operationName}:MaxCompletionTokens"); + if (configuredValue is > 0) + { + return configuredValue.Value; + } + + var defaultConfiguredValue = _configuration.GetValue("Azure:Operations:Defaults:MaxCompletionTokens"); + return defaultConfiguredValue is > 0 ? defaultConfiguredValue.Value : defaultValue; + } + + public string ResolveApiUrl(string? operationName = null) + { + var providerName = ResolveProviderName(operationName); + var profileName = ResolveProfileName(operationName); + var profileApiUrl = ResolveProfileSetting(providerName, profileName, "ApiUrl"); + var injectedEndpoint = ResolveInjectedEndpoint(providerName); + var legacyOpenAiApiUrl = _configuration["Azure:OpenAI:ApiUrl"]; + + if (!string.IsNullOrWhiteSpace(injectedEndpoint) && !string.IsNullOrWhiteSpace(profileApiUrl)) + { + return CombineEndpointAndPath(injectedEndpoint, profileApiUrl); + } + + if (!string.IsNullOrWhiteSpace(profileApiUrl)) + { + return profileApiUrl; + } + + if (!string.IsNullOrWhiteSpace(legacyOpenAiApiUrl)) + { + return legacyOpenAiApiUrl; + } + + throw new InvalidOperationException($"AI API URL is not configured for provider '{providerName}'."); + } + + private static string ResolveMaxTokensParameterName(string? configuredParameterName) + { + if (string.Equals(configuredParameterName, LegacyMaxTokensParameterName, StringComparison.Ordinal)) + { + return LegacyMaxTokensParameterName; + } + + return DefaultMaxTokensParameterName; + } + + private string? ResolveInjectedEndpoint(string providerName) + { + if (!string.Equals(providerName, DefaultProviderName, StringComparison.Ordinal)) + { + return _configuration[$"Azure:{providerName}:Endpoint"]; + } + + var injectedEndpoint = _configuration[OpenAiEndpointEnvironmentVariableName]; + if (!string.IsNullOrWhiteSpace(injectedEndpoint)) + { + return injectedEndpoint; + } + + return _configuration["Azure:OpenAI:Endpoint"]; + } + + private string? ResolveProfileName(string? operationName) + { + if (!string.IsNullOrWhiteSpace(operationName)) + { + var operationProfile = _configuration[$"Azure:Operations:{operationName}:Profile"]; + if (!string.IsNullOrWhiteSpace(operationProfile)) + { + return operationProfile.Trim(); + } + } + + var defaultProfile = _configuration["Azure:Operations:Defaults:Profile"]; + return string.IsNullOrWhiteSpace(defaultProfile) ? null : defaultProfile.Trim(); + } + + private string? ResolveProfileSetting(string providerName, string? profileName, string settingName) + { + if (string.IsNullOrWhiteSpace(profileName)) + { + return null; + } + + var profileSetting = _configuration[$"Azure:{providerName}:Profiles:{profileName}:{settingName}"]; + return string.IsNullOrWhiteSpace(profileSetting) ? null : profileSetting; + } + + private static string CombineEndpointAndPath(string endpoint, string profilePath) + { + const char UrlPathSeparator = '/'; + + if (Uri.TryCreate(profilePath, UriKind.Absolute, out var absoluteUri)) + { + return absoluteUri.ToString(); + } + + var trimmedEndpoint = endpoint.Trim().TrimEnd(UrlPathSeparator); + var trimmedPath = profilePath.Trim(); + if (!trimmedPath.StartsWith(UrlPathSeparator)) + { + trimmedPath = string.Concat(UrlPathSeparator, trimmedPath); + } + + return trimmedEndpoint + trimmedPath; + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIPromptRenderer.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIPromptRenderer.cs new file mode 100644 index 0000000000..a56d56f6af --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIPromptRenderer.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections.Generic; +using System.Collections.Concurrent; +using System.IO; +using System.Linq; +using System.Text.Json; +using Volo.Abp.DependencyInjection; + +namespace Unity.AI.Runtime; + +public class OpenAIPromptRenderer : ITransientDependency +{ + private const string PromptVersionV0 = "v0"; + private const string PromptVersionV1 = "v1"; + private static readonly string PromptTemplatesFolder = Path.Combine("AI", "Prompts", "Versions"); + private const string ApplicationAnalysisSystemTemplateName = "application-analysis.system"; + private const string ApplicationAnalysisUserTemplateName = "application-analysis.user"; + private const string AttachmentSummarySystemTemplateName = "attachment-summary.system"; + private const string AttachmentSummaryUserTemplateName = "attachment-summary.user"; + private const string ApplicationScoringSystemTemplateName = "application-scoring.system"; + private const string ApplicationScoringUserTemplateName = "application-scoring.user"; + private static readonly Dictionary PromptProfiles = + new(StringComparer.OrdinalIgnoreCase) + { + [PromptVersionV0] = PromptVersionV0, + [PromptVersionV1] = PromptVersionV1 + }; + private static readonly ConcurrentDictionary PromptTemplateCache = new(StringComparer.OrdinalIgnoreCase); + private static readonly JsonSerializerOptions JsonLogOptions = new() { WriteIndented = true }; + + public static string BuildApplicationAnalysisSystemPrompt(string version) + { + return GetRequiredPromptTemplate(version, ApplicationAnalysisSystemTemplateName); + } + + public static string BuildApplicationAnalysisUserPrompt(string version, string schema, string data, string attachments) + { + var replacements = new Dictionary + { + ["SCHEMA"] = schema, + ["DATA"] = data, + ["ATTACHMENTS"] = attachments + }; + + return RenderPromptTemplate(version, ApplicationAnalysisUserTemplateName, replacements); + } + + public static string BuildAttachmentSummarySystemPrompt(string version) + { + return GetRequiredPromptTemplate(version, AttachmentSummarySystemTemplateName); + } + + public static string BuildAttachmentSummaryUserPrompt(string version, string attachment) + { + return RenderPromptTemplate(version, AttachmentSummaryUserTemplateName, new Dictionary + { + ["ATTACHMENT"] = attachment + }); + } + + public static string BuildApplicationScoringSystemPrompt(string version) + { + return GetRequiredPromptTemplate(version, ApplicationScoringSystemTemplateName); + } + + public static string BuildApplicationScoringUserPrompt(string version, string data, string attachments, string section, string response) + { + return RenderPromptTemplate(version, ApplicationScoringUserTemplateName, new Dictionary + { + ["DATA"] = data, + ["ATTACHMENTS"] = attachments, + ["SECTION"] = section, + ["RESPONSE"] = response + }); + } + + public static string BuildApplicationScoringResponseTemplate(string sectionPayloadJson) + { + try + { + using var doc = JsonDocument.Parse(sectionPayloadJson); + if (!doc.RootElement.TryGetProperty("questions", out var questions) || questions.ValueKind != JsonValueKind.Array) + { + return "{}"; + } + + var template = new Dictionary(); + foreach (var question in questions.EnumerateArray()) + { + if (!question.TryGetProperty("id", out var idProp) || idProp.ValueKind != JsonValueKind.String) + { + continue; + } + + var questionId = idProp.GetString(); + if (string.IsNullOrWhiteSpace(questionId)) + { + continue; + } + + template[questionId] = new + { + answer = string.Empty, + rationale = string.Empty, + confidence = 0 + }; + } + + if (template.Count == 0) + { + return "{}"; + } + + return JsonSerializer.Serialize(template, JsonLogOptions); + } + catch (JsonException) + { + return "{}"; + } + } + + public static string BuildAliasedApplicationScoringSection(string? sectionName, string sectionJson, out IReadOnlyDictionary questionIdAliasMap) + { + questionIdAliasMap = new Dictionary(StringComparer.Ordinal); + + if (string.IsNullOrWhiteSpace(sectionJson)) + { + return JsonSerializer.Serialize(new { name = sectionName, questions = sectionJson }, JsonLogOptions); + } + + try + { + using var sectionDoc = JsonDocument.Parse(sectionJson); + if (sectionDoc.RootElement.ValueKind != JsonValueKind.Array) + { + return JsonSerializer.Serialize(new { name = sectionName, questions = sectionDoc.RootElement.Clone() }, JsonLogOptions); + } + + var aliasedQuestions = new List>(); + var aliasMap = new Dictionary(StringComparer.Ordinal); + var index = 1; + + foreach (var question in sectionDoc.RootElement.EnumerateArray()) + { + if (question.ValueKind != JsonValueKind.Object) + { + continue; + } + + var aliasedQuestion = new Dictionary(StringComparer.Ordinal); + string? questionAlias = null; + + foreach (var property in question.EnumerateObject()) + { + if (property.NameEquals("id") && property.Value.ValueKind == JsonValueKind.String) + { + var originalQuestionId = property.Value.GetString(); + if (!string.IsNullOrWhiteSpace(originalQuestionId)) + { + questionAlias = $"q{index++}"; + aliasMap[questionAlias] = originalQuestionId; + aliasedQuestion[property.Name] = questionAlias; + continue; + } + } + + aliasedQuestion[property.Name] = property.Value.Clone(); + } + + if (!string.IsNullOrWhiteSpace(questionAlias)) + { + aliasedQuestions.Add(aliasedQuestion); + } + } + + questionIdAliasMap = aliasMap; + return JsonSerializer.Serialize(new { name = sectionName, questions = aliasedQuestions }, JsonLogOptions); + } + catch (JsonException) + { + return JsonSerializer.Serialize(new { name = sectionName, questions = sectionJson }, JsonLogOptions); + } + } + + public static string ResolvePromptVersion(string? version) + { + if (!string.IsNullOrWhiteSpace(version) && + PromptProfiles.TryGetValue(version.Trim(), out var selectedVersion)) + { + return selectedVersion; + } + + return PromptVersionV1; + } + + private static bool TryGetPromptTemplate(string version, string templateName, out string template) + { + template = string.Empty; + var cacheKey = $"{version}/{templateName}"; + if (PromptTemplateCache.TryGetValue(cacheKey, out var cachedTemplate)) + { + template = cachedTemplate; + return true; + } + + var path = Path.Combine(AppContext.BaseDirectory, PromptTemplatesFolder, version, $"{templateName}.txt"); + if (!File.Exists(path)) + { + return false; + } + + var loaded = PromptTemplateCache.GetOrAdd(cacheKey, _ => File.ReadAllText(path)); + if (string.IsNullOrWhiteSpace(loaded)) + { + return false; + } + + template = loaded; + return true; + } + + private static string GetRequiredPromptTemplate(string version, string templateName) + { + if (TryGetPromptTemplate(version, templateName, out var template)) + { + return template; + } + + throw new InvalidOperationException( + $"Missing required prompt template '{templateName}.txt' for prompt version '{version}'."); + } + + private static string RenderPromptTemplate( + string version, + string templateName, + IReadOnlyDictionary runtimeReplacements) + { + return RenderPromptTemplateInternal( + version, + templateName, + runtimeReplacements, + new HashSet(StringComparer.OrdinalIgnoreCase)); + } + + private static string RenderPromptTemplateInternal( + string version, + string templateName, + IReadOnlyDictionary runtimeReplacements, + ISet resolutionStack) + { + if (!resolutionStack.Add(templateName)) + { + throw new InvalidOperationException( + $"Detected cyclic prompt fragment reference while resolving '{templateName}.txt' for prompt version '{version}'."); + } + + var template = GetRequiredPromptTemplate(version, templateName); + var replacements = new Dictionary(runtimeReplacements, StringComparer.Ordinal); + var baseTemplateName = GetTemplateBaseName(templateName); + + foreach (var placeholder in GetTemplatePlaceholders(template)) + { + if (replacements.ContainsKey(placeholder)) + { + continue; + } + + var fragmentTemplateName = ResolveFragmentTemplateName(version, baseTemplateName, placeholder); + if (!string.IsNullOrWhiteSpace(fragmentTemplateName)) + { + replacements[placeholder] = RenderPromptTemplateInternal( + version, + fragmentTemplateName, + new Dictionary(StringComparer.Ordinal), + resolutionStack).TrimEnd(); + } + } + + var rendered = template; + foreach (var replacement in replacements) + { + rendered = rendered.Replace($"{{{{{replacement.Key}}}}}", replacement.Value ?? string.Empty, StringComparison.Ordinal); + } + + var unresolved = GetTemplatePlaceholders(rendered); + if (unresolved.Count > 0) + { + throw new InvalidOperationException( + $"Unresolved prompt placeholders in '{templateName}.txt' for prompt version '{version}': {string.Join(", ", unresolved.OrderBy(item => item))}"); + } + + resolutionStack.Remove(templateName); + return rendered; + } + + private static string? ResolveFragmentTemplateName(string version, string baseTemplateName, string placeholderName) + { + var normalizedPlaceholder = placeholderName.ToLowerInvariant(); + var baseScopedCandidate = $"{baseTemplateName}.{normalizedPlaceholder}"; + if (TryGetPromptTemplate(version, baseScopedCandidate, out _)) + { + return baseScopedCandidate; + } + + if (string.Equals(placeholderName, "RESPONSE", StringComparison.Ordinal)) + { + var outputCandidate = $"{baseTemplateName}.output"; + if (TryGetPromptTemplate(version, outputCandidate, out _)) + { + return outputCandidate; + } + } + + if (TryResolveCommonTemplateName(placeholderName, out var commonTemplateName) && + TryGetPromptTemplate(version, commonTemplateName, out _)) + { + return commonTemplateName; + } + + return null; + } + + private static bool TryResolveCommonTemplateName(string placeholderName, out string commonTemplateName) + { + commonTemplateName = string.Empty; + if (!placeholderName.StartsWith("COMMON_", StringComparison.Ordinal)) + { + return false; + } + + var suffix = placeholderName.Substring("COMMON_".Length).ToLowerInvariant(); + suffix = suffix.Replace('_', '.'); + commonTemplateName = $"common.{suffix}"; + return true; + } + + private static string GetTemplateBaseName(string templateName) + { + var separatorIndex = templateName.IndexOf('.', StringComparison.Ordinal); + if (separatorIndex <= 0) + { + return templateName; + } + + return templateName.Substring(0, separatorIndex); + } + + private static HashSet GetTemplatePlaceholders(string template) + { + var placeholders = new HashSet(StringComparer.Ordinal); + var searchIndex = 0; + + while (searchIndex < template.Length) + { + var start = template.IndexOf("{{", searchIndex, StringComparison.Ordinal); + if (start < 0) + { + break; + } + + var end = template.IndexOf("}}", start + 2, StringComparison.Ordinal); + if (end < 0) + { + break; + } + + var placeholder = template.Substring(start + 2, end - start - 2).Trim(); + if (!string.IsNullOrWhiteSpace(placeholder)) + { + placeholders.Add(placeholder); + } + + searchIndex = end + 2; + } + + return placeholders; + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIResponseParser.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIResponseParser.cs new file mode 100644 index 0000000000..1abacf8dda --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIResponseParser.cs @@ -0,0 +1,251 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using Unity.AI.Models; +using Unity.AI.Responses; +using Volo.Abp.DependencyInjection; + +namespace Unity.AI.Runtime; + +public class OpenAIResponseParser : ITransientDependency +{ + public static ApplicationAnalysisResponse ParseApplicationAnalysisResponse(string raw) + { + var response = new ApplicationAnalysisResponse(); + if (!TryParseJsonObjectFromResponse(AddIdsToAnalysisItems(raw), out var root)) + { + return response; + } + + if (TryGetStringProperty(root, AIJsonKeys.Decision, out var decision)) + { + response.Decision = decision.Trim().ToUpperInvariant(); + } + + if (TryGetArrayProperty(root, AIJsonKeys.Errors, out var errorsArray)) + { + response.Errors = ParseFindings(errorsArray).ToList(); + } + + if (TryGetArrayProperty(root, AIJsonKeys.Warnings, out var warningsArray)) + { + response.Warnings = ParseFindings(warningsArray).ToList(); + } + + if (TryGetArrayProperty(root, AIJsonKeys.Summaries, out var summariesArray)) + { + response.Summaries = ParseFindings(summariesArray).ToList(); + } + + if (TryGetArrayProperty(root, AIJsonKeys.Recommendations, out var recommendationsArray)) + { + response.Recommendations = ParseFindings(recommendationsArray).ToList(); + } + + return response; + } + + private static string AddIdsToAnalysisItems(string analysisJson) + { + try + { + using var jsonDoc = JsonDocument.Parse(analysisJson); + using var memoryStream = new System.IO.MemoryStream(); + using (var writer = new Utf8JsonWriter(memoryStream, new JsonWriterOptions { Indented = true })) + { + writer.WriteStartObject(); + + foreach (var property in jsonDoc.RootElement.EnumerateObject()) + { + var outputPropertyName = property.Name; + + if (outputPropertyName == AIJsonKeys.Errors || + outputPropertyName == AIJsonKeys.Warnings || + outputPropertyName == AIJsonKeys.Summaries || + outputPropertyName == AIJsonKeys.Recommendations) + { + writer.WritePropertyName(outputPropertyName); + writer.WriteStartArray(); + + foreach (var item in property.Value.EnumerateArray()) + { + writer.WriteStartObject(); + + foreach (var itemProperty in item.EnumerateObject()) + { + itemProperty.WriteTo(writer); + } + + if (!item.TryGetProperty(AIJsonKeys.Id, out var idProp) || + idProp.ValueKind != JsonValueKind.String || + string.IsNullOrWhiteSpace(idProp.GetString())) + { + writer.WriteString(AIJsonKeys.Id, Guid.NewGuid().ToString()); + } + + writer.WriteEndObject(); + } + + writer.WriteEndArray(); + continue; + } + + property.WriteTo(writer); + } + + writer.WriteEndObject(); + writer.Flush(); + } + + return Encoding.UTF8.GetString(memoryStream.ToArray()); + } + catch + { + return analysisJson; + } + } + + public static ApplicationScoringResponse ParseApplicationScoringResponse(string raw, IReadOnlyDictionary? questionIdAliasMap = null) + { + var response = new ApplicationScoringResponse(); + if (!TryParseJsonObjectFromResponse(raw, out var root)) + { + return response; + } + + foreach (var property in root.EnumerateObject()) + { + if (property.Value.ValueKind != JsonValueKind.Object) + { + continue; + } + + var answer = property.Value.TryGetProperty("answer", out var answerProp) + ? answerProp.Clone() + : default; + var rationale = property.Value.TryGetProperty("rationale", out var rationaleProp) && + rationaleProp.ValueKind == JsonValueKind.String + ? rationaleProp.GetString() ?? string.Empty + : string.Empty; + var confidence = property.Value.TryGetProperty("confidence", out var confidenceProp) && + confidenceProp.ValueKind == JsonValueKind.Number && + confidenceProp.TryGetInt32(out var parsedConfidence) + ? NormalizeConfidence(parsedConfidence) + : 0; + + var questionId = questionIdAliasMap != null && + questionIdAliasMap.TryGetValue(property.Name, out var originalQuestionId) + ? originalQuestionId + : property.Name; + + response.Answers[questionId] = new ApplicationScoringAnswer + { + Answer = answer, + Rationale = rationale, + Confidence = confidence + }; + } + + return response; + } + + private static IEnumerable ParseFindings(JsonElement findingsArray) + { + foreach (var item in findingsArray.EnumerateArray()) + { + if (item.ValueKind != JsonValueKind.Object) + { + continue; + } + + var id = Guid.NewGuid().ToString(); + if (item.TryGetProperty(AIJsonKeys.Id, out var idProp) && idProp.ValueKind == JsonValueKind.String) + { + id = idProp.GetString() ?? id; + } + + var dismissed = item.TryGetProperty(AIJsonKeys.Dismissed, out var dismissedProp) && + (dismissedProp.ValueKind == JsonValueKind.True || dismissedProp.ValueKind == JsonValueKind.False) && + dismissedProp.GetBoolean(); + + string? title = null; + if (item.TryGetProperty(AIJsonKeys.Title, out var titleProp) && titleProp.ValueKind == JsonValueKind.String) + { + title = titleProp.GetString(); + } + + string? detail = null; + if (item.TryGetProperty(AIJsonKeys.Detail, out var detailProp) && detailProp.ValueKind == JsonValueKind.String) + { + detail = detailProp.GetString(); + } + + yield return new ApplicationAnalysisFinding + { + Id = id, + Dismissed = dismissed, + Title = title, + Detail = detail + }; + } + } + + private static bool TryParseJsonObjectFromResponse(string response, out JsonElement objectElement) + { + objectElement = default; + var cleaned = AIResponseJson.CleanJsonResponse(response); + if (string.IsNullOrWhiteSpace(cleaned)) + { + return false; + } + + try + { + using var doc = JsonDocument.Parse(cleaned); + if (doc.RootElement.ValueKind != JsonValueKind.Object) + { + return false; + } + + objectElement = doc.RootElement.Clone(); + return true; + } + catch (JsonException) + { + return false; + } + } + + private static bool TryGetStringProperty(JsonElement element, string propertyName, out string value) + { + value = string.Empty; + if (!element.TryGetProperty(propertyName, out var prop) || prop.ValueKind != JsonValueKind.String) + { + return false; + } + + value = prop.GetString() ?? string.Empty; + return true; + } + + private static bool TryGetArrayProperty(JsonElement element, string propertyName, out JsonElement value) + { + value = default; + if (!element.TryGetProperty(propertyName, out var prop) || prop.ValueKind != JsonValueKind.Array) + { + return false; + } + + value = prop.Clone(); + return true; + } + + private static int NormalizeConfidence(int confidence) + { + var clamped = Math.Clamp(confidence, 0, 100); + var rounded = (int)Math.Round(clamped / 5.0, MidpointRounding.AwayFromZero) * 5; + return Math.Clamp(rounded, 0, 100); + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIRuntimeService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIRuntimeService.cs new file mode 100644 index 0000000000..d9886d1f97 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAIRuntimeService.cs @@ -0,0 +1,557 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using Unity.AI.Extraction; +using Unity.AI.Models; +using Unity.AI.Prompts; +using Unity.AI.Requests; +using Unity.AI.Responses; +using Volo.Abp.DependencyInjection; + +namespace Unity.AI.Runtime +{ + [ExposeServices(typeof(IAIService))] + public class OpenAIRuntimeService : IAIService, ITransientDependency + { + private readonly IConfiguration _configuration; + private readonly ILogger _logger; + private readonly ITextExtractionService _textExtractionService; + private readonly OpenAITransportService _openAITransportService; + private readonly OpenAIConfigurationResolver _openAIConfigurationResolver; + private const string ApplicationAnalysisPromptType = AIPromptTypes.ApplicationAnalysis; + private const string AttachmentSummaryPromptType = AIPromptTypes.AttachmentSummary; + private const string ApplicationScoringPromptType = AIPromptTypes.ApplicationScoring; + private const string AIServiceNotConfiguredMessage = "AI service not available - service not configured."; + private const string AIServiceTemporarilyUnavailableMessage = "AI request failed - service temporarily unavailable."; + private const string AIRequestFailedRetryMessage = "AI request failed - please try again later."; + private const int MaxAiAttempts = 3; + private const int DefaultCompletionTokens = 2000; + private const int DefaultAttachmentSummaryCompletionTokens = 2000; + private const int DefaultApplicationAnalysisCompletionTokens = 4000; + private const int DefaultApplicationScoringCompletionTokens = 8000; + + private int AttachmentSummaryCompletionTokens => _openAIConfigurationResolver.ResolveCompletionTokens(AttachmentSummaryPromptType, DefaultAttachmentSummaryCompletionTokens); + private int ApplicationAnalysisCompletionTokens => _openAIConfigurationResolver.ResolveCompletionTokens(ApplicationAnalysisPromptType, DefaultApplicationAnalysisCompletionTokens); + private int ApplicationScoringCompletionTokens => _openAIConfigurationResolver.ResolveCompletionTokens(ApplicationScoringPromptType, DefaultApplicationScoringCompletionTokens); + private readonly string MissingApiKeyMessage = "OpenAI API key is not configured"; + + // Optional local debugging sink for prompt payload logs to a local file. + // Not intended for deployed/shared environments. + private bool IsPromptFileLoggingEnabled => _configuration.GetValue("Azure:Logging:EnablePromptFileLog") ?? false; + private const string PromptLogDirectoryName = "logs"; + private static readonly string PromptLogFileName = $"ai-prompts-{DateTime.UtcNow:yyyyMMdd-HHmmss}-{Environment.ProcessId}.log"; + + private static readonly JsonSerializerOptions JsonLogOptions = new() { WriteIndented = true }; + + public OpenAIRuntimeService( + IConfiguration configuration, + ILogger logger, + ITextExtractionService textExtractionService, + OpenAITransportService openAITransportService, + OpenAIConfigurationResolver openAIConfigurationResolver) + { + _configuration = configuration; + _logger = logger; + _textExtractionService = textExtractionService; + _openAITransportService = openAITransportService; + _openAIConfigurationResolver = openAIConfigurationResolver; + } + + public Task IsAvailableAsync() + { + if (string.IsNullOrEmpty(_openAIConfigurationResolver.ResolveApiKey())) + { + _logger.LogWarning("Error: {Message}", MissingApiKeyMessage); + return Task.FromResult(false); + } + + return Task.FromResult(true); + } + + public async Task GenerateCompletionAsync(AICompletionRequest request) + { + var result = await GenerateWithRetryAsync( + () => _openAITransportService.GenerateSummaryAsync( + request?.UserPrompt ?? string.Empty, + null, + request?.MaxTokens ?? DefaultCompletionTokens, + request?.Temperature), + AIProviderPayloadValidator.IsValidAttachmentSummaryText, + "completion"); + return new AICompletionResponse { Content = ResolveNarrativeContent(result) }; + } + + public async Task GenerateApplicationAnalysisAsync(ApplicationAnalysisRequest request) + { + ArgumentNullException.ThrowIfNull(request); + var promptVersion = OpenAIPromptRenderer.ResolvePromptVersion(request.PromptVersion ?? ResolvePromptVersionSetting(ApplicationAnalysisPromptType)); + var data = JsonSerializer.Serialize(request.Data, JsonLogOptions); + var schema = JsonSerializer.Serialize(request.Schema, JsonLogOptions); + + var attachmentsPayload = request.Attachments + .Select(a => new + { + name = string.IsNullOrWhiteSpace(a.Name) ? "attachment" : a.Name.Trim(), + summary = string.IsNullOrWhiteSpace(a.Summary) ? string.Empty : a.Summary.Trim() + }) + .Cast(); + + var attachments = JsonSerializer.Serialize(attachmentsPayload, JsonLogOptions); + var systemPrompt = OpenAIPromptRenderer.BuildApplicationAnalysisSystemPrompt(promptVersion); + var applicationAnalysisContent = OpenAIPromptRenderer.BuildApplicationAnalysisUserPrompt( + promptVersion, + schema, + data, + attachments); + await LogPromptInputAsync(ApplicationAnalysisPromptType, promptVersion, systemPrompt, applicationAnalysisContent); + var result = await GenerateWithRetryAsync( + () => _openAITransportService.GenerateSummaryAsync( + applicationAnalysisContent, + systemPrompt, + ApplicationAnalysisCompletionTokens, + operationName: ApplicationAnalysisPromptType, + promptVersion: promptVersion), + AIProviderPayloadValidator.IsValidApplicationAnalysisJson, + "application analysis"); + await LogPromptOutputAsync(ApplicationAnalysisPromptType, promptVersion, result.CaptureOutput); + + if (result.Outcome != AIOperationOutcome.Success) + { + return new ApplicationAnalysisResponse(); + } + + return OpenAIResponseParser.ParseApplicationAnalysisResponse(result.Content); + } + + public async Task GenerateAttachmentSummaryAsync(AttachmentSummaryRequest request) + { + ArgumentNullException.ThrowIfNull(request); + var fileName = request.FileName ?? string.Empty; + var fileContent = request.FileContent ?? Array.Empty(); + var contentType = request.ContentType ?? "application/octet-stream"; + var promptVersion = OpenAIPromptRenderer.ResolvePromptVersion(request.PromptVersion ?? ResolvePromptVersionSetting(AttachmentSummaryPromptType)); + + try + { + var extractedText = await _textExtractionService.ExtractTextAsync(fileName, fileContent, contentType); + var prompt = OpenAIPromptRenderer.BuildAttachmentSummarySystemPrompt(promptVersion); + + var attachmentText = string.IsNullOrWhiteSpace(extractedText) ? null : extractedText; + if (attachmentText != null) + { + _logger.LogDebug("Extracted {TextLength} characters from {FileName}", extractedText.Length, fileName); + } + else + { + _logger.LogDebug("No text extracted from {FileName}, analyzing metadata only", fileName); + } + + var attachmentPayload = new + { + name = fileName, + contentType, + sizeBytes = fileContent.Length, + text = attachmentText + }; + var attachment = JsonSerializer.Serialize(attachmentPayload, JsonLogOptions); + var contentToAnalyze = OpenAIPromptRenderer.BuildAttachmentSummaryUserPrompt(promptVersion, attachment); + + await LogPromptInputAsync(AttachmentSummaryPromptType, promptVersion, prompt, contentToAnalyze); + var result = await GenerateWithRetryAsync( + () => _openAITransportService.GenerateSummaryAsync( + contentToAnalyze, + prompt, + AttachmentSummaryCompletionTokens, + operationName: AttachmentSummaryPromptType, + promptVersion: promptVersion, + fileName: fileName), + AIProviderPayloadValidator.IsValidAttachmentSummaryText, + "attachment summary"); + await LogPromptOutputAsync(AttachmentSummaryPromptType, promptVersion, result.CaptureOutput); + + if (result.Outcome != AIOperationOutcome.Success) + { + return new AttachmentSummaryResponse + { + Summary = $"AI analysis not available for this attachment ({fileName})." + }; + } + + return new AttachmentSummaryResponse + { + Summary = ExtractSummaryFromJson(result.Content) + }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error generating attachment summary for {FileName}", fileName); + return new AttachmentSummaryResponse + { + Summary = $"AI analysis not available for this attachment ({fileName})." + }; + } + } + + public async Task GenerateApplicationScoringAsync(ApplicationScoringRequest request) + { + ArgumentNullException.ThrowIfNull(request); + var promptVersion = OpenAIPromptRenderer.ResolvePromptVersion(request.PromptVersion ?? ResolvePromptVersionSetting(ApplicationScoringPromptType)); + var dataJson = JsonSerializer.Serialize(request.Data, JsonLogOptions); + var sectionJson = JsonSerializer.Serialize(request.SectionSchema, JsonLogOptions); + + var attachmentSummaries = request.Attachments + .Select(a => $"{a.Name}: {a.Summary}") + .ToList(); + if (string.IsNullOrEmpty(_openAIConfigurationResolver.ResolveApiKey(ApplicationScoringPromptType))) + { + _logger.LogWarning("{Message}", MissingApiKeyMessage); + return new ApplicationScoringResponse(); + } + + try + { + var attachments = attachmentSummaries.Count > 0 + ? string.Join("\n- ", attachmentSummaries.Select((summary, index) => $"Attachment {index + 1}: {summary}")) + : "No attachments provided."; + + var section = OpenAIPromptRenderer.BuildAliasedApplicationScoringSection(request.SectionName, sectionJson, out var questionIdAliasMap); + var response = OpenAIPromptRenderer.BuildApplicationScoringResponseTemplate(section); + if (response == "{}") + { + _logger.LogWarning( + "Skipping AI application scoring for section {SectionName} because response template could not be built from section schema.", + request.SectionName); + return new ApplicationScoringResponse(); + } + + var applicationScoringContent = OpenAIPromptRenderer.BuildApplicationScoringUserPrompt( + promptVersion, + dataJson, + attachments, + section, + response); + var systemPrompt = OpenAIPromptRenderer.BuildApplicationScoringSystemPrompt(promptVersion); + + await LogPromptInputAsync(ApplicationScoringPromptType, promptVersion, systemPrompt, applicationScoringContent); + var result = await GenerateWithRetryAsync( + () => _openAITransportService.GenerateSummaryAsync( + applicationScoringContent, + systemPrompt, + ApplicationScoringCompletionTokens, + operationName: ApplicationScoringPromptType, + promptVersion: promptVersion), + content => AIProviderPayloadValidator.IsValidApplicationScoringJson(content, section), + $"application scoring section {request.SectionName}"); + await LogPromptOutputAsync(ApplicationScoringPromptType, promptVersion, result.CaptureOutput); + + if (result.Outcome != AIOperationOutcome.Success) + { + return new ApplicationScoringResponse(); + } + + return OpenAIResponseParser.ParseApplicationScoringResponse(result.Content, questionIdAliasMap); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error generating application scoring answers for section {SectionName}", request.SectionName); + return new ApplicationScoringResponse(); + } + } + + private async Task GenerateWithRetryAsync( + Func> operation, + Func validator, + string operationName) + { + var lastResult = AIOperationResult.InvalidOutput(); + + for (var attempt = 1; attempt <= MaxAiAttempts; attempt++) + { + lastResult = await operation(); + + if (lastResult.Outcome == AIOperationOutcome.Success && validator(lastResult.Content)) + { + return lastResult; + } + + if (lastResult.Outcome == AIOperationOutcome.Success) + { + lastResult = lastResult.WithOutcome(AIOperationOutcome.InvalidOutput); + } + + if (lastResult.Outcome == AIOperationOutcome.PermanentFailure) + { + return lastResult; + } + + if (attempt < MaxAiAttempts) + { + if (lastResult.Outcome == AIOperationOutcome.TransientFailure) + { + _logger.LogWarning( + "AI {OperationName} attempt {Attempt}/{MaxAttempts} failed transiently; retrying", + operationName, + attempt, + MaxAiAttempts); + } + else if (lastResult.Outcome == AIOperationOutcome.InvalidOutput) + { + _logger.LogWarning( + "AI {OperationName} attempt {Attempt}/{MaxAttempts} returned invalid response shape; retrying", + operationName, + attempt, + MaxAiAttempts); + } + } + } + + _logger.LogWarning( + "AI {OperationName} exhausted retries with outcome {Outcome}; returning last result", + operationName, + lastResult.Outcome); + return lastResult; + } + + private static string ResolveNarrativeContent(AIOperationResult result) + { + return result.Outcome switch + { + AIOperationOutcome.Success => result.Content, + AIOperationOutcome.PermanentFailure => AIServiceNotConfiguredMessage, + AIOperationOutcome.TransientFailure => AIServiceTemporarilyUnavailableMessage, + _ => AIRequestFailedRetryMessage + }; + } + + private static int? TryGetInt32(JsonElement element, string propertyName) + { + return element.TryGetProperty(propertyName, out var property) + && property.ValueKind == JsonValueKind.Number + && property.TryGetInt32(out var value) + ? value + : null; + } + + private string? ResolvePromptVersionSetting(string operationName) + { + var operationPromptVersion = _configuration[$"Azure:Operations:{operationName}:PromptVersion"]; + if (!string.IsNullOrWhiteSpace(operationPromptVersion)) + { + return operationPromptVersion; + } + + var defaultPromptVersion = _configuration["Azure:Operations:Defaults:PromptVersion"]; + if (!string.IsNullOrWhiteSpace(defaultPromptVersion)) + { + return defaultPromptVersion; + } + + return _configuration["Azure:OpenAI:PromptVersion"]; + } + + private async Task LogPromptInputAsync(string promptType, string promptVersion, string? systemPrompt, string userPrompt) + { + var formattedInput = FormatPromptInputForLog(systemPrompt, userPrompt); + _logger.LogInformation("AI {PromptType} ({PromptVersion}) input payload: {PromptInput}", promptType, promptVersion, formattedInput); + await WritePromptLogFileAsync(promptType, promptVersion, "INPUT", formattedInput); + } + + private async Task LogPromptOutputAsync(string promptType, string promptVersion, string output) + { + var formattedOutput = FormatPromptOutputForLog(output); + _logger.LogInformation("AI {PromptType} ({PromptVersion}) model output payload: {ModelOutput}", promptType, promptVersion, formattedOutput); + await WritePromptLogFileAsync(promptType, promptVersion, "OUTPUT", formattedOutput); + } + + private async Task WritePromptLogFileAsync(string promptType, string promptVersion, string payloadType, string payload) + { + if (!CanWritePromptFileLog()) + { + return; + } + + try + { + var now = DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"); + var logDirectory = Path.Combine(AppContext.BaseDirectory, PromptLogDirectoryName); + Directory.CreateDirectory(logDirectory); + + var logPath = Path.Combine(logDirectory, PromptLogFileName); + var entry = $"{now} [{promptType}] [{promptVersion}] {payloadType}\n{payload}\n\n"; + await File.AppendAllTextAsync(logPath, entry); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to write AI prompt log file."); + } + } + + private bool CanWritePromptFileLog() + { + return IsPromptFileLoggingEnabled; + } + private static string FormatPromptInputForLog(string? systemPrompt, string userPrompt) + { + var normalizedSystemPrompt = string.IsNullOrWhiteSpace(systemPrompt) ? string.Empty : systemPrompt.Trim(); + var normalizedUserPrompt = string.IsNullOrWhiteSpace(userPrompt) ? string.Empty : userPrompt.Trim(); + return $"SYSTEM_PROMPT\n{normalizedSystemPrompt}\n\nUSER_PROMPT\n{normalizedUserPrompt}"; + } + + private static string FormatPromptOutputForLog(string output) + { + if (string.IsNullOrWhiteSpace(output)) + { + return string.Empty; + } + + if (TryFormatProviderOutput(output, out var formattedProviderOutput)) + { + return formattedProviderOutput; + } + + if (TryParseJsonObjectFromResponse(output, out var jsonObject)) + { + return JsonSerializer.Serialize(jsonObject, JsonLogOptions); + } + + return output.Trim(); + } + + private static bool TryFormatProviderOutput(string output, out string formattedOutput) + { + formattedOutput = string.Empty; + + try + { + using var doc = JsonDocument.Parse(output); + var root = doc.RootElement; + if (root.ValueKind != JsonValueKind.Object + || !root.TryGetProperty("choices", out var choices) + || choices.ValueKind != JsonValueKind.Array + || choices.GetArrayLength() == 0) + { + return false; + } + + var firstChoice = choices[0]; + var content = TryGetChoiceContent(firstChoice); + if (string.IsNullOrWhiteSpace(content)) + { + return false; + } + + var lines = new List(); + + if (root.TryGetProperty("usage", out var usage) && usage.ValueKind == JsonValueKind.Object) + { + var promptTokens = TryGetInt32(usage, "prompt_tokens"); + var completionTokens = TryGetInt32(usage, "completion_tokens"); + int? reasoningTokens = null; + + if (usage.TryGetProperty("completion_tokens_details", out var completionTokenDetails) + && completionTokenDetails.ValueKind == JsonValueKind.Object) + { + reasoningTokens = TryGetInt32(completionTokenDetails, "reasoning_tokens"); + } + + if (promptTokens.HasValue) + { + lines.Add($"PromptTokens: {promptTokens.Value}"); + } + + if (completionTokens.HasValue) + { + lines.Add($"CompletionTokens: {completionTokens.Value}"); + } + + if (reasoningTokens.HasValue) + { + lines.Add($"ReasoningTokens: {reasoningTokens.Value}"); + } + } + + var normalizedContent = FormatPromptOutputContent(content); + lines.Add("Output:"); + lines.Add(normalizedContent); + formattedOutput = string.Join(Environment.NewLine, lines); + return true; + } + catch (JsonException) + { + return false; + } + } + + private static string? TryGetChoiceContent(JsonElement firstChoice) + { + if (!firstChoice.TryGetProperty("message", out var message) || message.ValueKind != JsonValueKind.Object) + { + return null; + } + + if (!message.TryGetProperty("content", out var contentProp) || contentProp.ValueKind != JsonValueKind.String) + { + return null; + } + + return contentProp.GetString(); + } + + private static string FormatPromptOutputContent(string content) + { + if (TryParseJsonObjectFromResponse(content, out var contentObject)) + { + return JsonSerializer.Serialize(contentObject, JsonLogOptions); + } + + return content.Trim(); + } + + private static bool TryParseJsonObjectFromResponse(string response, out JsonElement objectElement) + { + objectElement = default; + var cleaned = AIResponseJson.CleanJsonResponse(response); + if (string.IsNullOrWhiteSpace(cleaned)) + { + return false; + } + + try + { + using var doc = JsonDocument.Parse(cleaned); + if (doc.RootElement.ValueKind != JsonValueKind.Object) + { + return false; + } + + objectElement = doc.RootElement.Clone(); + return true; + } + catch (JsonException) + { + return false; + } + } + + private static string ExtractSummaryFromJson(string output) + { + if (!TryParseJsonObjectFromResponse(output, out var jsonObject)) + { + return output?.Trim() ?? string.Empty; + } + + if (jsonObject.TryGetProperty(AIJsonKeys.Summary, out var summaryProp) && + summaryProp.ValueKind == JsonValueKind.String) + { + return summaryProp.GetString() ?? string.Empty; + } + + return output?.Trim() ?? string.Empty; + } + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAITransportService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAITransportService.cs new file mode 100644 index 0000000000..374d0755e8 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AI/Runtime/OpenAITransportService.cs @@ -0,0 +1,217 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Unity.AI.Runtime; + +public class OpenAITransportService( + HttpClient httpClient, + OpenAIConfigurationResolver configurationResolver, + ILogger logger) : ITransientDependency +{ + private readonly HttpClient _httpClient = httpClient; + private readonly OpenAIConfigurationResolver _configurationResolver = configurationResolver; + private readonly ILogger _logger = logger; + + public async Task GenerateSummaryAsync( + string content, + string? systemPrompt, + int maxTokens = 150, + double? temperature = null, + string? operationName = null, + string? promptVersion = null, + string? fileName = null) + { + var providerName = _configurationResolver.ResolveProviderName(operationName); + if (!string.Equals(providerName, "OpenAI", StringComparison.Ordinal)) + { + _logger.LogWarning("Provider {ProviderName} is not supported by OpenAI transport.", providerName); + return AIOperationResult.PermanentFailure(new AIProviderResult($"Unsupported provider: {providerName}")); + } + + var apiKey = _configurationResolver.ResolveApiKey(operationName); + if (string.IsNullOrEmpty(apiKey)) + { + _logger.LogWarning("Error: OpenAI API key is not configured"); + return AIOperationResult.PermanentFailure(new AIProviderResult("OpenAI API key is not configured")); + } + + try + { + var resolvedSystemPrompt = string.IsNullOrWhiteSpace(systemPrompt) + ? "You are a professional grant analyst for the BC Government." + : systemPrompt; + + var requestPayload = new Dictionary + { + ["messages"] = new[] + { + new { role = "system", content = resolvedSystemPrompt }, + new { role = "user", content = content ?? string.Empty } + }, + [_configurationResolver.ResolveMaxTokensParameterNameForOperation(operationName)] = maxTokens + }; + + var resolvedTemperature = temperature ?? _configurationResolver.ResolveConfiguredTemperature(operationName); + if (resolvedTemperature.HasValue) + { + requestPayload["temperature"] = resolvedTemperature.Value; + } + + var json = JsonSerializer.Serialize(requestPayload); + var httpContent = new StringContent(json, Encoding.UTF8, "application/json"); + + using var request = new HttpRequestMessage(HttpMethod.Post, _configurationResolver.ResolveApiUrl(operationName)) + { + Content = httpContent + }; + request.Headers.TryAddWithoutValidation("Authorization", apiKey); + + var response = await _httpClient.SendAsync(request); + var responseContent = await response.Content.ReadAsStringAsync(); + var metadata = TryExtractProviderMetadata(responseContent); + var providerResponse = BuildProviderResponseFromMetadata( + string.Empty, + responseContent, + metadata, + (int)response.StatusCode); + + if (!response.IsSuccessStatusCode) + { + _logger.LogError("OpenAI API request failed: {StatusCode} - {Content}", response.StatusCode, responseContent); + return MapFailureOutcome(response.StatusCode, providerResponse); + } + + if (string.IsNullOrWhiteSpace(responseContent)) + { + return AIOperationResult.InvalidOutput(providerResponse); + } + + try + { + using var jsonDoc = JsonDocument.Parse(responseContent); + var choices = jsonDoc.RootElement.GetProperty("choices"); + if (choices.GetArrayLength() > 0) + { + var message = choices[0].GetProperty("message"); + var modelOutput = message.GetProperty("content").GetString(); + return string.IsNullOrWhiteSpace(modelOutput) + ? AIOperationResult.InvalidOutput(providerResponse) + : AIOperationResult.Success(BuildProviderResponseFromMetadata( + modelOutput, + responseContent, + metadata, + (int)response.StatusCode)); + } + + return AIOperationResult.InvalidOutput(providerResponse); + } + catch (Exception ex) when (ex is JsonException || ex is KeyNotFoundException || ex is InvalidOperationException) + { + _logger.LogWarning(ex, "AI response payload had an invalid output shape"); + return AIOperationResult.InvalidOutput(providerResponse); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error generating AI summary"); + return AIOperationResult.TransientFailure(new AIProviderResult(ex.Message)); + } + } + + private static AIOperationResult MapFailureOutcome(HttpStatusCode statusCode, AIProviderResult response) + { + var statusCodeValue = (int)statusCode; + if (statusCode == HttpStatusCode.RequestTimeout || statusCode == (HttpStatusCode)429 || statusCodeValue >= 500) + { + return AIOperationResult.TransientFailure(response); + } + + return AIOperationResult.PermanentFailure(response); + } + + private static AIProviderResult BuildProviderResponseFromMetadata( + string content, + string? rawResponse, + AIProviderResponseMetadata? metadata, + int? httpStatusCode = null) + { + return new AIProviderResult( + content, + rawResponse ?? string.Empty, + metadata?.Model, + metadata?.FinishReason, + httpStatusCode, + metadata?.PromptTokens, + metadata?.CompletionTokens, + metadata?.TotalTokens, + metadata?.ReasoningTokens); + } + + private static AIProviderResponseMetadata? TryExtractProviderMetadata(string? responseContent) + { + if (string.IsNullOrWhiteSpace(responseContent)) + { + return null; + } + + try + { + using var jsonDoc = JsonDocument.Parse(responseContent); + var root = jsonDoc.RootElement; + var model = root.TryGetProperty("model", out var modelProp) && modelProp.ValueKind == JsonValueKind.String + ? modelProp.GetString() + : null; + + string? finishReason = null; + if (root.TryGetProperty("choices", out var choices) + && choices.ValueKind == JsonValueKind.Array + && choices.GetArrayLength() > 0) + { + var firstChoice = choices[0]; + if (firstChoice.TryGetProperty("finish_reason", out var finishReasonProp) && finishReasonProp.ValueKind == JsonValueKind.String) + { + finishReason = finishReasonProp.GetString(); + } + } + + int? promptTokens = null; + int? completionTokens = null; + int? totalTokens = null; + int? reasoningTokens = null; + if (root.TryGetProperty("usage", out var usage) && usage.ValueKind == JsonValueKind.Object) + { + promptTokens = TryGetInt32(usage, "prompt_tokens"); + completionTokens = TryGetInt32(usage, "completion_tokens"); + totalTokens = TryGetInt32(usage, "total_tokens"); + + if (usage.TryGetProperty("completion_tokens_details", out var completionTokenDetails) + && completionTokenDetails.ValueKind == JsonValueKind.Object) + { + reasoningTokens = TryGetInt32(completionTokenDetails, "reasoning_tokens"); + } + } + + return new AIProviderResponseMetadata(model, finishReason, promptTokens, completionTokens, totalTokens, reasoningTokens); + } + catch (JsonException) + { + return null; + } + } + + private static int? TryGetInt32(JsonElement element, string propertyName) + { + return element.TryGetProperty(propertyName, out var prop) + && prop.ValueKind == JsonValueKind.Number + && prop.TryGetInt32(out var value) + ? value + : null; + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AIApplicationModule.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AIApplicationModule.cs index 6c9b4cc5b6..7acf7ae2e0 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AIApplicationModule.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/AIApplicationModule.cs @@ -1,11 +1,13 @@ using Microsoft.Extensions.DependencyInjection; +using Unity.Flex; +using Unity.GrantManager; +using Volo.Abp.Application; +using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; -using Volo.Abp.Application; using Volo.Abp.MultiTenancy; -using Volo.Abp.VirtualFileSystem; -using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.TenantManagement; +using Volo.Abp.VirtualFileSystem; namespace Unity.AI; @@ -13,7 +15,9 @@ namespace Unity.AI; typeof(AIApplicationContractsModule), typeof(AbpDddApplicationModule), typeof(AbpAutoMapperModule), - typeof(AbpTenantManagementDomainModule) + typeof(AbpTenantManagementDomainModule), + typeof(FlexApplicationModule), + typeof(GrantManagerDomainModule) )] public class AIApplicationModule : AbpModule { @@ -55,4 +59,4 @@ public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddAssemblyOf(); } -} +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Attachments/AttachmentSummaryAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Attachments/AttachmentSummaryAppService.cs new file mode 100644 index 0000000000..4f57fd4832 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Attachments/AttachmentSummaryAppService.cs @@ -0,0 +1,51 @@ +using Microsoft.AspNetCore.Authorization; +using System.Collections.Generic; +using System.Threading.Tasks; +using Unity.AI; +using Unity.AI.Operations; +using Unity.AI.Permissions; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace Unity.GrantManager.Attachments; + +[Authorize(AIPermissions.Analysis.GenerateAttachmentSummaries)] +[ExposeServices(typeof(AttachmentSummaryAppService), typeof(IAttachmentSummaryAppService))] +public class AttachmentSummaryAppService( + IAttachmentSummaryService attachmentSummaryService, + IFeatureChecker featureChecker) : AIAppService, IAttachmentSummaryAppService +{ + public async Task GenerateAttachmentSummaryAsync(System.Guid attachmentId, string? promptVersion = null) + { + if (!await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries")) + { + throw new UserFriendlyException("AI attachment summaries are not enabled."); + } + + await attachmentSummaryService.GenerateAndSaveAsync(attachmentId, promptVersion); + return new AttachmentSummaryResultDto { Completed = true }; + } + + public async Task> GenerateAttachmentSummariesAsync(List attachmentIds, string? promptVersion = null) + { + if (!await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries")) + { + throw new UserFriendlyException("AI attachment summaries are not enabled."); + } + + if (attachmentIds.Count == 0) + { + return []; + } + + var results = new List(); + foreach (var attachmentId in attachmentIds) + { + await attachmentSummaryService.GenerateAndSaveAsync(attachmentId, promptVersion); + results.Add(new AttachmentSummaryResultDto { Completed = true }); + } + + return results; + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/DataSeed/AIPromptDataSeeder.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/DataSeed/AIPromptDataSeeder.cs index dc0edc9a78..58859a5e83 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/DataSeed/AIPromptDataSeeder.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/DataSeed/AIPromptDataSeeder.cs @@ -235,7 +235,7 @@ OPTIONAL FIELDS (may be left blank): OUTPUT { - "rating": "", + "decision": "", "warnings": [ { "title": "", @@ -254,24 +254,19 @@ OPTIONAL FIELDS (may be left blank): "detail": "" } ], - "nextSteps": [ + "recommendations": [ { "title": "", "detail": "" } - ], - "recommendation": { - "decision": "", - "rationale": "" - } + ] } Important: - Use only APPLICATION CONTENT, ATTACHMENT SUMMARIES, FORM FIELD CONFIGURATION, and EVALUATION RUBRIC as evidence. + - decision must be PROCEED or HOLD. - Use summaries for overall application quality/readiness synthesis. - - Use nextSteps for reviewer-facing follow-up actions or considerations before scoring or decision-making. - - recommendation.decision must be PROCEED or HOLD. - - recommendation.rationale must explain the high-level recommendation in 1-2 complete sentences using provided evidence. + - Use recommendations for reviewer-facing follow-up actions or considerations before scoring or decision-making. - Use "title" and "detail" keys for all finding objects. - Return valid plain JSON only in the exact OUTPUT shape. """; @@ -306,8 +301,8 @@ 4. Return only the strongest evidence-backed reviewer conclusions. SCORE {{SCORE}} - OUTPUT - {{OUTPUT}} + RESPONSE + {{RESPONSE}} RULES {{RULES}} @@ -333,7 +328,7 @@ 4. Return only the strongest evidence-backed reviewer conclusions. // ── v1/analysis.output.txt ─────────────────────────────────────────────── private const string AnalysisOutput = """ { - "rating": "", + "decision": "", "errors": [ { "title": "", @@ -352,16 +347,12 @@ 4. Return only the strongest evidence-backed reviewer conclusions. "detail": "" } ], - "nextSteps": [ + "recommendations": [ { "title": "", "detail": "" } - ], - "recommendation": { - "decision": "", - "rationale": "" - } + ] } """; @@ -388,20 +379,16 @@ 4. Return only the strongest evidence-backed reviewer conclusions. - Use 3-6 words for title. - Summary titles should name the specific substantive reviewer conclusion, strength, or risk, not a generic evaluation label or abstract category. - Each detail must be 1-2 complete sentences. - - Summaries and nextSteps must be concrete, distinct, reviewer-relevant, and specific to this application's evidence. + - Summaries and recommendations must be concrete, distinct, reviewer-relevant, and specific to this application's evidence. - Avoid generic praise, checklist language, and repeated conclusions across lists. - Do not use a summary merely to say that supporting documents were provided; summarize the specific substantive evidence they add, or omit the finding. - If no findings exist, return empty arrays. - - Rating must be HIGH, MEDIUM, or LOW. + - Decision must be PROCEED or HOLD. - Use summaries for overall application quality/readiness synthesis. - - Use nextSteps for concrete reviewer-facing next actions based on the provided evidence. - - nextSteps may include proceeding with the normal review process when the application appears ready for that step. - - When evidence shows a meaningful gap, inconsistency, or uncertainty, use nextSteps for specific follow-up or verification actions. + - Use recommendations for concrete reviewer-facing next actions based on the provided evidence. + - Recommendations may include proceeding with the normal review process when the application appears ready for that step. + - When evidence shows a meaningful gap, inconsistency, or uncertainty, use recommendations for specific follow-up or verification actions. - Return an empty array only when no concrete next action would help the reviewer. - - recommendation.decision must be PROCEED or HOLD. - - Use HOLD only when provided evidence shows a material eligibility, feasibility, budget, or readiness concern that would reasonably block scoring or decision-making. - - recommendation.rationale must explain the high-level recommendation in 1-2 complete sentences using provided evidence. - - recommendation.rationale should name the 1-3 strongest evidence-based reasons for the recommendation. """; // ── v0/attachment.system.txt ───────────────────────────────────────────── @@ -441,8 +428,8 @@ 3. Return a concise reviewer-facing summary. ATTACHMENT {{ATTACHMENT}} - OUTPUT - {{OUTPUT}} + RESPONSE + {{RESPONSE}} RULES {{RULES}} @@ -553,9 +540,6 @@ 4. Choose the most conservative valid answer supported by that evidence. RESPONSE {{RESPONSE}} - OUTPUT - {{OUTPUT}} - RULES {{RULES}} {{COMMON_RULES}} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationAnalysisAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationAnalysisAppService.cs new file mode 100644 index 0000000000..fad67fc536 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationAnalysisAppService.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Threading.Tasks; +using Unity.AI; +using Unity.AI.Operations; +using Unity.AI.Permissions; +using Volo.Abp; +using Volo.Abp.Features; + +namespace Unity.GrantManager.GrantApplications; + +[Authorize(AIPermissions.Analysis.GenerateApplicationAnalysis)] +public class ApplicationAnalysisAppService( + IApplicationAnalysisService applicationAnalysisService, + IFeatureChecker featureChecker) + : AIAppService, IApplicationAnalysisAppService +{ + public async Task GenerateApplicationAnalysisAsync(Guid applicationId, string? promptVersion = null) + { + if (!await featureChecker.IsEnabledAsync("Unity.AI.ApplicationAnalysis")) + { + throw new UserFriendlyException("AI application analysis is not enabled."); + } + + await applicationAnalysisService.RegenerateAndSaveAsync(applicationId, promptVersion); + return new ApplicationAnalysisResultDto { Completed = true }; + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationContentAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationContentAppService.cs new file mode 100644 index 0000000000..cea61ecee7 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationContentAppService.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Threading.Tasks; +using Unity.AI; +using Unity.AI.Automation; +using Unity.AI.Permissions; +using Volo.Abp; +using Volo.Abp.Features; +using Volo.Abp.MultiTenancy; + +namespace Unity.GrantManager.GrantApplications; + +[Authorize(AIPermissions.Analysis.ViewAttachmentSummary)] +[Authorize(AIPermissions.Analysis.ViewApplicationAnalysis)] +[Authorize(AIPermissions.Analysis.ViewScoringResult)] +public class ApplicationContentAppService( + IApplicationAIGenerationQueue aiGenerationQueue, + IFeatureChecker featureChecker, + ICurrentTenant currentTenant) + : AIAppService, IApplicationContentAppService +{ + public async Task GenerateContentAsync(Guid applicationId, string? promptVersion = null) + { + var attachmentSummariesEnabled = await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries"); + var applicationAnalysisEnabled = await featureChecker.IsEnabledAsync("Unity.AI.ApplicationAnalysis"); + var scoringEnabled = await featureChecker.IsEnabledAsync("Unity.AI.Scoring"); + + if (!attachmentSummariesEnabled || !applicationAnalysisEnabled || !scoringEnabled) + { + throw new UserFriendlyException("AI generate all is not enabled."); + } + + await aiGenerationQueue.QueueApplicationPipelineAsync(applicationId, currentTenant.Id, promptVersion); + + return new ApplicationContentResultDto + { + Completed = true + }; + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationScoringAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationScoringAppService.cs new file mode 100644 index 0000000000..329a1ee2c4 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/GrantApplications/ApplicationScoringAppService.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Threading.Tasks; +using Unity.AI; +using Unity.AI.Operations; +using Unity.AI.Permissions; +using Volo.Abp; +using Volo.Abp.Features; + +namespace Unity.GrantManager.GrantApplications; + +[Authorize(AIPermissions.Analysis.GenerateScoring)] +public class ApplicationScoringAppService( + IApplicationScoringService applicationScoringService, + IFeatureChecker featureChecker) + : AIAppService, IApplicationScoringAppService +{ + public async Task GenerateApplicationScoringAsync(Guid applicationId, string? promptVersion = null) + { + if (!await featureChecker.IsEnabledAsync("Unity.AI.Scoring")) + { + throw new UserFriendlyException("AI scoring is not enabled."); + } + + await applicationScoringService.RegenerateAndSaveAsync(applicationId, promptVersion); + return new ApplicationScoringResultDto + { + Completed = true + }; + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AIConfigurationAppService.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AIConfigurationAppService.cs index af5dfd02e7..931f787553 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AIConfigurationAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AIConfigurationAppService.cs @@ -7,37 +7,38 @@ namespace Unity.AI.Settings; -public class AIConfigurationAppService : AIAppService, IAIConfigurationAppService +public class AIConfigurationAppService( + ISettingProvider settingProvider, + ISettingManager settingManager, + ICurrentTenant currentTenant) : AIAppService, IAIConfigurationAppService { - private readonly ISettingProvider _settingProvider; - private readonly ISettingManager _settingManager; - private readonly ICurrentTenant _currentTenant; + private readonly ISettingProvider _settingProvider = settingProvider; + private readonly ISettingManager _settingManager = settingManager; + private readonly ICurrentTenant _currentTenant = currentTenant; - public AIConfigurationAppService( - ISettingProvider settingProvider, - ISettingManager settingManager, - ICurrentTenant currentTenant) + public virtual async Task GetTenantConfigurationAsync() { - _settingProvider = settingProvider; - _settingManager = settingManager; - _currentTenant = currentTenant; - } - - public virtual async Task GetScoringSettingsAsync() - { - return new AIScoringSettingsDto + return new AITenantConfigurationDto { - ScoringAssistantEnabled = await _settingProvider.GetAsync( - AISettings.ScoringAssistantEnabled, defaultValue: false) + AutomaticGenerationEnabled = await _settingProvider.GetAsync( + AISettings.AutomaticGenerationEnabled, defaultValue: false), + ManualGenerationEnabled = await _settingProvider.GetAsync( + AISettings.ManualGenerationEnabled, defaultValue: false) }; } [Authorize(AIPermissions.Configuration.ConfigureAI)] - public virtual async Task UpdateScoringSettingsAsync(UpdateAIScoringSettingsDto input) + public virtual async Task UpdateTenantConfigurationAsync(UpdateAITenantConfigurationDto input) { await _settingManager.SetAsync( - AISettings.ScoringAssistantEnabled, - input.ScoringAssistantEnabled.ToString().ToLowerInvariant(), + AISettings.AutomaticGenerationEnabled, + input.AutomaticGenerationEnabled.ToString().ToLowerInvariant(), + TenantSettingValueProvider.ProviderName, + _currentTenant.Id?.ToString()); + + await _settingManager.SetAsync( + AISettings.ManualGenerationEnabled, + input.ManualGenerationEnabled.ToString().ToLowerInvariant(), TenantSettingValueProvider.ProviderName, _currentTenant.Id?.ToString()); } diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AISettingDefinitionProvider.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AISettingDefinitionProvider.cs index 5032d042af..36a1914729 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AISettingDefinitionProvider.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Settings/AISettingDefinitionProvider.cs @@ -10,9 +10,20 @@ public override void Define(ISettingDefinitionContext context) { context.Add( new SettingDefinition( - AISettings.ScoringAssistantEnabled, + AISettings.AutomaticGenerationEnabled, "false", - L("Setting:AI.ScoringAssistantEnabled"), + L("Setting:AI.AutomaticGenerationEnabled"), + isVisibleToClients: false, + isInherited: false, + isEncrypted: false) + .WithProviders(TenantSettingValueProvider.ProviderName) + ); + + context.Add( + new SettingDefinition( + AISettings.ManualGenerationEnabled, + "false", + L("Setting:AI.ManualGenerationEnabled"), isVisibleToClients: false, isInherited: false, isEncrypted: false) diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Unity.AI.Application.csproj b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Unity.AI.Application.csproj index e3be378d9b..7d4e3d6f08 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Unity.AI.Application.csproj +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Application/Unity.AI.Application.csproj @@ -1,25 +1,28 @@ - - net9.0 enable Unity.AI - + + + + + + + - @@ -27,5 +30,10 @@ runtime; build; native; contentfiles; analyzers - + + + PreserveNewest + PreserveNewest + + diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Localization/AI/en.json b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Localization/AI/en.json index d6b84d6ca1..f04da07630 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Localization/AI/en.json +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Localization/AI/en.json @@ -3,15 +3,22 @@ "texts": { "Permission:AI": "AI", "Permission:AI.Reporting": "AI Reporting", - "Permission:AI.ApplicationAnalysis": "AI Application Analysis", - "Permission:AI.AttachmentSummary": "AI Attachment Summary", - "Permission:AI.ScoringAssistant": "AI Scoring Assistant", - "Setting:AI.ScoringAssistantEnabled": "AI Scoring Assistant", + "Permission:AI.Analysis": "AI Analysis", + "Permission:AI.Analysis.ViewApplicationAnalysis": "View AI Application Analysis", + "Permission:AI.Analysis.ViewAttachmentSummary": "View AI Attachment Summary", + "Permission:AI.Analysis.ViewScoringResult": "View AI Scoring Result", + "Permission:AI.Analysis.GenerateApplicationAnalysis": "Generate AI Application Analysis", + "Permission:AI.Analysis.GenerateAttachmentSummaries": "Generate AI Attachment Summaries", + "Permission:AI.Analysis.GenerateScoring": "Generate AI Scoring", "Permission:AI.ConfigureAI": "AI Configuration", "Permission:AI.Prompts": "AI Prompt Management", "Permission:AI.Prompts.Create": "Create Prompts", "Permission:AI.Prompts.Update": "Edit Prompts", "Permission:AI.Prompts.Delete": "Delete Prompts", + + "Setting:AI.AutomaticGenerationEnabled": "Automatically Generate AI Analysis", + "Setting:AI.ManualGenerationEnabled": "Manually Initiate AI Analysis", + "AIPrompts": "AI Prompts", "AIPrompt": "AI Prompt", "AIPromptVersion": "Prompt Version", diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Settings/AISettings.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Settings/AISettings.cs index d335050785..d589a02c80 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Settings/AISettings.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Domain.Shared/Settings/AISettings.cs @@ -2,5 +2,6 @@ namespace Unity.AI.Settings; public static class AISettings { - public const string ScoringAssistantEnabled = "GrantManager.AI.ScoringAssistantEnabled"; + public const string AutomaticGenerationEnabled = "GrantManager.AI.AutomaticGenerationEnabled"; + public const string ManualGenerationEnabled = "GrantManager.AI.ManualGenerationEnabled"; } diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/PromptTools/AIPromptToolViewOptionsProvider.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/PromptTools/AIPromptToolViewOptionsProvider.cs new file mode 100644 index 0000000000..eb99661503 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/PromptTools/AIPromptToolViewOptionsProvider.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using System; +using Volo.Abp.DependencyInjection; + +namespace Unity.AI.Web.PromptTools; + +public class AIPromptToolViewOptionsProvider( + IWebHostEnvironment webHostEnvironment, + IConfiguration configuration) : IAIPromptToolViewOptionsProvider, ITransientDependency +{ + public bool IsDevPromptControlsEnabled => + string.Equals(webHostEnvironment.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase); + + public string DefaultPromptVersion + { + get + { + var configuredPromptVersion = configuration["Azure:Operations:Defaults:PromptVersion"]; + if (string.IsNullOrWhiteSpace(configuredPromptVersion)) + { + configuredPromptVersion = configuration["Azure:OpenAI:PromptVersion"]; + } + + return string.IsNullOrWhiteSpace(configuredPromptVersion) + ? "v1" + : configuredPromptVersion.Trim().ToLowerInvariant(); + } + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/PromptTools/IAIPromptToolViewOptionsProvider.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/PromptTools/IAIPromptToolViewOptionsProvider.cs new file mode 100644 index 0000000000..c9d75a4883 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/PromptTools/IAIPromptToolViewOptionsProvider.cs @@ -0,0 +1,7 @@ +namespace Unity.AI.Web.PromptTools; + +public interface IAIPromptToolViewOptionsProvider +{ + bool IsDevPromptControlsEnabled { get; } + string DefaultPromptVersion { get; } +} diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewComponent.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewComponent.cs index 3f880adaa6..9400f61c24 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewComponent.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewComponent.cs @@ -18,8 +18,10 @@ public virtual async Task InvokeAsync() { var model = new AISettingViewModel { - ScoringAssistantEnabled = await settingProvider.GetAsync( - AISettings.ScoringAssistantEnabled, defaultValue: false) + AutomaticGenerationEnabled = await settingProvider.GetAsync( + AISettings.AutomaticGenerationEnabled, defaultValue: false), + ManualGenerationEnabled = await settingProvider.GetAsync( + AISettings.ManualGenerationEnabled, defaultValue: false) }; return View("~/Views/Settings/AISettingGroup/Default.cshtml", model); diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewModel.cs b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewModel.cs index 3ae4713935..f7dfa675c4 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewModel.cs +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/AISettingViewModel.cs @@ -2,5 +2,6 @@ namespace Unity.AI.Web.Views.Settings.AISettingGroup; public class AISettingViewModel { - public bool ScoringAssistantEnabled { get; set; } + public bool AutomaticGenerationEnabled { get; set; } + public bool ManualGenerationEnabled { get; set; } } diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.cshtml index 809bd07b6d..c1f8b5071b 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.cshtml @@ -12,16 +12,34 @@
+
+ + +
+ When enabled, AI analysis runs automatically on new application intake (subject to form-level AI configuration). +
+
+
-
diff --git a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.js b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.js index 8ed936e630..b956d5bfe6 100644 --- a/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.js +++ b/applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.js @@ -20,10 +20,12 @@ $(function () { uiElements.settingForm.on('submit', function (event) { event.preventDefault(); - const scoringEnabled = $('#ScoringAssistantEnabled').is(':checked'); + const automaticEnabled = $('#AutomaticGenerationEnabled').is(':checked'); + const manualEnabled = $('#ManualGenerationEnabled').is(':checked'); - unity.aI.settings.aIConfiguration.updateScoringSettings({ - scoringAssistantEnabled: scoringEnabled + unity.aI.settings.aIConfiguration.updateTenantConfiguration({ + automaticGenerationEnabled: automaticEnabled, + manualGenerationEnabled: manualEnabled }).then(function () { $(document).trigger('AbpSettingSaved'); initialFormState = uiElements.settingForm.serialize(); diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.css b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.css index 9d075a3c6a..856b7c5a22 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.css @@ -3,6 +3,15 @@ justify-content: space-between; } +.custom-dynamic-table { + table-layout: fixed; + width: 100% !important; +} + +.custom-dynamic-table td { + overflow-wrap: anywhere; +} + .custom-dynamic-table.custom-table-actions th:last-child { width: 75px !important; max-width: 75px !important; diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js index 0fc4c6c6b7..6e1c2b2eda 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js @@ -247,10 +247,9 @@ $(function () { let fieldId = $element[0].id; let table = $(this).DataTable({ paging: false, - bInfo: false, - searching: true, - serverside: false, + searching: true, info: false, + autoWidth: false, lengthChange: false, deferRender: false, // Required for DOM manipulation in addNewRow and configureTable layout: { diff --git a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application.Contracts/Emails/EmailCommentDto.cs b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application.Contracts/Emails/EmailCommentDto.cs index c62bddaffe..7f03f9511c 100644 --- a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application.Contracts/Emails/EmailCommentDto.cs +++ b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application.Contracts/Emails/EmailCommentDto.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Unity.Notifications.Comments; namespace Unity.Notifications.Emails; @@ -7,9 +8,9 @@ namespace Unity.Notifications.Emails; public class EmailCommentDto { public string Subject { get; set; } = string.Empty; - public string From { get; set; } = string.Empty; public string Body { get; set; } = string.Empty; - public string ApplicationId { get; set; } = string.Empty; + public string OwnerId { get; set; } = string.Empty; + public CommentType CommentType { get; set; } public List MentionNamesEmail { get; set; } = []; public string? EmailTemplateName { get; set; } = string.Empty; } \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application/EmailNotificaions/EmailNotificationService.cs b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application/EmailNotificaions/EmailNotificationService.cs index 87881499f4..5471937cb6 100644 --- a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application/EmailNotificaions/EmailNotificationService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Application/EmailNotificaions/EmailNotificationService.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -6,6 +7,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; +using Unity.GrantManager.Notifications; using Unity.Notifications.Emails; using Unity.Notifications.Permissions; using Unity.Notifications.Settings; @@ -14,9 +16,8 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.Features; using Volo.Abp.SettingManagement; -using Microsoft.AspNetCore.Http; +using Volo.Abp.UI.Navigation.Urls; using Volo.Abp.Users; -using Unity.GrantManager.Notifications; namespace Unity.Notifications.EmailNotifications; @@ -27,8 +28,8 @@ public class EmailNotificationService( EmailNotificationManager emailNotificationManager, IExternalUserLookupServiceProvider externalUserLookupServiceProvider, ISettingManager settingManager, - IHttpContextAccessor httpContextAccessor, - IFeatureChecker featureChecker) : ApplicationService, IEmailNotificationService + IFeatureChecker featureChecker, + IAppUrlProvider appUrlProvider) : ApplicationService, IEmailNotificationService { public async Task InitializeDraftAsync(Guid applicationId) @@ -71,6 +72,12 @@ protected virtual async Task NotifyTeamsChannel(string chesEmailError) await notificationAppService.PostToTeamsAsync(activityTitle, activitySubtitle); } + public async Task GetBaseUrlAsync() + { + var appUrl = await appUrlProvider.GetUrlAsync(appName: "MVC"); + return appUrl; + } + public async Task SendCommentNotification(EmailCommentDto input) { HttpResponseMessage res = new(); @@ -79,18 +86,33 @@ public async Task SendCommentNotification(EmailCommentDto i if (await featureChecker.IsEnabledAsync("Unity.Notifications")) { var defaultFromAddress = await SettingProvider.GetOrNullAsync(NotificationsSettings.Mailing.DefaultFromAddress); - var scheme = "https"; - var request = (httpContextAccessor.HttpContext?.Request) ?? throw new InvalidOperationException("HttpContext or Request is null."); - var host = request.Host.ToUriComponent(); - var pathBase = "/GrantApplications/Details?ApplicationId="; - var baseUrl = $"{scheme}://{host}{pathBase}"; - var commentLink = $"{baseUrl}{input.ApplicationId}"; + var baseUrl = await GetBaseUrlAsync(); + + string commentLink = input.CommentType switch + { + Comments.CommentType.ApplicationComment or Comments.CommentType.AssessmentComment => + QueryHelpers.AddQueryString($"{baseUrl}/GrantApplications/Details", "ApplicationId", input.OwnerId), + Comments.CommentType.ApplicantComment => + QueryHelpers.AddQueryString($"{baseUrl}/GrantApplicants/Details", "ApplicantId", input.OwnerId), + _ => throw new InvalidOperationException("Invalid comment type.") + }; + var subject = $"Unity-Comment: {input.Subject}"; var fromEmail = defaultFromAddress ?? "NoReply@gov.bc.ca"; + + var hasSurname = !string.IsNullOrWhiteSpace(CurrentUser.SurName); + var hasName = !string.IsNullOrWhiteSpace(CurrentUser.Name); + + var currentUserText = (hasSurname, hasName) switch + { + (true, true) => $"{CurrentUser.SurName}, {CurrentUser.Name}", + _ => CurrentUser.UserName ?? "Unknown User" + }; + string htmlBody = $@" -

{input.From} mentioned you in a comment.

+

{currentUserText} mentioned you in a comment.

').hide(); + const dt = this.s.dt; + const namespace = this.s.namespace; + const opts = this.s.opts; + const filterData = this.s.filterData; + const updateButtonState = this._updateButtonState.bind(this); + const filterRow = $('').hide(); dt.columns().every(function () { - let column = this; + const column = this; // Only create filter cells for visible columns if (column.visible()) { - let title = $(column.header()).text(); - let colName = dt.settings()[0].aoColumns[column.index()].name || title; + const title = $(column.header()).text(); + const colName = dt.settings()[0].aoColumns[column.index()].name || title; if (title && title !== 'Actions' && title !== 'Action' && title !== 'Default') { - let placeholder = that.s.opts.placeholderPrefix ? - that.s.opts.placeholderPrefix + ' ' + title : - title; - // Get filter value by column name (not title) for persistence across reorders - let filterValue = that.s.filterData[colName] || column.search() || ''; + const placeholder = opts.placeholderPrefix + ? opts.placeholderPrefix + ' ' + title + : title; - let input = $('', { + const filterValue = filterData[colName] || column.search() || ''; + + const input = $('', { type: 'text', class: 'form-control input-sm custom-filter-input', placeholder: placeholder, @@ -158,7 +165,7 @@ 'data-column-name': colName }); - let cell = $('
diff --git a/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Domain.Shared/Comments/CommentType.cs b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Domain.Shared/Comments/CommentType.cs new file mode 100644 index 0000000000..3d003cfe8e --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Domain.Shared/Comments/CommentType.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Unity.Notifications.Comments; + +/// Edit Unity.GrantManager.Comments.CommentType if changing this enum as it is shared between the two projects and used in the API layer. +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum CommentType +{ + ApplicationComment, + AssessmentComment, + ApplicantComment, +} diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Handlers/UpsertSupplierHandler.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Handlers/UpsertSupplierHandler.cs index 475368d829..4dbe0f3c53 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Handlers/UpsertSupplierHandler.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Handlers/UpsertSupplierHandler.cs @@ -1,6 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -12,9 +12,9 @@ using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; using Volo.Abp.EventBus.Local; - -namespace Unity.Payments.Handlers -{ + +namespace Unity.Payments.Handlers +{ public class UpsertSupplierHandler(ISupplierAppService supplierAppService, SiteAppService siteAppService, ILogger logger, @@ -22,11 +22,14 @@ public class UpsertSupplierHandler(ISupplierAppService supplierAppService, IApplicationRepository applicationRepository) : ILocalEventHandler, ITransientDependency { - public async Task HandleEventAsync(UpsertSupplierEto eventData) + public async Task HandleEventAsync(UpsertSupplierEto eventData) { SupplierDto supplierDto = await GetSupplierFromEvent(eventData); var existingSites = await siteAppService.GetSitesBySupplierIdAsync(supplierDto.Id); - var existingSitesDictionary = existingSites?.ToDictionary(s => s.Number) ?? new Dictionary(); + var existingSitesDictionary = existingSites? + .GroupBy(s => s.Number) + .ToDictionary(g => g.Key, g => g.First()) + ?? new Dictionary(); var defaultPaymentGroup = await ResolveDefaultPaymentGroupAsync(eventData); await UpsertSitesFromEventDtoAsync(existingSitesDictionary, supplierDto.Id, eventData, defaultPaymentGroup); @@ -35,34 +38,40 @@ public async Task HandleEventAsync(UpsertSupplierEto eventData) await localEventBus.PublishAsync( new ApplicantSupplierEto { - SupplierId = supplierDto.Id, - ApplicantId = eventData.CorrelationId, - ExistingSitesDictionary = existingSitesDictionary, - SiteEtos = eventData.SiteEtos - } - ); - } - + SupplierId = supplierDto.Id, + ApplicantId = eventData.CorrelationId, + ExistingSitesDictionary = existingSitesDictionary, + SiteEtos = eventData.SiteEtos + } + ); + } + private async Task> UpsertSitesFromEventDtoAsync( Dictionary existingSitesDictionary, Guid supplierId, UpsertSupplierEto upsertSupplierEto, PaymentGroup defaultPaymentGroup) { - foreach (var siteEto in upsertSupplierEto.SiteEtos) + // Deduplicate incoming SiteEtos by SupplierSiteCode — CAS can return duplicate site codes + var uniqueSiteEtos = upsertSupplierEto.SiteEtos + .GroupBy(s => s.SupplierSiteCode) + .Select(g => g.First()) + .ToList(); + + foreach (var siteEto in uniqueSiteEtos) { var siteDto = supplierAppService.GetSiteDtoFromSiteEto(siteEto, supplierId, defaultPaymentGroup); - if (existingSitesDictionary.TryGetValue(siteDto.Number, out var existingSite)) - { - siteDto.Id = existingSite.Id; - await siteAppService.UpdateAsync(siteDto); - } - else - { - await siteAppService.InsertAsync(siteDto); - } - } + if (existingSitesDictionary.TryGetValue(siteDto.Number, out var existingSite)) + { + siteDto.Id = existingSite.Id; + await siteAppService.UpdateAsync(siteDto); + } + else + { + await siteAppService.InsertAsync(siteDto); + } + } return existingSitesDictionary; } @@ -107,57 +116,57 @@ private async Task GetSupplierFromEvent(UpsertSupplierEto eventData { var existing = await supplierAppService.GetBySupplierNumberAsync(eventData.Number); logger.LogInformation("Upserting supplier from event data: {Existing}", existing); - - // This is subject to some business rules and a domain implementation - if (existing != null) - { - existing.Number = eventData.Number; - UpdateSupplierDto updateSupplierDto = GetUpdateSupplierDtoFromEvent(eventData); - SupplierDto updatedSupplierDto = await supplierAppService.UpdateAsync(existing.Id, updateSupplierDto); - return updatedSupplierDto; - } - - CreateSupplierDto createSupplierDto = GetCreateSupplierDtoFromEvent(eventData); - SupplierDto supplierDto = await supplierAppService.CreateAsync(createSupplierDto); - - return supplierDto; - } - - - private static UpdateSupplierDto GetUpdateSupplierDtoFromEvent(UpsertSupplierEto eventData) - { - return new UpdateSupplierDto() - { - Name = eventData.Name, - Number = eventData.Number, - Subcategory = eventData.Subcategory, - ProviderId = eventData.ProviderId, - BusinessNumber = eventData.BusinessNumber, - Status = eventData.Status, - SupplierProtected = eventData.SupplierProtected, - StandardIndustryClassification = eventData.StandardIndustryClassification, - LastUpdatedInCAS = eventData.LastUpdatedInCAS, - CorrelationId = eventData.CorrelationId, - CorrelationProvider = eventData.CorrelationProvider, - }; - } - - private static CreateSupplierDto GetCreateSupplierDtoFromEvent(UpsertSupplierEto eventData) - { - return new CreateSupplierDto() - { - Name = eventData.Name, - Number = eventData.Number, - Subcategory = eventData.Subcategory, - ProviderId = eventData.ProviderId, - BusinessNumber = eventData.BusinessNumber, - Status = eventData.Status, - SupplierProtected = eventData.SupplierProtected, - StandardIndustryClassification = eventData.StandardIndustryClassification, - LastUpdatedInCAS = eventData.LastUpdatedInCAS, - CorrelationId = eventData.CorrelationId, - CorrelationProvider = eventData.CorrelationProvider, - }; - } - } -} + + // This is subject to some business rules and a domain implementation + if (existing != null) + { + existing.Number = eventData.Number; + UpdateSupplierDto updateSupplierDto = GetUpdateSupplierDtoFromEvent(eventData); + SupplierDto updatedSupplierDto = await supplierAppService.UpdateAsync(existing.Id, updateSupplierDto); + return updatedSupplierDto; + } + + CreateSupplierDto createSupplierDto = GetCreateSupplierDtoFromEvent(eventData); + SupplierDto supplierDto = await supplierAppService.CreateAsync(createSupplierDto); + + return supplierDto; + } + + + private static UpdateSupplierDto GetUpdateSupplierDtoFromEvent(UpsertSupplierEto eventData) + { + return new UpdateSupplierDto() + { + Name = eventData.Name, + Number = eventData.Number, + Subcategory = eventData.Subcategory, + ProviderId = eventData.ProviderId, + BusinessNumber = eventData.BusinessNumber, + Status = eventData.Status, + SupplierProtected = eventData.SupplierProtected, + StandardIndustryClassification = eventData.StandardIndustryClassification, + LastUpdatedInCAS = eventData.LastUpdatedInCAS, + CorrelationId = eventData.CorrelationId, + CorrelationProvider = eventData.CorrelationProvider, + }; + } + + private static CreateSupplierDto GetCreateSupplierDtoFromEvent(UpsertSupplierEto eventData) + { + return new CreateSupplierDto() + { + Name = eventData.Name, + Number = eventData.Number, + Subcategory = eventData.Subcategory, + ProviderId = eventData.ProviderId, + BusinessNumber = eventData.BusinessNumber, + Status = eventData.Status, + SupplierProtected = eventData.SupplierProtected, + StandardIndustryClassification = eventData.StandardIndustryClassification, + LastUpdatedInCAS = eventData.LastUpdatedInCAS, + CorrelationId = eventData.CorrelationId, + CorrelationProvider = eventData.CorrelationProvider, + }; + } + } +} diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Suppliers/SiteAppService.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Suppliers/SiteAppService.cs index b9286fee55..a3cca3fa53 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Suppliers/SiteAppService.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Application/Suppliers/SiteAppService.cs @@ -40,6 +40,18 @@ public virtual async Task InsertAsync(SiteDto siteDto) { try { + // Guard against duplicates — if a site with the same Number already exists + // for this supplier, update it instead of creating a second row + var existing = (await siteRepository.GetBySupplierAsync(siteDto.SupplierId)) + .Find(s => s.Number == siteDto.Number); + + if (existing != null) + { + logger.LogWarning("Site with Number {Number} already exists for SupplierId {SupplierId}. Updating instead of inserting.", siteDto.Number, siteDto.SupplierId); + siteDto.Id = existing.Id; + return await UpdateAsync(siteDto); + } + Site site = new Site(siteDto); await siteRepository.InsertAsync(site, true); return site.Id; diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs index e0c4c9f100..22ae8658f5 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequests.cshtml.cs @@ -209,6 +209,17 @@ public async Task OnGetAsync(string cacheKey) errorList.Add("The selected Application is not Approved. To continue please remove the item from the list."); } + var allLinks = await applicationLinksService.GetListByApplicationAsync(application.Id); + var parentLink = allLinks.Find(link => link.LinkType == ApplicationLinkType.Parent && link.ApplicationId != application.Id); + if (parentLink != null) + { + var parentApplication = await applicationService.GetAsync(parentLink.ApplicationId); + if (parentApplication.Id == Guid.Empty || parentApplication.StatusCode != GrantApplicationState.GRANT_APPROVED) + { + errorList.Add("Payment cannot be processed because the linked parent submission is not approved. Please ensure the parent submission is approved before creating a payment."); + } + } + if (!application.ApplicationForm.Payable) { errorList.Add("The selected application is not Payable. To continue please remove the item from the list."); @@ -308,7 +319,7 @@ private async Task GetRemainingAmountAllowedByApplicationAsync(GrantApp // Get parent links for this application var allLinks = await applicationLinksService.GetListByApplicationAsync(application.Id); - var parentLink = allLinks.Find(link => link.LinkType == ApplicationLinkType.Parent); + var parentLink = allLinks.Find(link => link.LinkType == ApplicationLinkType.Parent && link.ApplicationId != application.Id); // Rule 2: No parent link exists if (parentLink == null) @@ -474,7 +485,7 @@ private async Task PopulateParentChildValidationData() // Parent not in submission, get from first child's link var firstChild = await applicationService.GetAsync(children[0].CorrelationId); var allLinks = await applicationLinksService.GetListByApplicationAsync(firstChild.Id); - var parentLink = allLinks.Find(link => link.LinkType == ApplicationLinkType.Parent); + var parentLink = allLinks.Find(link => link.LinkType == ApplicationLinkType.Parent && link.ApplicationId != firstChild.Id); if (parentLink == null) { @@ -558,7 +569,7 @@ private async Task> ValidateParentChildPaymentAmounts() // Parent not in submission, get from first child's link var firstChild = await applicationService.GetAsync(children[0].CorrelationId); var allLinks = await applicationLinksService.GetListByApplicationAsync(firstChild.Id); - var parentLink = allLinks.Find(link => link.LinkType == ApplicationLinkType.Parent); + var parentLink = allLinks.Find(link => link.LinkType == ApplicationLinkType.Parent && link.ApplicationId != firstChild.Id); if (parentLink == null) { diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/Index.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/Index.js index dc9371b52e..ba06ae76b7 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/Index.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/Index.js @@ -2,6 +2,7 @@ $(function () { const l = abp.localization.getResource('Payments'); const nullPlaceholder = '—'; const formatter = createNumberFormatter(); + const guidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; let dt = $('#PaymentRequestListTable'); let dataTable; let isApprove = false; @@ -377,7 +378,29 @@ $(function () { name: 'applicantName', data: 'payeeName', className: 'data-table-header', - index: columnIndex + index: columnIndex, + render: function (data, type, row) { + let applicantName = (typeof data !== 'string' || data.trim() === '') ? 'Applicant Name' : data; + + if (type === 'sort' || type === 'filter') { + return applicantName; + } + + const safeApplicantName = $.fn.dataTable.render.text().display(applicantName); + + if (type === 'display' && abp.auth.isGranted('GrantApplicationManagement.Applicants.ViewList')) { + const applicantId = row?.correlationId; + const isGuid = applicantId && guidPattern.test(applicantId); + + if (row?.correlationProvider === 'Application' && isGuid) { + return `${safeApplicantName}`; + } + + return safeApplicantName; + } + + return applicantName; + }, }; } diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.js index 6e9b9346f5..a53d13f64d 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/SupplierInfo/SupplierInfo.js @@ -212,6 +212,9 @@ $(function () { return; } + const $btn = $(this); + $btn.attr('disabled', 'disabled'); + const applicantId = $('#PaymentInfo_ApplicantId').val(); const applicationId = $('#PaymentInfoViewApplicationId').val() || ''; $.ajax({ @@ -222,6 +225,9 @@ $(function () { console.error('Error loading sites:', error); abp.notify.error('Failed to refresh sites'); }, + complete: function () { + $btn.removeAttr('disabled'); + }, }); }); } @@ -297,10 +303,10 @@ $(function () { { text: 'Filter', className: 'custom-table-btn flex-none btn btn-secondary', - id: 'btn-toggle-filter', + id: 'btn-supplier-toggle-filter', action: function (e, dt, node, config) { }, attr: { - id: 'btn-toggle-filter', + id: 'btn-supplier-toggle-filter', }, }, ]; @@ -328,6 +334,9 @@ $(function () { dynamicButtonContainerId: 'siteDynamicButtonContainerId', }); + initializeFilterRowPlugin(dataTable, 'btn-supplier-toggle-filter'); + + function getColumns() { let columnIndex = 0; diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertColumnMappingDto.cs b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertColumnMappingDto.cs index d0498cde3b..01042b9ebc 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertColumnMappingDto.cs +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertColumnMappingDto.cs @@ -3,7 +3,9 @@ /// /// Data transfer object containing user-specified field-to-column mapping overrides for report configuration. /// Allows users to customize column names for specific fields instead of relying entirely on auto-generated names. - /// Fields not included in this mapping will receive auto-generated column names based on their labels. + /// Fields not included in this mapping will receive auto-generated column names based on the correlation provider: + /// for form versions, column names are derived from field keys (CHEFS Property Names); for worksheets and scoresheets, + /// column names are derived from field labels. /// public class UpsertColumnMappingDto { diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertReportColumnsMapDto.cs b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertReportColumnsMapDto.cs index 74ae0b8e75..c063c59a61 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertReportColumnsMapDto.cs +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application.Contracts/Configuration/UpsertReportColumnsMapDto.cs @@ -24,7 +24,8 @@ public class UpsertReportColumnsMapDto /// /// Gets or sets the optional column mapping configuration containing user-specified field-to-column mappings. /// When provided, these mappings override auto-generated column names for specific fields. - /// Empty mappings will result in fully auto-generated column names based on field labels. + /// Empty mappings will result in fully auto-generated column names derived from field keys + /// (for form versions) or field labels (for worksheets and scoresheets). /// public UpsertColumnMappingDto Mapping { get; set; } = new(); } diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Configuration/ReportMappingUtils.cs b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Configuration/ReportMappingUtils.cs index f23f9b2441..99b0400aae 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Configuration/ReportMappingUtils.cs +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Application/Configuration/ReportMappingUtils.cs @@ -16,6 +16,25 @@ internal static partial class ReportMappingUtils { private const int MaxColumnNameLength = 60; + /// + /// Determines the appropriate source value for auto-generating a default column name based on the correlation provider. + /// For the "formversion" provider, the field's Key (CHEFS Property Name) is used because it provides more stable, + /// developer-friendly identifiers. For all other providers (worksheets, scoresheets), the field's Label is used + /// as it provides more human-readable column names. + /// + /// The field metadata containing both Key and Label properties. + /// The correlation provider identifier (e.g., "formversion", "worksheet", "scoresheet"). + /// The Key for formversion providers, or the Label (falling back to empty string) for all other providers. + internal static string GetDefaultColumnNameSource(FieldPathTypeDto field, string correlationProvider) + { + if (string.Equals(correlationProvider, Providers.FormVersion, StringComparison.OrdinalIgnoreCase)) + { + return field.Key ?? string.Empty; + } + + return field.Label ?? string.Empty; + } + /// /// Generates sanitized and unique PostgreSQL-compatible column names from a dictionary of field keys and their display labels. /// Processes each label through sanitization to remove invalid characters, enforces uniqueness with numeric suffixes, @@ -269,6 +288,8 @@ private static bool IsValidColumnName(string columnName) /// derived from field metadata. Prioritizes user-specified column names where provided, while automatically generating /// sanitized and unique column names for unmapped fields. Ensures all column names are PostgreSQL-compliant and unique /// across the entire mapping configuration. + /// For the "formversion" provider, auto-generated column names are derived from the field Key (CHEFS Property Name) + /// rather than the Label, providing more stable and developer-friendly default names. /// /// DTO containing correlation information and optional user-provided column mappings organized by field path. /// Tuple containing an array of field metadata (with keys, labels, types, paths) and additional mapping metadata from the correlation provider. @@ -299,12 +320,14 @@ internal static ReportColumnsMap CreateNewMap(UpsertReportColumnsMapDto upsertRe var usedColumnNames = new HashSet(userProvidedMappings.Values, StringComparer.OrdinalIgnoreCase); // Generate column names for fields without user-provided mappings + // For formversion provider, use Key (CHEFS Property Name) as the source; for others, use Label var autoGeneratedColumnNames = new Dictionary(); foreach (var field in fieldsMap.Fields) { if (!userProvidedMappings.ContainsKey(field.Path)) { - var sanitizedName = SanitizeColumnName(field.Label ?? string.Empty); + var columnNameSource = GetDefaultColumnNameSource(field, upsertReportColmnsMapDto.CorrelationProvider); + var sanitizedName = SanitizeColumnName(columnNameSource); var uniqueName = EnsureUniqueness(sanitizedName, usedColumnNames); autoGeneratedColumnNames[field.Path] = uniqueName; usedColumnNames.Add(uniqueName); @@ -355,6 +378,8 @@ internal static ReportColumnsMap CreateNewMap(UpsertReportColumnsMapDto upsertRe /// and user-provided updates. Implements a three-tier priority system: user-provided column names take precedence, /// followed by existing column names from the database, with auto-generated names for new fields. Maintains column /// name uniqueness across the entire mapping while preserving established mappings where possible. + /// For newly discovered fields in the "formversion" provider, auto-generated column names are derived from the + /// field Key (CHEFS Property Name) rather than the Label. /// /// DTO containing optional user-provided column mappings to update or add, organized by field path. /// The existing ReportColumnsMap entity from the database containing current mapping configuration and correlation details. @@ -412,9 +437,11 @@ internal static ReportColumnsMap UpdateExistingMap(UpsertReportColumnsMapDto upd columnName = existingRow.ColumnName; } // Priority 3: Auto-generate for new fields + // For formversion provider, use Key (CHEFS Property Name) as the source; for others, use Label else { - var sanitizedName = SanitizeColumnName(field.Label ?? string.Empty); + var columnNameSource = GetDefaultColumnNameSource(field, updateReportColumnsMapDto.CorrelationProvider); + var sanitizedName = SanitizeColumnName(columnNameSource); columnName = EnsureUniqueness(sanitizedName, usedColumnNames); usedColumnNames.Add(columnName); } diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Menus/ReportingMenuContributor.cs b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Menus/ReportingMenuContributor.cs index 7df63808e4..d6e91808e7 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Menus/ReportingMenuContributor.cs +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Menus/ReportingMenuContributor.cs @@ -33,15 +33,6 @@ public async Task ConfigureMenuAsync(MenuConfigurationContext context) /// A completed task representing the synchronous menu item addition operations. private static Task ConfigureReportingMenuAsync(MenuConfigurationContext context) { - // Add Reconciliation menu item for IT Admin users - context.Menu.AddItem( - new ApplicationMenuItem( - ReportingMenus.Prefix, - displayName: "Reconciliation", - "~/TenantManagement/Reconciliation", - requiredPermissionName: IdentityConsts.ITAdminPermissionName - )); - // Add Reporting Configuration menu item for IT Admin users context.Menu.AddItem( new ApplicationMenuItem( diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.cshtml index 871fa26a82..c8ded88444 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.cshtml @@ -13,11 +13,12 @@ + -
+
-
+
@@ -29,7 +30,7 @@ } -
+ }
diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.css b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.css index 3ad76c57a9..d130b52d4c 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.css +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.css @@ -1,13 +1,11 @@ .report-config-content { - height: calc(97vh - 400px); - overflow: scroll; - overflow-x: hidden; + overflow: visible; } .provider-toggle-section { border-bottom: 1px solid #dee2e6; - padding-bottom: 1rem; - margin-bottom: 1rem; + padding-bottom: 0.5rem; + margin-bottom: 0.5rem; } .provider-toggle-section .btn-group { @@ -17,8 +15,8 @@ .provider-toggle-section .btn-group .btn { flex: none; - min-width: 120px; - padding: 0.5rem 1rem; + min-width: 100px; + padding: 0.375rem 0.75rem; font-weight: 500; transition: all 0.15s ease-in-out; } @@ -70,7 +68,7 @@ .report-config-content .action-bar { flex-shrink: 0; - margin-bottom: 1rem; + margin-bottom: 0.5rem; } .report-config-footer { @@ -160,6 +158,17 @@ .report-config-controls { display: flex !important; justify-content: space-between; + align-items: flex-end; +} + +/* Compact the version selector form-group within controls */ +.report-config-controls .form-group { + margin-bottom: 0; +} + +/* Reduce tab pane padding when reporting config is active */ +#nav-reporting-configuration.tab-pane { + padding: 0.5rem 0; } .report-config-btn-height-fix { diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.js b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.js index c094098fb2..bd0d4be183 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.js +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/src/Unity.Reporting.Web/Views/Shared/Components/ReportingConfiguration/Default.js @@ -440,7 +440,7 @@ $(function () { // Helper function to process detected changes alert (module-level to reduce nesting) function processDetectedChanges(detectedChanges) { - if (detectedChanges && detectedChanges.trim() !== '') { + if (detectedChanges?.trim() !== '') { setTimeout(function () { displayDetectedChangesAlert(detectedChanges); }, 100); @@ -467,6 +467,18 @@ $(function () { }; } + // Helper function to get the default column name source based on the current provider. + // Mirrors the server-side ReportMappingUtils.GetDefaultColumnNameSource() logic exactly: + // - formversion: use Key only (CHEFS Property Name), no fallback to Label + // - worksheet/scoresheet: use Label only, no fallback to Key + // No cross-field fallback ensures the client and server produce identical defaults. + function getDefaultColumnNameSource(field) { + if (currentProvider === 'formversion') { + return field.key || ''; + } + return field.label || ''; + } + // Helper function to transform fields metadata (module-level to reduce nesting) function transformFieldsMetadata(fieldsMetadata) { const items = fieldsMetadata.fields.map(field => ({ @@ -475,7 +487,7 @@ $(function () { type: field.type, path: field.path, dataPath: field.dataPath, - columnName: field.label || field.key, + columnName: getDefaultColumnNameSource(field), typePath: field.typePath })); @@ -670,10 +682,7 @@ $(function () { dynamicButtonContainerId: 'reportConfigDynamicButtons', useNullPlaceholder: true, externalSearchId: 'search-report-config', - // Enable scrolling - let CSS handle the height - scrollY: true, - scrollCollapse: true, - responsive: true + fixedHeaders: true }); // Add event handler for when DataTable completes drawing @@ -688,34 +697,8 @@ $(function () { // Check for dynamic columns placeholder and update warning const hasDynamicColumns = checkForDynamicColumnsInTable(); updateDynamicColumnsWarning(hasDynamicColumns); - - // Force column adjustment after draw if tab is visible - setTimeout(function () { - if (isReportingTabVisible()) { - forceTableColumnAdjustment(); - } - }, 50); }); - // Add event handler for when DataTable data is loaded - dataTable.on('xhr.dt', function () { - // Force layout adjustment after data is loaded - setTimeout(function () { - if (isReportingTabVisible()) { - adjustTableLayout(); - forceTableColumnAdjustment(); - } - }, 100); - }); - - // Initial adjustment with longer delay to ensure DOM is ready - setTimeout(function () { - if (isReportingTabVisible()) { - adjustTableLayout(); - forceTableColumnAdjustment(); - } - }, 500); - // Track changes on column name inputs with validation $('#ReportConfigurationTable').on('input', '.column-name-input', function () { const $input = $(this); @@ -851,38 +834,6 @@ $(function () { return reportingPanel?.classList.contains('show', 'active'); } - // Enhanced function to force table column adjustment - function forceTableColumnAdjustment() { - if (!dataTable) return; - - try { - // Multiple approaches to ensure columns are properly sized - // 1. Force recalc of column widths - dataTable.columns.adjust(); - - // 2. Trigger responsive recalc if responsive is enabled - if (dataTable.responsive) { - dataTable.responsive.recalc(); - } - - // 3. Force a layout recalculation by temporarily changing display - const wrapper = $('#ReportConfigurationTable_wrapper'); - if (wrapper.length) { - // Force browser reflow - wrapper.hide(); - wrapper.show(); - - // Final column adjustment after showing - setTimeout(function () { - dataTable.columns.adjust(); - }, 10); - } - - } catch (error) { - console.warn('Error during force column adjustment:', error); - } - } - // Column name sanitization function function sanitizeColumnName(name) { let sanitized = sanitizeSqlNames(name); @@ -914,8 +865,8 @@ $(function () { errors.push(`Column name exceeds maximum length of ${COLUMN_VALIDATION.MAX_LENGTH} characters`); } - // Check format (should be alphanumeric + underscores, not starting with number) - if (!/^[a-z_][a-z0-9_]*$/i.test(name)) { + // Check format (alphanumeric + underscores, not starting with number) + if (!/^[a-zA-Z_]\w*$/.test(name)) { errors.push('Column name must start with a letter or underscore and contain only letters, numbers, and underscores'); } @@ -1014,14 +965,14 @@ $(function () { function sanitizeSqlNames(name) { if (!name || typeof name !== 'string') return ''; - // Convert to lowercase and trim - let sanitized = name.toLowerCase().trim(); + // Trim whitespace + let sanitized = name.trim(); // Replace multiple spaces/hyphens with single underscore - sanitized = sanitized.replace(/[\s-]+/g, '_'); + sanitized = sanitized.replaceAll(/[\s-]+/g, '_'); // Remove all non-alphanumeric characters except underscores - sanitized = sanitized.replace(/[^a-z0-9_]/g, ''); + sanitized = sanitized.replaceAll(/\W/g, ''); // Remove leading/trailing underscores safely without vulnerable regex while (sanitized.startsWith('_')) { @@ -1046,7 +997,7 @@ $(function () { // View name sanitization function function sanitizeViewName(name) { - let sanitized = sanitizeSqlNames(name); + let sanitized = sanitizeSqlNames(name).toLowerCase(); // Truncate to max length if (sanitized.length > VIEW_NAME_VALIDATION.MAX_LENGTH) { @@ -1081,7 +1032,7 @@ $(function () { } // Check format (should be alphanumeric + underscores, not starting with number) - if (!/^[a-z_][a-z0-9_]*$/i.test(name)) { + if (!/^[a-zA-Z_]\w*$/.test(name)) { errors.push('View name must start with a letter or underscore and contain only letters, numbers, and underscores'); } @@ -1238,6 +1189,36 @@ $(function () { return; } + // Check if a view has been generated and warn the user + const viewStatus = ($('#reportingViewStatus').val() || '').toUpperCase(); + const hasGeneratedView = viewStatus === 'SUCCESS' || + $('.view-status-compact').find('.fl-checkmark').length > 0; + + if (hasGeneratedView) { + Swal.fire({ + title: 'Existing View Detected', + text: 'A database view has already been generated. These mapping changes will only take effect after you delete and re-create the view.', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Save Anyway', + cancelButtonText: 'Cancel', + customClass: { + confirmButton: 'btn btn-primary', + cancelButton: 'btn btn-secondary' + } + }).then(function (result) { + if (result.isConfirmed) { + performSave(correlationId); + } + }); + return; + } + + performSave(correlationId); + }); + + // Extracted save logic into a reusable function + function performSave(correlationId) { // Disable all control buttons during save setControlButtonsLoadingState(true); @@ -1302,7 +1283,7 @@ $(function () { // Re-enable all control buttons after save completes (success or error) setControlButtonsLoadingState(false); }); - }); + } // Helper function to update view name validation UI (module-level to reduce nesting) function updateViewNameValidationUI(isValid, errors, $viewNameInput, $confirmButton, $feedback) { @@ -1573,7 +1554,7 @@ $(function () { try { const errorResponse = JSON.parse(xhr.responseText); if (errorResponse?.error?.message) { - errorMessage = errorResponse.error.message; + errorMessage = errorResponse?.error?.message; } else if (typeof errorResponse === 'string') { errorMessage = errorResponse; } else { @@ -1595,9 +1576,9 @@ $(function () { try { const parsedError = JSON.parse(xhr.responseText); if (parsedError?.error?.message) { - errorMessage = parsedError.error.message; - } else if (parsedError.message) { - errorMessage = parsedError.message; + errorMessage = parsedError?.error?.message; + } else if (parsedError?.message) { + errorMessage = parsedError?.message; } else { errorMessage = xhr.responseText; } @@ -1636,7 +1617,7 @@ $(function () { const viewName = result.viewName; const $deleteViewListItem = $('#deleteViewListItem'); - if (viewName && viewName.trim() !== '') { + if (viewName?.trim()) { // Update the view name in the list item and show it $deleteViewListItem.html(`The associated database view (${viewName})`); $deleteViewListItem.show(); @@ -1718,6 +1699,9 @@ $(function () { dataTable.ajax.reload(); } + // Clear the cached view status after deletion + $('#reportingViewStatus').val(''); + // Refresh view status widget refreshViewStatusWidget(correlationId, getCorrelationProvider()); @@ -1734,7 +1718,7 @@ $(function () { } else if (xhr.status === 400) { const errorResponse = JSON.parse(xhr.responseText); if (errorResponse?.error?.message) { - errorMessage = errorResponse.error.message; + errorMessage = errorResponse?.error?.message; } else if (typeof errorResponse === 'string') { errorMessage = errorResponse; } else { @@ -1751,9 +1735,9 @@ $(function () { } else if (xhr.responseText) { const parsedError = JSON.parse(xhr.responseText); if (parsedError?.error?.message) { - errorMessage = parsedError.error.message; - } else if (parsedError.message) { - errorMessage = parsedError.message; + errorMessage = parsedError?.error?.message; + } else if (parsedError?.message) { + errorMessage = parsedError?.message; } else { errorMessage = xhr.responseText; } @@ -1820,79 +1804,253 @@ $(function () { // Initialize the delete button functionality updateCheckConfigurationExistsCallbacks(); - // Initialize version selector visibility based on provider - updateVersionSelectorVisibility(); + // ====================================================================== + // JSON Export / Import / Edit + // ====================================================================== - // Function to adjust table layout dynamically - function adjustTableLayout() { - if (dataTable && dataTable.settings().length > 0) { - try { - const container = $('.report-config-table-container'); - const containerHeight = container.height(); - - if (containerHeight > 100) { // Only adjust if container has reasonable height - // Calculate available height for the table body - // Updated for DataTables v2 class names - const wrapper = $('#ReportConfigurationTable_wrapper'); - const header = wrapper.find('.dt-scroll-head'); - const info = wrapper.find('.dt-info'); - const paginate = wrapper.find('.dt-paging'); - - const headerHeight = header.length ? header.outerHeight(true) : 0; - const infoHeight = info.length ? info.outerHeight(true) : 0; - const paginateHeight = paginate.length ? paginate.outerHeight(true) : 0; - const padding = 20; // Extra padding - - const availableHeight = containerHeight - headerHeight - infoHeight - paginateHeight - padding; - const minHeight = 200; // Minimum table body height - - const scrollBodyHeight = Math.max(minHeight, availableHeight); - - // Apply the calculated height - wrapper.find('.dt-scroll-body').css({ - 'max-height': scrollBodyHeight + 'px', - 'height': scrollBodyHeight + 'px' - }); + /** + * Builds the [{propertyName, path, columnName}] array from the current + * DataTable state. This is what gets exported / shown in the editor. + */ + function buildJsonMapping() { + return getCurrentTableData().map(function (row) { + return { + propertyName: row.propertyName, + path: row.path || '', + columnName: row.columnName + }; + }); + } + + /** + * Creates a composite lookup key from propertyName and path. + * @param {string} propertyName + * @param {string} path + * @returns {string} + */ + function compositeKey(propertyName, path) { + return (propertyName || '') + '|||' + (path || ''); + } + + function applyJsonMappingToTable(mappingArray) { + if (!dataTable) return { appliedCount: 0, unmatchedItems: [] }; + + // Build a lookup: (propertyName + path) → columnName + const lookup = {}; + mappingArray.forEach(function (item) { + const key = compositeKey(item.propertyName, item.path); + lookup[key] = item.columnName; + }); + + let appliedCount = 0; + const matchedKeys = new Set(); + + dataTable.rows().every(function () { + const rowData = this.data(); + const node = this.node(); + const $input = $(node).find('.column-name-input'); + if (!$input.length) return; + + const key = compositeKey(rowData.key, rowData.path); + if (key in lookup) { + matchedKeys.add(key); + const newValue = sanitizeColumnName(lookup[key] || ''); + if ($input.val() !== newValue) { + $input.val(newValue); + validateColumnNameInput($input, newValue, $input.data('path')); + appliedCount++; } - } catch (error) { - console.warn('Error adjusting table layout:', error); } + }); + + // Identify items from the import that did not match any table row + const unmatchedItems = mappingArray.filter(function (item) { + const key = compositeKey(item.propertyName, item.path); + return !matchedKeys.has(key); + }); + + if (appliedCount > 0) { + markAsChanged(); } + + return { appliedCount: appliedCount, unmatchedItems: unmatchedItems }; } - // Function to handle tab visibility changes with improved column adjustment - function handleTabVisibilityChange() { - // Check if the reporting configuration tab is now visible - if (isReportingTabVisible()) { - // Progressive approach with multiple attempts - const adjustmentSequence = [ - { delay: 50, action: 'initial' }, - { delay: 150, action: 'layout' }, - { delay: 300, action: 'columns' }, - { delay: 500, action: 'final' } - ]; - - adjustmentSequence.forEach(step => { - setTimeout(() => { - if (dataTable && isReportingTabVisible()) { - switch (step.action) { - case 'initial': - dataTable.columns.adjust(); - break; - case 'layout': - adjustTableLayout(); - break; - case 'columns': - forceTableColumnAdjustment(); - break; - case 'final': - dataTable.columns.adjust(); - dataTable.draw(false); - break; - } + // Shared validators for the JSON editor and file import + const mappingValidators = [ + { + name: 'isArray', + message: 'JSON must be an array of objects.', + validate: function (data) { return Array.isArray(data); } + }, + { + name: 'uniquePropertyNames', + message: 'Duplicate propertyName+path combinations detected. Rows sharing the same combination will all receive the last columnName value when applied — use inline table editing for those rows instead.', + severity: 'warning', + validate: function (data) { + if (!Array.isArray(data)) return true; + const keys = data.map(function (r) { return compositeKey(r.propertyName, r.path); }); + return new Set(keys).size === keys.length; + } + }, + { + name: 'uniqueColumnNames', + message: 'Duplicate columnName values found. Each columnName must be unique.', + validate: function (data) { + if (!Array.isArray(data)) return true; + const cols = data.filter(function (r) { return r.columnName; }) + .map(function (r) { return r.columnName.toLowerCase(); }); + return new Set(cols).size === cols.length; + } + }, + { + name: 'columnNameFormat', + message: 'One or more column names contain invalid characters. Use only letters, numbers, and underscores.', + validate: function (data) { + if (!Array.isArray(data)) return true; + return data.every(function (r) { + if (!r.columnName) return true; // empty is allowed + return /^[a-zA-Z_]\w*$/.test(r.columnName); + }); + } + }, + { + name: 'columnNameLength', + message: 'One or more column names exceed the maximum length of ' + COLUMN_VALIDATION.MAX_LENGTH + ' characters.', + validate: function (data) { + if (!Array.isArray(data)) return true; + return data.every(function (r) { + if (!r.columnName) return true; + return r.columnName.length <= COLUMN_VALIDATION.MAX_LENGTH; + }); + } + }, + { + name: 'reservedWords', + message: 'One or more column names use a PostgreSQL reserved word.', + validate: function (data) { + if (!Array.isArray(data)) return true; + return data.every(function (r) { + if (!r.columnName) return true; + return !COLUMN_VALIDATION.RESERVED_WORDS.includes(r.columnName.toLowerCase()); + }); + } + } + ]; + + // Create the editor instance (lazy – modal built on first use) + const mappingEditor = new UnityJsonEditor({ + title: 'Edit Column Mapping', + requiredFields: ['propertyName', 'path', 'columnName'], + validators: mappingValidators, + onSave: function (data, warnings) { + const result = applyJsonMappingToTable(data); + const msg = result.appliedCount + ' column mapping(s) updated. Remember to Save to persist changes.'; + const allWarnings = (warnings || []).slice(); + if (result.unmatchedItems.length > 0) { + const unmatchedNames = result.unmatchedItems.map(function (item) { + return item.propertyName + (item.path ? ' (' + item.path + ')' : ''); + }); + allWarnings.push({ message: result.unmatchedItems.length + ' item(s) could not be matched and were ignored: ' + unmatchedNames.join(', ') }); + } + if (allWarnings.length > 0) { + abp.message.warn(msg + '\n\n\u26A0 ' + allWarnings.map(function (w) { return w.message; }).join('\n')); + } else { + abp.message.success(msg); + } + } + }); + + // --- Export --- + $('#btn-export-json-mapping').on('click', function (e) { + e.preventDefault(); + if (!dataTable) { + abp.message.warn('No mapping data loaded.'); + return; + } + + const mapping = buildJsonMapping(); + if (mapping.length === 0) { + abp.message.warn('No mapping data to export.'); + return; + } + + const provider = getCorrelationProvider(); + const correlationId = getCurrentCorrelationId(); + const filename = 'column-mapping-' + provider + '-' + (correlationId || 'new') + '.json'; + UnityJsonEditor.exportToFile(mapping, filename); + }); + + // --- Import --- + $('#btn-import-json-mapping').on('click', function (e) { + e.preventDefault(); + if (!dataTable) { + abp.message.warn('No mapping data loaded. Please load a configuration first.'); + return; + } + + let importWarnings = []; + UnityJsonEditor.importFromFile({ + validators: mappingValidators.concat([ + { + name: 'hasRequiredFields', + message: 'Each item must have "propertyName" and "columnName" fields.', + validate: function (data) { + if (!Array.isArray(data)) return false; + return data.every(function (r) { + return r !== null && typeof r === 'object' && + 'propertyName' in r && 'columnName' in r; + }); } - }, step.delay); - }); + } + ]), + onWarning: function (warnings) { + importWarnings = warnings; + } + }).then(function (data) { + const result = applyJsonMappingToTable(data); + const msg = result.appliedCount + ' column mapping(s) imported. Remember to Save to persist changes.'; + const allWarnings = importWarnings.slice(); + if (result.unmatchedItems.length > 0) { + const unmatchedNames = result.unmatchedItems.map(function (item) { + return item.propertyName + (item.path ? ' (' + item.path + ')' : ''); + }); + allWarnings.push({ message: result.unmatchedItems.length + ' item(s) could not be matched and were ignored: ' + unmatchedNames.join(', ') }); + } + if (allWarnings.length > 0) { + abp.message.warn(msg + '\n\n\u26A0 ' + allWarnings.map(function (w) { return w.message; }).join('\n')); + } else { + abp.message.success(msg); + } + }).catch(function (err) { + abp.message.error(err.message || 'Failed to import file.'); + }); + }); + + // --- Edit JSON --- + $('#btn-edit-json-mapping').on('click', function (e) { + e.preventDefault(); + if (!dataTable) { + abp.message.warn('No mapping data loaded. Please load a configuration first.'); + return; + } + + const mapping = buildJsonMapping(); + mappingEditor.open(mapping); + }); + + // Initialize version selector visibility based on provider + updateVersionSelectorVisibility(); + + // Function to handle tab visibility changes + // When the tab becomes visible, recalculate column widths and trigger + // ScrollResize to set the correct scroll body height. + function handleTabVisibilityChange() { + if (isReportingTabVisible() && dataTable) { + setTimeout(function () { + dataTable.columns.adjust(); + dataTable.draw(false); + }, 50); } } @@ -1918,17 +2076,6 @@ $(function () { }, 150); }); - // Also handle window resize events - $(window).on('resize', function () { - if (isReportingTabVisible()) { - adjustTableLayout(); - // Add column adjustment on resize - setTimeout(function () { - forceTableColumnAdjustment(); - }, 100); - } - }); - // Add intersection observer for visibility detection (fallback) if (window.IntersectionObserver) { const observer = new IntersectionObserver((entries) => { @@ -1971,4 +2118,11 @@ $(function () { }); } } + + // Keep the hidden view-status field in sync when async generation completes + PubSub.subscribe('view_generation_completed', function (msg, data) { + if (data?.finalStatus) { + $('#reportingViewStatus').val(data.finalStatus); + } + }); }); \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Configuration/ColumnsMappingServiceTests.cs b/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Configuration/ColumnsMappingServiceTests.cs index 32ca6d8646..0c2490dd55 100644 --- a/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Configuration/ColumnsMappingServiceTests.cs +++ b/applications/Unity.GrantManager/modules/Unity.Reporting/test/Unity.Reporting.Application.Tests/Configuration/ColumnsMappingServiceTests.cs @@ -748,5 +748,392 @@ await Should.ThrowAsync(async () => } #endregion + + #region Column Name Source by Provider Tests + + // Helper method to call internal GetDefaultColumnNameSource method via reflection + private static string CallGetDefaultColumnNameSource(FieldPathTypeDto field, string correlationProvider) + { + var type = typeof(ReportMappingUtils); + var method = type.GetMethod("GetDefaultColumnNameSource", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public); + return (string)method!.Invoke(null, [field, correlationProvider])!; + } + + // Helper method to call internal CreateNewMap method via reflection + private static ReportColumnsMap CallCreateNewMap(UpsertReportColumnsMapDto dto, FieldPathMetaMapDto fieldsMap) + { + var type = typeof(ReportMappingUtils); + var method = type.GetMethod("CreateNewMap", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public); + return (ReportColumnsMap)method!.Invoke(null, [dto, fieldsMap])!; + } + + // Helper method to call internal UpdateExistingMap method via reflection + private static ReportColumnsMap CallUpdateExistingMap(UpsertReportColumnsMapDto dto, ReportColumnsMap existing, FieldPathMetaMapDto fieldsMap) + { + var type = typeof(ReportMappingUtils); + var method = type.GetMethod("UpdateExistingMap", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public); + return (ReportColumnsMap)method!.Invoke(null, [dto, existing, fieldsMap])!; + } + + [Fact] + public void GetDefaultColumnNameSource_Should_Return_Key_For_FormVersion_Provider() + { + // Arrange + var field = new FieldPathTypeDto + { + Key = "firstName", + Label = "First Name" + }; + + // Act + var result = CallGetDefaultColumnNameSource(field, "formversion"); + + // Assert + result.ShouldBe("firstName"); + } + + [Fact] + public void GetDefaultColumnNameSource_Should_Return_Label_For_Worksheet_Provider() + { + // Arrange + var field = new FieldPathTypeDto + { + Key = "firstName", + Label = "First Name" + }; + + // Act + var result = CallGetDefaultColumnNameSource(field, "worksheet"); + + // Assert + result.ShouldBe("First Name"); + } + + [Fact] + public void GetDefaultColumnNameSource_Should_Return_Label_For_Scoresheet_Provider() + { + // Arrange + var field = new FieldPathTypeDto + { + Key = "score1", + Label = "Score One" + }; + + // Act + var result = CallGetDefaultColumnNameSource(field, "scoresheet"); + + // Assert + result.ShouldBe("Score One"); + } + + [Fact] + public void GetDefaultColumnNameSource_Should_Be_Case_Insensitive_For_FormVersion() + { + // Arrange + var field = new FieldPathTypeDto + { + Key = "myKey", + Label = "My Label" + }; + + // Act + var result = CallGetDefaultColumnNameSource(field, "FormVersion"); + + // Assert + result.ShouldBe("myKey"); + } + + [Fact] + public void GetDefaultColumnNameSource_Should_Return_Empty_When_Key_Is_Null_For_FormVersion() + { + // Arrange + var field = new FieldPathTypeDto + { + Key = null!, + Label = "Some Label" + }; + + // Act + var result = CallGetDefaultColumnNameSource(field, "formversion"); + + // Assert + result.ShouldBe(string.Empty); + } + + [Fact] + public void GetDefaultColumnNameSource_Should_Return_Empty_When_Label_Is_Null_For_Worksheet() + { + // Arrange + var field = new FieldPathTypeDto + { + Key = "someKey", + Label = null + }; + + // Act + var result = CallGetDefaultColumnNameSource(field, "worksheet"); + + // Assert + result.ShouldBe(string.Empty); + } + + [Fact] + public void CreateNewMap_Should_Use_Key_For_FormVersion_Auto_Generated_ColumnNames() + { + // Arrange + var dto = new UpsertReportColumnsMapDto + { + CorrelationId = Guid.NewGuid(), + CorrelationProvider = "formversion", + Mapping = new UpsertColumnMappingDto { Rows = [] } + }; + + var fieldsMap = new FieldPathMetaMapDto + { + Fields = + [ + new FieldPathTypeDto + { + Id = "1", + Key = "firstName", + Label = "First Name", + Type = "textfield", + Path = "firstName", + DataPath = "firstName", + TypePath = "textfield" + }, + new FieldPathTypeDto + { + Id = "2", + Key = "emailAddress", + Label = "Email Address", + Type = "email", + Path = "emailAddress", + DataPath = "emailAddress", + TypePath = "email" + } + ] + }; + + // Act + var result = CallCreateNewMap(dto, fieldsMap); + + // Assert + result.ShouldNotBeNull(); + var mapping = System.Text.Json.JsonSerializer.Deserialize(result.Mapping)!; + + // Column names should be derived from Key (not Label) + mapping.Rows[0].ColumnName.ShouldBe("firstname"); + mapping.Rows[1].ColumnName.ShouldBe("emailaddress"); + } + + [Fact] + public void CreateNewMap_Should_Use_Label_For_Worksheet_Auto_Generated_ColumnNames() + { + // Arrange + var dto = new UpsertReportColumnsMapDto + { + CorrelationId = Guid.NewGuid(), + CorrelationProvider = "worksheet", + Mapping = new UpsertColumnMappingDto { Rows = [] } + }; + + var fieldsMap = new FieldPathMetaMapDto + { + Fields = + [ + new FieldPathTypeDto + { + Id = "1", + Key = "firstName", + Label = "First Name", + Type = "textfield", + Path = "ws1->firstName", + DataPath = "ws1->firstName", + TypePath = "textfield" + } + ] + }; + + // Act + var result = CallCreateNewMap(dto, fieldsMap); + + // Assert + result.ShouldNotBeNull(); + var mapping = System.Text.Json.JsonSerializer.Deserialize(result.Mapping)!; + + // Column name should be derived from Label (not Key) for worksheet + mapping.Rows[0].ColumnName.ShouldBe("first_name"); + } + + [Fact] + public void UpdateExistingMap_Should_Use_Key_For_FormVersion_New_Field_ColumnNames() + { + // Arrange + var existingMapping = new Mapping + { + Rows = + [ + new MapRow + { + PropertyName = "firstName", + ColumnName = "existing_col", + Path = "firstName", + DataPath = "firstName", + Label = "First Name", + Type = "textfield", + TypePath = "textfield", + Id = "1" + } + ] + }; + + var existing = new ReportColumnsMap + { + CorrelationId = Guid.NewGuid(), + CorrelationProvider = "formversion", + Mapping = System.Text.Json.JsonSerializer.Serialize(existingMapping) + }; + + var dto = new UpsertReportColumnsMapDto + { + CorrelationId = existing.CorrelationId, + CorrelationProvider = "formversion", + Mapping = new UpsertColumnMappingDto + { + Rows = + [ + new UpsertMapRowDto { PropertyName = "firstName", ColumnName = "existing_col", Path = "firstName" } + ] + } + }; + + var fieldsMap = new FieldPathMetaMapDto + { + Fields = + [ + new FieldPathTypeDto + { + Id = "1", + Key = "firstName", + Label = "First Name", + Type = "textfield", + Path = "firstName", + DataPath = "firstName", + TypePath = "textfield" + }, + // New field discovered + new FieldPathTypeDto + { + Id = "2", + Key = "lastName", + Label = "Last Name", + Type = "textfield", + Path = "lastName", + DataPath = "lastName", + TypePath = "textfield" + } + ] + }; + + // Act + var result = CallUpdateExistingMap(dto, existing, fieldsMap); + + // Assert + result.ShouldNotBeNull(); + var mapping = System.Text.Json.JsonSerializer.Deserialize(result.Mapping)!; + + // Existing field should keep its column name + mapping.Rows[0].ColumnName.ShouldBe("existing_col"); + + // New field should be auto-generated from Key (not Label) for formversion + mapping.Rows[1].ColumnName.ShouldBe("lastname"); + } + + [Fact] + public void UpdateExistingMap_Should_Use_Label_For_Worksheet_New_Field_ColumnNames() + { + // Arrange + var existingMapping = new Mapping + { + Rows = + [ + new MapRow + { + PropertyName = "score1", + ColumnName = "existing_score", + Path = "ws1->score1", + DataPath = "ws1->score1", + Label = "Score 1", + Type = "number", + TypePath = "number", + Id = "1" + } + ] + }; + + var existing = new ReportColumnsMap + { + CorrelationId = Guid.NewGuid(), + CorrelationProvider = "worksheet", + Mapping = System.Text.Json.JsonSerializer.Serialize(existingMapping) + }; + + var dto = new UpsertReportColumnsMapDto + { + CorrelationId = existing.CorrelationId, + CorrelationProvider = "worksheet", + Mapping = new UpsertColumnMappingDto + { + Rows = + [ + new UpsertMapRowDto { PropertyName = "score1", ColumnName = "existing_score", Path = "ws1->score1" } + ] + } + }; + + var fieldsMap = new FieldPathMetaMapDto + { + Fields = + [ + new FieldPathTypeDto + { + Id = "1", + Key = "score1", + Label = "Score 1", + Type = "number", + Path = "ws1->score1", + DataPath = "ws1->score1", + TypePath = "number" + }, + // New field discovered + new FieldPathTypeDto + { + Id = "2", + Key = "totalScore", + Label = "Total Score", + Type = "number", + Path = "ws1->totalScore", + DataPath = "ws1->totalScore", + TypePath = "number" + } + ] + }; + + // Act + var result = CallUpdateExistingMap(dto, existing, fieldsMap); + + // Assert + result.ShouldNotBeNull(); + var mapping = System.Text.Json.JsonSerializer.Deserialize(result.Mapping)!; + + // Existing field should keep its column name + mapping.Rows[0].ColumnName.ShouldBe("existing_score"); + + // New field should be auto-generated from Label (not Key) for worksheet + mapping.Rows[1].ColumnName.ShouldBe("total_score"); + } + + #endregion } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalScriptContributor.cs b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalScriptContributor.cs index f2472b27c6..4dea6cfe20 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalScriptContributor.cs +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalScriptContributor.cs @@ -50,6 +50,7 @@ public override void ConfigureBundle(BundleConfigurationContext context) context.Files.Add("/themes/ux2/plugins/scrollResize.js"); context.Files.Add("/themes/ux2/plugins/colvisAlpha.js"); context.Files.Add("/themes/ux2/table-utils.js"); + context.Files.Add("/themes/ux2/json-editor.js"); context.Files.Add("/js/DateUtils.js"); } } diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalStyleContributor.cs b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalStyleContributor.cs index a4fbbd6a49..a1beefb47f 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalStyleContributor.cs +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Bundling/UnityThemeUX2GlobalStyleContributor.cs @@ -12,6 +12,7 @@ public override void ConfigureBundle(BundleConfigurationContext context) context.Files.Add("/themes/ux2/fluenticons.min.css"); context.Files.Add("/themes/ux2/layout.css"); context.Files.Add("/themes/ux2/unity-styles.css"); + context.Files.Add("/themes/ux2/json-editor.css"); context.Files.AddIfNotContains("/libs/datatables.net-bs5/css/dataTables.bootstrap5.min.css"); context.Files.AddIfNotContains("/libs/datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css"); diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Themes/UX2/Components/Topbar/Default.cshtml b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Themes/UX2/Components/Topbar/Default.cshtml index d31fa1bcb9..9383cf230e 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Themes/UX2/Components/Topbar/Default.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Themes/UX2/Components/Topbar/Default.cshtml @@ -42,6 +42,10 @@ { Switch Grant Programs } + @if (CurrentTenant.Id != null) + { + Applicant Portal Configuration + } @if (await FeatureChecker.IsEnabledAsync("Unity.Payments") && isAuthorizedForPaymentConfiguration) { Payments Configuration @@ -51,6 +55,10 @@ Scoresheets Configuration Custom Fields Configuration } + @if (CurrentUser.IsInRole("ITOperations")) + { + Unity Admin + } @if (CurrentUser.IsInRole("system_admin") && await FeatureChecker.IsEnabledAsync("SettingManagement.Enable")) { Settings diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/json-editor.css b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/json-editor.css new file mode 100644 index 0000000000..312279d8b2 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/json-editor.css @@ -0,0 +1,95 @@ +/* ========================================================================== + UnityJsonEditor - Reusable JSON editor component styles + ========================================================================== */ + +/* Header: title + item count + close */ +.uje-status-text { + font-size: 0.8125rem; + color: #6c757d; + white-space: nowrap; +} + +/* Body: flex column — textarea fills available space, status bar stays pinned below */ +.modal-body:has(.uje-textarea-wrapper) { + display: flex; + flex-direction: column; + overflow: hidden; +} + +.uje-textarea-wrapper { + position: relative; + flex: 1 1 auto; + overflow: hidden; +} + +.uje-textarea { + font-family: 'Cascadia Code', 'Fira Code', 'SF Mono', 'Consolas', 'Liberation Mono', 'Menlo', monospace; + font-size: 0.8125rem; + line-height: 1.5; + min-height: 120px; + max-height: 350px; + height: 100%; + tab-size: 2; + white-space: pre; + overflow-wrap: normal; + overflow-x: auto; + resize: none; +} + + .uje-textarea:focus { + border-color: #86b7fe; + box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.15); + } + + .uje-textarea[readonly] { + background-color: #f8f9fa; + cursor: default; + } + +/* Footer: buttons left-aligned */ +.uje-footer-actions { + display: flex; + gap: 0.5rem; + align-items: center; +} + +/* Status bar: reserved space at bottom of body for validation messages */ +.uje-status-bar { + flex: 0 0 auto; + min-height: 1.5em; + max-height: 4.5em; + overflow-y: auto; + font-size: 0.8125rem; + width: 100%; + padding-top: 0.375rem; +} + +.uje-validation-msg i { + font-size: 0.875rem; +} + +/* Scroll-to-top button */ +.uje-scroll-top { + position: absolute; + bottom: 0.5rem; + right: 0.75rem; + width: 1.75rem; + height: 1.75rem; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #ced4da; + border-radius: 0.25rem; + background-color: rgba(255, 255, 255, 0.9); + color: #6c757d; + font-size: 0.75rem; + cursor: pointer; + opacity: 0.7; + transition: opacity 0.15s ease-in-out; +} + + .uje-scroll-top:hover { + opacity: 1; + color: #495057; + border-color: #86b7fe; + } diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/json-editor.js b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/json-editor.js new file mode 100644 index 0000000000..94e04f4c68 --- /dev/null +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/json-editor.js @@ -0,0 +1,637 @@ +/** + * UnityJsonEditor - A reusable, extensible JSON editor component. + * + * Provides a Bootstrap modal with a monospace textarea for editing JSON data, + * real-time validation, format/beautify, and file export/import capabilities. + * Supports custom validators for domain-specific rules. + * + * @requires jQuery, Bootstrap 5 + * + * @example + * // Basic usage + * const editor = new UnityJsonEditor({ + * title: 'Edit Mapping', + * onSave: function(data) { + * console.log('Saved:', data); + * } + * }); + * editor.open([{ key: 'value' }]); + * + * @example + * // With custom validators + * const editor = new UnityJsonEditor({ + * title: 'Edit Column Mapping', + * requiredFields: ['propertyName', 'columnName'], + * validators: [ + * { + * name: 'uniqueColumns', + * message: 'Column names must be unique', + * validate: function(data) { + * const cols = data.map(r => r.columnName); + * return new Set(cols).size === cols.length; + * } + * } + * ], + * onSave: function(data) { applyChanges(data); } + * }); + * + * @example + * // File operations (standalone, no modal needed) + * UnityJsonEditor.exportToFile(myData, 'config.json'); + * UnityJsonEditor.importFromFile({ accept: '.json' }).then(function(data) { + * console.log('Imported:', data); + * }); + */ +const UnityJsonEditor = (function ($) { + 'use strict'; + + let _instanceCount = 0; + + /** + * Default configuration options. + * @type {object} + */ + const DEFAULTS = { + /** Modal dialog title */ + title: 'Edit JSON', + + /** Bootstrap modal size class: 'modal-sm', 'modal-lg', 'modal-xl' */ + size: 'modal-lg', + + /** Number of visible rows in the textarea */ + rows: 18, + + /** Text for the save/apply button */ + saveButtonText: 'Apply', + + /** Text for the cancel button */ + cancelButtonText: 'Cancel', + + /** Text for the format button */ + formatButtonText: 'Format', + + /** Whether the modal should be read-only (disables editing and save) */ + readOnly: false, + + /** + * Array of field names required on each item when the data is an array of objects. + * Set to null or [] to skip required-field validation. + * @type {string[]|null} + */ + requiredFields: null, + + /** + * Custom validators array. Each validator is an object with: + * - name {string}: Identifier for the validator + * - message {string}: Message shown on failure + * - severity {string}: 'error' (default) blocks save; 'warning' allows save + * - validate {function(data): boolean}: Returns true if valid + * + * Validators run after JSON syntax and required-field checks pass. + * @type {Array<{name: string, message: string, severity?: string, validate: function}>} + */ + validators: [], + + /** + * Callback invoked when the user clicks Save/Apply and all validation passes. + * Receives the parsed JSON data and an array of active warnings. + * @type {function(data, warnings): void|null} + */ + onSave: null, + + /** + * Callback invoked when the user cancels or closes the modal without saving. + * Not called when the modal is closed after a successful save. + * @type {function(): void|null} + */ + onCancel: null, + + /** + * Callback invoked when validation fails with errors. + * Receives an array of error objects: [{ validator: string, message: string }]. + * @type {function(errors): void|null} + */ + onValidationError: null + }; + + // ======================================================================== + // Constructor + // ======================================================================== + + /** + * Creates a new UnityJsonEditor instance. + * @param {object} opts - Configuration options (merged with DEFAULTS). + */ + function UnityJsonEditor(opts) { + this._id = ++_instanceCount; + this._opts = $.extend({}, DEFAULTS, opts); + this._modalId = 'unityJsonEditorModal_' + this._id; + this._modal = null; + this._bsModal = null; + this._textarea = null; + this._statusBar = null; + this._saveBtn = null; + this._lastWarnings = []; + this._savedFlag = false; + this._built = false; + } + + // ======================================================================== + // Static helpers (usable without an instance) + // ======================================================================== + + /** + * Exports data as a downloadable JSON file. + * @param {*} data - Data to serialize. + * @param {string} [filename='export.json'] - Download filename. + */ + UnityJsonEditor.exportToFile = function (data, filename = 'export.json') { + const json = typeof data === 'string' ? data : JSON.stringify(data, null, 2); + const blob = new Blob([json], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + a.remove(); + setTimeout(function () { URL.revokeObjectURL(url); }, 100); + }; + + /** + * Opens a file picker and reads a JSON file. + * @param {object} [opts] - Options. + * @param {string} [opts.accept='.json'] - File input accept attribute. + * @param {Array<{name:string,message:string,severity?:string,validate:function}>} [opts.validators] - Optional validators to run on imported data. + * @param {function} [opts.onWarning] - Callback receiving an array of warning objects when warnings are present but no errors. + * @returns {Promise<*>} Resolves with parsed JSON data, rejects on error. + */ + UnityJsonEditor.importFromFile = function (opts) { + opts = opts || {}; + const accept = opts.accept || '.json'; + const validators = opts.validators || []; + const onWarning = opts.onWarning || null; + + return new Promise(function (resolve, reject) { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = accept; + input.style.display = 'none'; + + input.addEventListener('change', function () { + // Remove from DOM now that the browser has fired the change event + input.remove(); + + const file = input.files?.[0]; + if (!file) { + reject(new Error('No file selected.')); + return; + } + _processImportedFile(file, validators, onWarning) + .then(resolve) + .catch(reject); + }); + + document.body.appendChild(input); + input.click(); + }); + }; + + // ======================================================================== + // Prototype (instance methods) + // ======================================================================== + + UnityJsonEditor.prototype = { + constructor: UnityJsonEditor, + + /** + * Opens the editor modal with the given data. + * @param {*} data - Data to edit (will be serialized to JSON). + */ + open: function (data) { + if (!this._built) { + this._build(); + } + + this._savedFlag = false; + const json = typeof data === 'string' ? data : JSON.stringify(data, null, 2); + this._textarea.val(json); + this._clearStatus(); + this._validate(); + this._bsModal.show(); + }, + + /** + * Closes the editor modal. + */ + close: function () { + if (this._bsModal) { + this._bsModal.hide(); + } + }, + + /** + * Returns the current parsed data from the editor, or null if invalid. + * @returns {*|null} + */ + getData: function () { + try { + return JSON.parse(this._textarea.val()); + } catch (e) { + console.debug('getData: invalid JSON in editor', e.message); + return null; + } + }, + + /** + * Updates configuration options on the fly. + * @param {object} opts - Options to merge. + */ + setOptions: function (opts) { + $.extend(this._opts, opts); + if (this._built) { + this._updateUI(); + } + }, + + /** + * Destroys the editor instance and removes the modal from the DOM. + */ + destroy: function () { + if (this._bsModal) { + this._bsModal.dispose(); + } + if (this._modal) { + this._modal.remove(); + } + this._built = false; + }, + + // ==================================================================== + // Private methods + // ==================================================================== + + /** + * Builds the Bootstrap modal and appends it to the document body. + * @private + */ + _build: function () { + const opts = this._opts; + const id = this._modalId; + + const html = + ''; + + this._modal = $(html); + $('body').append(this._modal); + + this._textarea = this._modal.find('.uje-textarea'); + this._statusBar = this._modal.find('.uje-validation-msg'); + this._statusText = this._modal.find('.uje-status-text'); + this._saveBtn = this._modal.find('.uje-save-btn'); + this._bsModal = new bootstrap.Modal(document.getElementById(id)); + + // Event: real-time validation on input + this._textarea.on('input', () => { + this._validate(); + }); + + // Event: format button + this._modal.find('.uje-format-btn').on('click', () => { + this._format(); + }); + + // Event: save button + if (!opts.readOnly) { + this._saveBtn.on('click', () => { + this._onSave(); + }); + } + + // Event: modal hidden — only fire onCancel when not closed via save + this._modal.on('hidden.bs.modal', () => { + if (!this._savedFlag && typeof opts.onCancel === 'function') { + opts.onCancel(); + } + this._savedFlag = false; + }); + + // Tab key inserts spaces instead of changing focus + this._textarea.on('keydown', (e) => { + if (e.key === 'Tab') { + e.preventDefault(); + const target = e.target; + const start = target.selectionStart; + const end = target.selectionEnd; + const value = $(target).val(); + $(target).val(value.substring(0, start) + ' ' + value.substring(end)); + target.selectionStart = target.selectionEnd = start + 2; + $(this._textarea).trigger('input'); + } + }); + + // Scroll-to-top button: show when scrolled, click to jump to top + const $scrollBtn = this._modal.find('.uje-scroll-top'); + this._textarea.on('scroll', function () { + $scrollBtn.toggle(this.scrollTop > 100); + }); + $scrollBtn.on('click', () => { + this._textarea[0].scrollTop = 0; + $scrollBtn.hide(); + }); + + this._built = true; + }, + + /** + * Updates UI elements to reflect current options. + * @private + */ + _updateUI: function () { + const opts = this._opts; + this._modal.find('.modal-title').text(opts.title); + this._modal.find('.uje-format-btn').text(_escapeHtml(opts.formatButtonText)); + if (this._saveBtn.length) { + this._saveBtn.text(opts.saveButtonText); + } + this._textarea.prop('readonly', opts.readOnly); + }, + + /** + * Formats/beautifies the JSON in the textarea. + * @private + */ + _format: function () { + try { + const raw = this._textarea.val(); + const parsed = JSON.parse(raw); + this._textarea.val(JSON.stringify(parsed, null, 2)); + this._validate(); + } catch (e) { + console.debug('_format: could not parse JSON', e.message); + this._validate(); + } + }, + + /** + * Checks required fields on each item in an array of objects. + * @private + * @param {*} data - Parsed JSON data. + * @returns {string|null} Error message if validation fails, null if valid. + */ + _checkRequiredFields: function (data) { + const requiredFields = this._opts.requiredFields; + if (!requiredFields || requiredFields.length === 0 || !Array.isArray(data)) { + return null; + } + + for (const [i, item] of data.entries()) { + if (typeof item !== 'object' || item === null) { + return 'Item at index ' + i + ' is not an object.'; + } + for (const field of requiredFields) { + if (!(field in item) || item[field] === null || item[field] === undefined) { + return 'Item at index ' + i + ' is missing required field "' + field + '".'; + } + } + } + + return null; + }, + + /** + * Runs all validation checks and updates the UI. + * @private + * @returns {boolean} True if no errors (warnings are acceptable). + */ + _validate: function () { + const raw = this._textarea.val().trim(); + this._lastWarnings = []; + + // Empty check + if (!raw) { + this._showStatus('warning', 'Editor is empty'); + this._setSaveEnabled(false); + return false; + } + + // JSON syntax check + let data; + try { + data = JSON.parse(raw); + } catch (e) { + this._showStatus('error', 'Invalid JSON: ' + e.message); + this._setSaveEnabled(false); + return false; + } + + // Required fields check (only for arrays of objects) + const requiredFieldsError = this._checkRequiredFields(data); + if (requiredFieldsError) { + this._showStatus('error', requiredFieldsError); + this._setSaveEnabled(false); + return false; + } + + // Custom validators (errors + warnings) + const result = _runValidators(data, this._opts.validators, this._opts.requiredFields); + + // Errors block save + if (result.errors.length > 0) { + this._showStatus('error', result.errors[0].message); + this._setSaveEnabled(false); + if (typeof this._opts.onValidationError === 'function') { + this._opts.onValidationError(result.errors); + } + return false; + } + + // Warnings allow save but show amber status + const itemCount = Array.isArray(data) ? data.length + ' items' : 'Object'; + if (result.warnings.length > 0) { + this._lastWarnings = result.warnings; + const warningText = result.warnings[0].message; + this._showStatus('warning', 'Valid JSON \u00B7 ' + itemCount, '\u26A0 ' + warningText); + this._textarea.removeClass('is-invalid'); + this._setSaveEnabled(true); + return true; + } + + // All passed — no errors, no warnings + this._showStatus('success', 'Valid JSON \u00B7 ' + itemCount); + this._setSaveEnabled(true); + return true; + }, + + /** + * Handles the save action. + * @private + */ + _onSave: function () { + if (!this._validate()) return; + + const data = JSON.parse(this._textarea.val()); + const warnings = this._lastWarnings || []; + if (typeof this._opts.onSave === 'function') { + this._opts.onSave(data, warnings); + } + this._savedFlag = true; + this.close(); + }, + + /** + * Displays a status message. + * @private + * @param {'success'|'error'|'warning'} type + * @param {string} message + */ + _showStatus: function (type, message, secondLine) { + const iconMap = { success: 'fa-check-circle', error: 'fa-times-circle', warning: 'fa-exclamation-circle' }; + const colorMap = { success: 'text-success', error: 'text-danger', warning: 'text-warning' }; + const icon = iconMap[type] || iconMap.warning; + const colorClass = colorMap[type] || colorMap.warning; + + let html = '' + _escapeHtml(message); + if (secondLine) { + html += '
' + _escapeHtml(secondLine); + } + + this._statusBar + .html(html) + .removeClass('text-success text-danger text-warning') + .addClass(colorClass); + + this._textarea + .toggleClass('is-invalid', type === 'error') + .toggleClass('is-valid', type === 'success'); + }, + + /** + * Clears the status bar. + * @private + */ + _clearStatus: function () { + this._statusBar.html('').removeClass('text-success text-danger text-warning'); + this._textarea.removeClass('is-invalid is-valid'); + }, + + /** + * Enables or disables the save button. + * @private + * @param {boolean} enabled + */ + _setSaveEnabled: function (enabled) { + if (this._saveBtn.length) { + this._saveBtn.prop('disabled', !enabled); + } + } + }; + + // ======================================================================== + // Private utility functions + // ======================================================================== + + /** + * Runs an array of custom validators against parsed data. + * Validators with severity:'warning' produce warnings (non-blocking); + * all others produce errors (blocking). + * @param {*} data - Parsed JSON data. + * @param {Array} validators - Validator definitions. + * @param {string[]|null} requiredFields - Required field names (for context). + * @returns {{errors: Array<{validator: string, message: string}>, warnings: Array<{validator: string, message: string}>}} + */ + function _runValidators(data, validators, requiredFields) { + const errors = []; + const warnings = []; + if (!validators || validators.length === 0) return { errors: errors, warnings: warnings }; + + for (const v of validators) { + const isWarning = v.severity === 'warning'; + const target = isWarning ? warnings : errors; + try { + const result = v.validate(data, requiredFields); + if (result === false) { + target.push({ validator: v.name, message: v.message || 'Validation failed: ' + v.name }); + } else if (typeof result === 'object' && result !== null && result.valid === false) { + target.push({ validator: v.name, message: result.message || v.message || 'Validation failed: ' + v.name }); + } + } catch (ex) { + errors.push({ validator: v.name, message: 'Validator "' + v.name + '" error: ' + ex.message }); + } + } + return { errors: errors, warnings: warnings }; + } + + /** + * Reads a file, parses JSON, runs validators, and resolves with the data. + * Extracted from importFromFile to keep function nesting shallow. + * @param {File} file - The file to read. + * @param {Array} validators - Validators to run on the parsed data. + * @param {function|null} onWarning - Callback for non-blocking warnings. + * @returns {Promise<*>} Resolves with parsed JSON data, rejects on error. + */ + function _processImportedFile(file, validators, onWarning) { + return file.text().then(function (text) { + const data = JSON.parse(text); + + // Run validators if provided + const result = _runValidators(data, validators, null); + if (result.errors.length > 0) { + throw new Error(result.errors.map(function (err) { return err.message; }).join('\n')); + } + + // Report warnings but allow import + if (result.warnings.length > 0 && typeof onWarning === 'function') { + onWarning(result.warnings); + } + + return data; + }).catch(function (ex) { + throw new Error('Invalid JSON file: ' + ex.message); + }); + } + + /** + * Escapes HTML special characters. + * @param {string} str + * @returns {string} + */ + function _escapeHtml(str) { + const div = document.createElement('div'); + div.appendChild(document.createTextNode(str)); + return div.innerHTML; + } + + return UnityJsonEditor; + +})(jQuery); diff --git a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js index cfad9c7c22..3217b80343 100644 --- a/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js +++ b/applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/wwwroot/themes/ux2/plugins/filterRow.js @@ -32,6 +32,7 @@ 'use strict'; let DataTable = $.fn.dataTable; + let _filterRowInstanceCount = 0; // Ensure DataTable is loaded if (!DataTable) { @@ -55,7 +56,7 @@ this.s = { dt: new DataTable.Api(settings), - namespace: '.dtFilterRow', + namespace: '.dtFilterRow' + (++_filterRowInstanceCount), filterData: {}, opts: $.extend({}, DataTable.FilterRow.defaults, opts) }; @@ -89,8 +90,7 @@ * @private */ _constructor: function () { - let that = this; - let dt = this.s.dt; + const dt = this.s.dt; // Create the filter row this._buildFilterRow(); @@ -104,20 +104,24 @@ this._restoreFilterState(); // Listen for column visibility and reorder events - dt.on('column-reorder' + this.s.namespace, function () { - that._rebuildFilterRow(); + dt.on('column-reorder' + this.s.namespace, () => { + this._rebuildFilterRow(); + }); + + dt.on('column-visibility' + this.s.namespace, () => { + this._rebuildFilterRow(); }); - dt.on('column-visibility' + this.s.namespace, function () { - that._rebuildFilterRow(); + // Update button state whenever the global search changes + dt.on('search' + this.s.namespace, () => { + this._updateButtonState(); }); // Listen for destroy event to cleanup - dt.on('destroy' + this.s.namespace, function () { - that._destroy(); + dt.on('destroy' + this.s.namespace, () => { + this._destroy(); }); - // Show filter row if autoShow is enabled if (this.s.opts.autoShow) { this.dom.filterRow.show(); } @@ -131,26 +135,29 @@ * @private */ _buildFilterRow: function () { - let dt = this.s.dt; - let that = this; - let filterRow = $('
').append(input); + const cell = $('').append(input); // Apply search value if it differs from current column search if (column.search() !== filterValue) { @@ -166,29 +173,26 @@ } // Bind keyup event for filtering - input.on('keyup' + that.s.namespace, function () { - let val = this.value; + input.on('keyup' + namespace, function () { + const val = this.value; + if (column.search() !== val) { column.search(val).draw(); // Store by column name for persistence - that.s.filterData[colName] = val; - that._updateButtonState(); + filterData[colName] = val; + updateButtonState(); } }); filterRow.append(cell); } else { - // Empty cell for action columns filterRow.append($('')); } } - // Skip hidden columns - don't add any td element }); - // Remove existing filter row if present dt.table().header().parentNode.querySelector('.tr-toggle-filter')?.remove(); - // Append to table header $(dt.table().header()).after(filterRow); this.dom.filterRow = filterRow; }, @@ -198,23 +202,23 @@ * @private */ _rebuildFilterRow: function () { - let dt = this.s.dt; - let that = this; - // Preserve current filter values before rebuilding - this.dom.filterRow?.find('.custom-filter-input').each(function() { - let colName = $(this).data('column-name'); - let val = $(this).val(); + this.dom.filterRow?.find('.custom-filter-input').each((_, el) => { + const colName = $(el).data('column-name'); + const val = $(el).val(); if (colName && val) { - that.s.filterData[colName] = val; + this.s.filterData[colName] = val; } }); - - let wasVisible = this.dom.filterRow?.is(':visible'); + + const wasVisible = this.dom.filterRow?.is(':visible'); + this._buildFilterRow(); + if (wasVisible) { this.dom.filterRow.show(); } + this._updateButtonState(); }, @@ -223,17 +227,14 @@ * @private */ _initializePopover: function () { - let that = this; - let btnSelector = '#' + this.s.opts.buttonId; - let $btn = $(btnSelector); + const btnSelector = '#' + this.s.opts.buttonId; + const $btn = $(btnSelector); - if (!$btn.length) { - return; // Button not found, skip popover - } + if (!$btn.length) return; this.dom.button = $btn; - $btn.on('click' + this.s.namespace, function () { + $btn.on('click' + this.s.namespace, () => { $btn.popover('toggle'); }); @@ -247,58 +248,65 @@
`, - content: function () { - let isChecked = that.dom.filterRow.is(':visible'); + content: () => { + const isChecked = this.dom.filterRow.is(':visible'); + return `
- +
- CLEAR FILTER + `; }, placement: this.s.opts.popoverPlacement }); - // Handle popover shown event - $btn.on('shown.bs.popover' + this.s.namespace, function () { - let $popover = $('.popover.custom-popover'); + $btn.on('shown.bs.popover' + this.s.namespace, () => { - // Toggle filter row visibility - $popover.find('#showFilter').on('click', function () { - that.dom.filterRow.toggle(); - that.s.dt.trigger('filterRow-visibility', [that.dom.filterRow.is(':visible')]); - }); + const popoverId = $btn.attr('aria-describedby'); + const $popover = popoverId ? $('#' + popoverId) : $('.popover.custom-popover'); - // Clear all filters - $popover.find('#btnClearFilter').on('click', function () { - that.clearFilters(); - $btn.popover('hide'); - }); + $popover.find('#showFilter') + .off('click' + this.s.namespace) + .on('click' + this.s.namespace, () => { + this.dom.filterRow.toggle(); + this.s.dt.trigger('filterRow-visibility', [ + this.dom.filterRow.is(':visible') + ]); + }); - // Close popover on outside click/hover - $(document).on('click.popover' + that.s.namespace, function (e) { - if (!$(e.target).closest(btnSelector).length && - !$(e.target).closest('.popover').length) { + $popover.find('#btnClearFilter') + .off('click' + this.s.namespace) + .on('click' + this.s.namespace, () => { + this.clearFilters(); $btn.popover('hide'); - } - }); + }); - $(document).on('mouseenter.popover' + that.s.namespace, function (e) { - if (!$(e.target).closest(btnSelector).length && - !$(e.target).closest('.popover').length) { - $btn.popover('hide'); - } - }); + // ✅ FIXED OUTSIDE CLICK + $(document) + .off('mousedown' + this.s.namespace) + .on('mousedown' + this.s.namespace, (e) => { + + const $popoverEl = $('.popover.custom-popover'); + if (!$popoverEl.is(':visible')) return; + + const $target = $(e.target); + + const insidePopover = $target.closest('.popover.custom-popover').length > 0; + const insideButton = $target.closest(btnSelector).length > 0; + + if (!insidePopover && !insideButton) { + $btn.popover('hide'); + } + }); }); // Cleanup popover events on hide - $btn.on('hide.bs.popover' + this.s.namespace, function () { - let $popover = $('.popover.custom-popover'); - $popover.find('#showFilter').off('click'); - $popover.find('#btnClearFilter').off('click'); - $(document).off('click.popover' + that.s.namespace); - $(document).off('mouseenter.popover' + that.s.namespace); + $btn.on('hide.bs.popover' + this.s.namespace, () => { + $(document).off('mousedown' + this.s.namespace); }); }, @@ -308,30 +316,20 @@ */ _updateButtonState: function () { let dt = this.s.dt; - let hasFilters = false; - - // Check column filters - dt.columns().every(function () { - if (this.search()) { - hasFilters = true; - return false; - } - }); + let hasFilters = dt.search() !== ''; - // Check global search - let externalSearchId = dt.init().externalSearchInputId; - if (externalSearchId) { - let searchVal = $(externalSearchId).val(); - if (searchVal && searchVal !== '') { - hasFilters = true; - } + if (!hasFilters) { + dt.columns().every(function () { + if (this.search()) { + hasFilters = true; + return false; + } + }); } - // Update button text if (this.dom.button) { - this.dom.button.text(hasFilters ? - this.s.opts.buttonTextActive : - this.s.opts.buttonText + this.dom.button.text( + hasFilters ? this.s.opts.buttonTextActive : this.s.opts.buttonText ); } }, @@ -341,20 +339,20 @@ * @private */ _restoreFilterState: function () { - let dt = this.s.dt; - let that = this; + const dt = this.s.dt; + const filterData = this.s.filterData; let needsRedraw = false; dt.columns().every(function (i) { - let column = this; - let colName = dt.settings()[0].aoColumns[i].name; - let title = $(column.header()).text(); - let searchVal = column.search(); + const column = this; + const colName = dt.settings()[0].aoColumns[i].name; + const title = $(column.header()).text(); + const searchVal = column.search(); + + const key = colName || title; - // Store by column name (preferred) or fallback to title - let key = colName || title; if (searchVal) { - that.s.filterData[key] = searchVal; + filterData[key] = searchVal; needsRedraw = true; } }); @@ -385,32 +383,25 @@ let externalSearchId = dtInit.externalSearchInputId; let initialSortOrder = (dtInit && dtInit.order) ? dtInit.order : []; - // Clear external search if (externalSearchId) { $(externalSearchId).val(''); } - // Clear the search input field - $('#search').val(''); + this.dom.filterRow.find('.custom-filter-input').val(''); - // Clear custom filter inputs - $('.custom-filter-input').val(''); - - // Clear DataTable searches dt.search('').columns().search(''); + dt.order(initialSortOrder).draw(); - // Clear order - dt.order(initialSortOrder); - - // If we want to reset quick date range dropdown to default (last 6 months) and trigger change - // The change event handler will reload the table, so would need to remove ajax.reload() here - $('#quickDateRange').val($('#quickDateRange option[selected]').val()).trigger('change'); - - // Update button state - this._updateButtonState(); + let $quickDateRange = $('#quickDateRange'); + if ($quickDateRange.length) { + let defaultVal = $quickDateRange.find('option[selected]').val(); + if (defaultVal) { + $quickDateRange.val(defaultVal).trigger('change'); + } + } - // Clear internal filter data this.s.filterData = {}; + this._updateButtonState(); }, /** @@ -462,12 +453,7 @@ } } - // Remove filter row from DOM - if (this.dom.filterRow) { - this.dom.filterRow.remove(); - } - - // Remove reference from settings + this.dom.filterRow?.remove(); dt.settings()[0]._filterRow = null; } }; @@ -491,4 +477,22 @@ }); return DataTable.FilterRow; + })(jQuery); + + +$(document).on('mousedown', function (e) { + const $popover = $('.popover.custom-popover'); + if (!$popover.is(':visible')) return; + + const $target = $(e.target); + const popoverId = $popover.attr('id'); + const $trigger = $('[aria-describedby="' + popoverId + '"]'); + + const insidePopover = $target.closest('.popover.custom-popover').length > 0; + const insideButton = $trigger.length > 0 && $target.closest($trigger).length > 0; + + if (!insidePopover && !insideButton) { + $trigger.popover('hide'); + } +}); \ No newline at end of file diff --git a/applications/Unity.GrantManager/scripts/ApplicantElectoralUpdate.md b/applications/Unity.GrantManager/scripts/ApplicantElectoralUpdate.md new file mode 100644 index 0000000000..f9218514d9 --- /dev/null +++ b/applications/Unity.GrantManager/scripts/ApplicantElectoralUpdate.md @@ -0,0 +1,64 @@ +# Applicant Electoral District Update + +## Overview + +This process cross-references application electoral districts against the BC Geocoder API and generates SQL fix scripts for any mismatches. + +## Steps + +### 1. Extract Data from the Database + +Run `GetElectoralDistrictData.sql` against the database and save the results as a CSV file in the `data/` folder: + +``` +data/electoral_districts.csv +``` + +The query returns all applications joined with their applicant addresses, including `ApplicationId`, `ReferenceNo`, `ApplicantElectoralDistrict`, `Street`, `Street2`, `City`, and `AddressType`. + +### 2. Validate Electoral Districts + +Run `Validate-ElectoralDistricts.ps1` with the extracted CSV. This geocodes each unique address via the BC Geocoder API, looks up the electoral district from the WFS endpoint, and compares it to the value stored in the database. + +```powershell +.\Validate-ElectoralDistricts.ps1 ` + -InputCsv ".\data\electoral_districts.csv" ` + -GeocoderLocationBase "https://geocoder.api.gov.bc.ca" ` + -GeocoderApiBase "https://openmaps.gov.bc.ca/geo/pub/wfs?service=WFS&version=2.0.0&request=GetFeature&typeName=" +``` + +This produces a validated CSV with match results: + +``` +data/electoral_districts_validated.csv +``` + +Each row includes the expected electoral district, geocoder score, and a `DistrictMatch` column (`MATCH`, `MISMATCH`, `UNKNOWN`, or `SKIPPED`). + +### 3. Generate SQL Fix Scripts + +Run `Generate-ElectoralDistrictFixes.ps1` against the validated CSV. This produces SQL UPDATE statements for mismatched rows. + +```powershell +.\Generate-ElectoralDistrictFixes.ps1 ` + -InputCsv ".\data\electoral_districts_validated.csv" ` + -MinScore 70 ` + -AddressType 1 ` + -IncludeLowConfidence +``` + +This generates two SQL scripts: + +| File | Description | +|------|-------------| +| `electoral_districts_validated_update.sql` | High-confidence updates (score >= 70) — sets the district to the expected value | +| `electoral_districts_validated_nullify.sql` | Low-confidence updates (score < 70) — sets the district to NULL | + +Both scripts use conditional updates that only apply when the current database value still matches the value at extract time, preventing overwrites of legitimate changes. + +### 4. Apply the Fix Scripts + +Review the generated SQL files, then execute them against the database: + +1. **Always apply the high-confidence script first** (`_update.sql`). +2. **Optionally apply the low-confidence script** (`_nullify.sql`) if you want to clear unreliable district values. diff --git a/applications/Unity.GrantManager/scripts/Generate-ElectoralDistrictFixes.ps1 b/applications/Unity.GrantManager/scripts/Generate-ElectoralDistrictFixes.ps1 new file mode 100644 index 0000000000..4dbe27756c --- /dev/null +++ b/applications/Unity.GrantManager/scripts/Generate-ElectoralDistrictFixes.ps1 @@ -0,0 +1,198 @@ +<# +.SYNOPSIS + Generates PostgreSQL UPDATE statements to fix mismatched electoral districts. + +.DESCRIPTION + Reads the validated CSV output from Validate-ElectoralDistricts.ps1 and generates + SQL UPDATE statements for rows where: + - DistrictMatch is MISMATCH and GeocoderScore >= MinScore: SET to the expected district (main file) + - DistrictMatch is MISMATCH and GeocoderScore < MinScore: SET to NULL (separate file, opt-in) + - AddressType matches the specified type (1=Physical, 2=Mailing) + +.PARAMETER InputCsv + Path to the validated CSV file (output of Validate-ElectoralDistricts.ps1). + +.PARAMETER OutputSql + Path to the high-confidence output .sql file. Defaults to _update.sql. + +.PARAMETER MinScore + Minimum geocoder score to trust. Rows at or above get the expected district; + rows below get NULL (if -IncludeLowConfidence is set). Default: 70. + +.PARAMETER AddressType + AddressType to filter on. 1 = Physical, 2 = Mailing. Default: 1 (Physical). + +.PARAMETER IncludeLowConfidence + When set, generates a separate .sql file for low-confidence rows (score < MinScore) + that sets ApplicantElectoralDistrict to NULL. File is _nullify.sql. + +.EXAMPLE + .\Generate-ElectoralDistrictFixes.ps1 ` + -InputCsv ".\data\electoral_districts_validated.csv" ` + -MinScore 70 ` + -AddressType 1 ` + -IncludeLowConfidence +#> +param( + [Parameter(Mandatory)] + [string]$InputCsv, + + [string]$OutputSql = "", + + [int]$MinScore = 70, + + [ValidateSet("1", "2")] + [string]$AddressType = "1", + + [switch]$IncludeLowConfidence +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# ── Output path defaults ────────────────────────────────────────────── +$dir = [System.IO.Path]::GetDirectoryName((Resolve-Path $InputCsv)) +$name = [System.IO.Path]::GetFileNameWithoutExtension($InputCsv) + +if (-not $OutputSql) { + $OutputSql = Join-Path $dir "${name}_update.sql" +} +$NullifySql = Join-Path $dir "${name}_nullify.sql" + +# ── Read CSV ────────────────────────────────────────────────────────── +$data = Import-Csv -Path $InputCsv +Write-Host "Loaded $($data.Count) rows from $InputCsv" -ForegroundColor Cyan + +# ── Resolve address type label ──────────────────────────────────────── +$addressTypeLabel = switch ($AddressType) { + "1" { "Physical" } + "2" { "Mailing" } +} +Write-Host "Filtering for AddressType: $AddressType ($addressTypeLabel)" -ForegroundColor Cyan + +# ── Filter all mismatches for this address type ────────────────────── +$allMismatches = @($data | Where-Object { + $_.DistrictMatch -eq "MISMATCH" -and + $_.GeocoderScore -ne "" -and + $_.AddressType -eq $AddressType +}) + +# Split into high-confidence (update to expected) and low-confidence (set to NULL) +$highConfidence = @($allMismatches | Where-Object { [int]$_.GeocoderScore -ge $MinScore }) +$lowConfidence = @($allMismatches | Where-Object { [int]$_.GeocoderScore -lt $MinScore }) + +Write-Host "Found $($allMismatches.Count) total MISMATCH rows for AddressType = $AddressType ($addressTypeLabel)" -ForegroundColor Cyan +Write-Host " High confidence (score >= $MinScore): $($highConfidence.Count) -> will SET to expected district" -ForegroundColor Green +$lowConfMsg = if ($IncludeLowConfidence) { " -> will SET to NULL (separate file)" } else { " (skipped, use -IncludeLowConfidence to generate)" } +Write-Host " Low confidence (score < $MinScore): $($lowConfidence.Count)$lowConfMsg" -ForegroundColor Yellow + +if ($highConfidence.Count -eq 0 -and (-not $IncludeLowConfidence -or $lowConfidence.Count -eq 0)) { + Write-Host "No rows to update. Exiting." -ForegroundColor Yellow + return +} + +# ── Helper ─────────────────────────────────────────────────────────── +function Escape-SqlString { + param([string]$value) + return $value.Replace("'", "''") +} + +# ── Generate high-confidence SQL ───────────────────────────────────── +if ($highConfidence.Count -gt 0) { + $sb = [System.Text.StringBuilder]::new() + [void]$sb.AppendLine("-- Electoral District Fix Script (High Confidence)") + [void]$sb.AppendLine("-- Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')") + [void]$sb.AppendLine("-- Source: $InputCsv") + [void]$sb.AppendLine("-- Filter: MISMATCH rows, AddressType = $AddressType ($addressTypeLabel), Score >= $MinScore") + [void]$sb.AppendLine("-- Total updates: $($highConfidence.Count)") + [void]$sb.AppendLine("") + [void]$sb.AppendLine("BEGIN;") + [void]$sb.AppendLine("") + + foreach ($row in $highConfidence) { + $appId = $row.ApplicationId.Trim() + $parsedGuid = [System.Guid]::Empty + if (-not [System.Guid]::TryParse($appId, [ref]$parsedGuid)) { + Write-Host " SKIPPED: Invalid ApplicationId '$appId' (ReferenceNo: $($row.ReferenceNo))" -ForegroundColor Red + continue + } + $appId = $parsedGuid.ToString() + $currentED = Escape-SqlString $row.ApplicantElectoralDistrict.Trim() + $expectedED = Escape-SqlString $row.ExpectedElectoralDistrict.Trim() + $score = $row.GeocoderScore + $refNo = $row.ReferenceNo + + [void]$sb.AppendLine("-- ReferenceNo: $refNo | Score: $score | '$currentED' -> '$expectedED'") + [void]$sb.AppendLine("UPDATE ""Applications"" SET ""ApplicantElectoralDistrict"" = '$expectedED' WHERE ""Id"" = '$appId' AND ""ApplicantElectoralDistrict"" = '$currentED';") + [void]$sb.AppendLine("") + } + + [void]$sb.AppendLine("COMMIT;") + $sb.ToString() | Out-File -FilePath $OutputSql -Encoding UTF8 + Write-Host "`nHigh-confidence SQL written to: $OutputSql" -ForegroundColor Green +} +else { + Write-Host "`nNo high-confidence rows to write." -ForegroundColor DarkGray +} + +# ── Generate low-confidence SQL (separate file, opt-in) ────────────── +if ($IncludeLowConfidence -and $lowConfidence.Count -gt 0) { + $sbNull = [System.Text.StringBuilder]::new() + [void]$sbNull.AppendLine("-- Electoral District Nullify Script (Low Confidence)") + [void]$sbNull.AppendLine("-- Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')") + [void]$sbNull.AppendLine("-- Source: $InputCsv") + [void]$sbNull.AppendLine("-- Filter: MISMATCH rows, AddressType = $AddressType ($addressTypeLabel), Score < $MinScore") + [void]$sbNull.AppendLine("-- Total updates: $($lowConfidence.Count)") + [void]$sbNull.AppendLine("-- Action: SET ApplicantElectoralDistrict = NULL (unreliable geocoding)") + [void]$sbNull.AppendLine("") + [void]$sbNull.AppendLine("BEGIN;") + [void]$sbNull.AppendLine("") + + foreach ($row in $lowConfidence) { + $appId = $row.ApplicationId.Trim() + $parsedGuid = [System.Guid]::Empty + if (-not [System.Guid]::TryParse($appId, [ref]$parsedGuid)) { + Write-Host " SKIPPED: Invalid ApplicationId '$appId' (ReferenceNo: $($row.ReferenceNo))" -ForegroundColor Red + continue + } + $appId = $parsedGuid.ToString() + $currentED = Escape-SqlString $row.ApplicantElectoralDistrict.Trim() + $score = $row.GeocoderScore + $refNo = $row.ReferenceNo + + [void]$sbNull.AppendLine("-- ReferenceNo: $refNo | Score: $score | '$currentED' -> NULL") + [void]$sbNull.AppendLine("UPDATE ""Applications"" SET ""ApplicantElectoralDistrict"" = NULL WHERE ""Id"" = '$appId' AND ""ApplicantElectoralDistrict"" = '$currentED';") + [void]$sbNull.AppendLine("") + } + + [void]$sbNull.AppendLine("COMMIT;") + $sbNull.ToString() | Out-File -FilePath $NullifySql -Encoding UTF8 + Write-Host "Low-confidence SQL written to: $NullifySql" -ForegroundColor Yellow +} +elseif ($IncludeLowConfidence) { + Write-Host "`nNo low-confidence rows to write." -ForegroundColor DarkGray +} + +# ── Summary ─────────────────────────────────────────────────────────── +Write-Host "" +Write-Host "=============================" -ForegroundColor White +Write-Host " SQL Generation Summary" -ForegroundColor White +Write-Host "=============================" -ForegroundColor White +Write-Host "Address type: $AddressType ($addressTypeLabel)" +Write-Host "Score threshold: $MinScore" +Write-Host "-----------------------------" +Write-Host "High confidence: $($highConfidence.Count) (SET to expected)" -ForegroundColor Green +Write-Host "Low confidence: $($lowConfidence.Count) (SET to NULL)" -ForegroundColor Yellow +Write-Host "Total mismatches: $($allMismatches.Count)" +Write-Host "-----------------------------" +if ($highConfidence.Count -gt 0) { + Write-Host "Update file: $OutputSql" -ForegroundColor White +} +if ($IncludeLowConfidence -and $lowConfidence.Count -gt 0) { + Write-Host "Nullify file: $NullifySql" -ForegroundColor White +} +elseif ($lowConfidence.Count -gt 0) { + Write-Host "Nullify file: (not generated - use -IncludeLowConfidence)" -ForegroundColor DarkGray +} +Write-Host "" +Write-Host "Review the SQL file(s), then execute against your PostgreSQL database." -ForegroundColor Yellow diff --git a/applications/Unity.GrantManager/scripts/GetElectoralDistrictData.sql b/applications/Unity.GrantManager/scripts/GetElectoralDistrictData.sql new file mode 100644 index 0000000000..1fa5aa3a0b --- /dev/null +++ b/applications/Unity.GrantManager/scripts/GetElectoralDistrictData.sql @@ -0,0 +1,12 @@ +SELECT ap."CreationTime", +ap."Id" as "ApplicationId", +ap."ReferenceNo", +ap."ApplicantElectoralDistrict", +ad."Id" as "AddressId", +ad."Street", +ad."Street2", +ad."City", +ad."AddressType" +FROM public."Applications" ap +LEFT JOIN "ApplicantAddresses" ad on ad."ApplicationId" = ap."Id" +ORDER BY ap."CreationTime" DESC \ No newline at end of file diff --git a/applications/Unity.GrantManager/scripts/Validate-ElectoralDistricts.ps1 b/applications/Unity.GrantManager/scripts/Validate-ElectoralDistricts.ps1 new file mode 100644 index 0000000000..5889bf4c2a --- /dev/null +++ b/applications/Unity.GrantManager/scripts/Validate-ElectoralDistricts.ps1 @@ -0,0 +1,310 @@ +<# +.SYNOPSIS + Cross-references electoral districts in a CSV against the BC Geocoder API. + +.DESCRIPTION + Reads a CSV with address data, looks up each unique address via the BC Geocoder + location API to get coordinates, then queries the electoral district WFS endpoint. + Deduplicates addresses so identical Street+Street2+City combinations are only + looked up once. Handles rate limiting with exponential backoff. + Outputs a new CSV with all original columns plus the expected electoral district. + +.PARAMETER InputCsv + Path to the input CSV file. + +.PARAMETER OutputCsv + Path to the output CSV file. Defaults to _validated.csv. + +.PARAMETER GeocoderLocationBase + Base URL for the geocoder location API (GEOCODER_LOCATION_API_BASE). + Example: https://geocoder.api.gov.bc.ca + +.PARAMETER GeocoderApiBase + Base URL for the geocoder WFS API (GEOCODER_API_BASE). + Example: https://openmaps.gov.bc.ca/geo/pub/wfs?service=WFS&version=2.0.0&request=GetFeature&typeName= + +.PARAMETER InitialDelayMs + Initial delay between API calls in milliseconds. Default: 250. + +.EXAMPLE + .\Validate-ElectoralDistricts.ps1 ` + -InputCsv ".\data\electoral_districts.csv" ` + -GeocoderLocationBase "https://geocoder.api.gov.bc.ca" ` + -GeocoderApiBase "https://openmaps.gov.bc.ca/geo/pub/wfs?service=WFS&version=2.0.0&request=GetFeature&typeName=" +#> +param( + [Parameter(Mandatory)] + [string]$InputCsv, + + [string]$OutputCsv = "", + + [Parameter(Mandatory)] + [string]$GeocoderLocationBase, + + [Parameter(Mandatory)] + [string]$GeocoderApiBase, + + [int]$InitialDelayMs = 100 +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = "Stop" + +# ── Output path defaults ────────────────────────────────────────────── +if (-not $OutputCsv) { + $dir = [System.IO.Path]::GetDirectoryName((Resolve-Path $InputCsv)) + $name = [System.IO.Path]::GetFileNameWithoutExtension($InputCsv) + $OutputCsv = Join-Path $dir "${name}_validated.csv" +} + +# ── Read CSV ────────────────────────────────────────────────────────── +$data = Import-Csv -Path $InputCsv +Write-Host "Loaded $($data.Count) rows from $InputCsv" -ForegroundColor Cyan + +# ── Helpers ─────────────────────────────────────────────────────────── +function Test-NullOrEmpty { + param([string]$value) + return [string]::IsNullOrWhiteSpace($value) -or $value.Trim() -eq 'NULL' +} + +function Get-CleanValue { + param([string]$value) + if (Test-NullOrEmpty $value) { return "" } + return $value.Trim() +} + +function Get-AddressKey { + param($row) + $street = Get-CleanValue $row.Street + $street2 = Get-CleanValue $row.Street2 + $city = Get-CleanValue $row.City + return "$street|$street2|$city".ToLowerInvariant() +} + +function Build-AddressString { + param($street, $street2, $city) + $parts = @($street, $street2, $city) | ForEach-Object { Get-CleanValue $_ } | Where-Object { $_ -ne "" } + return ($parts -join ", ") +} + +function Get-AddressTypeName { + param([string]$value) + $clean = Get-CleanValue $value + switch ($clean) { + "1" { return "Physical" } + "2" { return "Mailing" } + default { return "" } + } +} + +# ── Deduplicate addresses ──────────────────────────────────────────── +$addressLookup = [ordered]@{} +$skippedCount = 0 + +foreach ($row in $data) { + $street = Get-CleanValue $row.Street + $street2 = Get-CleanValue $row.Street2 + $city = Get-CleanValue $row.City + + # Skip rows where both street fields and city are empty/NULL + if ($street -eq "" -and $street2 -eq "" -and $city -eq "") { + $skippedCount++ + continue + } + + $key = Get-AddressKey $row + if (-not $addressLookup.Contains($key)) { + $addressLookup[$key] = @{ + Street = $row.Street + Street2 = $row.Street2 + City = $row.City + ExpectedED = $null + Score = $null + FullAddress = $null + Error = $null + } + } +} + +$uniqueCount = $addressLookup.Count +Write-Host "Unique addresses to look up: $uniqueCount (skipped $skippedCount rows with empty address)" -ForegroundColor Cyan + +# ── Rate-limited HTTP caller with exponential backoff ───────────────── +$script:currentDelayMs = $InitialDelayMs +$maxDelayMs = 30000 +$minDelayMs = 100 + +function Invoke-GeocoderRequest { + param( + [string]$Uri, + [int]$MaxRetries = 6 + ) + + for ($attempt = 1; $attempt -le ($MaxRetries + 1); $attempt++) { + try { + $response = Invoke-RestMethod -Uri $Uri -Method Get -ErrorAction Stop + + # On success, gently reduce the inter-call delay + $script:currentDelayMs = [Math]::Max($minDelayMs, [int]([Math]::Floor($script:currentDelayMs * 0.95))) + + return $response + } + catch { + $statusCode = 0 + if ($_.Exception.Response) { + $statusCode = [int]$_.Exception.Response.StatusCode + } + + if (($statusCode -eq 429 -or $statusCode -eq 503) -and $attempt -le $MaxRetries) { + # Exponential backoff + $script:currentDelayMs = [Math]::Min($maxDelayMs, $script:currentDelayMs * 2) + Write-Host " Rate limited (HTTP $statusCode). Backing off $($script:currentDelayMs)ms (attempt $attempt/$MaxRetries)..." -ForegroundColor Yellow + Start-Sleep -Milliseconds $script:currentDelayMs + } + else { + throw + } + } + } +} + +# ── Process each unique address ─────────────────────────────────────── +$processed = 0 +$errorCount = 0 + +# Electoral district WFS parameters (from appsettings.json Geocoder:ElectoralDistrict) +$edFeature = "pub:WHSE_ADMIN_BOUNDARIES.EBC_PROV_ELECTORAL_DIST_SVW" +$edProperty = "ED_NAME" +$edQueryType = "SHAPE" + +foreach ($entry in $addressLookup.GetEnumerator()) { + $processed++ + $addr = $entry.Value + $addressString = Build-AddressString $addr.Street $addr.Street2 $addr.City + + Write-Host "[$processed/$uniqueCount] $addressString" -ForegroundColor Cyan + + try { + # Step 1: Geocode address → coordinates + $encodedAddress = [System.Uri]::EscapeDataString($addressString) + $locationUri = "$GeocoderLocationBase/addresses.json?outputSRS=3005&addressString=$encodedAddress" + + Start-Sleep -Milliseconds $script:currentDelayMs + $locationResult = Invoke-GeocoderRequest -Uri $locationUri + + if (-not $locationResult.features -or $locationResult.features.Count -eq 0) { + Write-Host " No location results" -ForegroundColor Yellow + $addr.Error = "No location results" + $errorCount++ + continue + } + + $coords = $locationResult.features[0].geometry.coordinates + $coordX = $coords[0] # EPSG:3005 easting (mirrors C# ResultMapper: coordinates[0]) + $coordY = $coords[1] # EPSG:3005 northing (mirrors C# ResultMapper: coordinates[1]) + $score = $locationResult.features[0].properties.score + $fullAddr = $locationResult.features[0].properties.fullAddress + + $addr.Score = $score + $addr.FullAddress = $fullAddr + Write-Host " Resolved: $fullAddr (score: $score)" -ForegroundColor DarkGray + + # Step 2: Look up electoral district from coordinates + $edUri = "${GeocoderApiBase}${edFeature}" + + "&srsname=EPSG:3005" + + "&propertyName=${edProperty}" + + "&outputFormat=application/json" + + "&cql_filter=INTERSECTS(${edQueryType},POINT($coordX $coordY))" + + Start-Sleep -Milliseconds $script:currentDelayMs + $edResult = Invoke-GeocoderRequest -Uri $edUri + + if (-not $edResult.features -or $edResult.features.Count -eq 0) { + Write-Host " No electoral district found for coordinates" -ForegroundColor Yellow + $addr.ExpectedED = "" + $addr.Error = "No electoral district for coordinates ($coordX, $coordY)" + $errorCount++ + continue + } + + $expectedED = $edResult.features[0].properties.ED_NAME + $addr.ExpectedED = $expectedED + Write-Host " Electoral District: $expectedED" -ForegroundColor Green + } + catch { + Write-Host " ERROR: $_" -ForegroundColor Red + $addr.Error = $_.ToString() + $errorCount++ + } +} + +# ── Build output CSV ────────────────────────────────────────────────── +Write-Host "`nBuilding output CSV..." -ForegroundColor Cyan + +$output = [System.Collections.Generic.List[PSCustomObject]]::new() + +foreach ($row in $data) { + $key = Get-AddressKey $row + + $expectedED = "" + $lookupError = "" + $geoScore = "" + $geoFullAddr = "" + $matchResult = "SKIPPED" + + if ($addressLookup.Contains($key)) { + $lookup = $addressLookup[$key] + $expectedED = if ($lookup.ExpectedED) { $lookup.ExpectedED } else { "" } + $lookupError = if ($lookup.Error) { $lookup.Error } else { "" } + $geoScore = if ($lookup.Score -ne $null) { $lookup.Score } else { "" } + $geoFullAddr = if ($lookup.FullAddress) { $lookup.FullAddress } else { "" } + + if ($expectedED -and $row.ApplicantElectoralDistrict) { + if ($expectedED.Trim() -eq $row.ApplicantElectoralDistrict.Trim()) { + $matchResult = "MATCH" + } + else { + $matchResult = "MISMATCH" + } + } + else { + $matchResult = "UNKNOWN" + } + } + + $outRow = [ordered]@{} + foreach ($prop in $row.PSObject.Properties) { + $outRow[$prop.Name] = $prop.Value + } + $outRow["AddressTypeName"] = Get-AddressTypeName $row.AddressType + $outRow["ExpectedElectoralDistrict"] = $expectedED + $outRow["DistrictMatch"] = $matchResult + $outRow["GeocoderScore"] = $geoScore + $outRow["GeocoderFullAddress"] = $geoFullAddr + $outRow["LookupError"] = $lookupError + + $output.Add([PSCustomObject]$outRow) +} + +$output | Export-Csv -Path $OutputCsv -NoTypeInformation -Encoding UTF8 + +# ── Summary ─────────────────────────────────────────────────────────── +$matchCount = @($output | Where-Object { $_.DistrictMatch -eq "MATCH" }).Count +$mismatchCount = @($output | Where-Object { $_.DistrictMatch -eq "MISMATCH" }).Count +$unknownCount = @($output | Where-Object { $_.DistrictMatch -eq "UNKNOWN" }).Count +$skippedRows = @($output | Where-Object { $_.DistrictMatch -eq "SKIPPED" }).Count + +Write-Host "" +Write-Host "=============================" -ForegroundColor White +Write-Host " Electoral District Audit" -ForegroundColor White +Write-Host "=============================" -ForegroundColor White +Write-Host "Total rows: $($data.Count)" +Write-Host "Unique addresses: $uniqueCount" +Write-Host "API errors: $errorCount" -ForegroundColor $(if ($errorCount -gt 0) { "Red" } else { "Green" }) +Write-Host "-----------------------------" +Write-Host "MATCH: $matchCount" -ForegroundColor Green +Write-Host "MISMATCH: $mismatchCount" -ForegroundColor $(if ($mismatchCount -gt 0) { "Red" } else { "Green" }) +Write-Host "UNKNOWN: $unknownCount" -ForegroundColor Yellow +Write-Host "SKIPPED: $skippedRows" -ForegroundColor DarkGray +Write-Host "-----------------------------" +Write-Host "Output: $OutputCsv" -ForegroundColor White diff --git a/applications/Unity.GrantManager/sonar-project.properties b/applications/Unity.GrantManager/sonar-project.properties new file mode 100644 index 0000000000..358970de64 --- /dev/null +++ b/applications/Unity.GrantManager/sonar-project.properties @@ -0,0 +1,30 @@ +# SonarCloud configuration for Unity Grant Manager +sonar.projectKey=bcgov_Unity +sonar.organization=bcgov-sonarcloud +sonar.host.url=https://sonarcloud.io + +# Project metadata +sonar.projectName=Unity +sonar.projectDescription=Grant management application for the Province of British Columbia + +# Source code settings +sonar.sources=src,modules +sonar.tests=test + +# Quality gate settings (from Azure SonarQube) +sonar.qualitygate.wait=true + +# SonarQube Exclusions (from existing Azure configuration) +sonar.exclusions=src/Unity.GrantManager.EntityFrameworkCore/Migrations/**,modules/Unity.Payments/src/Unity.Payments.Web/Pages/BatchPayments/Index.js,**/bin/**,**/obj/**,**/wwwroot/lib/**,**/*.Designer.cs,**/node_modules/** + +# Test exclusions +sonar.test.exclusions=**/bin/**,**/obj/** + +# Coverage analysis explicitly disabled (excludes all files from coverage) +sonar.coverage.exclusions=**/* + +# Code duplication exclusions (from existing Azure configuration + all files) +sonar.cpd.exclusions=**/*.aspx,**/*.aspx.designer.cs,**/*.cshtml,**/*.html,**/*.js,**/* + +# SCM settings +sonar.scm.provider=git \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationAnalysisRecommendation.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationAnalysisRecommendation.cs deleted file mode 100644 index c84a3d4793..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/Models/ApplicationAnalysisRecommendation.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Unity.GrantManager.AI.Models -{ - public class ApplicationAnalysisRecommendation - { - [JsonPropertyName(AIJsonKeys.Decision)] - public string? Decision { get; set; } - - [JsonPropertyName(AIJsonKeys.Rationale)] - public string? Rationale { get; set; } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/IApplicantProfileContactService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/IApplicantProfileContactService.cs index 3db1d7dcd6..779b4f7148 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/IApplicantProfileContactService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/IApplicantProfileContactService.cs @@ -14,11 +14,14 @@ namespace Unity.GrantManager.ApplicantProfile; public interface IApplicantProfileContactService { /// - /// Retrieves contacts linked to the specified applicant profile. - /// - /// The unique identifier of the applicant profile. - /// A list of with IsEditable set to true. - Task> GetProfileContactsAsync(Guid profileId); + /// Retrieves contacts linked to the applicant profile by resolving applicant IDs from + /// form submissions that match the given OIDC subject. When the subject resolves to a + /// single applicant ID the returned contacts are editable; when multiple applicant IDs + /// are found they are read-only. + /// + /// The pre-normalized OIDC subject identifier used to resolve applicant IDs from submissions. + /// A list of with IsEditable reflecting the applicant-count rule. + Task> GetApplicantContactsAsync(string subject); /// /// Retrieves application contacts associated with submissions matching the given OIDC subject. diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/ContactInfoItemDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/ContactInfoItemDto.cs index 112eed817b..ac0ec9b771 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/ContactInfoItemDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/ContactInfoItemDto.cs @@ -18,5 +18,6 @@ public class ContactInfoItemDto public bool IsEditable { get; set; } public Guid? ApplicationId { get; set; } public string? ReferenceNo { get; set; } + public DateTime? CreationTime { get; set; } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs index f5ef23aac4..4de11bf387 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/ProfileData/OrgInfoItemDto.cs @@ -5,6 +5,8 @@ namespace Unity.GrantManager.ApplicantProfile.ProfileData public class OrgInfoItemDto { public Guid Id { get; set; } + public string? ApplicantRefId { get; set; } + public string? ApplicantName { get; set; } public string? OrgName { get; set; } public string? OrganizationType { get; set; } public string? OrgNumber { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantTenantDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantTenantDto.cs index 9794ad422a..e9e5b5c24a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantTenantDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantTenantDto.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Unity.GrantManager.Applicants { @@ -6,5 +7,6 @@ public class ApplicantTenantDto { public Guid TenantId { get; set; } public string TenantName { get; set; } = string.Empty; + public Dictionary Metadata { get; set; } = []; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantTenantMetadataKeys.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantTenantMetadataKeys.cs new file mode 100644 index 0000000000..e8b08e9fdd --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Applicants/ApplicantTenantMetadataKeys.cs @@ -0,0 +1,11 @@ +namespace Unity.GrantManager.Applicants +{ + /// + /// Well-known keys for the dictionary. + /// Shared with external consumers (e.g. Applicant Portal plugins). + /// + public static class ApplicantTenantMetadataKeys + { + public const string DefaultFromAddress = "DefaultFromAddress"; + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/AIConfigDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/AIConfigDto.cs new file mode 100644 index 0000000000..5389b7a5b5 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/AIConfigDto.cs @@ -0,0 +1,8 @@ +namespace Unity.GrantManager.ApplicationForms +{ + public class AIConfigDto + { + public bool AutomaticallyGenerateAIAnalysis { get; set; } + public bool ManuallyInitiateAIAnalysis { get; set; } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs index 4e70a8880c..0351e6aecb 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/ApplicationFormDto.cs @@ -24,12 +24,14 @@ public class ApplicationFormDto : EntityDto public bool PreventPayment { get; set; } public Guid AccountCodingId { get; set; } public bool RenderFormIoToHtml { get; set; } - public Guid? ScoresheetId { get; set; } - public Guid? TenantId { get; set; } - public bool IsDirectApproval { get; set; } - public AddressType? ElectoralDistrictAddressType { get; set; } - public string? Prefix { get; set; } - public SuffixConfigType? SuffixType { get; set; } - public int? DefaultPaymentGroup { get; set; } - } -} + public Guid? ScoresheetId { get; set; } + public Guid? TenantId { get; set; } + public bool IsDirectApproval { get; set; } + public bool AutomaticallyGenerateAIAnalysis { get; set; } + public bool ManuallyInitiateAIAnalysis { get; set; } + public AddressType? ElectoralDistrictAddressType { get; set; } + public string? Prefix { get; set; } + public SuffixConfigType? SuffixType { get; set; } + public int? DefaultPaymentGroup { get; set; } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs index 425ca81bdf..5de7519628 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicationForms/IApplicationFormAppService.cs @@ -18,6 +18,7 @@ public interface IApplicationFormAppService : ICrudAppService< Task> GetVersionsAsync(Guid id); Task> GetPublishedVersionsAsync(Guid id); Task PatchOtherConfig(Guid id, OtherConfigDto config); + Task PatchAiConfig(Guid id, AIConfigDto config); Task GetFormPaymentApprovalThresholdByApplicationIdAsync(Guid applicationId); Task GetFormPreventPaymentStatusByApplicationId(Guid applicationId); Task GetFormDetailsByApplicationIdAsync(Guid applicationId); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentAppService.cs index 1b638f3bc3..f41512c411 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentAppService.cs @@ -9,6 +9,7 @@ public interface IAttachmentAppService : IApplicationService { Task> GetApplicationAsync(Guid applicationId); Task> GetAssessmentAsync(Guid assessmentId); + Task> GetApplicantAsync(Guid applicantId); Task ResyncSubmissionAttachmentsAsync(Guid applicationId); Task> GetAttachmentsAsync(AttachmentParametersDto attachmentParametersDto); Task GetAttachmentMetadataAsync(AttachmentType attachmentType, Guid attachmentId); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentPreviewAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentPreviewAppService.cs new file mode 100644 index 0000000000..120b434209 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentPreviewAppService.cs @@ -0,0 +1,11 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace Unity.GrantManager.Attachments; + +public interface IAttachmentPreviewAppService : IApplicationService +{ + Task GetOrCreatePreviewPdfAsync(AttachmentType attachmentType, Guid ownerId, string fileName); + Task GetOrCreateChefsPreviewPdfAsync(Guid formSubmissionId, Guid chefsFileId, string fileName, byte[] originalContent); +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentSummaryAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentSummaryAppService.cs deleted file mode 100644 index 65589ed840..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/IAttachmentSummaryAppService.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.Application.Services; - -namespace Unity.GrantManager.Attachments; - -public interface IAttachmentSummaryAppService : IApplicationService -{ - Task GenerateAttachmentSummaryAsync(Guid attachmentId, string? promptVersion = null); - Task> GenerateAttachmentSummariesAsync(List attachmentIds, string? promptVersion = null); -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/ILibreOfficeConversionService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/ILibreOfficeConversionService.cs new file mode 100644 index 0000000000..7ecc034769 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Attachments/ILibreOfficeConversionService.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Unity.GrantManager.Attachments; + +public interface ILibreOfficeConversionService +{ + bool IsInstalled(); + Task ConvertToPdfAsync(byte[] fileContent, string fileName); +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateApplicationAnalysisBackgroundJobArgs.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisBackgroundJobArgs.cs similarity index 73% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateApplicationAnalysisBackgroundJobArgs.cs rename to applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisBackgroundJobArgs.cs index 7829f8028b..d1f71301fa 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateApplicationAnalysisBackgroundJobArgs.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisBackgroundJobArgs.cs @@ -1,10 +1,8 @@ using System; - -namespace Unity.GrantManager.AI.BackgroundJobs; - +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; public class GenerateApplicationAnalysisBackgroundJobArgs { public Guid ApplicationId { get; set; } - public string? PromptVersion { get; set; } public Guid? TenantId { get; set; } -} + public string? PromptVersion { get; set; } +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateApplicationScoringBackgroundJobArgs.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringBackgroundJobArgs.cs similarity index 73% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateApplicationScoringBackgroundJobArgs.cs rename to applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringBackgroundJobArgs.cs index 234f8ec706..06b0d0cd97 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateApplicationScoringBackgroundJobArgs.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringBackgroundJobArgs.cs @@ -1,10 +1,8 @@ using System; - -namespace Unity.GrantManager.AI.BackgroundJobs; - +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; public class GenerateApplicationScoringBackgroundJobArgs { public Guid ApplicationId { get; set; } - public string? PromptVersion { get; set; } public Guid? TenantId { get; set; } -} + public string? PromptVersion { get; set; } +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateAttachmentSummaryBackgroundJobArgs.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryBackgroundJobArgs.cs similarity index 76% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateAttachmentSummaryBackgroundJobArgs.cs rename to applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryBackgroundJobArgs.cs index 7836e5abe3..bf87e59783 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateAttachmentSummaryBackgroundJobArgs.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryBackgroundJobArgs.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; - -namespace Unity.GrantManager.AI.BackgroundJobs; - +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; public class GenerateAttachmentSummaryBackgroundJobArgs { public List AttachmentIds { get; set; } = []; - public string? PromptVersion { get; set; } public Guid? TenantId { get; set; } -} + public string? PromptVersion { get; set; } +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateContentBackgroundJobArgs.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJobArgs.cs similarity index 55% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateContentBackgroundJobArgs.cs rename to applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJobArgs.cs index d320bf8316..9cfc51304c 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/AI/BackgroundJobs/GenerateContentBackgroundJobArgs.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJobArgs.cs @@ -1,10 +1,8 @@ using System; - -namespace Unity.GrantManager.AI.BackgroundJobs; - -public class GenerateContentBackgroundJobArgs +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; +public class RunApplicationAIPipelineJobArgs { public Guid ApplicationId { get; set; } - public string? PromptVersion { get; set; } public Guid? TenantId { get; set; } + public string? PromptVersion { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs index 1dda8c6696..e1883fbe35 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationDto.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Unity.GrantManager.AI.Responses; +using Unity.AI.Responses; using Unity.GrantManager.ApplicationForms; using Volo.Abp.Application.Dtos; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationLiteDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationLiteDto.cs index 9a4381db84..0d9267bc8c 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationLiteDto.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/GrantApplicationLiteDto.cs @@ -10,4 +10,5 @@ public class GrantApplicationLiteDto : AuditedEntityDto public string ApplicantName { get; set; } = string.Empty; public string OrganizationName { get; set; } = string.Empty; public string UnityApplicantId { get; set; } = string.Empty; + public string UnityApplicationId { get; set; } = string.Empty; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationStatusService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationStatusService.cs index b28cb95405..fb8dafc378 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationStatusService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IApplicationStatusService.cs @@ -7,4 +7,6 @@ namespace Unity.GrantManager.GrantApplications; public interface IApplicationStatusService : IApplicationService { Task> GetListAsync(); + + Task UpdateExternalStatusLabelsAsync(UpdateApplicationStatusExternalLabelsDto input); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs index 2491deb1c9..953a10a65d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/IGrantApplicationAppService.cs @@ -19,8 +19,8 @@ public interface IGrantApplicationAppService Task GetAsync(Guid id); Task TriggerAction(Guid applicationId, GrantApplicationAction triggerAction); Task GetAccountCodingIdFromFormIdAsync(Guid formId); - Task HideAIAnalysisItemAsync(Guid applicationId, string itemId); - Task ShowAIAnalysisItemAsync(Guid applicationId, string itemId); + Task DismissAIAnalysisItemAsync(Guid applicationId, string itemId); + Task RestoreAIAnalysisItemAsync(Guid applicationId, string itemId); Task> GetListAsync(GrantApplicationListInputDto input); Task IsApplicantRedStopAsync(Guid applicationId); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicationStatusExternalLabelDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicationStatusExternalLabelDto.cs new file mode 100644 index 0000000000..28cb19e244 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicationStatusExternalLabelDto.cs @@ -0,0 +1,14 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Unity.GrantManager.GrantApplications; + +public class UpdateApplicationStatusExternalLabelDto +{ + [Required] + public Guid Id { get; set; } + + [Required] + [StringLength(ApplicationStatusConsts.MaxNameLength, MinimumLength = 1)] + public string ExternalStatus { get; set; } = string.Empty; +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicationStatusExternalLabelsDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicationStatusExternalLabelsDto.cs new file mode 100644 index 0000000000..a622b32d6a --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/GrantApplications/UpdateApplicationStatusExternalLabelsDto.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Unity.GrantManager.GrantApplications; + +public class UpdateApplicationStatusExternalLabelsDto +{ + [Required] + public List Statuses { get; set; } = []; +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Identity/IUserTenantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Identity/IUserTenantAppService.cs index 668421df6b..5ac06a0aa1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Identity/IUserTenantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Identity/IUserTenantAppService.cs @@ -8,5 +8,6 @@ public interface IUserTenantAppService : IApplicationService { Task GetUserAdminAccountAsync(string oidcSub); Task> GetUserTenantsAsync(string oidcSub); + Task> GetListAsync(); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/GetSubmissionsListInput.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/GetSubmissionsListInput.cs new file mode 100644 index 0000000000..723c0cd41e --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/GetSubmissionsListInput.cs @@ -0,0 +1,15 @@ +using System; + +namespace Unity.GrantManager.Intakes; + +[Serializable] +public class GetSubmissionsListInput +{ + public bool ReturnAllSubmissions { get; set; } = true; + + public string? TenantName { get; set; } + + public DateTime? DateFrom { get; set; } + + public DateTime? DateTo { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs index 8962ab097e..618cf756ac 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Intakes/ISubmissionAppService.cs @@ -14,10 +14,9 @@ public interface ISubmissionAppService : IApplicationService /// /// List submissions for a form /// - /// ID of the form - /// A list of form fields to search on. Refer to the related `versions/{formVersionId}/fields` endpoint for a list of valid values to query for. The list should be comma separated. + /// Filter parameters including tenant, date range, and whether to include all submissions. /// List<FormSubmissionSummary> - Task> GetSubmissionsList(bool allSubmissions); + Task> GetSubmissionsListAsync(GetSubmissionsListInput input); /// /// Get a form submission diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Unity.GrantManager.Application.Contracts.csproj b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Unity.GrantManager.Application.Contracts.csproj index 4f76fb8d6a..7df55afd60 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Unity.GrantManager.Application.Contracts.csproj +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/Unity.GrantManager.Application.Contracts.csproj @@ -1,35 +1,32 @@ - - + - net9.0 enable Unity.GrantManager - + - - + + - - - - + + + + - - **/Assessments/AssessmentListItemDto.cs, **/Assessments/AssessmentScoresDto.cs - + + **/Assessments/AssessmentListItemDto.cs, **/Assessments/AssessmentScoresDto.cs + - - + \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateApplicationAnalysisBackgroundJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateApplicationAnalysisBackgroundJob.cs deleted file mode 100644 index e9bd6ee84b..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateApplicationAnalysisBackgroundJob.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; -using Unity.GrantManager.AI.Operations; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.DependencyInjection; -using Volo.Abp.MultiTenancy; - -namespace Unity.GrantManager.AI.BackgroundJobs; - -public class GenerateApplicationAnalysisBackgroundJob( - IApplicationAnalysisService applicationAnalysisService, - ICurrentTenant currentTenant, - ILogger logger) : AsyncBackgroundJob, ITransientDependency -{ - public override async Task ExecuteAsync(GenerateApplicationAnalysisBackgroundJobArgs args) - { - using (currentTenant.Change(args.TenantId)) - { - logger.LogInformation("Executing AI application analysis background job for application {ApplicationId}.", args.ApplicationId); - await applicationAnalysisService.RegenerateAndSaveAsync(args.ApplicationId, args.PromptVersion); - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateApplicationScoringBackgroundJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateApplicationScoringBackgroundJob.cs deleted file mode 100644 index a445993a68..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateApplicationScoringBackgroundJob.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using Unity.GrantManager.AI.Operations; -using Unity.GrantManager.Intakes.Events; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus.Local; -using Volo.Abp.MultiTenancy; - -namespace Unity.GrantManager.AI.BackgroundJobs; - -public class GenerateApplicationScoringBackgroundJob( - IApplicationScoringService applicationScoringService, - ILocalEventBus localEventBus, - ICurrentTenant currentTenant, - ILogger logger) : AsyncBackgroundJob, ITransientDependency -{ - public override async Task ExecuteAsync(GenerateApplicationScoringBackgroundJobArgs args) - { - using (currentTenant.Change(args.TenantId)) - { - logger.LogInformation("Executing AI application scoring background job for application {ApplicationId}.", args.ApplicationId); - - var result = await applicationScoringService.RegenerateAndSaveAsync(args.ApplicationId, args.PromptVersion); - if (!string.Equals(result, "{}", StringComparison.Ordinal)) - { - await localEventBus.PublishAsync(new AIApplicationScoringGeneratedEvent - { - ApplicationId = args.ApplicationId - }); - } - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateAttachmentSummaryBackgroundJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateAttachmentSummaryBackgroundJob.cs deleted file mode 100644 index ed6a1ebd91..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateAttachmentSummaryBackgroundJob.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; -using Unity.GrantManager.AI.Operations; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.DependencyInjection; -using Volo.Abp.MultiTenancy; - -namespace Unity.GrantManager.AI.BackgroundJobs; - -public class GenerateAttachmentSummaryBackgroundJob( - IAttachmentSummaryService attachmentSummaryService, - ICurrentTenant currentTenant, - ILogger logger) : AsyncBackgroundJob, ITransientDependency -{ - public override async Task ExecuteAsync(GenerateAttachmentSummaryBackgroundJobArgs args) - { - using (currentTenant.Change(args.TenantId)) - { - logger.LogInformation( - "Executing AI attachment summary background job for {AttachmentCount} attachment(s).", - args.AttachmentIds.Count); - - await attachmentSummaryService.GenerateAndSaveAsync(args.AttachmentIds, args.PromptVersion); - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/OpenAIRuntimeService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/OpenAIRuntimeService.cs deleted file mode 100644 index 6335c3b765..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/Runtime/OpenAIRuntimeService.cs +++ /dev/null @@ -1,1488 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; -using Unity.GrantManager.AI.Extraction; -using Unity.GrantManager.AI.Models; -using Unity.GrantManager.AI.Prompts; -using Unity.GrantManager.AI.Requests; -using Unity.GrantManager.AI.Responses; -using Volo.Abp.DependencyInjection; -using Volo.Abp.MultiTenancy; - -namespace Unity.GrantManager.AI.Runtime -{ - [ExposeServices(typeof(IAIService))] - public class OpenAIRuntimeService : IAIService, ITransientDependency - { - private readonly HttpClient _httpClient; - private readonly IConfiguration _configuration; - private readonly ILogger _logger; - private readonly ITextExtractionService _textExtractionService; - private readonly ICurrentTenant _currentTenant; - private readonly IHostEnvironment _hostEnvironment; - private const string ApplicationAnalysisPromptType = AIPromptTypes.ApplicationAnalysis; - private const string AttachmentSummaryPromptType = AIPromptTypes.AttachmentSummary; - private const string ApplicationScoringPromptType = AIPromptTypes.ApplicationScoring; - private const string PromptVersionV0 = "v0"; - private const string PromptVersionV1 = "v1"; - private static readonly string PromptTemplatesFolder = Path.Combine("AI", "Prompts", "Versions"); - private const string ApplicationAnalysisSystemTemplateName = "application-analysis.system"; - private const string ApplicationAnalysisUserTemplateName = "application-analysis.user"; - private const string AttachmentSummarySystemTemplateName = "attachment-summary.system"; - private const string AttachmentSummaryUserTemplateName = "attachment-summary.user"; - private const string ApplicationScoringSystemTemplateName = "application-scoring.system"; - private const string ApplicationScoringUserTemplateName = "application-scoring.user"; - private const string AIServiceNotConfiguredMessage = "AI service not available - service not configured."; - private const string AIServiceTemporarilyUnavailableMessage = "AI request failed - service temporarily unavailable."; - private const string AIRequestFailedRetryMessage = "AI request failed - please try again later."; - private const int MaxAiAttempts = 3; - private const string DefaultMaxTokensParameterName = "max_completion_tokens"; - private const string LegacyMaxTokensParameterName = "max_tokens"; - private const string DefaultProviderName = "OpenAI"; - private const int DefaultCompletionTokens = 2000; - private const int DefaultAttachmentSummaryCompletionTokens = 2000; - private const int DefaultApplicationAnalysisCompletionTokens = 4000; - private const int DefaultApplicationScoringCompletionTokens = 8000; - - private int AttachmentSummaryCompletionTokens => ResolveCompletionTokens(AttachmentSummaryPromptType, DefaultAttachmentSummaryCompletionTokens); - private int ApplicationAnalysisCompletionTokens => ResolveCompletionTokens(ApplicationAnalysisPromptType, DefaultApplicationAnalysisCompletionTokens); - private int ApplicationScoringCompletionTokens => ResolveCompletionTokens(ApplicationScoringPromptType, DefaultApplicationScoringCompletionTokens); - private readonly string MissingApiKeyMessage = "OpenAI API key is not configured"; - - // Optional local debugging sink for prompt payload logs to a local file. - // Not intended for deployed/shared environments. - private bool IsPromptFileLoggingEnabled => _configuration.GetValue("Azure:Logging:EnablePromptFileLog") ?? false; - private const string PromptLogDirectoryName = "logs"; - private static readonly string PromptLogFileName = $"ai-prompts-{DateTime.UtcNow:yyyyMMdd-HHmmss}-{Environment.ProcessId}.log"; - - private static readonly JsonSerializerOptions JsonLogOptions = new() { WriteIndented = true }; - - private static readonly Dictionary PromptProfiles = - new Dictionary(StringComparer.OrdinalIgnoreCase) - { - [PromptVersionV0] = PromptVersionV0, - [PromptVersionV1] = PromptVersionV1 - }; - private static readonly ConcurrentDictionary PromptTemplateCache = new(StringComparer.OrdinalIgnoreCase); - - public OpenAIRuntimeService( - HttpClient httpClient, - IConfiguration configuration, - ILogger logger, - ITextExtractionService textExtractionService, - ICurrentTenant currentTenant, - IHostEnvironment hostEnvironment) - { - _httpClient = httpClient; - _configuration = configuration; - _logger = logger; - _textExtractionService = textExtractionService; - _currentTenant = currentTenant; - _hostEnvironment = hostEnvironment; - } - - public Task IsAvailableAsync() - { - if (string.IsNullOrEmpty(ResolveApiKey())) - { - _logger.LogWarning("Error: {Message}", MissingApiKeyMessage); - return Task.FromResult(false); - } - - return Task.FromResult(true); - } - - public async Task GenerateCompletionAsync(AICompletionRequest request) - { - var result = await GenerateWithRetryAsync( - () => GenerateSummaryAsync( - request?.UserPrompt ?? string.Empty, - null, - request?.MaxTokens ?? DefaultCompletionTokens, - request?.Temperature), - AIProviderPayloadValidator.IsValidAttachmentSummaryText, - "completion"); - return new AICompletionResponse { Content = ResolveNarrativeContent(result) }; - } - - public async Task GenerateApplicationAnalysisAsync(ApplicationAnalysisRequest request) - { - ArgumentNullException.ThrowIfNull(request); - var promptVersion = ResolvePromptVersion(request.PromptVersion ?? ResolvePromptVersionSetting(ApplicationAnalysisPromptType)); - var data = JsonSerializer.Serialize(request.Data, JsonLogOptions); - var schema = JsonSerializer.Serialize(request.Schema, JsonLogOptions); - - var attachmentsPayload = request.Attachments - .Select(a => new - { - name = string.IsNullOrWhiteSpace(a.Name) ? "attachment" : a.Name.Trim(), - summary = string.IsNullOrWhiteSpace(a.Summary) ? string.Empty : a.Summary.Trim() - }) - .Cast(); - - var attachments = JsonSerializer.Serialize(attachmentsPayload, JsonLogOptions); - var systemPrompt = BuildApplicationAnalysisSystemPrompt(promptVersion); - var applicationAnalysisContent = BuildApplicationAnalysisUserPrompt( - promptVersion, - schema, - data, - attachments); - await LogPromptInputAsync(ApplicationAnalysisPromptType, promptVersion, systemPrompt, applicationAnalysisContent); - var result = await GenerateWithRetryAsync( - () => GenerateSummaryAsync( - applicationAnalysisContent, - systemPrompt, - ApplicationAnalysisCompletionTokens, - operationName: ApplicationAnalysisPromptType, - promptVersion: promptVersion), - AIProviderPayloadValidator.IsValidApplicationAnalysisJson, - "application analysis"); - await LogPromptOutputAsync(ApplicationAnalysisPromptType, promptVersion, result.CaptureOutput); - - if (result.Outcome != AIOperationOutcome.Success) - { - return new ApplicationAnalysisResponse(); - } - - return ParseApplicationAnalysisResponse(AddIdsToAnalysisItems(result.Content)); - } - - private async Task GenerateSummaryAsync( - string content, - string? systemPrompt, - int maxTokens = 150, - double? temperature = null, - string? operationName = null, - string? promptVersion = null, - string? fileName = null) - { - var providerName = ResolveProviderName(operationName); - if (!string.Equals(providerName, DefaultProviderName, StringComparison.Ordinal)) - { - _logger.LogWarning("Provider {ProviderName} is not supported by OpenAIRuntimeService.", providerName); - return AIOperationResult.PermanentFailure(new AIProviderResult($"Unsupported provider: {providerName}")); - } - - var apiKey = ResolveApiKey(operationName); - if (string.IsNullOrEmpty(apiKey)) - { - _logger.LogWarning("Error: {Message}", MissingApiKeyMessage); - return AIOperationResult.PermanentFailure(new AIProviderResult(MissingApiKeyMessage)); - } - - _logger.LogDebug("Calling OpenAI chat completions. PromptLength: {PromptLength}, MaxTokens: {MaxTokens}", content?.Length ?? 0, maxTokens); - - try - { - var resolvedSystemPrompt = string.IsNullOrWhiteSpace(systemPrompt) - ? "You are a professional grant analyst for the BC Government." - : systemPrompt; - var userPrompt = content ?? string.Empty; - - var requestBody = new - { - messages = new[] - { - new { role = "system", content = resolvedSystemPrompt }, - new { role = "user", content = userPrompt } - } - }; - - var requestPayload = new Dictionary - { - ["messages"] = requestBody.messages, - [ResolveMaxTokensParameterNameForOperation(operationName)] = maxTokens - }; - - var resolvedTemperature = temperature ?? ResolveConfiguredTemperature(operationName); - if (resolvedTemperature.HasValue) - { - requestPayload["temperature"] = resolvedTemperature.Value; - } - - var json = JsonSerializer.Serialize(requestPayload); - var httpContent = new StringContent(json, Encoding.UTF8, "application/json"); - - _httpClient.DefaultRequestHeaders.Clear(); - _httpClient.DefaultRequestHeaders.Add("Authorization", apiKey); - - var response = await _httpClient.PostAsync(ResolveApiUrl(operationName), httpContent); - var responseContent = await response.Content.ReadAsStringAsync(); - var metadata = TryExtractProviderMetadata(responseContent); - var providerResponse = BuildProviderResponseFromMetadata( - string.Empty, - responseContent, - metadata, - (int)response.StatusCode); - - _logger.LogDebug( - "OpenAI chat completions response received. StatusCode: {StatusCode}, ResponseLength: {ResponseLength}", - response.StatusCode, - responseContent?.Length ?? 0); - LogProviderMetadata(operationName, promptVersion, fileName, providerResponse, response.IsSuccessStatusCode); - - if (!response.IsSuccessStatusCode) - { - _logger.LogError("OpenAI API request failed: {StatusCode} - {Content}", response.StatusCode, responseContent); - return MapFailureOutcome(response.StatusCode, providerResponse); - } - - if (string.IsNullOrWhiteSpace(responseContent)) - { - return AIOperationResult.InvalidOutput(providerResponse); - } - - try - { - using var jsonDoc = JsonDocument.Parse(responseContent); - var choices = jsonDoc.RootElement.GetProperty("choices"); - if (choices.GetArrayLength() > 0) - { - var message = choices[0].GetProperty("message"); - var modelOutput = message.GetProperty("content").GetString(); - return string.IsNullOrWhiteSpace(modelOutput) - ? AIOperationResult.InvalidOutput(providerResponse) - : AIOperationResult.Success(BuildProviderResponseFromMetadata( - modelOutput, - responseContent, - metadata, - (int)response.StatusCode)); - } - - return AIOperationResult.InvalidOutput(providerResponse); - } - catch (Exception ex) when (ex is JsonException || ex is KeyNotFoundException || ex is InvalidOperationException) - { - _logger.LogWarning(ex, "AI response payload had an invalid output shape"); - return AIOperationResult.InvalidOutput(providerResponse); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error generating AI summary"); - return AIOperationResult.TransientFailure(new AIProviderResult(ex.Message)); - } - } - - public async Task GenerateAttachmentSummaryAsync(AttachmentSummaryRequest request) - { - ArgumentNullException.ThrowIfNull(request); - var fileName = request.FileName ?? string.Empty; - var fileContent = request.FileContent ?? Array.Empty(); - var contentType = request.ContentType ?? "application/octet-stream"; - var promptVersion = ResolvePromptVersion(request.PromptVersion ?? ResolvePromptVersionSetting(AttachmentSummaryPromptType)); - - try - { - var extractedText = await _textExtractionService.ExtractTextAsync(fileName, fileContent, contentType); - var prompt = BuildAttachmentSummarySystemPrompt(promptVersion); - - var attachmentText = string.IsNullOrWhiteSpace(extractedText) ? null : extractedText; - if (attachmentText != null) - { - _logger.LogDebug("Extracted {TextLength} characters from {FileName}", extractedText.Length, fileName); - } - else - { - _logger.LogDebug("No text extracted from {FileName}, analyzing metadata only", fileName); - } - - var attachmentPayload = new - { - name = fileName, - contentType, - sizeBytes = fileContent.Length, - text = attachmentText - }; - var attachment = JsonSerializer.Serialize(attachmentPayload, JsonLogOptions); - var contentToAnalyze = BuildAttachmentSummaryUserPrompt(promptVersion, attachment); - - await LogPromptInputAsync(AttachmentSummaryPromptType, promptVersion, prompt, contentToAnalyze); - var result = await GenerateWithRetryAsync( - () => GenerateSummaryAsync( - contentToAnalyze, - prompt, - AttachmentSummaryCompletionTokens, - operationName: AttachmentSummaryPromptType, - promptVersion: promptVersion, - fileName: fileName), - AIProviderPayloadValidator.IsValidAttachmentSummaryText, - "attachment summary"); - await LogPromptOutputAsync(AttachmentSummaryPromptType, promptVersion, result.CaptureOutput); - - if (result.Outcome != AIOperationOutcome.Success) - { - return new AttachmentSummaryResponse - { - Summary = $"AI analysis not available for this attachment ({fileName})." - }; - } - - return new AttachmentSummaryResponse - { - Summary = ExtractSummaryFromJson(result.Content) - }; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error generating attachment summary for {FileName}", fileName); - return new AttachmentSummaryResponse - { - Summary = $"AI analysis not available for this attachment ({fileName})." - }; - } - } - - private string AddIdsToAnalysisItems(string analysisJson) - { - try - { - using var jsonDoc = JsonDocument.Parse(analysisJson); - using var memoryStream = new System.IO.MemoryStream(); - using (var writer = new Utf8JsonWriter(memoryStream, new JsonWriterOptions { Indented = true })) - { - writer.WriteStartObject(); - - foreach (var property in jsonDoc.RootElement.EnumerateObject()) - { - var outputPropertyName = property.Name; - - if (outputPropertyName == AIJsonKeys.Errors || - outputPropertyName == AIJsonKeys.Warnings || - outputPropertyName == AIJsonKeys.Summaries || - outputPropertyName == AIJsonKeys.NextSteps) - { - writer.WritePropertyName(outputPropertyName); - writer.WriteStartArray(); - - foreach (var item in property.Value.EnumerateArray()) - { - writer.WriteStartObject(); - - // Add unique ID first - writer.WriteString("id", Guid.NewGuid().ToString()); - writer.WriteBoolean(AIJsonKeys.Hidden, false); - - // Copy existing properties - foreach (var itemProperty in item.EnumerateObject()) - { - if (itemProperty.NameEquals(AIJsonKeys.Id) || itemProperty.NameEquals(AIJsonKeys.Hidden)) - { - continue; - } - - itemProperty.WriteTo(writer); - } - - writer.WriteEndObject(); - } - - writer.WriteEndArray(); - } - else - { - if (outputPropertyName != property.Name) - { - writer.WritePropertyName(outputPropertyName); - property.Value.WriteTo(writer); - continue; - } - - property.WriteTo(writer); - } - } - - writer.WriteEndObject(); - } - - return Encoding.UTF8.GetString(memoryStream.ToArray()); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error adding IDs to analysis items, returning original JSON"); - return analysisJson; // Return original if processing fails - } - } - - public async Task GenerateApplicationScoringAsync(ApplicationScoringRequest request) - { - ArgumentNullException.ThrowIfNull(request); - var promptVersion = ResolvePromptVersion(request.PromptVersion ?? ResolvePromptVersionSetting(ApplicationScoringPromptType)); - var dataJson = JsonSerializer.Serialize(request.Data, JsonLogOptions); - var sectionJson = JsonSerializer.Serialize(request.SectionSchema, JsonLogOptions); - - var attachmentSummaries = request.Attachments - .Select(a => $"{a.Name}: {a.Summary}") - .ToList(); - if (string.IsNullOrEmpty(ResolveApiKey(ApplicationScoringPromptType))) - { - _logger.LogWarning("{Message}", MissingApiKeyMessage); - return new ApplicationScoringResponse(); - } - - try - { - var attachments = attachmentSummaries.Count > 0 - ? string.Join("\n- ", attachmentSummaries.Select((summary, index) => $"Attachment {index + 1}: {summary}")) - : "No attachments provided."; - - object sectionQuestionsPayload = sectionJson; - if (!string.IsNullOrWhiteSpace(sectionJson)) - { - try - { - using var sectionDoc = JsonDocument.Parse(sectionJson); - sectionQuestionsPayload = sectionDoc.RootElement.Clone(); - } - catch (JsonException) - { - // Keep raw string payload when JSON parsing fails. - } - } - - var sectionPayload = new - { - name = request.SectionName, - questions = sectionQuestionsPayload - }; - var section = JsonSerializer.Serialize(sectionPayload, JsonLogOptions); - var response = BuildApplicationScoringResponseTemplate(section); - if (response == "{}") - { - _logger.LogWarning( - "Skipping AI application scoring for section {SectionName} because response template could not be built from section schema.", - request.SectionName); - return new ApplicationScoringResponse(); - } - - var applicationScoringContent = BuildApplicationScoringUserPrompt( - promptVersion, - dataJson, - attachments, - section, - response); - var systemPrompt = BuildApplicationScoringSystemPrompt(promptVersion); - - await LogPromptInputAsync(ApplicationScoringPromptType, promptVersion, systemPrompt, applicationScoringContent); - var result = await GenerateWithRetryAsync( - () => GenerateSummaryAsync( - applicationScoringContent, - systemPrompt, - ApplicationScoringCompletionTokens, - operationName: ApplicationScoringPromptType, - promptVersion: promptVersion), - content => AIProviderPayloadValidator.IsValidApplicationScoringJson(content, sectionJson), - $"application scoring section {request.SectionName}"); - await LogPromptOutputAsync(ApplicationScoringPromptType, promptVersion, result.CaptureOutput); - - if (result.Outcome != AIOperationOutcome.Success) - { - return new ApplicationScoringResponse(); - } - - return ParseApplicationScoringResponse(result.Content); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error generating application scoring answers for section {SectionName}", request.SectionName); - return new ApplicationScoringResponse(); - } - } - - private async Task GenerateWithRetryAsync( - Func> operation, - Func validator, - string operationName) - { - var lastResult = AIOperationResult.InvalidOutput(); - - for (var attempt = 1; attempt <= MaxAiAttempts; attempt++) - { - lastResult = await operation(); - - if (lastResult.Outcome == AIOperationOutcome.Success && validator(lastResult.Content)) - { - return lastResult; - } - - if (lastResult.Outcome == AIOperationOutcome.Success) - { - lastResult = lastResult.WithOutcome(AIOperationOutcome.InvalidOutput); - } - - if (lastResult.Outcome == AIOperationOutcome.PermanentFailure) - { - return lastResult; - } - - if (attempt < MaxAiAttempts) - { - if (lastResult.Outcome == AIOperationOutcome.TransientFailure) - { - _logger.LogWarning( - "AI {OperationName} attempt {Attempt}/{MaxAttempts} failed transiently; retrying", - operationName, - attempt, - MaxAiAttempts); - } - else if (lastResult.Outcome == AIOperationOutcome.InvalidOutput) - { - _logger.LogWarning( - "AI {OperationName} attempt {Attempt}/{MaxAttempts} returned invalid response shape; retrying", - operationName, - attempt, - MaxAiAttempts); - } - } - } - - _logger.LogWarning( - "AI {OperationName} exhausted retries with outcome {Outcome}; returning last result", - operationName, - lastResult.Outcome); - return lastResult; - } - - private static string ResolveNarrativeContent(AIOperationResult result) - { - return result.Outcome switch - { - AIOperationOutcome.Success => result.Content, - AIOperationOutcome.PermanentFailure => AIServiceNotConfiguredMessage, - AIOperationOutcome.TransientFailure => AIServiceTemporarilyUnavailableMessage, - _ => AIRequestFailedRetryMessage - }; - } - - private static AIOperationResult MapFailureOutcome(HttpStatusCode statusCode, AIProviderResult response) - { - var statusCodeValue = (int)statusCode; - - if (statusCode == HttpStatusCode.RequestTimeout - || statusCode == (HttpStatusCode)429 - || statusCodeValue >= 500) - { - return AIOperationResult.TransientFailure(response); - } - - return AIOperationResult.PermanentFailure(response); - } - - private static AIProviderResult BuildProviderResponseFromMetadata( - string content, - string? rawResponse, - AIProviderResponseMetadata? metadata, - int? httpStatusCode = null) - { - return new AIProviderResult( - content, - rawResponse ?? string.Empty, - metadata?.Model, - metadata?.FinishReason, - httpStatusCode, - metadata?.PromptTokens, - metadata?.CompletionTokens, - metadata?.TotalTokens, - metadata?.ReasoningTokens); - } - - private static AIProviderResponseMetadata? TryExtractProviderMetadata(string? responseContent) - { - if (string.IsNullOrWhiteSpace(responseContent)) - { - return null; - } - - try - { - using var jsonDoc = JsonDocument.Parse(responseContent); - var root = jsonDoc.RootElement; - var model = root.TryGetProperty("model", out var modelProp) && modelProp.ValueKind == JsonValueKind.String - ? modelProp.GetString() - : null; - - string? finishReason = null; - if (root.TryGetProperty("choices", out var choices) - && choices.ValueKind == JsonValueKind.Array - && choices.GetArrayLength() > 0) - { - var firstChoice = choices[0]; - if (firstChoice.TryGetProperty("finish_reason", out var finishReasonProp) && finishReasonProp.ValueKind == JsonValueKind.String) - { - finishReason = finishReasonProp.GetString(); - } - } - - int? promptTokens = null; - int? completionTokens = null; - int? totalTokens = null; - int? reasoningTokens = null; - if (root.TryGetProperty("usage", out var usage) && usage.ValueKind == JsonValueKind.Object) - { - promptTokens = TryGetInt32(usage, "prompt_tokens"); - completionTokens = TryGetInt32(usage, "completion_tokens"); - totalTokens = TryGetInt32(usage, "total_tokens"); - - if (usage.TryGetProperty("completion_tokens_details", out var completionTokenDetails) - && completionTokenDetails.ValueKind == JsonValueKind.Object) - { - reasoningTokens = TryGetInt32(completionTokenDetails, "reasoning_tokens"); - } - } - - return new AIProviderResponseMetadata(model, finishReason, promptTokens, completionTokens, totalTokens, reasoningTokens); - } - catch (JsonException) - { - return null; - } - } - - private void LogProviderMetadata( - string? operationName, - string? promptVersion, - string? fileName, - AIProviderResult response, - bool success) - { - if (string.IsNullOrWhiteSpace(response.Model) - && string.IsNullOrWhiteSpace(response.FinishReason) - && response.HttpStatusCode == null - && response.PromptTokens == null - && response.CompletionTokens == null - && response.TotalTokens == null - && response.ReasoningTokens == null) - { - return; - } - - if (response.PromptTokens != null || response.CompletionTokens != null || response.TotalTokens != null) - { - _logger.LogInformation( - "AI token usage. OperationName={OperationName}, InputTokens={InputTokens}, CompletionTokens={CompletionTokens}, TotalTokens={TotalTokens}, Environment={Environment}, TenantId={TenantId}, Status={Status}, PromptVersion={PromptVersion}, Model={Model}, HttpStatusCode={HttpStatusCode}, FileName={FileName}", - operationName ?? "completion", - response.PromptTokens, - response.CompletionTokens, - response.TotalTokens, - _hostEnvironment.EnvironmentName, - _currentTenant.Id, - success ? "success" : "failed", - promptVersion, - response.Model, - response.HttpStatusCode, - fileName); - } - - _logger.LogDebug( - "AI provider response metadata for {OperationName}: Model={Model}, FinishReason={FinishReason}, HttpStatusCode={HttpStatusCode}, PromptTokens={PromptTokens}, CompletionTokens={CompletionTokens}, TotalTokens={TotalTokens}, ReasoningTokens={ReasoningTokens}", - operationName ?? "completion", - response.Model, - response.FinishReason, - response.HttpStatusCode, - response.PromptTokens, - response.CompletionTokens, - response.TotalTokens, - response.ReasoningTokens); - } - - private static int? TryGetInt32(JsonElement element, string propertyName) - { - return element.TryGetProperty(propertyName, out var property) - && property.ValueKind == JsonValueKind.Number - && property.TryGetInt32(out var value) - ? value - : null; - } - - private static string ResolveMaxTokensParameterName(string? configuredParameterName) - { - if (string.Equals(configuredParameterName, LegacyMaxTokensParameterName, StringComparison.Ordinal)) - { - return LegacyMaxTokensParameterName; - } - - return DefaultMaxTokensParameterName; - } - - private int ResolveCompletionTokens(string operationName, int defaultValue) - { - var configuredValue = _configuration.GetValue($"Azure:Operations:{operationName}:MaxCompletionTokens"); - if (configuredValue is > 0) - { - return configuredValue.Value; - } - - var defaultConfiguredValue = _configuration.GetValue("Azure:Operations:Defaults:MaxCompletionTokens"); - return defaultConfiguredValue is > 0 ? defaultConfiguredValue.Value : defaultValue; - } - - private string? ResolvePromptVersionSetting(string operationName) - { - var operationPromptVersion = _configuration[$"Azure:Operations:{operationName}:PromptVersion"]; - if (!string.IsNullOrWhiteSpace(operationPromptVersion)) - { - return operationPromptVersion; - } - - var defaultPromptVersion = _configuration["Azure:Operations:Defaults:PromptVersion"]; - if (!string.IsNullOrWhiteSpace(defaultPromptVersion)) - { - return defaultPromptVersion; - } - - return _configuration["Azure:OpenAI:PromptVersion"]; - } - - private string ResolveProviderName(string? operationName = null) - { - if (!string.IsNullOrWhiteSpace(operationName)) - { - var configuredProvider = _configuration[$"Azure:Operations:{operationName}:Provider"]; - if (!string.IsNullOrWhiteSpace(configuredProvider)) - { - return configuredProvider.Trim(); - } - } - - var defaultProvider = _configuration["Azure:Operations:Defaults:Provider"]; - return string.IsNullOrWhiteSpace(defaultProvider) ? DefaultProviderName : defaultProvider.Trim(); - } - - private string? ResolveApiKey(string? operationName = null) - { - var providerName = ResolveProviderName(operationName); - return _configuration[$"Azure:{providerName}:ApiKey"]; - } - - private string ResolveMaxTokensParameterNameForOperation(string? operationName = null) - { - var providerName = ResolveProviderName(operationName); - var profileName = ResolveProfileName(operationName); - var profileParameterName = ResolveProfileSetting(providerName, profileName, "MaxTokensParameter"); - return ResolveMaxTokensParameterName(profileParameterName); - } - - private double? ResolveConfiguredTemperature(string? operationName = null) - { - var providerName = ResolveProviderName(operationName); - var profileName = ResolveProfileName(operationName); - var profileTemperature = ResolveProfileSetting(providerName, profileName, "Temperature"); - if (profileTemperature != null - && double.TryParse(profileTemperature, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out var parsedTemperature)) - { - return parsedTemperature; - } - - return null; - } - - private string ResolveApiUrl(string? operationName) - { - var providerName = ResolveProviderName(operationName); - var profileName = ResolveProfileName(operationName); - var profileApiUrl = ResolveProfileSetting(providerName, profileName, "ApiUrl"); - var legacyOpenAiApiUrl = _configuration["Azure:OpenAI:ApiUrl"]; - - if (!string.IsNullOrWhiteSpace(profileApiUrl)) - { - return profileApiUrl; - } - - if (!string.IsNullOrWhiteSpace(legacyOpenAiApiUrl)) - { - return legacyOpenAiApiUrl; - } - - throw new InvalidOperationException($"AI API URL is not configured for provider '{providerName}'."); - } - - private string? ResolveProfileName(string? operationName) - { - if (!string.IsNullOrWhiteSpace(operationName)) - { - var operationProfile = _configuration[$"Azure:Operations:{operationName}:Profile"]; - if (!string.IsNullOrWhiteSpace(operationProfile)) - { - return operationProfile.Trim(); - } - } - - var defaultProfile = _configuration["Azure:Operations:Defaults:Profile"]; - return string.IsNullOrWhiteSpace(defaultProfile) ? null : defaultProfile.Trim(); - } - - private string? ResolveProfileSetting(string providerName, string? profileName, string settingName) - { - if (string.IsNullOrWhiteSpace(profileName)) - { - return null; - } - - var profileSetting = _configuration[$"Azure:{providerName}:Profiles:{profileName}:{settingName}"]; - return string.IsNullOrWhiteSpace(profileSetting) ? null : profileSetting; - } - - private static ApplicationAnalysisResponse ParseApplicationAnalysisResponse(string raw) - { - var response = new ApplicationAnalysisResponse(); - - if (!TryParseJsonObjectFromResponse(raw, out var root)) - { - return response; - } - - if (TryGetStringProperty(root, AIJsonKeys.Rating, out var rating)) - { - response.Rating = rating; - } - - if (root.TryGetProperty("errors", out var errors) && errors.ValueKind == JsonValueKind.Array) - { - response.Errors = ParseFindings(errors); - } - - if (root.TryGetProperty("warnings", out var warnings) && warnings.ValueKind == JsonValueKind.Array) - { - response.Warnings = ParseFindings(warnings); - } - - if (root.TryGetProperty(AIJsonKeys.Summaries, out var summaries) && summaries.ValueKind == JsonValueKind.Array) - { - response.Summaries = ParseFindings(summaries); - } - - if (root.TryGetProperty(AIJsonKeys.NextSteps, out var nextSteps) && nextSteps.ValueKind == JsonValueKind.Array) - { - response.NextSteps = ParseFindings(nextSteps); - } - - if (root.TryGetProperty(AIJsonKeys.Recommendation, out var recommendation) && recommendation.ValueKind == JsonValueKind.Object) - { - response.Recommendation = ParseRecommendation(recommendation); - } - - return response; - } - - private static bool TryGetStringProperty(JsonElement root, string propertyName, out string? value) - { - value = null; - if (!root.TryGetProperty(propertyName, out var property) || property.ValueKind != JsonValueKind.String) - { - return false; - } - - value = property.GetString(); - return !string.IsNullOrWhiteSpace(value); - } - - private static List ParseFindings(JsonElement array) - { - var findings = new List(); - foreach (var item in array.EnumerateArray()) - { - if (item.ValueKind != JsonValueKind.Object) - { - continue; - } - - var id = item.TryGetProperty(AIJsonKeys.Id, out var idProp) && idProp.ValueKind == JsonValueKind.String - ? idProp.GetString() - : null; - var hidden = item.TryGetProperty(AIJsonKeys.Hidden, out var hiddenProp) && - (hiddenProp.ValueKind == JsonValueKind.True || hiddenProp.ValueKind == JsonValueKind.False) && - hiddenProp.GetBoolean(); - string? title = null; - if (item.TryGetProperty(AIJsonKeys.Title, out var titleProp) && titleProp.ValueKind == JsonValueKind.String) - { - title = titleProp.GetString(); - } - - string? detail = null; - if (item.TryGetProperty(AIJsonKeys.Detail, out var detailProp) && detailProp.ValueKind == JsonValueKind.String) - { - detail = detailProp.GetString(); - } - - findings.Add(new ApplicationAnalysisFinding - { - Id = id, - Hidden = hidden, - Title = title, - Detail = detail - }); - } - - return findings; - } - - private static ApplicationAnalysisRecommendation? ParseRecommendation(JsonElement recommendation) - { - string? decision = null; - if (recommendation.TryGetProperty(AIJsonKeys.Decision, out var decisionProp) && - decisionProp.ValueKind == JsonValueKind.String) - { - decision = decisionProp.GetString(); - } - - string? rationale = null; - if (recommendation.TryGetProperty(AIJsonKeys.Rationale, out var rationaleProp) && - rationaleProp.ValueKind == JsonValueKind.String) - { - rationale = rationaleProp.GetString(); - } - - if (string.IsNullOrWhiteSpace(decision) && string.IsNullOrWhiteSpace(rationale)) - { - return null; - } - - return new ApplicationAnalysisRecommendation - { - Decision = decision, - Rationale = rationale - }; - } - - private static ApplicationScoringResponse ParseApplicationScoringResponse(string raw) - { - var response = new ApplicationScoringResponse(); - if (!TryParseJsonObjectFromResponse(raw, out var root)) - { - return response; - } - - foreach (var property in root.EnumerateObject()) - { - if (property.Value.ValueKind != JsonValueKind.Object) - { - continue; - } - - var answer = property.Value.TryGetProperty("answer", out var answerProp) - ? answerProp.Clone() - : default; - var rationale = property.Value.TryGetProperty("rationale", out var rationaleProp) && - rationaleProp.ValueKind == JsonValueKind.String - ? rationaleProp.GetString() ?? string.Empty - : string.Empty; - var confidence = property.Value.TryGetProperty("confidence", out var confidenceProp) && - confidenceProp.ValueKind == JsonValueKind.Number && - confidenceProp.TryGetInt32(out var parsedConfidence) - ? NormalizeConfidence(parsedConfidence) - : 0; - - response.Answers[property.Name] = new ApplicationScoringAnswer - { - Answer = answer, - Rationale = rationale, - Confidence = confidence - }; - } - - return response; - } - - private static int NormalizeConfidence(int confidence) - { - var clamped = Math.Clamp(confidence, 0, 100); - var rounded = (int)Math.Round(clamped / 5.0, MidpointRounding.AwayFromZero) * 5; - return Math.Clamp(rounded, 0, 100); - } - - private static string BuildApplicationScoringResponseTemplate(string sectionPayloadJson) - { - try - { - using var doc = JsonDocument.Parse(sectionPayloadJson); - if (!doc.RootElement.TryGetProperty("questions", out var questions) || questions.ValueKind != JsonValueKind.Array) - { - return "{}"; - } - - var template = new Dictionary(); - foreach (var question in questions.EnumerateArray()) - { - if (!question.TryGetProperty("id", out var idProp) || idProp.ValueKind != JsonValueKind.String) - { - continue; - } - - var questionId = idProp.GetString(); - if (string.IsNullOrWhiteSpace(questionId)) - { - continue; - } - - template[questionId] = new - { - answer = string.Empty, - rationale = string.Empty, - confidence = 0 - }; - } - - if (template.Count == 0) - { - return "{}"; - } - - return JsonSerializer.Serialize(template, JsonLogOptions); - } - catch (JsonException) - { - return "{}"; - } - } - - private async Task LogPromptInputAsync(string promptType, string promptVersion, string? systemPrompt, string userPrompt) - { - var formattedInput = FormatPromptInputForLog(systemPrompt, userPrompt); - _logger.LogInformation("AI {PromptType} ({PromptVersion}) input payload: {PromptInput}", promptType, promptVersion, formattedInput); - await WritePromptLogFileAsync(promptType, promptVersion, "INPUT", formattedInput); - } - - private async Task LogPromptOutputAsync(string promptType, string promptVersion, string output) - { - var formattedOutput = FormatPromptOutputForLog(output); - _logger.LogInformation("AI {PromptType} ({PromptVersion}) model output payload: {ModelOutput}", promptType, promptVersion, formattedOutput); - await WritePromptLogFileAsync(promptType, promptVersion, "OUTPUT", formattedOutput); - } - - private async Task WritePromptLogFileAsync(string promptType, string promptVersion, string payloadType, string payload) - { - if (!CanWritePromptFileLog()) - { - return; - } - - try - { - var now = DateTimeOffset.Now.ToString("yyyy-MM-dd HH:mm:ss zzz"); - var logDirectory = Path.Combine(AppContext.BaseDirectory, PromptLogDirectoryName); - Directory.CreateDirectory(logDirectory); - - var logPath = Path.Combine(logDirectory, PromptLogFileName); - var entry = $"{now} [{promptType}] [{promptVersion}] {payloadType}\n{payload}\n\n"; - await File.AppendAllTextAsync(logPath, entry); - } - catch (Exception ex) - { - _logger.LogWarning(ex, "Failed to write AI prompt log file."); - } - } - - private bool CanWritePromptFileLog() - { - return IsPromptFileLoggingEnabled; - } - private static string FormatPromptInputForLog(string? systemPrompt, string userPrompt) - { - var normalizedSystemPrompt = string.IsNullOrWhiteSpace(systemPrompt) ? string.Empty : systemPrompt.Trim(); - var normalizedUserPrompt = string.IsNullOrWhiteSpace(userPrompt) ? string.Empty : userPrompt.Trim(); - return $"SYSTEM_PROMPT\n{normalizedSystemPrompt}\n\nUSER_PROMPT\n{normalizedUserPrompt}"; - } - - private static string FormatPromptOutputForLog(string output) - { - if (string.IsNullOrWhiteSpace(output)) - { - return string.Empty; - } - - if (TryFormatProviderOutput(output, out var formattedProviderOutput)) - { - return formattedProviderOutput; - } - - if (TryParseJsonObjectFromResponse(output, out var jsonObject)) - { - return JsonSerializer.Serialize(jsonObject, JsonLogOptions); - } - - return output.Trim(); - } - - private static bool TryFormatProviderOutput(string output, out string formattedOutput) - { - formattedOutput = string.Empty; - - try - { - using var doc = JsonDocument.Parse(output); - var root = doc.RootElement; - if (root.ValueKind != JsonValueKind.Object - || !root.TryGetProperty("choices", out var choices) - || choices.ValueKind != JsonValueKind.Array - || choices.GetArrayLength() == 0) - { - return false; - } - - var firstChoice = choices[0]; - var content = TryGetChoiceContent(firstChoice); - if (string.IsNullOrWhiteSpace(content)) - { - return false; - } - - var lines = new List(); - - if (root.TryGetProperty("usage", out var usage) && usage.ValueKind == JsonValueKind.Object) - { - var promptTokens = TryGetInt32(usage, "prompt_tokens"); - var completionTokens = TryGetInt32(usage, "completion_tokens"); - int? reasoningTokens = null; - - if (usage.TryGetProperty("completion_tokens_details", out var completionTokenDetails) - && completionTokenDetails.ValueKind == JsonValueKind.Object) - { - reasoningTokens = TryGetInt32(completionTokenDetails, "reasoning_tokens"); - } - - if (promptTokens.HasValue) - { - lines.Add($"PromptTokens: {promptTokens.Value}"); - } - - if (completionTokens.HasValue) - { - lines.Add($"CompletionTokens: {completionTokens.Value}"); - } - - if (reasoningTokens.HasValue) - { - lines.Add($"ReasoningTokens: {reasoningTokens.Value}"); - } - } - - var normalizedContent = FormatPromptOutputContent(content); - lines.Add("Output:"); - lines.Add(normalizedContent); - formattedOutput = string.Join(Environment.NewLine, lines); - return true; - } - catch (JsonException) - { - return false; - } - } - - private static string? TryGetChoiceContent(JsonElement firstChoice) - { - if (!firstChoice.TryGetProperty("message", out var message) || message.ValueKind != JsonValueKind.Object) - { - return null; - } - - if (!message.TryGetProperty("content", out var contentProp) || contentProp.ValueKind != JsonValueKind.String) - { - return null; - } - - return contentProp.GetString(); - } - - private static string FormatPromptOutputContent(string content) - { - if (TryParseJsonObjectFromResponse(content, out var contentObject)) - { - return JsonSerializer.Serialize(contentObject, JsonLogOptions); - } - - return content.Trim(); - } - - private static bool TryParseJsonObjectFromResponse(string response, out JsonElement objectElement) - { - objectElement = default; - var cleaned = AIResponseJson.CleanJsonResponse(response); - if (string.IsNullOrWhiteSpace(cleaned)) - { - return false; - } - - try - { - using var doc = JsonDocument.Parse(cleaned); - if (doc.RootElement.ValueKind != JsonValueKind.Object) - { - return false; - } - - objectElement = doc.RootElement.Clone(); - return true; - } - catch (JsonException) - { - return false; - } - } - - private static string ResolvePromptVersion(string? version) - { - if (!string.IsNullOrWhiteSpace(version) && - PromptProfiles.TryGetValue(version.Trim(), out var selectedVersion)) - { - return selectedVersion; - } - - return PromptVersionV1; - } - - private static string BuildApplicationAnalysisSystemPrompt(string version) - { - return GetRequiredPromptTemplate(version, ApplicationAnalysisSystemTemplateName); - } - - private static string BuildApplicationAnalysisUserPrompt( - string version, - string schema, - string data, - string attachments) - { - var replacements = new Dictionary - { - ["SCHEMA"] = schema, - ["DATA"] = data, - ["ATTACHMENTS"] = attachments - }; - - return RenderPromptTemplate(version, ApplicationAnalysisUserTemplateName, replacements); - } - - private static string BuildAttachmentSummarySystemPrompt(string version) - { - return GetRequiredPromptTemplate(version, AttachmentSummarySystemTemplateName); - } - - private static string BuildAttachmentSummaryUserPrompt(string version, string attachment) - { - return RenderPromptTemplate(version, AttachmentSummaryUserTemplateName, new Dictionary - { - ["ATTACHMENT"] = attachment - }); - } - - private static string BuildApplicationScoringSystemPrompt(string version) - { - return GetRequiredPromptTemplate(version, ApplicationScoringSystemTemplateName); - } - - private static string BuildApplicationScoringUserPrompt( - string version, - string data, - string attachments, - string section, - string response) - { - return RenderPromptTemplate(version, ApplicationScoringUserTemplateName, new Dictionary - { - ["DATA"] = data, - ["ATTACHMENTS"] = attachments, - ["SECTION"] = section, - ["RESPONSE"] = response - }); - } - - private static bool TryGetPromptTemplate(string version, string templateName, out string template) - { - template = string.Empty; - var cacheKey = $"{version}/{templateName}"; - if (PromptTemplateCache.TryGetValue(cacheKey, out var cachedTemplate)) - { - template = cachedTemplate; - return true; - } - - var path = Path.Combine(AppContext.BaseDirectory, PromptTemplatesFolder, version, $"{templateName}.txt"); - if (!File.Exists(path)) - { - return false; - } - - var loaded = PromptTemplateCache.GetOrAdd(cacheKey, _ => File.ReadAllText(path)); - if (string.IsNullOrWhiteSpace(loaded)) - { - return false; - } - - template = loaded; - return true; - } - - private static string GetRequiredPromptTemplate(string version, string templateName) - { - if (TryGetPromptTemplate(version, templateName, out var template)) - { - return template; - } - - throw new InvalidOperationException( - $"Missing required prompt template '{templateName}.txt' for prompt version '{version}'."); - } - - private static string RenderPromptTemplate( - string version, - string templateName, - IReadOnlyDictionary runtimeReplacements) - { - return RenderPromptTemplateInternal( - version, - templateName, - runtimeReplacements, - new HashSet(StringComparer.OrdinalIgnoreCase)); - } - - private static string RenderPromptTemplateInternal( - string version, - string templateName, - IReadOnlyDictionary runtimeReplacements, - ISet resolutionStack) - { - if (!resolutionStack.Add(templateName)) - { - throw new InvalidOperationException( - $"Detected cyclic prompt fragment reference while resolving '{templateName}.txt' for prompt version '{version}'."); - } - - var template = GetRequiredPromptTemplate(version, templateName); - var replacements = new Dictionary(runtimeReplacements, StringComparer.Ordinal); - var baseTemplateName = GetTemplateBaseName(templateName); - - foreach (var placeholder in GetTemplatePlaceholders(template)) - { - if (replacements.ContainsKey(placeholder)) - { - continue; - } - - var fragmentTemplateName = ResolveFragmentTemplateName(version, baseTemplateName, placeholder); - if (!string.IsNullOrWhiteSpace(fragmentTemplateName)) - { - replacements[placeholder] = RenderPromptTemplateInternal( - version, - fragmentTemplateName, - new Dictionary(StringComparer.Ordinal), - resolutionStack).TrimEnd(); - } - } - - var rendered = template; - foreach (var replacement in replacements) - { - rendered = rendered.Replace($"{{{{{replacement.Key}}}}}", replacement.Value ?? string.Empty, StringComparison.Ordinal); - } - - var unresolved = GetTemplatePlaceholders(rendered); - if (unresolved.Count > 0) - { - throw new InvalidOperationException( - $"Unresolved prompt placeholders in '{templateName}.txt' for prompt version '{version}': {string.Join(", ", unresolved.OrderBy(item => item))}"); - } - - resolutionStack.Remove(templateName); - return rendered; - } - - private static string? ResolveFragmentTemplateName(string version, string baseTemplateName, string placeholderName) - { - var normalizedPlaceholder = placeholderName.ToLowerInvariant(); - var baseScopedCandidate = $"{baseTemplateName}.{normalizedPlaceholder}"; - if (TryGetPromptTemplate(version, baseScopedCandidate, out _)) - { - return baseScopedCandidate; - } - - if (TryResolveCommonTemplateName(placeholderName, out var commonTemplateName) && - TryGetPromptTemplate(version, commonTemplateName, out _)) - { - return commonTemplateName; - } - - return null; - } - - private static bool TryResolveCommonTemplateName(string placeholderName, out string commonTemplateName) - { - commonTemplateName = string.Empty; - if (!placeholderName.StartsWith("COMMON_", StringComparison.Ordinal)) - { - return false; - } - - var suffix = placeholderName.Substring("COMMON_".Length).ToLowerInvariant(); - suffix = suffix.Replace('_', '.'); - commonTemplateName = $"common.{suffix}"; - return true; - } - - private static string GetTemplateBaseName(string templateName) - { - var separatorIndex = templateName.IndexOf('.', StringComparison.Ordinal); - if (separatorIndex <= 0) - { - return templateName; - } - - return templateName.Substring(0, separatorIndex); - } - - private static HashSet GetTemplatePlaceholders(string template) - { - var placeholders = new HashSet(StringComparer.Ordinal); - var searchIndex = 0; - - while (searchIndex < template.Length) - { - var start = template.IndexOf("{{", searchIndex, StringComparison.Ordinal); - if (start < 0) - { - break; - } - - var end = template.IndexOf("}}", start + 2, StringComparison.Ordinal); - if (end < 0) - { - break; - } - - var placeholder = template.Substring(start + 2, end - start - 2).Trim(); - if (!string.IsNullOrWhiteSpace(placeholder)) - { - placeholders.Add(placeholder); - } - - searchIndex = end + 2; - } - - return placeholders; - } - - private static string ExtractSummaryFromJson(string output) - { - if (!TryParseJsonObjectFromResponse(output, out var jsonObject)) - { - return output?.Trim() ?? string.Empty; - } - - if (jsonObject.TryGetProperty(AIJsonKeys.Summary, out var summaryProp) && - summaryProp.ValueKind == JsonValueKind.String) - { - return summaryProp.GetString() ?? string.Empty; - } - - return output?.Trim() ?? string.Empty; - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/AddressInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/AddressInfoDataProvider.cs index c047e7e4fb..adae496d40 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/AddressInfoDataProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/AddressInfoDataProvider.cs @@ -18,7 +18,8 @@ namespace Unity.GrantManager.ApplicantProfile /// Addresses are resolved via both the ApplicationId and ApplicantId /// relationships, with duplicates removed. Addresses linked via /// ApplicationId are always read-only. Addresses linked via ApplicantId - /// are editable only when that set resolves to a single ApplicantId. + /// are editable only when they have no ApplicationId and the subject's + /// form submissions resolve to a single ApplicantId. /// [ExposeServices(typeof(IApplicantProfileDataProvider))] public class AddressInfoDataProvider( @@ -56,7 +57,14 @@ public async Task GetDataAsync(ApplicantProfileInfoRequ from submission in matchingSubmissions join address in addressesQuery on submission.ApplicationId equals address.ApplicationId join application in applicationsQuery on address.ApplicationId equals application.Id - select new { address, address.CreationTime, application.ReferenceNo, IsFromApplicantPath = false, address.ApplicantId }; + select new + { + address, + address.CreationTime, + application.ReferenceNo, + IsFromApplicantPath = false, + address.ApplicantId + }; // Addresses linked via ApplicantId — conditionally editable var byApplicantId = @@ -64,8 +72,15 @@ from submission in matchingSubmissions join address in addressesQuery on submission.ApplicantId equals address.ApplicantId join application in applicationsQuery on address.ApplicationId equals application.Id into apps from application in apps.DefaultIfEmpty() - select new { address, address.CreationTime, ReferenceNo = application != null ? application.ReferenceNo : null, IsFromApplicantPath = true, address.ApplicantId }; - + select new + { + address, + address.CreationTime, + ReferenceNo = application != null ? application.ReferenceNo : null, + IsFromApplicantPath = true, + address.ApplicantId + }; + var results = await byApplicationId .Concat(byApplicantId) .ToListAsync(); @@ -76,13 +91,13 @@ from application in apps.DefaultIfEmpty() .Select(g => g.OrderBy(r => r.IsFromApplicantPath).First()) .ToList(); - // Addresses from the ApplicantId path are editable only when - // that path resolves to a single ApplicantId - var applicantPathEditable = results - .Where(r => r.IsFromApplicantPath && r.ApplicantId != null) - .Select(r => r.ApplicantId) + // Determine editability from submissions, not addresses + var distinctApplicantIds = await matchingSubmissions + .Select(s => s.ApplicantId) .Distinct() - .Count() <= 1; + .ToListAsync(); + + var distinctApplicants = distinctApplicantIds.Count > 1; var addressDtos = deduplicated.Select(r => new AddressInfoItemDto { @@ -95,8 +110,8 @@ from application in apps.DefaultIfEmpty() Province = r.address.Province ?? string.Empty, PostalCode = r.address.Postal ?? string.Empty, Country = r.address.Country ?? string.Empty, - IsPrimary = r.address.HasProperty("isPrimary") && r.address.GetProperty("isPrimary"), - IsEditable = r.IsFromApplicantPath && applicantPathEditable, + IsPrimary = r.address.HasProperty(AddressExtraPropertyNames.IsPrimary) && r.address.GetProperty(AddressExtraPropertyNames.IsPrimary), + IsEditable = r.IsFromApplicantPath && !distinctApplicants, ReferenceNo = r.ReferenceNo }).ToList(); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileAppService.cs index e7146685ee..bcb856bb16 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileAppService.cs @@ -1,15 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; using Unity.GrantManager.Applicants; using Unity.GrantManager.Applications; +using Unity.Notifications.Settings; using Volo.Abp; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; +using Volo.Abp.Settings; using Volo.Abp.TenantManagement; namespace Unity.GrantManager.ApplicantProfile @@ -20,7 +22,8 @@ public class ApplicantProfileAppService( ITenantRepository tenantRepository, IRepository applicantTenantMapRepository, IRepository applicationFormSubmissionRepository, - IEnumerable dataProviders) + IEnumerable dataProviders, + ISettingProvider settingProvider) : ApplicationService, IApplicantProfileAppService { private readonly Dictionary _providersByKey @@ -69,12 +72,13 @@ public async Task> GetApplicantTenantsAsync(ApplicantPr // Extract the username part from the OIDC sub (part before '@') var subUsername = SubjectNormalizer.Normalize(request.Subject); if (subUsername is null) return []; + List mappings = []; // Query the ApplicantTenantMaps table in the host database using (currentTenant.Change(null)) { var queryable = await applicantTenantMapRepository.GetQueryableAsync(); - var mappings = await queryable + mappings = await queryable .Where(m => m.OidcSubUsername == subUsername) .Select(m => new ApplicantTenantDto { @@ -82,8 +86,27 @@ public async Task> GetApplicantTenantsAsync(ApplicantPr TenantName = m.TenantName }) .ToListAsync(); + } + + // Apply tenant specific metadata + foreach (var map in mappings) + { + await AddTenantMetadataAsync(map); + } + + return mappings; + } - return mappings; + /// + /// Add on any relevant tenant specific metadata + /// + /// The applicant tenant DTO to enrich with tenant-specific metadata. + private async Task AddTenantMetadataAsync(ApplicantTenantDto tenantMap) + { + using (currentTenant.Change(tenantMap.TenantId)) + { + var defaultEmailAddress = await settingProvider.GetOrNullAsync(NotificationsSettings.Mailing.DefaultFromAddress); + tenantMap.Metadata[ApplicantTenantMetadataKeys.DefaultFromAddress] = defaultEmailAddress ?? "NoReply@gov.bc.ca"; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileContactService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileContactService.cs index eba51fa136..06dd26366d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileContactService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ApplicantProfileContactService.cs @@ -15,8 +15,11 @@ namespace Unity.GrantManager.ApplicantProfile; /// /// Applicant-profile-specific contact service. Retrieves contacts linked to applicant profiles, /// application-level contacts matched by OIDC subject, and applicant agent contacts derived from -/// the submission login token. This service operates independently from the generic -/// and queries repositories directly. +/// the submission login token. Profile contacts are resolved by looking up form submissions that +/// match the OIDC subject to obtain applicant IDs, then querying +/// records against those IDs. When a single applicant ID is resolved the contacts are editable; +/// when multiple IDs are found the contacts are read-only. This service operates independently from the +/// generic and queries repositories directly. /// public class ApplicantProfileContactService( IContactRepository contactRepository, @@ -27,19 +30,28 @@ public class ApplicantProfileContactService( IRepository applicationRepository) : IApplicantProfileContactService, ITransientDependency { - private const string ApplicantProfileEntityType = "ApplicantProfile"; + private const string ApplicantEntityType = "Applicant"; /// - public async Task> GetProfileContactsAsync(Guid profileId) + public async Task> GetApplicantContactsAsync(string subject) { var contactLinksQuery = await contactLinkRepository.GetQueryableAsync(); var contactsQuery = await contactRepository.GetQueryableAsync(); + var submissionsQuery = await applicationFormSubmissionRepository.GetQueryableAsync(); + + var applicantIds = await submissionsQuery + .Where(s => s.OidcSub == subject) + .Select(s => s.ApplicantId) + .Distinct() + .ToListAsync(); + + var isEditable = applicantIds.Count <= 1; return await ( from link in contactLinksQuery join contact in contactsQuery on link.ContactId equals contact.Id - where link.RelatedEntityType == ApplicantProfileEntityType - && link.RelatedEntityId == profileId + where link.RelatedEntityType == ApplicantEntityType + && applicantIds.Contains(link.RelatedEntityId) && link.IsActive select new ContactInfoItemDto { @@ -54,9 +66,9 @@ join contact in contactsQuery on link.ContactId equals contact.Id ContactType = link.RelatedEntityType, Role = link.Role, IsPrimary = link.IsPrimary, - IsEditable = true, - ApplicationId = null, - ReferenceNo = null + IsEditable = isEditable, + ReferenceNo = null, + CreationTime = contact.CreationTime }).ToListAsync(); } @@ -85,7 +97,8 @@ join application in applicationsQuery on submission.ApplicationId equals applica IsPrimary = false, IsEditable = false, ApplicationId = appContact.ApplicationId, - ReferenceNo = application.ReferenceNo + ReferenceNo = application.ReferenceNo, + CreationTime = appContact.CreationTime }).ToListAsync(); return applicationContacts; @@ -117,7 +130,8 @@ join application in applicationsQuery on submission.ApplicationId equals applica IsPrimary = false, IsEditable = false, ApplicationId = agent.ApplicationId, - ReferenceNo = application.ReferenceNo + ReferenceNo = application.ReferenceNo, + CreationTime = agent.CreationTime }).ToListAsync(); return agentContacts; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ContactInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ContactInfoDataProvider.cs index 5062536063..8b7cbe547d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ContactInfoDataProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/ContactInfoDataProvider.cs @@ -1,3 +1,4 @@ +using System.Linq; using System.Threading.Tasks; using Unity.GrantManager.ApplicantProfile.ProfileData; using Volo.Abp.DependencyInjection; @@ -7,7 +8,7 @@ namespace Unity.GrantManager.ApplicantProfile { /// /// Provides contact information for the applicant profile by aggregating - /// profile-linked contacts, application-level contacts, and applicant agent contacts. + /// applicant linked contacts, application-level contacts, and applicant agent contacts. /// [ExposeServices(typeof(IApplicantProfileDataProvider))] public class ContactInfoDataProvider( @@ -33,8 +34,8 @@ public async Task GetDataAsync(ApplicantProfileInfoRequ using (currentTenant.Change(tenantId)) { - var profileContacts = await applicantProfileContactService.GetProfileContactsAsync(request.ProfileId); - dto.Contacts.AddRange(profileContacts); + var applicantContacts = await applicantProfileContactService.GetApplicantContactsAsync(normalizedSubject); + dto.Contacts.AddRange(applicantContacts); var applicationContacts = await applicantProfileContactService.GetApplicationContactsBySubjectAsync(normalizedSubject); dto.Contacts.AddRange(applicationContacts); @@ -43,6 +44,14 @@ public async Task GetDataAsync(ApplicantProfileInfoRequ dto.Contacts.AddRange(agentContacts); } + if (dto.Contacts.Count > 0 && !dto.Contacts.Any(c => c.IsPrimary)) + { + var latest = dto.Contacts + .OrderByDescending(c => c.CreationTime) + .First(); + latest.IsPrimary = true; + } + return dto; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/OrgInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/OrgInfoDataProvider.cs index 0534e2f0a7..8b02ea0817 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/OrgInfoDataProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/OrgInfoDataProvider.cs @@ -47,6 +47,8 @@ join applicant in applicantsQuery on submission.ApplicantId equals applicant.Id select new { applicant.Id, + applicant.UnityApplicantId, + applicant.ApplicantName, applicant.OrgName, applicant.OrganizationType, applicant.OrgNumber, @@ -58,11 +60,14 @@ join applicant in applicantsQuery on submission.ApplicantId equals applicant.Id applicant.Sector, applicant.SubSector }) + .Distinct() .ToListAsync(); dto.Organizations.AddRange(results.Select(r => new OrgInfoItemDto { Id = r.Id, + ApplicantRefId = r.UnityApplicantId, + ApplicantName = r.ApplicantName, OrgName = r.OrgName, OrganizationType = r.OrganizationType, OrgNumber = r.OrgNumber, diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/PaymentInfoDataProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/PaymentInfoDataProvider.cs index fc73e7f825..973cc86a38 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/PaymentInfoDataProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/PaymentInfoDataProvider.cs @@ -5,6 +5,7 @@ using Unity.GrantManager.ApplicantProfile.ProfileData; using Unity.GrantManager.Applications; using Unity.Payments.Domain.PaymentRequests; +using Unity.Payments.Codes; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; @@ -47,16 +48,22 @@ from submission in submissionsQuery join application in applicationsQuery on submission.ApplicationId equals application.Id where submission.OidcSub == normalizedSubject select new { application.Id, application.ReferenceNo } - ).Distinct().ToDictionaryAsync(a => a.Id, a => a.ReferenceNo); + ) + .Distinct() + .ToDictionaryAsync(a => a.Id, a => a.ReferenceNo); if (applicationLookup.Count == 0) return dto; // Payment info is secured via feature flags and permissions, so direct query for this data instead of using module service var paymentsQueryable = await paymentRequestRepository.GetQueryableAsync(); +#pragma warning disable CA1862 // EF Core does not support StringComparison overloads - https://github.com/dotnet/efcore/issues/1222 var paymentDetails = await paymentsQueryable - .Where(pr => applicationLookup.Keys.Contains(pr.CorrelationId)) + .Where(pr => applicationLookup.Keys.Contains(pr.CorrelationId) + && pr.PaymentStatus != null + && pr.PaymentStatus.Trim().ToUpper() == CasPaymentRequestStatus.FullyPaid.ToUpper()) .ToListAsync(); +#pragma warning restore CA1862 dto.Payments.AddRange(paymentDetails.Select(p => new PaymentInfoItemDto { @@ -65,7 +72,7 @@ join application in applicationsQuery on submission.ApplicationId equals applica ReferenceNo = applicationLookup.TryGetValue(p.CorrelationId, out var refNo) ? refNo : string.Empty, Amount = p.Amount, PaymentDate = p.PaymentDate, - PaymentStatus = p.Status.ToString() + PaymentStatus = CasPaymentRequestStatus.FullyPaid })); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs index 9b541dadf9..73c468aa06 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/ApplicantAppService.cs @@ -357,19 +357,22 @@ public async Task GetNextUnityApplicantIdAsync() foreach (var id in orderedIds) { - if (id == candidate) - { - candidate++; - } - else // Gap found: candidate is the first available ID. - { - break; - } + if (id < candidate) continue; // Skip duplicates already passed. + if (id == candidate) candidate++; + else break; // Gap found: candidate is the first available ID. } return candidate; } + [RemoteService(true)] + public async Task IsUnityApplicantIdAvailableAsync(string unityApplicantId, Guid currentApplicantId) + { + if (string.IsNullOrEmpty(unityApplicantId)) return true; + var existing = await applicantRepository.GetByUnityApplicantIdAsync(unityApplicantId); + return existing == null || existing.Id == currentApplicantId; + } + [RemoteService(true)] public async Task GetExistingApplicantAsync(string? unityApplicantId) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs index 0cedccdf1c..9921573dfe 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Applicants/IApplicantAppService.cs @@ -20,6 +20,7 @@ public interface IApplicantAppService : IApplicationService Task RelateDefaultSupplierAsync(ApplicantAgentDto applicantAgentDto); Task UpdateApplicantOrgMatchAsync(Applicant applicant); Task GetNextUnityApplicantIdAsync(); + Task IsUnityApplicantIdAvailableAsync(string unityApplicantId, Guid currentApplicantId); Task> GetApplicantsBySiteIdAsync(Guid siteId); Task GetApplicantLookUpAutocompleteQueryAsync(string? applicantLookUpQuery); Task> GetListAsync(ApplicantListRequestDto input); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs index d95d45758a..1fc0efd1bb 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicationForms/ApplicationFormAppService.cs @@ -176,6 +176,15 @@ public async Task PatchOtherConfig(Guid id, OtherConfigDto config) await Repository.UpdateAsync(form); } + [Authorize(GrantManagerPermissions.ApplicationForms.Default)] + public async Task PatchAiConfig(Guid id, AIConfigDto config) + { + var form = await Repository.GetAsync(id); + form.AutomaticallyGenerateAIAnalysis = config.AutomaticallyGenerateAIAnalysis; + form.ManuallyInitiateAIAnalysis = config.ManuallyInitiateAIAnalysis; + await Repository.UpdateAsync(form); + } + [Authorize(PaymentsPermissions.Payments.EditFormPaymentConfiguration)] public async Task GetFormPreventPaymentStatusByApplicationId(Guid applicationId) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Assessments/AssessmentAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Assessments/AssessmentAppService.cs index a94fa33b62..09d14f365a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Assessments/AssessmentAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Assessments/AssessmentAppService.cs @@ -6,7 +6,6 @@ using System.Text.Json; using System.Threading.Tasks; using Unity.AI.Permissions; -using Unity.AI.Settings; using Unity.Flex; using Unity.Flex.Scoresheets; using Unity.Flex.Scoresheets.Enums; @@ -94,12 +93,11 @@ public async Task GetDisplayList(Guid applicationId) var assessments = await _assessmentRepository.GetListWithAssessorsAsync(applicationId); var assessmentList = ObjectMapper.Map, List>(assessments); - // If AI Scoring feature is disabled, tenant setting is off, or user lacks permission, filter out AI assessments + // If AI Scoring feature is disabled or user lacks permission, filter out AI assessments var aiScoringEnabled = await _featureChecker.IsEnabledAsync("Unity.AI.Scoring"); - var aiScoringSettingEnabled = aiScoringEnabled && await SettingProvider.GetAsync(AISettings.ScoringAssistantEnabled, defaultValue: false); - var canViewAI = await AuthorizationService.IsGrantedAsync(AIPermissions.ScoringAssistant.ScoringAssistantDefault); + var canViewAI = await AuthorizationService.IsGrantedAsync(AIPermissions.Analysis.ViewScoringResult); assessmentList = assessmentList - .Where(a => !a.IsAiAssessment || (aiScoringSettingEnabled && canViewAI)) + .Where(a => !a.IsAiAssessment || (aiScoringEnabled && canViewAI)) .OrderByDescending(a => a.IsAiAssessment) .ThenByDescending(a => a.StartDate) .ToList(); @@ -398,17 +396,17 @@ public async Task UpdateAssessmentScore(AssessmentScoresDto dto) /// /// Thrown when the specified assessment is not an AI assessment. /// - [Authorize(AIPermissions.ScoringAssistant.ScoringAssistantDefault)] - public async Task CloneFromAiAsync(Guid aiAssessmentId) - { - if (!await _featureChecker.IsEnabledAsync("Unity.AI.Scoring")) - { - throw new UserFriendlyException("AI scoring is not enabled."); - } - - var aiAssessment = await _assessmentRepository.GetAsync(aiAssessmentId); - if (!aiAssessment.IsAiAssessment) - { + [Authorize(AIPermissions.Analysis.ViewScoringResult)] + public async Task CloneFromAiAsync(Guid aiAssessmentId) + { + if (!await _featureChecker.IsEnabledAsync("Unity.AI.Scoring")) + { + throw new UserFriendlyException("AI scoring is not enabled."); + } + + var aiAssessment = await _assessmentRepository.GetAsync(aiAssessmentId); + if (!aiAssessment.IsAiAssessment) + { throw new BusinessException(GrantManagerDomainErrorCodes.CannotCloneNonAiAssessment); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs index 3073e17437..a535776df1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs @@ -21,6 +21,7 @@ public class AttachmentAppService( IApplicationAttachmentRepository applicationAttachmentRepository, IApplicationChefsFileAttachmentRepository applicationChefsFileAttachmentRepository, IAssessmentAttachmentRepository assessmentAttachmentRepository, + IApplicantAttachmentRepository applicantAttachmentRepository, IIntakeFormSubmissionManager intakeFormSubmissionManager, IPersonRepository personUserRepository) : ApplicationService, IAttachmentAppService { @@ -54,6 +55,11 @@ public async Task> GetAssessmentAsync(Guid assess }).ToList(); } + public async Task> GetApplicantAsync(Guid applicantId) + { + return await GetAttachmentsAsync(new AttachmentParametersDto(AttachmentType.APPLICANT, applicantId)); + } + public async Task> GetApplicationChefsFileAttachmentsAsync(Guid applicationId) { return await applicationChefsFileAttachmentRepository.GetListAsync(applicationId); @@ -79,6 +85,9 @@ public async Task> GetAttachmentsAsync(AttachmentParam AttachmentType.ASSESSMENT => await GetAttachmentsInternalAsync( assessmentAttachmentRepository, attachment => attachment.AssessmentId == attachmentParametersDto.AttachedResourceId), + AttachmentType.APPLICANT => await GetAttachmentsInternalAsync( + applicantAttachmentRepository, + attachment => attachment.ApplicantId == attachmentParametersDto.AttachedResourceId), _ => throw new ArgumentException("Attachment type is not supported", nameof(attachmentParametersDto)), }; } @@ -117,6 +126,8 @@ public async Task GetAttachmentMetadataAsync(AttachmentTy attachmentId, assessmentAttachmentRepository), AttachmentType.CHEFS => await GetMetadataInternalAsync( attachmentId, applicationChefsFileAttachmentRepository), + AttachmentType.APPLICANT => await GetMetadataInternalAsync( + attachmentId, applicantAttachmentRepository), _ => throw new ArgumentException("Invalid attachment type", nameof(attachmentType)), }; } @@ -152,6 +163,10 @@ public async Task UpdateAttachmentMetadataAsync(UpdateAtt updateAttachment, applicationChefsFileAttachmentRepository, AttachmentType.CHEFS), + AttachmentType.APPLICANT => await UpdateMetadataInternalAsync( + updateAttachment, + applicantAttachmentRepository, + AttachmentType.APPLICANT), _ => throw new ArgumentException("Invalid attachment type", nameof(updateAttachment)), }; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentPreviewAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentPreviewAppService.cs new file mode 100644 index 0000000000..df2c80b7ca --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentPreviewAppService.cs @@ -0,0 +1,181 @@ +using Amazon.S3; +using Amazon.S3.Model; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using System; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; +using Volo.Abp.DependencyInjection; + +namespace Unity.GrantManager.Attachments; + +public class AttachmentPreviewAppService : ApplicationService, IAttachmentPreviewAppService, ITransientDependency, IDisposable +{ + private readonly IFileAppService _fileAppService; + private readonly ILibreOfficeConversionService _libreOfficeConversionService; + private readonly AmazonS3Client _amazonS3Client; + private readonly string _bucket; + private readonly string _applicationFolder; + private readonly string _assessmentFolder; + private readonly string _applicantFolder; + + public AttachmentPreviewAppService( + IFileAppService fileAppService, + ILibreOfficeConversionService libreOfficeConversionService, + IConfiguration configuration) + { + _fileAppService = fileAppService; + _libreOfficeConversionService = libreOfficeConversionService; + + var s3Config = new AmazonS3Config + { + RegionEndpoint = null, + ServiceURL = configuration["S3:Endpoint"], + AllowAutoRedirect = true, + ForcePathStyle = true + }; + _amazonS3Client = new AmazonS3Client( + configuration["S3:AccessKeyId"], + configuration["S3:SecretAccessKey"], + s3Config); + + _bucket = configuration["S3:Bucket"] ?? throw new InvalidOperationException("Missing server configuration: S3:Bucket"); + _applicationFolder = NormalizeFolder(configuration["S3:ApplicationS3Folder"] ?? throw new InvalidOperationException("Missing server configuration: S3:ApplicationS3Folder")); + _assessmentFolder = NormalizeFolder(configuration["S3:AssessmentS3Folder"] ?? throw new InvalidOperationException("Missing server configuration: S3:AssessmentS3Folder")); + _applicantFolder = NormalizeFolder(configuration["S3:ApplicantS3Folder"] ?? throw new InvalidOperationException("Missing server configuration: S3:ApplicantS3Folder")); + } + + public async Task GetOrCreatePreviewPdfAsync(AttachmentType attachmentType, Guid ownerId, string fileName) + { + var folder = attachmentType switch + { + AttachmentType.APPLICATION => _applicationFolder, + AttachmentType.ASSESSMENT => _assessmentFolder, + AttachmentType.APPLICANT => _applicantFolder, + _ => throw new ArgumentException($"Unsupported attachment type for preview: {attachmentType}") + }; + + var originalKey = $"{folder}/{ownerId}/{fileName}"; + var previewKey = $"{folder}/{ownerId}/preview/{fileName}.pdf"; + var previewName = fileName + ".pdf"; + var safeFileName = SanitizeForLog(fileName); + var safePreviewKey = SanitizeForLog(previewKey); + + // Try S3 cache first + var cached = await TryGetCachedPreviewAsync(previewKey, previewName); + if (cached != null) + { + Logger.LogInformation("AttachmentPreviewAppService: serving cached preview for {FileName} [{AttachmentType}/{OwnerId}]", safeFileName, attachmentType, ownerId); + return cached; + } + + // Cache miss — download original, convert, cache, return + Logger.LogInformation("AttachmentPreviewAppService: no cached preview found for {FileName} [{AttachmentType}/{OwnerId}] — starting LibreOffice conversion", safeFileName, attachmentType, ownerId); + BlobDto original; + try + { + original = await _fileAppService.GetBlobAsync(new GetBlobRequestDto { S3ObjectKey = originalKey, Name = fileName }); + } + catch (AmazonS3Exception ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) + { + Logger.LogWarning(ex, "AttachmentPreviewAppService: original file not found in S3 for {FileName} [{AttachmentType}/{OwnerId}]", safeFileName, attachmentType, ownerId); + return null; + } + var pdfBytes = await _libreOfficeConversionService.ConvertToPdfAsync(original.Content, fileName); + await UploadPreviewAsync(previewKey, pdfBytes); + Logger.LogInformation("AttachmentPreviewAppService: conversion complete for {FileName} — preview cached at {PreviewKey}", safeFileName, safePreviewKey); + + return new BlobDto { Content = pdfBytes, ContentType = "application/pdf", Name = previewName }; + } + + public async Task GetOrCreateChefsPreviewPdfAsync(Guid formSubmissionId, Guid chefsFileId, string fileName, byte[] originalContent) + { + var previewKey = $"chefs/{formSubmissionId}/{chefsFileId}/preview/{fileName}.pdf"; + var previewName = fileName + ".pdf"; + var safeFileNameForLog = SanitizeForLog(fileName); + + // Try S3 cache first + var cached = await TryGetCachedPreviewAsync(previewKey, previewName); + if (cached != null) + { + Logger.LogInformation("AttachmentPreviewAppService: serving cached preview for CHEFS file {FileName} [{FormSubmissionId}/{ChefsFileId}]", safeFileNameForLog, formSubmissionId, chefsFileId); + return cached; + } + + // Cache miss — convert provided content, cache, return + Logger.LogInformation("AttachmentPreviewAppService: no cached preview found for CHEFS file {FileName} [{FormSubmissionId}/{ChefsFileId}] — starting LibreOffice conversion", safeFileNameForLog, formSubmissionId, chefsFileId); + var pdfBytes = await _libreOfficeConversionService.ConvertToPdfAsync(originalContent, fileName); + await UploadPreviewAsync(previewKey, pdfBytes); + Logger.LogInformation("AttachmentPreviewAppService: conversion complete for CHEFS file {FileName} — preview cached at {PreviewKey}", safeFileNameForLog, SanitizeForLog(previewKey)); + + return new BlobDto { Content = pdfBytes, ContentType = "application/pdf", Name = previewName }; + } + + private async Task TryGetCachedPreviewAsync(string previewKey, string previewName) + { + try + { + var cached = await _fileAppService.GetBlobAsync(new GetBlobRequestDto { S3ObjectKey = previewKey, Name = previewName }); + if (cached?.Content?.Length > 0) + return cached; + } + catch (AmazonS3Exception ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) + { + // Cache miss — expected when preview has not been generated yet + } + catch (Exception ex) + { + Logger.LogWarning(ex, "AttachmentPreviewAppService: unexpected error checking preview cache for key {PreviewKey}", SanitizeForLog(previewKey)); + } + return null; + } + + private async Task UploadPreviewAsync(string previewKey, byte[] pdfBytes) + { + using var stream = new MemoryStream(pdfBytes); + var putRequest = new PutObjectRequest + { + BucketName = _bucket, + Key = EscapeKeyFileName(previewKey), + ContentType = "application/pdf", + InputStream = stream, + UseChunkEncoding = false, + DisablePayloadSigning = false + }; + await _amazonS3Client.PutObjectAsync(putRequest); + } + + private static string SanitizeForLog(string value) + { + if (string.IsNullOrEmpty(value)) + return string.Empty; + + return value + .Replace("\r", "\\r") + .Replace("\n", "\\n"); + } + + private static string NormalizeFolder(string folder) + => folder.EndsWith('/') ? folder.TrimEnd('/') : folder; + + private static string EscapeKeyFileName(string s3ObjectKey) + { + var lastSlash = s3ObjectKey.LastIndexOf('/'); + if (lastSlash < 0) return Uri.EscapeDataString(s3ObjectKey); + return s3ObjectKey[..(lastSlash + 1)] + Uri.EscapeDataString(s3ObjectKey[(lastSlash + 1)..]); + } + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _amazonS3Client.Dispose(); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentSummaryAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentSummaryAppService.cs deleted file mode 100644 index 005ce5667f..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentSummaryAppService.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Unity.AI.Permissions; -using Unity.GrantManager.AI.BackgroundJobs; -using Volo.Abp; -using Volo.Abp.Application.Services; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Features; - -namespace Unity.GrantManager.Attachments; - -[Authorize(AIPermissions.AttachmentSummary.AttachmentSummaryDefault)] -[Dependency(ReplaceServices = true)] -[ExposeServices(typeof(AttachmentSummaryAppService), typeof(IAttachmentSummaryAppService))] -public class AttachmentSummaryAppService( - IBackgroundJobManager backgroundJobManager, - IFeatureChecker featureChecker) : ApplicationService, IAttachmentSummaryAppService -{ - private const string SummaryGenerationQueuedMessage = "AI summary generation queued."; - - public async Task GenerateAttachmentSummaryAsync(Guid attachmentId, string? promptVersion = null) - { - if (!await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries")) - { - throw new UserFriendlyException("AI attachment summaries are not enabled."); - } - - await backgroundJobManager.EnqueueAsync(new GenerateAttachmentSummaryBackgroundJobArgs - { - AttachmentIds = [attachmentId], - PromptVersion = promptVersion, - TenantId = CurrentTenant.Id - }); - - return SummaryGenerationQueuedMessage; - } - - public async Task> GenerateAttachmentSummariesAsync(List attachmentIds, string? promptVersion = null) - { - if (!await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries")) - { - throw new UserFriendlyException("AI attachment summaries are not enabled."); - } - - if (attachmentIds.Count == 0) - { - return []; - } - - await backgroundJobManager.EnqueueAsync(new GenerateAttachmentSummaryBackgroundJobArgs - { - AttachmentIds = attachmentIds, - PromptVersion = promptVersion, - TenantId = CurrentTenant.Id - }); - - return attachmentIds.Select(_ => SummaryGenerationQueuedMessage).ToList(); - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/LibreOfficeConversionService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/LibreOfficeConversionService.cs new file mode 100644 index 0000000000..2844fb28c5 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/LibreOfficeConversionService.cs @@ -0,0 +1,130 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Unity.GrantManager.Attachments; + +public class LibreOfficeConversionService : ILibreOfficeConversionService, ITransientDependency +{ + private const string LibreOfficeBinary = "/usr/bin/libreoffice"; + private static readonly Lazy IsInstalledCache = new(ProbeIsInstalled, true); + + private static string GetSafeFileName(string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + { + throw new ArgumentException("File name must be provided.", nameof(fileName)); + } + + var safeFileName = Path.GetFileName(fileName); + if (safeFileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) + { + throw new ArgumentException("File name contains invalid characters.", nameof(fileName)); + } + + return safeFileName; + } + + private static bool ProbeIsInstalled() + { + try + { + using var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = LibreOfficeBinary, + Arguments = "--version", + UseShellExecute = false + } + }; + + process.Start(); + var exited = process.WaitForExit(5000); + + return exited && process.ExitCode == 0; + } + catch + { + return false; + } + } + + public bool IsInstalled() + { + return IsInstalledCache.Value; + } + + public async Task ConvertToPdfAsync(byte[] fileContent, string fileName) + { + var safeFileName = GetSafeFileName(fileName); + var tempDir = Path.Combine(Path.GetTempPath(), "unity-libreoffice-preview", Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(tempDir); + + try + { + var inputPath = Path.Combine(tempDir, safeFileName); + await File.WriteAllBytesAsync(inputPath, fileContent); + + var startInfo = new ProcessStartInfo + { + FileName = LibreOfficeBinary, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false + }; + startInfo.ArgumentList.Add($"-env:UserInstallation=file://{tempDir}"); + startInfo.ArgumentList.Add("--headless"); + startInfo.ArgumentList.Add("--convert-to"); + startInfo.ArgumentList.Add("pdf"); + startInfo.ArgumentList.Add("--outdir"); + startInfo.ArgumentList.Add(tempDir); + startInfo.ArgumentList.Add(inputPath); + + using var process = new Process + { + StartInfo = startInfo + }; + + process.Start(); + + var standardOutputTask = process.StandardOutput.ReadToEndAsync(); + var standardErrorTask = process.StandardError.ReadToEndAsync(); + var exitTask = process.WaitForExitAsync(); + var completedTask = await Task.WhenAny(exitTask, Task.Delay(60000)); + + if (completedTask != exitTask) + { + process.Kill(entireProcessTree: true); + await process.WaitForExitAsync(); + await Task.WhenAll(standardOutputTask, standardErrorTask); + throw new InvalidOperationException($"LibreOffice conversion timed out for file: {safeFileName}"); + } + + await exitTask; + await Task.WhenAll(standardOutputTask, standardErrorTask); + + if (process.ExitCode != 0) + { + var error = await standardErrorTask; + throw new InvalidOperationException($"LibreOffice conversion failed for file: {safeFileName}. Error: {error}"); + } + + var pdfFileName = Path.GetFileNameWithoutExtension(safeFileName) + ".pdf"; + var pdfPath = Path.Combine(tempDir, pdfFileName); + + if (!File.Exists(pdfPath)) + { + throw new InvalidOperationException($"LibreOffice did not produce a PDF output for file: {safeFileName}"); + } + + return await File.ReadAllBytesAsync(pdfPath); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs index 065e17d24a..50a92ebbd6 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProvider.cs @@ -21,14 +21,16 @@ public partial class S3BlobProvider : BlobProviderBase, ITransientDependency { private readonly IHttpContextAccessor _httpContextAccessor; private readonly IApplicationAttachmentRepository _applicationAttachmentRepository; - private readonly IAssessmentAttachmentRepository _assessmentAttachmentRepository; + private readonly IAssessmentAttachmentRepository _assessmentAttachmentRepository; + private readonly IApplicantAttachmentRepository _applicantAttachmentRepository; private readonly AmazonS3Client _amazonS3Client; - public S3BlobProvider(IHttpContextAccessor httpContextAccessor, IApplicationAttachmentRepository attachmentRepository, IAssessmentAttachmentRepository assessmentAttachmentRepository, IConfiguration configuration) + public S3BlobProvider(IHttpContextAccessor httpContextAccessor, IApplicationAttachmentRepository attachmentRepository, IAssessmentAttachmentRepository assessmentAttachmentRepository, IApplicantAttachmentRepository applicantAttachmentRepository, IConfiguration configuration) { _httpContextAccessor = httpContextAccessor; _applicationAttachmentRepository = attachmentRepository; _assessmentAttachmentRepository = assessmentAttachmentRepository; + _applicantAttachmentRepository = applicantAttachmentRepository; AmazonS3Config s3config = new() { @@ -63,6 +65,19 @@ public override async Task DeleteAsync(BlobProviderDeleteArgs args) }; await _amazonS3Client.DeleteObjectAsync(deleteObjectRequest); + + // Also delete the cached preview PDF if one was generated (S3 DeleteObject is idempotent) + var lastSlash = s3ObjectKey.LastIndexOf('/'); + if (lastSlash >= 0) + { + var previewKey = s3ObjectKey[..lastSlash] + "/preview/" + s3ObjectKey[(lastSlash + 1)..] + ".pdf"; + await _amazonS3Client.DeleteObjectAsync(new DeleteObjectRequest + { + BucketName = config.Bucket, + Key = EscapeKeyFileName(previewKey) + }); + } + if (attachmentType == "Application") { if (attachmentTypeId.IsNullOrEmpty()) @@ -89,6 +104,19 @@ public override async Task DeleteAsync(BlobProviderDeleteArgs args) await _assessmentAttachmentRepository.DeleteAsync(attachment); } } + else if (attachmentType == "Applicant") + { + if (attachmentTypeId.IsNullOrEmpty()) + { + throw new AbpValidationException("Missing ApplicantId"); + } + IQueryable queryableAttachment = _applicantAttachmentRepository.GetQueryableAsync().Result; + ApplicantAttachment? attachment = queryableAttachment.FirstOrDefault(a => a.S3ObjectKey.Equals(s3ObjectKey) && a.ApplicantId.Equals(new Guid(attachmentTypeId.ToString()))); + if (attachment != null) + { + await _applicantAttachmentRepository.DeleteAsync(attachment); + } + } else { throw new AbpValidationException("Wrong AttachmentType:"+attachmentType); @@ -146,30 +174,34 @@ public override async Task SaveAsync(BlobProviderSaveArgs args) var httpContext = _httpContextAccessor.HttpContext ?? throw new InvalidOperationException("No active HttpContext."); var queryParams = httpContext.Request?.Query ?? throw new InvalidOperationException("No query parameters in the current request."); var routeData = _httpContextAccessor.HttpContext.GetRouteData(); - var assessmentId = routeData.Values["assessmentId"]; + var assessmentId = routeData.Values["assessmentId"]; + var applicationId = routeData.Values["applicationId"]; + var applicantId = routeData.Values["applicantId"]; + queryParams.TryGetValue("userId", out StringValues currentUserId); if (assessmentId != null) { - queryParams.TryGetValue("userId", out StringValues currentUserId); -#pragma warning disable CS8604 // Possible null reference argument. + + #pragma warning disable CS8604 // Possible null reference argument. await UploadAssessmentAttachment(args, assessmentId.ToString(), currentUserId.ToString()); -#pragma warning restore CS8604 // Possible null reference argument. + #pragma warning restore CS8604 // Possible null reference argument. + } + else if(applicationId != null) + { + #pragma warning disable CS8604 // Possible null reference argument. + await UploadApplicationAttachment(args, applicationId.ToString(), currentUserId.ToString()); + #pragma warning restore CS8604 // Possible null reference argument. + } + else if (applicantId != null) + { + #pragma warning disable CS8604 // Possible null reference argument. + await UploadApplicantAttachment(args, applicantId.ToString(), currentUserId.ToString()); + #pragma warning restore CS8604 // Possible null reference argument. } else { - var applicationId = routeData.Values["applicationId"]; - if(applicationId != null) - { - queryParams.TryGetValue("userId", out StringValues currentUserId); -#pragma warning disable CS8604 // Possible null reference argument. - await UploadApplicationAttachment(args, applicationId.ToString(), currentUserId.ToString()); -#pragma warning restore CS8604 // Possible null reference argument. - } - else - { - throw new AbpValidationException("Missing parameter: applicationId/assessmentId"); - } - } + throw new AbpValidationException("Missing parameter: applicationId/assessmentId/applicantId"); + } } private async Task UploadAssessmentAttachment(BlobProviderSaveArgs args, string assessmentId, string currentUserId) @@ -246,6 +278,43 @@ await _applicationAttachmentRepository.InsertAsync( } } + private async Task UploadApplicantAttachment(BlobProviderSaveArgs args, string applicantId, string currentUserId) + { + var config = args.Configuration.GetS3BlobProviderConfiguration(); + var bucket = config.Bucket; + var folder = args.Configuration.GetS3BlobProviderConfiguration().ApplicantS3Folder; + if (!folder.EndsWith('/')) + { + folder += "/"; + } + folder += applicantId; + var key = folder + "/" + args.BlobName; + var escapedKey = folder + "/" + Uri.EscapeDataString(args.BlobName); + var mimeType = GetMimeType(args.BlobName); + await UploadToS3(args, bucket, escapedKey, mimeType); + IQueryable queryableAttachment = _applicantAttachmentRepository.GetQueryableAsync().Result; + ApplicantAttachment? attachment = queryableAttachment.FirstOrDefault(a => a.S3ObjectKey.Equals(key) && a.ApplicantId.Equals(new Guid(applicantId))); + if (attachment == null) + { + await _applicantAttachmentRepository.InsertAsync( + new ApplicantAttachment + { + ApplicantId = new Guid(applicantId), + S3ObjectKey = key, + UserId = new Guid(currentUserId), + FileName = args.BlobName, + Time = DateTime.UtcNow, + }); + } + else + { + attachment.UserId = new Guid(currentUserId); + attachment.FileName = args.BlobName; + attachment.Time = DateTime.UtcNow; + await _applicantAttachmentRepository.UpdateAsync(attachment); + } + } + public async Task UploadToS3(BlobProviderSaveArgs args, string bucket, string key, string mimeType) { byte[] fileBytes; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProviderConfiguration.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProviderConfiguration.cs index 9c611dcc6f..9430802abd 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProviderConfiguration.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/S3BlobProviderConfiguration.cs @@ -51,5 +51,12 @@ public string AssessmentS3Folder .GetConfiguration("S3BlobProvider.AssessmentS3Folder"); set => _containerConfiguration .SetConfiguration("S3BlobProvider.AssessmentS3Folder", value); + } + public string ApplicantS3Folder + { + get => _containerConfiguration + .GetConfiguration("S3BlobProvider.ApplicantS3Folder"); + set => _containerConfiguration + .SetConfiguration("S3BlobProvider.ApplicantS3Folder", value); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationAnalysisAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationAnalysisAppService.cs deleted file mode 100644 index 39e0f3676b..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationAnalysisAppService.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using Unity.GrantManager.AI.BackgroundJobs; -using Unity.AI.Permissions; -using Volo.Abp; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.Features; - -namespace Unity.GrantManager.GrantApplications; - -[Authorize(AIPermissions.ApplicationAnalysis.ApplicationAnalysisDefault)] -public class ApplicationAnalysisAppService( - IBackgroundJobManager backgroundJobManager, - IFeatureChecker featureChecker) - : GrantManagerAppService, IApplicationAnalysisAppService -{ - public async Task GenerateApplicationAnalysisAsync(Guid applicationId, string? promptVersion = null) - { - try - { - if (!await featureChecker.IsEnabledAsync("Unity.AI.ApplicationAnalysis")) - { - throw new UserFriendlyException("AI application analysis is not enabled."); - } - - await backgroundJobManager.EnqueueAsync(new GenerateApplicationAnalysisBackgroundJobArgs - { - ApplicationId = applicationId, - PromptVersion = promptVersion, - TenantId = CurrentTenant.Id - }); - - return "{}"; - } - catch (Exception ex) - { - Logger.LogError(ex, "Error queueing AI analysis for application {ApplicationId}", applicationId); - throw new UserFriendlyException("Failed to queue AI analysis. Please try again."); - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationContentAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationContentAppService.cs deleted file mode 100644 index 7e70bad658..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationContentAppService.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using Unity.AI.Permissions; -using Unity.GrantManager.AI.BackgroundJobs; -using Volo.Abp; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.Features; - -namespace Unity.GrantManager.GrantApplications; - -[Authorize(AIPermissions.AttachmentSummary.AttachmentSummaryDefault)] -[Authorize(AIPermissions.ApplicationAnalysis.ApplicationAnalysisDefault)] -[Authorize(AIPermissions.ScoringAssistant.ScoringAssistantDefault)] -public class ApplicationContentAppService( - IBackgroundJobManager backgroundJobManager, - IFeatureChecker featureChecker) - : GrantManagerAppService, IApplicationContentAppService -{ - public async Task GenerateContentAsync(Guid applicationId, string? promptVersion = null) - { - try - { - var attachmentSummariesEnabled = await featureChecker.IsEnabledAsync("Unity.AI.AttachmentSummaries"); - var applicationAnalysisEnabled = await featureChecker.IsEnabledAsync("Unity.AI.ApplicationAnalysis"); - var scoringEnabled = await featureChecker.IsEnabledAsync("Unity.AI.Scoring"); - - if (!attachmentSummariesEnabled || !applicationAnalysisEnabled || !scoringEnabled) - { - throw new UserFriendlyException("AI generate all is not enabled."); - } - - await backgroundJobManager.EnqueueAsync(new GenerateContentBackgroundJobArgs - { - ApplicationId = applicationId, - PromptVersion = promptVersion, - TenantId = CurrentTenant.Id - }); - - return "{}"; - } - catch (Exception ex) - { - Logger.LogError(ex, "Error queueing full AI content pipeline for application {ApplicationId}", applicationId); - throw new UserFriendlyException("Failed to queue AI generate all. Please try again."); - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationScoringAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationScoringAppService.cs deleted file mode 100644 index b3a260430c..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationScoringAppService.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using Unity.AI.Permissions; -using Unity.GrantManager.AI.BackgroundJobs; -using Volo.Abp; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.Features; - -namespace Unity.GrantManager.GrantApplications; - -[Authorize(AIPermissions.ScoringAssistant.ScoringAssistantDefault)] -public class ApplicationScoringAppService( - IBackgroundJobManager backgroundJobManager, - IFeatureChecker featureChecker) - : GrantManagerAppService, IApplicationScoringAppService -{ - public async Task GenerateApplicationScoringAsync(Guid applicationId, string? promptVersion = null) - { - try - { - if (!await featureChecker.IsEnabledAsync("Unity.AI.Scoring")) - { - throw new UserFriendlyException("AI scoring is not enabled."); - } - - await backgroundJobManager.EnqueueAsync(new GenerateApplicationScoringBackgroundJobArgs - { - ApplicationId = applicationId, - PromptVersion = promptVersion, - TenantId = CurrentTenant.Id - }); - - return "{}"; - } - catch (Exception ex) - { - Logger.LogError(ex, "Error queueing AI application scoring generation for application {ApplicationId}", applicationId); - throw new UserFriendlyException("Failed to queue AI application scoring generation. Please try again."); - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationStatusAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationStatusAppService.cs index 57ea951e99..4427a21044 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationStatusAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/ApplicationStatusAppService.cs @@ -19,10 +19,27 @@ public ApplicationStatusAppService(IApplicationStatusRepository repository) _applicationStatusRepository = repository; } - public async Task> GetListAsync() + public virtual async Task> GetListAsync() { var statuses = await _applicationStatusRepository.GetListAsync(); return ObjectMapper.Map, List>(statuses.OrderBy(s => s.StatusCode).ToList()); } + + public virtual async Task UpdateExternalStatusLabelsAsync(UpdateApplicationStatusExternalLabelsDto input) + { + // Load all statuses in a single query by IDs + var statusIds = input.Statuses.Select(s => s.Id).ToList(); + var statuses = await _applicationStatusRepository.GetListAsync(s => statusIds.Contains(s.Id)); + var statusMap = statuses.ToDictionary(s => s.Id); + + foreach (var statusDto in input.Statuses) + { + if (statusMap.TryGetValue(statusDto.Id, out var status)) + { + status.ExternalStatus = statusDto.ExternalStatus; + await _applicationStatusRepository.UpdateAsync(status); + } + } + } } \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/ApplicationAIGenerationQueue.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/ApplicationAIGenerationQueue.cs new file mode 100644 index 0000000000..e5f52cf296 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/ApplicationAIGenerationQueue.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Unity.AI.Automation; +using Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; + +namespace Unity.GrantManager.GrantApplications.Automation; + +public class ApplicationAIGenerationQueue(IBackgroundJobManager backgroundJobManager) + : IApplicationAIGenerationQueue, ITransientDependency +{ + public async Task QueueAttachmentSummariesAsync(IReadOnlyList attachmentIds, Guid? tenantId, string? promptVersion = null) + { + await backgroundJobManager.EnqueueAsync(new GenerateAttachmentSummaryBackgroundJobArgs + { + AttachmentIds = [.. attachmentIds], + PromptVersion = promptVersion, + TenantId = tenantId + }); + } + + public async Task QueueApplicationAnalysisAsync(Guid applicationId, Guid? tenantId, string? promptVersion = null) + { + await backgroundJobManager.EnqueueAsync(new GenerateApplicationAnalysisBackgroundJobArgs + { + ApplicationId = applicationId, + PromptVersion = promptVersion, + TenantId = tenantId + }); + } + + public async Task QueueApplicationScoringAsync(Guid applicationId, Guid? tenantId, string? promptVersion = null) + { + await backgroundJobManager.EnqueueAsync(new GenerateApplicationScoringBackgroundJobArgs + { + ApplicationId = applicationId, + PromptVersion = promptVersion, + TenantId = tenantId + }); + } + + public async Task QueueApplicationPipelineAsync(Guid applicationId, Guid? tenantId, string? promptVersion = null) + { + await backgroundJobManager.EnqueueAsync(new RunApplicationAIPipelineJobArgs + { + ApplicationId = applicationId, + PromptVersion = promptVersion, + TenantId = tenantId + }); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisJob.cs new file mode 100644 index 0000000000..c3d3448687 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationAnalysisJob.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; +using System.Threading.Tasks; +using Unity.GrantManager.GrantApplications; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; +public class GenerateApplicationAnalysisJob( + IApplicationAnalysisAppService applicationAnalysisService, + ICurrentTenant currentTenant, + ILogger logger) : AsyncBackgroundJob, ITransientDependency +{ + public override async Task ExecuteAsync(GenerateApplicationAnalysisBackgroundJobArgs args) + { + using (currentTenant.Change(args.TenantId)) + { + logger.LogInformation("Executing AI application analysis job for application {ApplicationId}.", args.ApplicationId); + var result = await applicationAnalysisService.GenerateApplicationAnalysisAsync(args.ApplicationId, args.PromptVersion); + if (result.Completed) + { + logger.LogInformation("Completed AI application analysis job for application {ApplicationId}.", args.ApplicationId); + } + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringJob.cs new file mode 100644 index 0000000000..61d87d63a7 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateApplicationScoringJob.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.Logging; +using System.Threading.Tasks; +using Unity.GrantManager.GrantApplications; +using Unity.GrantManager.GrantApplications.Automation.Events; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Local; +using Volo.Abp.MultiTenancy; +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; +public class GenerateApplicationScoringJob( + IApplicationScoringAppService applicationScoringService, + ILocalEventBus localEventBus, + ICurrentTenant currentTenant, + ILogger logger) : AsyncBackgroundJob, ITransientDependency +{ + public override async Task ExecuteAsync(GenerateApplicationScoringBackgroundJobArgs args) + { + using (currentTenant.Change(args.TenantId)) + { + logger.LogInformation("Executing AI application scoring job for application {ApplicationId}.", args.ApplicationId); + var result = await applicationScoringService.GenerateApplicationScoringAsync(args.ApplicationId, args.PromptVersion); + if (result.Completed) + { + await localEventBus.PublishAsync(new ApplicationAIScoringGeneratedEvent + { + ApplicationId = args.ApplicationId + }); + } + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryJob.cs new file mode 100644 index 0000000000..c47c667005 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/GenerateAttachmentSummaryJob.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.Logging; +using System.Threading.Tasks; +using Unity.GrantManager.Attachments; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; +public class GenerateAttachmentSummaryJob( + IAttachmentSummaryAppService attachmentSummaryService, + ICurrentTenant currentTenant, + ILogger logger) : AsyncBackgroundJob, ITransientDependency +{ + public override async Task ExecuteAsync(GenerateAttachmentSummaryBackgroundJobArgs args) + { + using (currentTenant.Change(args.TenantId)) + { + logger.LogInformation( + "Executing AI attachment summary job for {AttachmentCount} attachment(s).", + args.AttachmentIds.Count); + var results = await attachmentSummaryService.GenerateAttachmentSummariesAsync(args.AttachmentIds, args.PromptVersion); + logger.LogInformation("Completed AI attachment summaries for {CompletedCount} attachment(s).", results.Count); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateContentBackgroundJob.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJob.cs similarity index 53% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateContentBackgroundJob.cs rename to applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJob.cs index 2e55de9895..9c06a650f5 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/AI/BackgroundJobs/GenerateContentBackgroundJob.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/BackgroundJobs/RunApplicationAIPipelineJob.cs @@ -1,30 +1,31 @@ using Microsoft.Extensions.Logging; using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; -using Unity.AI.Settings; -using Unity.GrantManager.AI.Operations; -using Unity.GrantManager.Intakes.Events; +using Unity.GrantManager.Applications; +using Unity.GrantManager.Attachments; +using Unity.GrantManager.GrantApplications; +using Unity.GrantManager.GrantApplications.Automation.Events; using Volo.Abp.BackgroundJobs; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Local; using Volo.Abp.Features; using Volo.Abp.MultiTenancy; -using Volo.Abp.Settings; -namespace Unity.GrantManager.AI.BackgroundJobs; +namespace Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; -public class GenerateContentBackgroundJob( - IAttachmentSummaryService attachmentSummaryService, - IApplicationAnalysisService applicationAnalysisService, - IApplicationScoringService applicationScoringService, - IAIService aiService, +public class RunApplicationAIPipelineJob( + IApplicationChefsFileAttachmentRepository applicationChefsFileAttachmentRepository, + IAttachmentSummaryAppService attachmentSummaryAppService, + IApplicationAnalysisAppService applicationAnalysisAppService, + IApplicationScoringAppService applicationScoringAppService, IFeatureChecker featureChecker, - ISettingProvider settingProvider, ILocalEventBus localEventBus, ICurrentTenant currentTenant, - ILogger logger) : AsyncBackgroundJob, ITransientDependency + ILogger logger) : AsyncBackgroundJob, ITransientDependency { - public override async Task ExecuteAsync(GenerateContentBackgroundJobArgs args) + public override async Task ExecuteAsync(RunApplicationAIPipelineJobArgs args) { using (currentTenant.Change(args.TenantId)) { @@ -32,28 +33,21 @@ public override async Task ExecuteAsync(GenerateContentBackgroundJobArgs args) var applicationAnalysisEnabled = await featureChecker.IsEnabledAsync("Unity.AI.ApplicationAnalysis"); var scoringEnabled = await featureChecker.IsEnabledAsync("Unity.AI.Scoring"); - if (scoringEnabled) - { - scoringEnabled = await settingProvider.GetAsync(AISettings.ScoringAssistantEnabled, defaultValue: false); - } - if (!attachmentSummariesEnabled && !applicationAnalysisEnabled && !scoringEnabled) { logger.LogDebug("All AI features are disabled, skipping queued AI generation for application {ApplicationId}.", args.ApplicationId); return; } - if (!await aiService.IsAvailableAsync()) - { - logger.LogWarning("AI service is not available, skipping queued AI generation for application {ApplicationId}.", args.ApplicationId); - return; - } - logger.LogInformation("Executing queued AI content pipeline for application {ApplicationId}.", args.ApplicationId); if (attachmentSummariesEnabled) { - await attachmentSummaryService.GenerateForApplicationAsync(args.ApplicationId, args.PromptVersion); + var attachmentResults = await attachmentSummaryAppService.GenerateAttachmentSummariesAsync( + await GetAttachmentIdsAsync(args.ApplicationId), + args.PromptVersion); + + logger.LogInformation("Completed AI attachment summaries for application {ApplicationId} with {AttachmentCount} result(s).", args.ApplicationId, attachmentResults.Count); } Exception? analysisException = null; @@ -63,7 +57,11 @@ public override async Task ExecuteAsync(GenerateContentBackgroundJobArgs args) { try { - await applicationAnalysisService.RegenerateAndSaveAsync(args.ApplicationId, args.PromptVersion); + var analysisResult = await applicationAnalysisAppService.GenerateApplicationAnalysisAsync(args.ApplicationId, args.PromptVersion); + if (analysisResult.Completed) + { + logger.LogInformation("Completed AI application analysis stage for application {ApplicationId}.", args.ApplicationId); + } } catch (Exception ex) { @@ -76,10 +74,10 @@ public override async Task ExecuteAsync(GenerateContentBackgroundJobArgs args) { try { - var result = await applicationScoringService.RegenerateAndSaveAsync(args.ApplicationId, args.PromptVersion); - if (!string.Equals(result, "{}", StringComparison.Ordinal)) + var result = await applicationScoringAppService.GenerateApplicationScoringAsync(args.ApplicationId, args.PromptVersion); + if (result.Completed) { - await localEventBus.PublishAsync(new AIApplicationScoringGeneratedEvent + await localEventBus.PublishAsync(new ApplicationAIScoringGeneratedEvent { ApplicationId = args.ApplicationId }); @@ -103,4 +101,10 @@ await localEventBus.PublishAsync(new AIApplicationScoringGeneratedEvent } } } + + private async Task> GetAttachmentIdsAsync(Guid applicationId) + { + var attachments = await applicationChefsFileAttachmentRepository.GetListAsync(a => a.ApplicationId == applicationId); + return attachments.Select(a => a.Id).ToList(); + } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Events/ApplicationAIScoringGeneratedEvent.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Events/ApplicationAIScoringGeneratedEvent.cs new file mode 100644 index 0000000000..a22b5a7154 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Events/ApplicationAIScoringGeneratedEvent.cs @@ -0,0 +1,8 @@ +using System; + +namespace Unity.GrantManager.GrantApplications.Automation.Events; + +public class ApplicationAIScoringGeneratedEvent +{ + public Guid ApplicationId { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/CreateAIAssessmentHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Handlers/CreateAIAssessmentOnScoringGeneratedHandler.cs similarity index 72% rename from applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/CreateAIAssessmentHandler.cs rename to applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Handlers/CreateAIAssessmentOnScoringGeneratedHandler.cs index b75842328c..c93eff4685 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/CreateAIAssessmentHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Handlers/CreateAIAssessmentOnScoringGeneratedHandler.cs @@ -2,43 +2,38 @@ using System; using System.Threading.Tasks; using Unity.AI.Settings; -using Unity.GrantManager.Assessments; using Unity.GrantManager.Applications; -using Unity.GrantManager.Intakes.Events; +using Unity.GrantManager.Assessments; +using Unity.GrantManager.GrantApplications.Automation.Events; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus; using Volo.Abp.Features; using Volo.Abp.Settings; using Volo.Abp.Uow; - -namespace Unity.GrantManager.Intakes.Handlers; - -public class CreateAIAssessmentHandler( +namespace Unity.GrantManager.GrantApplications.Automation.Handlers; +public class CreateAIAssessmentOnScoringGeneratedHandler( AssessmentManager assessmentManager, IApplicationRepository applicationRepository, IFeatureChecker featureChecker, ISettingProvider settingProvider, IUnitOfWorkManager unitOfWorkManager, - ILogger logger) : ILocalEventHandler, ITransientDependency + ILogger logger) : ILocalEventHandler, ITransientDependency { - public async Task HandleEventAsync(AIApplicationScoringGeneratedEvent eventData) + public async Task HandleEventAsync(ApplicationAIScoringGeneratedEvent eventData) { if (eventData == null || eventData.ApplicationId == Guid.Empty) { - logger.LogWarning("Event data or application ID is null in CreateAIAssessmentHandler."); + logger.LogWarning("Event data or application ID is null in CreateAIAssessmentOnScoringGeneratedHandler."); return; } - - if (!await featureChecker.IsEnabledAsync("Unity.AI.Scoring")) + if (!await settingProvider.GetAsync(AISettings.AutomaticGenerationEnabled, defaultValue: false)) { return; } - - if (!await settingProvider.GetAsync(AISettings.ScoringAssistantEnabled, defaultValue: false)) + if (!await featureChecker.IsEnabledAsync("Unity.AI.Scoring")) { return; } - try { using var uow = unitOfWorkManager.Begin(requiresNew: true); @@ -52,4 +47,4 @@ public async Task HandleEventAsync(AIApplicationScoringGeneratedEvent eventData) logger.LogError(ex, "Error creating AI assessment for application {ApplicationId}.", eventData.ApplicationId); } } -} +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Handlers/QueueApplicationAIPipelineOnProcessHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Handlers/QueueApplicationAIPipelineOnProcessHandler.cs new file mode 100644 index 0000000000..6bb6e37027 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/Automation/Handlers/QueueApplicationAIPipelineOnProcessHandler.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Threading.Tasks; +using Unity.AI.Settings; +using Unity.GrantManager.Applications; +using Unity.GrantManager.GrantApplications.Automation.BackgroundJobs; +using Unity.GrantManager.Intakes.Events; +using Volo.Abp.BackgroundJobs; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus; +using Volo.Abp.Settings; + +namespace Unity.GrantManager.GrantApplications.Automation.Handlers; + +public class QueueApplicationAIPipelineOnProcessHandler( + IBackgroundJobManager backgroundJobManager, + ISettingProvider settingProvider, + IApplicationFormRepository applicationFormRepository, + ILogger logger) : ILocalEventHandler, ITransientDependency +{ + public async Task HandleEventAsync(ApplicationProcessEvent eventData) + { + if (eventData?.Application == null) + { + logger.LogWarning("Event data or application is null in QueueApplicationAIPipelineOnProcessHandler."); + return; + } + + var automaticGenerationEnabled = await settingProvider.GetAsync(AISettings.AutomaticGenerationEnabled, defaultValue: false); + if (!automaticGenerationEnabled) + { + logger.LogDebug("Automatic AI generation is disabled at tenant level, skipping intake pipeline for application {ApplicationId}.", eventData.Application.Id); + return; + } + + var applicationForm = await applicationFormRepository.GetAsync(eventData.Application.ApplicationFormId); + if (!applicationForm.AutomaticallyGenerateAIAnalysis) + { + logger.LogDebug("Automatic AI analysis is disabled at form level for application {ApplicationId}, skipping intake pipeline.", eventData.Application.Id); + return; + } + + try + { + await backgroundJobManager.EnqueueAsync(new RunApplicationAIPipelineJobArgs + { + ApplicationId = eventData.Application.Id, + TenantId = eventData.Application.TenantId + }); + logger.LogInformation("Queued AI pipeline for application {ApplicationId}.", eventData.Application.Id); + } + catch (Exception ex) + { + logger.LogError(ex, "Error queueing AI pipeline for application {ApplicationId}.", eventData.Application.Id); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs index 022a1ad34d..b05dfa0bbf 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantApplications/GrantApplicationAppService.cs @@ -14,8 +14,8 @@ using System.Threading.Tasks; using Unity.Flex.WorksheetInstances; using Unity.Flex.Worksheets; -using Unity.GrantManager.AI.Models; -using Unity.GrantManager.AI.Responses; +using Unity.AI.Models; +using Unity.AI.Responses; using Unity.GrantManager.Applicants; using Unity.GrantManager.ApplicationForms; using Unity.GrantManager.Applications; @@ -1045,6 +1045,7 @@ from applicant in applicantGroup.DefaultIfEmpty() Id = applications.Id, ProjectName = applications.ProjectName, ReferenceNo = applications.ReferenceNo, + UnityApplicationId = applications.UnityApplicationId ?? string.Empty, ApplicantName = applicant != null ? (applicant.ApplicantName ?? GrantManagerConsts.UnknownValue) : GrantManagerConsts.UnknownValue, OrganizationName = applicant != null ? (applicant.OrgName ?? string.Empty) : string.Empty, UnityApplicantId = applicant != null ? (applicant.UnityApplicantId ?? string.Empty) : string.Empty @@ -1071,22 +1072,22 @@ private static Dictionary ExtractCustomFieldsForWorksheet(dynami return result; } - public async Task HideAIAnalysisItemAsync(Guid applicationId, string itemId) - { - return await UpdateAIAnalysisItemVisibilityStateAsync(applicationId, itemId, isHidden: true); - } - - public async Task ShowAIAnalysisItemAsync(Guid applicationId, string itemId) - { - return await UpdateAIAnalysisItemVisibilityStateAsync(applicationId, itemId, isHidden: false); - } - - private async Task UpdateAIAnalysisItemVisibilityStateAsync(Guid applicationId, string itemId, bool isHidden) - { - if (string.IsNullOrWhiteSpace(itemId)) - { - throw new UserFriendlyException("AI analysis item id is required."); - } + public async Task DismissAIAnalysisItemAsync(Guid applicationId, string itemId) + { + return await UpdateAIAnalysisItemDismissedStateAsync(applicationId, itemId, isDismissed: true); + } + + public async Task RestoreAIAnalysisItemAsync(Guid applicationId, string itemId) + { + return await UpdateAIAnalysisItemDismissedStateAsync(applicationId, itemId, isDismissed: false); + } + + private async Task UpdateAIAnalysisItemDismissedStateAsync(Guid applicationId, string itemId, bool isDismissed) + { + if (string.IsNullOrWhiteSpace(itemId)) + { + throw new UserFriendlyException("AI analysis item id is required."); + } var application = await applicationRepository.GetAsync(applicationId); @@ -1094,67 +1095,67 @@ private async Task UpdateAIAnalysisItemVisibilityStateAsync(Guid applica { throw new UserFriendlyException("No AI analysis available for this application."); } - - try - { - var updatedAnalysis = SetAnalysisItemHiddenState(application.AIAnalysis, itemId, isHidden); - application.AIAnalysis = updatedAnalysis; - await applicationRepository.UpdateAsync(application); - return updatedAnalysis; - } - catch (Exception ex) - { - var action = isHidden ? "hiding" : "showing"; - var userMessage = isHidden - ? "Failed to hide the AI item. Please try again." - : "Failed to show the AI item. Please try again."; + + try + { + var updatedAnalysis = SetAnalysisItemDismissedState(application.AIAnalysis, itemId, isDismissed); + application.AIAnalysis = updatedAnalysis; + await applicationRepository.UpdateAsync(application); + return updatedAnalysis; + } + catch (Exception ex) + { + var action = isDismissed ? "dismissing" : "restoring"; + var userMessage = isDismissed + ? "Failed to dismiss the AI item. Please try again." + : "Failed to restore the AI item. Please try again."; Logger.LogError(ex, "Error {Action} AI analysis item {ItemId} for application {ApplicationId}", action, itemId, applicationId); throw new UserFriendlyException(userMessage); - } - } - - private static string SetAnalysisItemHiddenState(string analysisJson, string itemId, bool isHidden) - { - if (string.IsNullOrWhiteSpace(analysisJson)) - { - return analysisJson; - } + } + } + + private static string SetAnalysisItemDismissedState(string analysisJson, string itemId, bool isDismissed) + { + if (string.IsNullOrWhiteSpace(analysisJson)) + { + return analysisJson; + } try { var analysis = System.Text.Json.JsonSerializer.Deserialize(analysisJson, AiAnalysisReadOptions); - if (analysis == null) - { - return analysisJson; - } - - UpdateFindingHiddenState(analysis.Errors, itemId, isHidden); - UpdateFindingHiddenState(analysis.Warnings, itemId, isHidden); - UpdateFindingHiddenState(analysis.Summaries, itemId, isHidden); - UpdateFindingHiddenState(analysis.NextSteps, itemId, isHidden); - - return System.Text.Json.JsonSerializer.Serialize(analysis, AiAnalysisWriteOptions); - } - catch (System.Text.Json.JsonException) - { - return analysisJson; - } - } - - private static void UpdateFindingHiddenState(IEnumerable findings, string itemId, bool isHidden) - { - foreach (var finding in findings) - { - if (!string.Equals(finding.Id, itemId, StringComparison.Ordinal)) - { - continue; - } - - finding.Hidden = isHidden; - return; - } - } + if (analysis == null) + { + return analysisJson; + } + + UpdateFindingDismissedState(analysis.Errors, itemId, isDismissed); + UpdateFindingDismissedState(analysis.Warnings, itemId, isDismissed); + UpdateFindingDismissedState(analysis.Summaries, itemId, isDismissed); + UpdateFindingDismissedState(analysis.Recommendations, itemId, isDismissed); + + return System.Text.Json.JsonSerializer.Serialize(analysis, AiAnalysisWriteOptions); + } + catch (System.Text.Json.JsonException) + { + return analysisJson; + } + } + + private static void UpdateFindingDismissedState(IEnumerable findings, string itemId, bool isDismissed) + { + foreach (var finding in findings) + { + if (!string.Equals(finding.Id, itemId, StringComparison.Ordinal)) + { + continue; + } + + finding.Dismissed = isDismissed; + return; + } + } private static ApplicationAnalysisResponse? ParseAiAnalysisData(string? analysisJson) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs index 2cfa84db89..168a2dc905 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationAutoMapperProfile.cs @@ -45,6 +45,8 @@ public GrantManagerApplicationAutoMapperProfile() .ForMember(dest => dest.OwnerId, opt => opt.MapFrom(src => src.AssessmentId)); CreateMap() .ForMember(dest => dest.OwnerId, opt => opt.MapFrom(src => src.ApplicationId)); + CreateMap() + .ForMember(dest => dest.OwnerId, opt => opt.MapFrom(src => src.ApplicantId)); CreateMap() .ForMember(dest => dest.Badge, opt => opt.MapFrom(src => src.CommenterBadge)) .ForMember(dest => dest.Commenter, opt => opt.MapFrom(src => src.CommenterDisplayName)) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs index 033d04d512..dae27b6bc8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantManagerApplicationModule.cs @@ -120,6 +120,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) provider.SecretAccessKey = configuration["S3:SecretAccessKey"] ?? ""; provider.ApplicationS3Folder = configuration["S3:ApplicationS3Folder"] ?? ""; provider.AssessmentS3Folder = configuration["S3:AssessmentS3Folder"] ?? ""; + provider.ApplicantS3Folder = configuration["S3:ApplicantS3Folder"] ?? ""; }); }); }); @@ -160,8 +161,10 @@ public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddTransient(); context.Services.AddTransient(); context.Services.AddTransient(); + context.Services.AddTransient(); context.Services.AddTransient(); context.Services.AddTransient(); + context.Services.AddTransient(); context.Services.AddTransient(); // Register generic IInboxMessageHandler adapters for each portal command handler @@ -169,8 +172,10 @@ public override void ConfigureServices(ServiceConfigurationContext context) context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); + context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); + context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); context.Services.AddTransient(sp => new PortalCommandHandlerAdapter(sp.GetRequiredService())); context.Services.AddScoped(); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressCreateHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressCreateHandler.cs new file mode 100644 index 0000000000..5c97ac4481 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressCreateHandler.cs @@ -0,0 +1,94 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Unity.GrantManager.Applications; +using Unity.GrantManager.GrantApplications; +using Unity.GrantManager.GrantsPortal.Messages; +using Unity.GrantManager.GrantsPortal.Messages.Commands; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Uow; + +namespace Unity.GrantManager.GrantsPortal.Handlers; + +public class AddressCreateHandler( + IApplicantAddressRepository applicantAddressRepository, + ILogger logger) : IPortalCommandHandler, ITransientDependency +{ + public string DataType => "ADDRESS_CREATE_COMMAND"; + + [UnitOfWork] + public virtual async Task HandleAsync(PluginDataPayload payload) + { + var addressId = Guid.Parse(payload.AddressId ?? throw new ArgumentException("addressId is required")); + var profileId = Guid.Parse(payload.ProfileId ?? throw new ArgumentException("profileId is required")); + var innerData = payload.Data?.ToObject() + ?? throw new ArgumentException("Address data is required"); + + if (innerData.ApplicantId == Guid.Empty) + { + throw new ArgumentException("applicantId is required"); + } + + // Idempotency: if the address already exists, treat as success + var existing = await applicantAddressRepository.FindAsync(addressId); + if (existing != null) + { + logger.LogInformation("Address {AddressId} already exists. Treating as idempotent success.", addressId); + return "Address already exists"; + } + + logger.LogInformation("Creating address {AddressId} for profile {ProfileId}", addressId, profileId); + + var address = new ApplicantAddress + { + ApplicantId = innerData.ApplicantId, + Street = innerData.Street, + Street2 = innerData.Street2, + Unit = innerData.Unit, + City = innerData.City, + Province = innerData.Province, + Postal = innerData.PostalCode, + Country = innerData.Country, + AddressType = MapAddressType(innerData.AddressType) + }; + + EntityHelper.TrySetId(address, () => addressId); + + address.SetProperty(AddressExtraPropertyNames.ProfileId, profileId.ToString()); + address.SetProperty(AddressExtraPropertyNames.IsPrimary, innerData.IsPrimary); + + // Demote existing primary addresses for the same applicant + if (innerData.IsPrimary) + { + var siblingAddresses = await applicantAddressRepository.FindByApplicantIdAsync(innerData.ApplicantId); + + foreach (var sibling in siblingAddresses) + { + if (!sibling.HasProperty(AddressExtraPropertyNames.IsPrimary)) continue; + if (!sibling.GetProperty(AddressExtraPropertyNames.IsPrimary)) continue; + + var trackedSibling = await applicantAddressRepository.GetAsync(sibling.Id); + trackedSibling.SetProperty(AddressExtraPropertyNames.IsPrimary, false); + await applicantAddressRepository.UpdateAsync(trackedSibling); + } + } + + await applicantAddressRepository.InsertAsync(address); + + logger.LogInformation("Address {AddressId} created successfully", addressId); + return "Address created successfully"; + } + + private static AddressType MapAddressType(string? portalAddressType) + { + return portalAddressType?.ToUpperInvariant() switch + { + "MAILING" => AddressType.MailingAddress, + "PHYSICAL" => AddressType.PhysicalAddress, + "BUSINESS" => AddressType.BusinessAddress, + _ => AddressType.PhysicalAddress + }; + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressDeleteHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressDeleteHandler.cs new file mode 100644 index 0000000000..a45a2c8a49 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressDeleteHandler.cs @@ -0,0 +1,33 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Unity.GrantManager.Applications; +using Unity.GrantManager.GrantsPortal.Messages; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Uow; + +namespace Unity.GrantManager.GrantsPortal.Handlers; + +public class AddressDeleteHandler( + IApplicantAddressRepository applicantAddressRepository, + ILogger logger) : IPortalCommandHandler, ITransientDependency +{ + public string DataType => "ADDRESS_DELETE_COMMAND"; + + [UnitOfWork] + public virtual async Task HandleAsync(PluginDataPayload payload) + { + var addressId = Guid.Parse(payload.AddressId ?? throw new ArgumentException("addressId is required")); + + logger.LogInformation("Deleting address {AddressId} for profile {ProfileId}", addressId, payload.ProfileId); + + var address = await applicantAddressRepository.FindAsync(addressId); + if (address != null) + { + await applicantAddressRepository.DeleteAsync(address); + } + + logger.LogInformation("Address {AddressId} deleted successfully", addressId); + return "Address deleted successfully"; + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressEditHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressEditHandler.cs index 202464a00e..01f6010d0a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressEditHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressEditHandler.cs @@ -5,6 +5,7 @@ using Unity.GrantManager.GrantApplications; using Unity.GrantManager.GrantsPortal.Messages; using Unity.GrantManager.GrantsPortal.Messages.Commands; +using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Uow; @@ -36,12 +37,35 @@ public virtual async Task HandleAsync(PluginDataPayload payload) address.Country = innerData.Country; address.AddressType = MapAddressType(innerData.AddressType); + if (innerData.IsPrimary && address.ApplicantId.HasValue) + { + await DemoteSiblingPrimaryAddressesAsync(address.ApplicantId.Value, addressId); + } + + address.SetProperty(AddressExtraPropertyNames.IsPrimary, innerData.IsPrimary); + await applicantAddressRepository.UpdateAsync(address); logger.LogInformation("Address {AddressId} updated successfully", addressId); return "Address updated successfully"; } + private async Task DemoteSiblingPrimaryAddressesAsync(Guid applicantId, Guid excludeAddressId) + { + var siblingAddresses = await applicantAddressRepository.FindByApplicantIdAsync(applicantId); + + foreach (var sibling in siblingAddresses) + { + if (sibling.Id == excludeAddressId) continue; + if (!sibling.HasProperty(AddressExtraPropertyNames.IsPrimary)) continue; + if (!sibling.GetProperty(AddressExtraPropertyNames.IsPrimary)) continue; + + var trackedSibling = await applicantAddressRepository.GetAsync(sibling.Id); + trackedSibling.SetProperty(AddressExtraPropertyNames.IsPrimary, false); + await applicantAddressRepository.UpdateAsync(trackedSibling); + } + } + private static AddressType MapAddressType(string? portalAddressType) { return portalAddressType?.ToUpperInvariant() switch diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressSetPrimaryHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressSetPrimaryHandler.cs index 96607436d3..0496e683f4 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressSetPrimaryHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/AddressSetPrimaryHandler.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Unity.GrantManager.Applications; +using Unity.GrantManager.GrantApplications; using Unity.GrantManager.GrantsPortal.Messages; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; @@ -26,8 +27,8 @@ public virtual async Task HandleAsync(PluginDataPayload payload) var address = await applicantAddressRepository.GetAsync(addressId); - address.SetProperty("profileId", profileId.ToString()); - address.SetProperty("isPrimary", true); + address.SetProperty(AddressExtraPropertyNames.ProfileId, profileId.ToString()); + address.SetProperty(AddressExtraPropertyNames.IsPrimary, true); if (address.ApplicantId.HasValue) { @@ -36,10 +37,11 @@ public virtual async Task HandleAsync(PluginDataPayload payload) foreach (var sibling in siblingAddresses) { if (sibling.Id == addressId) continue; - if (!sibling.HasProperty("isPrimary")) continue; + if (!sibling.HasProperty(AddressExtraPropertyNames.IsPrimary)) continue; + if (!sibling.GetProperty(AddressExtraPropertyNames.IsPrimary)) continue; var trackedSibling = await applicantAddressRepository.GetAsync(sibling.Id); - trackedSibling.SetProperty("isPrimary", false); + trackedSibling.SetProperty(AddressExtraPropertyNames.IsPrimary, false); await applicantAddressRepository.UpdateAsync(trackedSibling); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactCreateHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactCreateHandler.cs index 1e618a100b..8a8368ef26 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactCreateHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactCreateHandler.cs @@ -1,13 +1,10 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -using Unity.GrantManager.Applications; using Unity.GrantManager.Contacts; using Unity.GrantManager.GrantsPortal.Messages; using Unity.GrantManager.GrantsPortal.Messages.Commands; -using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Entities; using Volo.Abp.Uow; @@ -17,10 +14,10 @@ namespace Unity.GrantManager.GrantsPortal.Handlers; public class ContactCreateHandler( IContactRepository contactRepository, IContactLinkRepository contactLinkRepository, - IApplicationFormSubmissionRepository applicationFormSubmissionRepository, - IApplicantAgentRepository applicantAgentRepository, ILogger logger) : IPortalCommandHandler, ITransientDependency { + private const string ApplicantEntityType = "Applicant"; + public string DataType => "CONTACT_CREATE_COMMAND"; [UnitOfWork] @@ -54,22 +51,29 @@ public virtual async Task HandleAsync(PluginDataPayload payload) EntityHelper.TrySetId(contact, () => contactId); - // Lookup applicant agent IDs associated with this subject's submissions - var applicantAgentIds = await GetApplicantAgentIdsAsync(payload.Subject); - if (applicantAgentIds.Count > 0) + await contactRepository.InsertAsync(contact); + + // Demote existing primary contact links for the same applicant + if (innerData.IsPrimary) { - contact.SetProperty("applicantAgentIds", applicantAgentIds); - logger.LogInformation("Found {Count} applicant agent(s) for subject {Subject}", applicantAgentIds.Count, payload.Subject); + var contactLinks = await contactLinkRepository.GetListAsync( + cl => cl.RelatedEntityType == ApplicantEntityType + && cl.RelatedEntityId == innerData.ApplicantId + && cl.IsActive); + + foreach (var stale in contactLinks.Where(cl => cl.IsPrimary)) + { + stale.IsPrimary = false; + await contactLinkRepository.UpdateAsync(stale); + } } - await contactRepository.InsertAsync(contact); - // Create a contact link to track the relationship and primary status var contactLink = new ContactLink { ContactId = contactId, - RelatedEntityType = innerData.ContactType ?? "PORTAL", - RelatedEntityId = profileId, + RelatedEntityType = ApplicantEntityType, + RelatedEntityId = innerData.ApplicantId, Role = innerData.Role, IsPrimary = innerData.IsPrimary, IsActive = true @@ -80,63 +84,4 @@ public virtual async Task HandleAsync(PluginDataPayload payload) logger.LogInformation("Contact {ContactId} created successfully", contactId); return "Contact created successfully"; } - - private async Task> GetApplicantAgentIdsAsync(string? subject) - { - if (string.IsNullOrWhiteSpace(subject)) - { - return []; - } - - var normalizedSub = NormalizeOidcSub(subject); - if (string.IsNullOrWhiteSpace(normalizedSub)) - { - return []; - } - - // Find submissions matching the normalized OidcSub - var submissions = await applicationFormSubmissionRepository.GetListAsync(s => s.OidcSub == normalizedSub); - if (submissions.Count == 0) - { - logger.LogDebug("No submissions found for subject {Subject} (normalized: {NormalizedSub})", subject, normalizedSub); - return []; - } - - // Get distinct application IDs from the submissions - var applicationIds = submissions - .Select(s => s.ApplicationId) - .Distinct() - .ToList(); - - // Lookup applicant agents linked to those applications - var agents = await applicantAgentRepository - .GetListAsync(a => a.ApplicationId != null && applicationIds.Contains(a.ApplicationId!.Value)); - - return [.. agents - .Select(a => a.Id.ToString()) - .Distinct()]; - } - - /// - /// Normalizes a raw OIDC subject by stripping the IDP suffix (after @) and uppercasing. - /// This matches the format stored in ApplicationFormSubmission.OidcSub. - /// - internal static string? NormalizeOidcSub(string? subject) - { - if (string.IsNullOrWhiteSpace(subject)) - { - return null; - } - - var atIndex = subject.IndexOf('@'); - - if (atIndex == 0) - { - return null; - } - - return atIndex > 0 - ? subject[..atIndex].ToUpperInvariant() - : subject.ToUpperInvariant(); - } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactEditHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactEditHandler.cs index c640ec3808..2aa38756bc 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactEditHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactEditHandler.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Unity.GrantManager.Contacts; @@ -11,8 +13,11 @@ namespace Unity.GrantManager.GrantsPortal.Handlers; public class ContactEditHandler( IContactRepository contactRepository, + IContactLinkRepository contactLinkRepository, ILogger logger) : IPortalCommandHandler, ITransientDependency { + private const string ApplicantEntityType = "Applicant"; + public string DataType => "CONTACT_EDIT_COMMAND"; [UnitOfWork] @@ -22,21 +27,77 @@ public virtual async Task HandleAsync(PluginDataPayload payload) var innerData = payload.Data?.ToObject() ?? throw new ArgumentException("Contact data is required"); + if (innerData.ApplicantId == Guid.Empty) + { + throw new ArgumentException("applicantId is required"); + } + logger.LogInformation("Editing contact {ContactId} for profile {ProfileId}", contactId, payload.ProfileId); + await UpdateContactAsync(contactId, innerData); + await SyncContactLinkAsync(contactId, innerData); + + logger.LogInformation("Contact {ContactId} updated successfully", contactId); + return "Contact updated successfully"; + } + + private async Task UpdateContactAsync(Guid contactId, ContactEditData data) + { var contact = await contactRepository.GetAsync(contactId); - contact.Name = innerData.Name; - contact.Email = innerData.Email; - contact.Title = innerData.Title; - contact.HomePhoneNumber = innerData.HomePhoneNumber; - contact.MobilePhoneNumber = innerData.MobilePhoneNumber; - contact.WorkPhoneNumber = innerData.WorkPhoneNumber; - contact.WorkPhoneExtension = innerData.WorkPhoneExtension; + contact.Name = data.Name; + contact.Email = data.Email; + contact.Title = data.Title; + contact.HomePhoneNumber = data.HomePhoneNumber; + contact.MobilePhoneNumber = data.MobilePhoneNumber; + contact.WorkPhoneNumber = data.WorkPhoneNumber; + contact.WorkPhoneExtension = data.WorkPhoneExtension; await contactRepository.UpdateAsync(contact); + } - logger.LogInformation("Contact {ContactId} updated successfully", contactId); - return "Contact updated successfully"; + private async Task SyncContactLinkAsync(Guid contactId, ContactEditData data) + { + var contactLinks = await contactLinkRepository.GetListAsync( + cl => cl.RelatedEntityType == ApplicantEntityType + && cl.RelatedEntityId == data.ApplicantId + && cl.IsActive); + + if (data.IsPrimary) + { + await DemoteOtherPrimaryLinksAsync(contactLinks, contactId); + } + + var targetLink = contactLinks.FirstOrDefault(cl => cl.ContactId == contactId); + if (targetLink != null) + { + var hasChanges = false; + + if (targetLink.IsPrimary != data.IsPrimary) + { + targetLink.IsPrimary = data.IsPrimary; + hasChanges = true; + } + + if (data.Role is not null && targetLink.Role != data.Role) + { + targetLink.Role = data.Role; + hasChanges = true; + } + + if (hasChanges) + { + await contactLinkRepository.UpdateAsync(targetLink); + } + } + } + + private async Task DemoteOtherPrimaryLinksAsync(List contactLinks, Guid contactId) + { + foreach (var stale in contactLinks.Where(cl => cl.IsPrimary && cl.ContactId != contactId)) + { + stale.IsPrimary = false; + await contactLinkRepository.UpdateAsync(stale); + } } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactSetPrimaryHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactSetPrimaryHandler.cs index b02a8c43fa..0c2fbbf151 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactSetPrimaryHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Handlers/ContactSetPrimaryHandler.cs @@ -1,8 +1,10 @@ +using Microsoft.Extensions.Logging; using System; +using System.Linq; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Unity.GrantManager.Contacts; using Unity.GrantManager.GrantsPortal.Messages; +using Unity.GrantManager.GrantsPortal.Messages.Commands; using Volo.Abp.DependencyInjection; using Volo.Abp.Uow; @@ -12,6 +14,8 @@ public class ContactSetPrimaryHandler( IContactLinkRepository contactLinkRepository, ILogger logger) : IPortalCommandHandler, ITransientDependency { + private const string ApplicantEntityType = "Applicant"; + public string DataType => "CONTACT_SET_PRIMARY_COMMAND"; [UnitOfWork] @@ -19,17 +23,33 @@ public virtual async Task HandleAsync(PluginDataPayload payload) { var contactId = Guid.Parse(payload.ContactId ?? throw new ArgumentException("contactId is required")); var profileId = Guid.Parse(payload.ProfileId ?? throw new ArgumentException("profileId is required")); + var innerData = payload.Data?.ToObject() + ?? throw new ArgumentException("Contact data is required"); + + if (innerData.ApplicantId == Guid.Empty) + { + throw new ArgumentException("applicantId is required"); + } logger.LogInformation("Setting contact {ContactId} as primary for profile {ProfileId}", contactId, profileId); - // Find all contact links for this profile and clear their primary flag - var profileLinks = await contactLinkRepository.GetListAsync( - cl => cl.RelatedEntityId == profileId && cl.IsActive); + // Only update links whose primary flag actually needs to change + var contactLinks = await contactLinkRepository.GetListAsync( + cl => cl.RelatedEntityType == ApplicantEntityType + && cl.RelatedEntityId == innerData.ApplicantId + && cl.IsActive); + + foreach (var stale in contactLinks.Where(cl => cl.IsPrimary && cl.ContactId != contactId)) + { + stale.IsPrimary = false; + await contactLinkRepository.UpdateAsync(stale); + } - foreach (var link in profileLinks) + var newPrimary = contactLinks.FirstOrDefault(cl => cl.ContactId == contactId && !cl.IsPrimary); + if (newPrimary != null) { - link.IsPrimary = link.ContactId == contactId; - await contactLinkRepository.UpdateAsync(link); + newPrimary.IsPrimary = true; + await contactLinkRepository.UpdateAsync(newPrimary); } logger.LogInformation("Contact {ContactId} set as primary", contactId); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressCreateData.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressCreateData.cs new file mode 100644 index 0000000000..368b6059a1 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressCreateData.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; +using System; + +namespace Unity.GrantManager.GrantsPortal.Messages.Commands; + +public class AddressCreateData : AddressDataBase +{ + [JsonProperty("applicantId")] + public Guid ApplicantId { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressDataBase.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressDataBase.cs new file mode 100644 index 0000000000..6316d366f1 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressDataBase.cs @@ -0,0 +1,33 @@ +using Newtonsoft.Json; + +namespace Unity.GrantManager.GrantsPortal.Messages.Commands; + +public abstract class AddressDataBase +{ + [JsonProperty("addressType")] + public string? AddressType { get; set; } + + [JsonProperty("street")] + public string Street { get; set; } = string.Empty; + + [JsonProperty("street2")] + public string? Street2 { get; set; } + + [JsonProperty("unit")] + public string? Unit { get; set; } + + [JsonProperty("city")] + public string City { get; set; } = string.Empty; + + [JsonProperty("province")] + public string Province { get; set; } = string.Empty; + + [JsonProperty("postalCode")] + public string PostalCode { get; set; } = string.Empty; + + [JsonProperty("country")] + public string? Country { get; set; } + + [JsonProperty("isPrimary")] + public bool IsPrimary { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressEditData.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressEditData.cs index 3d6c655fb4..491fc6eab8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressEditData.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/AddressEditData.cs @@ -1,33 +1,5 @@ -using Newtonsoft.Json; - namespace Unity.GrantManager.GrantsPortal.Messages.Commands; -public class AddressEditData +public class AddressEditData : AddressDataBase { - [JsonProperty("addressType")] - public string? AddressType { get; set; } - - [JsonProperty("street")] - public string Street { get; set; } = string.Empty; - - [JsonProperty("street2")] - public string? Street2 { get; set; } - - [JsonProperty("unit")] - public string? Unit { get; set; } - - [JsonProperty("city")] - public string City { get; set; } = string.Empty; - - [JsonProperty("province")] - public string Province { get; set; } = string.Empty; - - [JsonProperty("postalCode")] - public string PostalCode { get; set; } = string.Empty; - - [JsonProperty("country")] - public string? Country { get; set; } - - [JsonProperty("isPrimary")] - public bool IsPrimary { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactCreateData.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactCreateData.cs index e89566c42d..56ebd4a9a4 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactCreateData.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactCreateData.cs @@ -1,36 +1,5 @@ -using Newtonsoft.Json; - namespace Unity.GrantManager.GrantsPortal.Messages.Commands; -public class ContactCreateData +public class ContactCreateData : ContactDataBase { - [JsonProperty("name")] - public string Name { get; set; } = string.Empty; - - [JsonProperty("email")] - public string Email { get; set; } = string.Empty; - - [JsonProperty("title")] - public string? Title { get; set; } - - [JsonProperty("contactType")] - public string? ContactType { get; set; } - - [JsonProperty("homePhoneNumber")] - public string? HomePhoneNumber { get; set; } - - [JsonProperty("mobilePhoneNumber")] - public string? MobilePhoneNumber { get; set; } - - [JsonProperty("workPhoneNumber")] - public string? WorkPhoneNumber { get; set; } - - [JsonProperty("workPhoneExtension")] - public string? WorkPhoneExtension { get; set; } - - [JsonProperty("role")] - public string? Role { get; set; } - - [JsonProperty("isPrimary")] - public bool IsPrimary { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactDataBase.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactDataBase.cs new file mode 100644 index 0000000000..7fde20c344 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactDataBase.cs @@ -0,0 +1,40 @@ +using Newtonsoft.Json; +using System; + +namespace Unity.GrantManager.GrantsPortal.Messages.Commands; + +public abstract class ContactDataBase +{ + [JsonProperty("name")] + public string Name { get; set; } = string.Empty; + + [JsonProperty("email")] + public string Email { get; set; } = string.Empty; + + [JsonProperty("title")] + public string? Title { get; set; } + + [JsonProperty("contactType")] + public string? ContactType { get; set; } + + [JsonProperty("homePhoneNumber")] + public string? HomePhoneNumber { get; set; } + + [JsonProperty("mobilePhoneNumber")] + public string? MobilePhoneNumber { get; set; } + + [JsonProperty("workPhoneNumber")] + public string? WorkPhoneNumber { get; set; } + + [JsonProperty("workPhoneExtension")] + public string? WorkPhoneExtension { get; set; } + + [JsonProperty("role")] + public string? Role { get; set; } + + [JsonProperty("isPrimary")] + public bool IsPrimary { get; set; } + + [JsonProperty("applicantId")] + public Guid ApplicantId { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactEditData.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactEditData.cs index a4f4f5d605..cb653c1cf2 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactEditData.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactEditData.cs @@ -1,36 +1,5 @@ -using Newtonsoft.Json; - namespace Unity.GrantManager.GrantsPortal.Messages.Commands; -public class ContactEditData +public class ContactEditData : ContactDataBase { - [JsonProperty("name")] - public string Name { get; set; } = string.Empty; - - [JsonProperty("email")] - public string Email { get; set; } = string.Empty; - - [JsonProperty("title")] - public string? Title { get; set; } - - [JsonProperty("contactType")] - public string? ContactType { get; set; } - - [JsonProperty("homePhoneNumber")] - public string? HomePhoneNumber { get; set; } - - [JsonProperty("mobilePhoneNumber")] - public string? MobilePhoneNumber { get; set; } - - [JsonProperty("workPhoneNumber")] - public string? WorkPhoneNumber { get; set; } - - [JsonProperty("workPhoneExtension")] - public string? WorkPhoneExtension { get; set; } - - [JsonProperty("role")] - public string? Role { get; set; } - - [JsonProperty("isPrimary")] - public bool IsPrimary { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactSetPrimaryData.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactSetPrimaryData.cs new file mode 100644 index 0000000000..a213a846a8 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/GrantsPortal/Messages/Commands/ContactSetPrimaryData.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; +using System; + +namespace Unity.GrantManager.GrantsPortal.Messages.Commands; + +public class ContactSetPrimaryData +{ + [JsonProperty("applicantId")] + public Guid ApplicantId { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/AIApplicationScoringGeneratedEvent.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/AIApplicationScoringGeneratedEvent.cs deleted file mode 100644 index b5dc7bdf72..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Events/AIApplicationScoringGeneratedEvent.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace Unity.GrantManager.Intakes.Events; - -public class AIApplicationScoringGeneratedEvent -{ - public Guid ApplicationId { get; set; } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs index f757747e49..f1d92723ee 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/DetermineElectoralDistrictHandler.cs @@ -91,12 +91,35 @@ public async Task DetermineElectoralDistrictAsync(Application? application, Appl } // Extract from geo services - var address = matchedAddressType.GetFullAddress(); + var address = matchedAddressType.GetSearchAddress(); var geoAddressDetails = await geocoderApiService.GetAddressDetailsAsync(address); if (geoAddressDetails == null || geoAddressDetails.Coordinates == null) { - logger.LogWarning("No coordinates found for address: {Address}", address); + logger.LogWarning("No coordinates found for address: {Address} for application {ApplicationId}.", + address, application.Id); + return; + } + + logger.LogInformation( + "Geocoder resolved address for application {ApplicationId}: " + + "Input={Address}, Resolved={ResolvedAddress}, Score={GeocoderScore}, " + + "Coordinates=({Latitude}, {Longitude})", + application.Id, + address, + geoAddressDetails.FullAddress, + geoAddressDetails.Score, + geoAddressDetails.Coordinates.Latitude, + geoAddressDetails.Coordinates.Longitude); + + if (geoAddressDetails.Score < 60) + { + application.ApplicantElectoralDistrict = null; + logger.LogWarning( + "Low geocoder confidence score {GeocoderScore} for application {ApplicationId}. " + + "Input={Address}, Resolved={ResolvedAddress}. " + + "Electoral district set to null due to unreliable geocoding.", + geoAddressDetails.Score, application.Id, address, geoAddressDetails.FullAddress); return; } @@ -105,12 +128,17 @@ public async Task DetermineElectoralDistrictAsync(Application? application, Appl if (electoralDistrict.Name != null) { application.ApplicantElectoralDistrict = electoralDistrict.Name; - logger.LogInformation("Electoral district '{ElectoralDistrict}' determined for address: {Address}", - electoralDistrict.Name, address); + logger.LogInformation( + "Electoral district '{ElectoralDistrict}' determined for application {ApplicationId}. " + + "Address={Address}, GeocoderScore={GeocoderScore}", + electoralDistrict.Name, application.Id, address, geoAddressDetails.Score); } else { - logger.LogWarning("Electoral district could not be determined for address: {Address}", address); + logger.LogWarning( + "Electoral district could not be determined for application {ApplicationId}. " + + "Address={Address}, GeocoderScore={GeocoderScore}", + application.Id, address, geoAddressDetails.Score); } } catch (Exception ex) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateAIContentHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateAIContentHandler.cs deleted file mode 100644 index c4d882b043..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/Handlers/GenerateAIContentHandler.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using Unity.GrantManager.AI.BackgroundJobs; -using Unity.GrantManager.Intakes.Events; -using Volo.Abp.BackgroundJobs; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus; -using Volo.Abp.MultiTenancy; - -namespace Unity.GrantManager.Intakes.Handlers; - -public class GenerateAIContentHandler( - IBackgroundJobManager backgroundJobManager, - ICurrentTenant currentTenant, - ILogger logger) : ILocalEventHandler, ITransientDependency -{ - public async Task HandleEventAsync(ApplicationProcessEvent eventData) - { - if (eventData?.Application == null) - { - logger.LogWarning("Event data or application is null in GenerateAIContentHandler."); - return; - } - - try - { - await backgroundJobManager.EnqueueAsync(new GenerateContentBackgroundJobArgs - { - ApplicationId = eventData.Application.Id, - TenantId = currentTenant.Id - }); - - logger.LogInformation("Queued AI content generation for application {ApplicationId}.", eventData.Application.Id); - } - catch (Exception ex) - { - logger.LogError(ex, "Error queueing AI content generation for application {ApplicationId}.", eventData.Application.Id); - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs index 3bdefcbbd7..7d2faae6a8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Intakes/SubmissionAppService.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using System; using System.Collections.Generic; using System.Linq; @@ -105,7 +105,7 @@ public async Task GetChefsFileAttachment(Guid? formSubmissionId, Guid? // Check and decode the file name if it is URL encoded if (!string.IsNullOrEmpty(name) && name.Contains('%')) { - name = Uri.UnescapeDataString(name); + name = Uri.UnescapeDataString(name); } return new BlobDto { Name = name, Content = contentBytes, ContentType = contentType }; @@ -141,7 +141,7 @@ join applicationForm in await applicationFormRepository.GetQueryableAsync() on a return applicationFormSubmissionData; } - public async Task> GetSubmissionsList(bool allSubmissions) + public async Task> GetSubmissionsListAsync(GetSubmissionsListInput input) { var chefsSubmissions = new List(); var serializerOptions = CreateJsonSerializerOptions(); @@ -149,19 +149,49 @@ public async Task> GetSubmissionsList(b var unityRefNos = new HashSet(); var checkedForms = new HashSet(); + if (!string.IsNullOrWhiteSpace(input.TenantName)) + { + tenants = tenants + .Where(t => string.Equals(t.Name, input.TenantName, StringComparison.OrdinalIgnoreCase)) + .ToList(); + } + foreach (var tenant in tenants) { using (CurrentTenant.Change(tenant.Id)) { + //This could be overloaded to include the input.DateFrom, and input.DateTo when calling applicationRepository, + //the problem is we need to use all forms returned from app repository to search Chefs via IDs. + //so date filtering at the moment occurs post-processing await ProcessTenantSubmissions(tenant, chefsSubmissions, serializerOptions, checkedForms, unityRefNos); } } - UpdateSubmissionsWithUnityFlags(chefsSubmissions, unityRefNos); + foreach (var submission in chefsSubmissions) + { + submission.inUnity = unityRefNos.Contains(submission.ConfirmationId.ToString()); + } - if (!allSubmissions) + if (input.DateFrom.HasValue || input.DateTo.HasValue) { - chefsSubmissions.RemoveAll(s => unityRefNos.Contains(s.ConfirmationId.ToString())); + DateTime? exclusiveUpperBoundForDateTo = null; + if (input.DateTo.HasValue && input.DateTo.Value.TimeOfDay == TimeSpan.Zero) + { + // Inclusive end-of-day + exclusiveUpperBoundForDateTo = input.DateTo.Value.Date.AddDays(1); + } + chefsSubmissions.RemoveAll(submission => + (input.DateFrom.HasValue && submission.CreatedAt < input.DateFrom.Value) || + (input.DateTo.HasValue && ( + exclusiveUpperBoundForDateTo.HasValue + ? submission.CreatedAt >= exclusiveUpperBoundForDateTo.Value + : submission.CreatedAt > input.DateTo.Value + ))); + } + + if (!input.ReturnAllSubmissions) + { + chefsSubmissions.RemoveAll(submission => submission.inUnity); } return new PagedResultDto(chefsSubmissions.Count, chefsSubmissions); @@ -246,12 +276,4 @@ private async Task FetchChefsSubmissions( Logger.LogError(ex, "GetSubmissionsList Exception: {Message}", ex.Message); } } - - private static void UpdateSubmissionsWithUnityFlags(List chefsSubmissions, HashSet unityRefNos) - { - foreach (var submission in chefsSubmissions) - { - submission.inUnity = unityRefNos.Contains(submission.ConfirmationId.ToString()); - } - } -} \ No newline at end of file +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Unity.GrantManager.Application.csproj b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Unity.GrantManager.Application.csproj index 3ff76f7291..dcd0c31780 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Unity.GrantManager.Application.csproj +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Unity.GrantManager.Application.csproj @@ -1,4 +1,4 @@ - + @@ -49,11 +49,5 @@ - - - PreserveNewest - PreserveNewest - - diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Attachments/AttachmentType.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Attachments/AttachmentType.cs index 944cd73765..956f7be21d 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Attachments/AttachmentType.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Attachments/AttachmentType.cs @@ -8,5 +8,6 @@ public enum AttachmentType APPLICATION = 0, ASSESSMENT = 1, CHEFS = 2, - EMAIL = 3 + EMAIL = 3, + APPLICANT = 4 } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Comments/CommentType.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Comments/CommentType.cs index fdf669ff36..5e4f3be809 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Comments/CommentType.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Comments/CommentType.cs @@ -1,8 +1,12 @@ -namespace Unity.GrantManager.Comments +using System.Text.Json.Serialization; + +namespace Unity.GrantManager.Comments; + +/// If changing this enum, also update the corresponding Unity.Notifications.Comments.CommentType enum, as it is shared between the two projects and used in the API layer. +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum CommentType { - public enum CommentType - { - ApplicationComment, - AssessmentComment - } + ApplicationComment, + AssessmentComment, + ApplicantComment, } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantApplications/AddressExtraPropertyNames.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantApplications/AddressExtraPropertyNames.cs new file mode 100644 index 0000000000..7139afe1d6 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/GrantApplications/AddressExtraPropertyNames.cs @@ -0,0 +1,7 @@ +namespace Unity.GrantManager.GrantApplications; + +public static class AddressExtraPropertyNames +{ + public const string IsPrimary = "isPrimary"; + public const string ProfileId = "profileId"; +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json index fe3e30cd2c..89d5df054e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json @@ -102,10 +102,20 @@ "ReviewerList:Subtotal": "Subtotal", "ReviewerList:CloneAssessment": "Clone Assessment", - "AssessmentResultAttachments:Id": "#", - "AssessmentResultAttachments:DocumentName": "Document Name", - "AssessmentResultAttachments:UploadedDate": "Date", - "AssessmentResultAttachments:AttachedBy": "Attached by", + "AssessmentResultAttachments:Id": "#", + "AssessmentResultAttachments:DocumentName": "Document Name", + "AssessmentResultAttachments:UploadedDate": "Date", + "AssessmentResultAttachments:AttachedBy": "Attached by", + "ChefsAttachments:Title": "Submission Attachments", + "ChefsAttachments:Filter": "Filter", + "ChefsAttachments:Download": "Download", + "ChefsAttachments:GenerateSummaries": "Generate AI Summaries", + "ChefsAttachments:GenerateSummary": "Generate Summary", + "ChefsAttachments:HideAISummaries": "Hide AI Summaries", + "ChefsAttachments:ShowAISummaries": "Show AI Summaries", + "ChefsAttachments:HideSummaries": "Hide Summaries", + "ChefsAttachments:ShowSummaries": "Show Summaries", + "ChefsAttachments:NoSummariesAvailable": "No summaries available", "Enum:AssessmentState.IN_PROGRESS": "In Progress", "Enum:AssessmentState.IN_REVIEW": "Under Review by Team Lead", @@ -478,6 +488,19 @@ "ApplicationLinks:Category": "Category", "ApplicationLinks:ID": "ID", "ApplicationLinks:Status": "Status", - "ApplicationLinks:LinkType": "Link Type" + "ApplicationLinks:LinkType": "Link Type", + + "ApplicantPortalSettings:Title": "Applicant Portal Configuration", + "ApplicantPortalSettings:ManageStatuses": "Manage Statuses", + "ApplicantPortalSettings:PortalStatusHeading": "Applicant Portal Status", + "ApplicantPortalSettings:InternalStatus": "Internal Status", + "ApplicantPortalSettings:PortalStatusLabel": "Portal Status Label", + "ApplicantPortalSettings:SaveChanges": "Save Changes", + "ApplicantPortalSettings:ResetChanges": "Reset", + "ApplicantPortalSettings:SaveSuccess": "Portal status labels updated successfully.", + "ApplicantPortalSettings:SaveError": "An error occurred while saving portal status labels.", + "ApplicantPortalSettings:ValidationRequired": "Portal status label cannot be empty.", + "ApplicantPortalSettings:NoChanges": "No changes to save.", + "ApplicantPortalSettings:ChangesReset": "Changes have been reset to original values." } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs index f82c83afa4..d06415e6ca 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAddress.cs @@ -42,19 +42,15 @@ public virtual Application Application public Guid? TenantId { get; set; } /// - /// Returns the address as a single comma-separated string, ordered by relevance. + /// Returns a search-friendly address string (Street, Street2, City) for geocoding lookups. /// - public string GetFullAddress() + public string GetSearchAddress() { var parts = new[] { Street, Street2, - Unit, - City, - Province, - Postal, - Country + City }; var address = string.Join(", ", parts diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAttachment.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAttachment.cs new file mode 100644 index 0000000000..7cd3c10d2d --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicantAttachment.cs @@ -0,0 +1,12 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Unity.GrantManager.Attachments; + +namespace Unity.GrantManager.Applications; + +public class ApplicantAttachment : AbstractS3Attachment +{ + [NotMapped] + public override AttachmentType AttachmentType => AttachmentType.APPLICANT; + public Guid ApplicantId { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs index a7324e8678..d4377ae09e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/ApplicationForm.cs @@ -33,6 +33,8 @@ public class ApplicationForm : FullAuditedAggregateRoot, IMultiTenant public Guid? ParentFormId { get; set; } public bool RenderFormIoToHtml { get; set; } = false; public bool IsDirectApproval { get; set; } = false; + public bool AutomaticallyGenerateAIAnalysis { get; set; } = false; + public bool ManuallyInitiateAIAnalysis { get; set; } = false; [MaxLength(100)] public string? Prefix { get; set; } public SuffixConfigType? SuffixType { get; set; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicantAttachmentRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicantAttachmentRepository.cs new file mode 100644 index 0000000000..da65ccc89c --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Applications/IApplicantAttachmentRepository.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace Unity.GrantManager.Applications +{ + public interface IApplicantAttachmentRepository : IRepository + { + Task> GetListAsync( + int skipCount, + int maxResultCount, + string sorting, + string filter + ); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/ApplicantComment.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/ApplicantComment.cs new file mode 100644 index 0000000000..8c9e257e9a --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/ApplicantComment.cs @@ -0,0 +1,8 @@ +using System; + +namespace Unity.GrantManager.Comments; + +public class ApplicantComment : CommentBase +{ + public Guid ApplicantId { get; set; } +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/ApplicationComment.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/ApplicationComment.cs index a300320d4a..c50a6d5603 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/ApplicationComment.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/ApplicationComment.cs @@ -1,9 +1,8 @@ using System; -namespace Unity.GrantManager.Comments +namespace Unity.GrantManager.Comments; + +public class ApplicationComment : CommentBase { - public class ApplicationComment : CommentBase - { - public Guid ApplicationId { get; set; } - } + public Guid ApplicationId { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/AssessmentComment.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/AssessmentComment.cs index c0f39d6152..b21da5c24b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/AssessmentComment.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/AssessmentComment.cs @@ -1,9 +1,8 @@ using System; -namespace Unity.GrantManager.Comments +namespace Unity.GrantManager.Comments; + +public class AssessmentComment : CommentBase { - public class AssessmentComment : CommentBase - { - public Guid AssessmentId { get; set; } - } + public Guid AssessmentId { get; set; } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/CommentsManager.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/CommentsManager.cs index 1f185ab2e7..101cf3252c 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/CommentsManager.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Comments/CommentsManager.cs @@ -13,16 +13,21 @@ public class CommentsManager : DomainService, ICommentsManager { private readonly ICommentsRepository _applicationCommentsRepository; private readonly ICommentsRepository _assessmentCommentsRepository; + private readonly ICommentsRepository _applicantCommentsRepository; + private readonly ICurrentUser _currentUser; private readonly IPersonRepository _personRepository; public CommentsManager(ICommentsRepository applicationCommentsRepository, ICommentsRepository assessmentCommentsRepository, + ICommentsRepository applicantCommentsRepository, ICurrentUser currentUser, IPersonRepository personRepository) { _applicationCommentsRepository = applicationCommentsRepository; _assessmentCommentsRepository = assessmentCommentsRepository; + _applicantCommentsRepository = applicantCommentsRepository; + _currentUser = currentUser; _personRepository = personRepository; } @@ -39,7 +44,10 @@ public async Task CreateCommentAsync(Guid ownerId, string comment, CommentType.AssessmentComment => await _assessmentCommentsRepository .InsertAsync(new AssessmentComment() { Comment = comment, AssessmentId = ownerId, CommenterId = commenterId }, autoSave: true), - _ => throw new NotImplementedException(), + CommentType.ApplicantComment => await _applicantCommentsRepository + .InsertAsync(new ApplicantComment() + { Comment = comment, ApplicantId = ownerId, CommenterId = commenterId }, autoSave: true), + _ => throw new ArgumentOutOfRangeException(nameof(assessmentComment)), }; } @@ -53,8 +61,11 @@ public async Task> GetCommentsAsync(Guid ownerId, Com case CommentType.AssessmentComment: var assessmentCommentsQry = await _assessmentCommentsRepository.GetQueryableAsync(); return assessmentCommentsQry.Where(c => c.AssessmentId.Equals(ownerId)).OrderByDescending(s => s.CreationTime).ToList(); + case CommentType.ApplicantComment: + var applicantCommentsQry = await _applicantCommentsRepository.GetQueryableAsync(); + return applicantCommentsQry.Where(c => c.ApplicantId.Equals(ownerId)).OrderByDescending(s => s.CreationTime).ToList(); default: - throw new NotImplementedException(); + throw new ArgumentOutOfRangeException(nameof(type)); } } @@ -70,8 +81,12 @@ public async Task UpdateCommentAsync(Guid ownerId, Guid commentId, var assessmentComment = await GetCommentAsync(ownerId, commentId, type) ?? throw new EntityNotFoundException(); assessmentComment.Comment = comment; return await _assessmentCommentsRepository.UpdateAsync((AssessmentComment)assessmentComment!, autoSave: true); + case CommentType.ApplicantComment: + var applicantComment = await GetCommentAsync(ownerId, commentId, type) ?? throw new EntityNotFoundException(); + applicantComment.Comment = comment; + return await _applicantCommentsRepository.UpdateAsync((ApplicantComment)applicantComment!, autoSave: true); default: - throw new NotImplementedException(); + throw new ArgumentOutOfRangeException(nameof(type)); } } @@ -85,8 +100,11 @@ public async Task UpdateCommentAsync(Guid ownerId, Guid commentId, case CommentType.AssessmentComment: var assessmentCommentsQry = await _assessmentCommentsRepository.GetQueryableAsync(); return assessmentCommentsQry.FirstOrDefault(s => s.AssessmentId == ownerId && s.Id == commentId); + case CommentType.ApplicantComment: + var applicantCommentsQry = await _applicantCommentsRepository.GetQueryableAsync(); + return applicantCommentsQry.FirstOrDefault(s => s.ApplicantId == ownerId && s.Id == commentId); default: - throw new NotImplementedException(); + throw new ArgumentOutOfRangeException(nameof(type)); } } @@ -100,7 +118,7 @@ join user in await _personRepository.GetQueryableAsync() on applicationComment.C where applicationComment.ApplicationId == ownerId orderby applicationComment.PinDateTime.HasValue descending, applicationComment.PinDateTime ascending, - applicationComment.CreationTime descending + (applicationComment.LastModificationTime ?? applicationComment.CreationTime) descending select new CommentListItem { Comment = applicationComment.Comment, @@ -120,7 +138,7 @@ join user in await _personRepository.GetQueryableAsync() on assessmentComment.Co where assessmentComment.AssessmentId == ownerId orderby assessmentComment.PinDateTime.HasValue descending, assessmentComment.PinDateTime ascending, - assessmentComment.CreationTime descending + (assessmentComment.LastModificationTime ?? assessmentComment.CreationTime) descending select new CommentListItem { Comment = assessmentComment.Comment, @@ -134,8 +152,28 @@ assessmentComment.CreationTime descending PinDateTime = assessmentComment.PinDateTime, }; return assessmentCommentsQry.ToList(); + case CommentType.ApplicantComment: + var applicantCommentsQry = from applicantComment in await _applicantCommentsRepository.GetQueryableAsync() + join user in await _personRepository.GetQueryableAsync() on applicantComment.CommenterId equals user.Id + where applicantComment.ApplicantId == ownerId + orderby applicantComment.PinDateTime.HasValue descending, + applicantComment.PinDateTime ascending, + (applicantComment.LastModificationTime ?? applicantComment.CreationTime) descending + select new CommentListItem + { + Comment = applicantComment.Comment, + CommenterId = applicantComment.CommenterId, + CommenterDisplayName = user.OidcDisplayName, + CommenterBadge = user.Badge, + CreationTime = applicantComment.CreationTime, + OwnerId = ownerId, + Id = applicantComment.Id, + LastModificationTime = applicantComment.LastModificationTime, + PinDateTime = applicantComment.PinDateTime, + }; + return applicantCommentsQry.ToList(); default: - throw new NotImplementedException(); + throw new ArgumentOutOfRangeException(nameof(type)); } } @@ -173,6 +211,9 @@ private async Task UpdateCommentInRepositoryAsync(CommentBase comment, CommentTy case CommentType.AssessmentComment: await _assessmentCommentsRepository.UpdateAsync((AssessmentComment)comment, autoSave: true); break; + case CommentType.ApplicantComment: + await _applicantCommentsRepository.UpdateAsync((ApplicantComment)comment, autoSave: true); + break; default: throw new ArgumentOutOfRangeException(nameof(type)); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/GrantManagerDataSeederContributor.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/GrantManagerDataSeederContributor.cs index 3958d29de3..e469c96074 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/GrantManagerDataSeederContributor.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/GrantManagerDataSeederContributor.cs @@ -30,7 +30,7 @@ public static class GrantApplicationStates public const string INITITAL_REVIEW_COMPLETED = "Initial Review Completed"; public const string UNDER_ASSESSMENT = "Under Assessment"; public const string ASSESSMENT_COMPLETED = "Assessment Completed"; - public const string GRANT_APPROVED = "Grant Approved"; + public const string GRANT_APPROVED = "Approved"; public const string DECLINED = "Declined"; public const string DEFER = "Deferred"; public const string ON_HOLD = "On Hold"; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs index d1b132d5f4..d92d21a3dd 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Domain/Permissions/PermissionGrantsDataSeeder.cs @@ -135,6 +135,7 @@ await _permissionDataSeeder.SeedAsync(RolePermissionValueProvider.ProviderName, .. Dashboard_CommonPermissions, .. Tags_CommonPermissions, AIPermissions.Configuration.ConfigureAI, + FlexPermissions.Worksheets.Default, FlexPermissions.Worksheets.Delete ], context.TenantId); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs index ee2bdd7ed2..eca253ff34 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/EntityFrameworkCore/GrantTenantDbContext.cs @@ -38,6 +38,8 @@ public class GrantTenantDbContext : AbpDbContext public DbSet ApplicantAddresses { get; set; } public DbSet ApplicationTags { get; set; } public DbSet ApplicantAgents { get; set; } + public DbSet ApplicantComments { get; set; } + public DbSet ApplicantAttachments { get; set; } public DbSet ApplicationAttachments { get; set; } public DbSet ApplicationFormSubmissions { get; set; } public DbSet AssessmentAttachments { get; set; } @@ -180,6 +182,19 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) b.HasOne().WithMany().HasForeignKey(x => x.ApplicantId).IsRequired(); }); + modelBuilder.Entity(b => + { + b.ToTable(GrantManagerConsts.TenantTablePrefix + "ApplicantComments", GrantManagerConsts.DbSchema); + + b.ConfigureByConvention(); + b.HasOne().WithMany().HasForeignKey(x => x.ApplicantId).IsRequired(); + + b.HasOne() + .WithMany() + .HasPrincipalKey(x => x.Id) + .HasForeignKey(x => x.CommenterId); + }); + modelBuilder.Entity(b => { b.ToTable(GrantManagerConsts.TenantTablePrefix + "ApplicationFormSubmissions", @@ -203,6 +218,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(x => x.CommenterId); }); + modelBuilder.Entity(b => + { + b.ToTable(GrantManagerConsts.TenantTablePrefix + "ApplicantAttachments", GrantManagerConsts.DbSchema); + + b.ConfigureByConvention(); + b.HasOne().WithMany().HasForeignKey(x => x.ApplicantId).IsRequired(); + }); + modelBuilder.Entity(b => { b.ToTable(GrantManagerConsts.TenantTablePrefix + "ApplicationAttachments", GrantManagerConsts.DbSchema); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260413232525_RenameAIPermissions.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260413232525_RenameAIPermissions.Designer.cs new file mode 100644 index 0000000000..8b320cd0b7 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260413232525_RenameAIPermissions.Designer.cs @@ -0,0 +1,3030 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace Unity.GrantManager.Migrations.HostMigrations +{ + [DbContext(typeof(GrantManagerDbContext))] + [Migration("20260413232525_RenameAIPermissions")] + partial class RenameAIPermissions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzBlobTrigger", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("TriggerName") + .HasColumnType("text") + .HasColumnName("trigger_name"); + + b.Property("TriggerGroup") + .HasColumnType("text") + .HasColumnName("trigger_group"); + + b.Property("BlobData") + .HasColumnType("bytea") + .HasColumnName("blob_data"); + + b.HasKey("SchedulerName", "TriggerName", "TriggerGroup"); + + b.ToTable("qrtz_blob_triggers", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzCalendar", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("CalendarName") + .HasColumnType("text") + .HasColumnName("calendar_name"); + + b.Property("Calendar") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("calendar"); + + b.HasKey("SchedulerName", "CalendarName"); + + b.ToTable("qrtz_calendars", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzCronTrigger", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("TriggerName") + .HasColumnType("text") + .HasColumnName("trigger_name"); + + b.Property("TriggerGroup") + .HasColumnType("text") + .HasColumnName("trigger_group"); + + b.Property("CronExpression") + .IsRequired() + .HasColumnType("text") + .HasColumnName("cron_expression"); + + b.Property("TimeZoneId") + .HasColumnType("text") + .HasColumnName("time_zone_id"); + + b.HasKey("SchedulerName", "TriggerName", "TriggerGroup"); + + b.ToTable("qrtz_cron_triggers", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzFiredTrigger", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("EntryId") + .HasColumnType("text") + .HasColumnName("entry_id"); + + b.Property("FiredTime") + .HasColumnType("bigint") + .HasColumnName("fired_time"); + + b.Property("InstanceName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("instance_name"); + + b.Property("IsNonConcurrent") + .HasColumnType("bool") + .HasColumnName("is_nonconcurrent"); + + b.Property("JobGroup") + .HasColumnType("text") + .HasColumnName("job_group"); + + b.Property("JobName") + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("RequestsRecovery") + .HasColumnType("bool") + .HasColumnName("requests_recovery"); + + b.Property("ScheduledTime") + .HasColumnType("bigint") + .HasColumnName("sched_time"); + + b.Property("State") + .IsRequired() + .HasColumnType("text") + .HasColumnName("state"); + + b.Property("TriggerGroup") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trigger_group"); + + b.Property("TriggerName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trigger_name"); + + b.HasKey("SchedulerName", "EntryId"); + + b.HasIndex("InstanceName") + .HasDatabaseName("idx_qrtz_ft_trig_inst_name"); + + b.HasIndex("JobGroup") + .HasDatabaseName("idx_qrtz_ft_job_group"); + + b.HasIndex("JobName") + .HasDatabaseName("idx_qrtz_ft_job_name"); + + b.HasIndex("RequestsRecovery") + .HasDatabaseName("idx_qrtz_ft_job_req_recovery"); + + b.HasIndex("TriggerGroup") + .HasDatabaseName("idx_qrtz_ft_trig_group"); + + b.HasIndex("TriggerName") + .HasDatabaseName("idx_qrtz_ft_trig_name"); + + b.HasIndex("SchedulerName", "TriggerName", "TriggerGroup") + .HasDatabaseName("idx_qrtz_ft_trig_nm_gp"); + + b.ToTable("qrtz_fired_triggers", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzJobDetail", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("JobName") + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("JobGroup") + .HasColumnType("text") + .HasColumnName("job_group"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("IsDurable") + .HasColumnType("bool") + .HasColumnName("is_durable"); + + b.Property("IsNonConcurrent") + .HasColumnType("bool") + .HasColumnName("is_nonconcurrent"); + + b.Property("IsUpdateData") + .HasColumnType("bool") + .HasColumnName("is_update_data"); + + b.Property("JobClassName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_class_name"); + + b.Property("JobData") + .HasColumnType("bytea") + .HasColumnName("job_data"); + + b.Property("RequestsRecovery") + .HasColumnType("bool") + .HasColumnName("requests_recovery"); + + b.HasKey("SchedulerName", "JobName", "JobGroup"); + + b.HasIndex("RequestsRecovery") + .HasDatabaseName("idx_qrtz_j_req_recovery"); + + b.ToTable("qrtz_job_details", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzLock", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("LockName") + .HasColumnType("text") + .HasColumnName("lock_name"); + + b.HasKey("SchedulerName", "LockName"); + + b.ToTable("qrtz_locks", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzPausedTriggerGroup", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("TriggerGroup") + .HasColumnType("text") + .HasColumnName("trigger_group"); + + b.HasKey("SchedulerName", "TriggerGroup"); + + b.ToTable("qrtz_paused_trigger_grps", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSchedulerState", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("InstanceName") + .HasColumnType("text") + .HasColumnName("instance_name"); + + b.Property("CheckInInterval") + .HasColumnType("bigint") + .HasColumnName("checkin_interval"); + + b.Property("LastCheckInTime") + .HasColumnType("bigint") + .HasColumnName("last_checkin_time"); + + b.HasKey("SchedulerName", "InstanceName"); + + b.ToTable("qrtz_scheduler_state", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSimplePropertyTrigger", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("TriggerName") + .HasColumnType("text") + .HasColumnName("trigger_name"); + + b.Property("TriggerGroup") + .HasColumnType("text") + .HasColumnName("trigger_group"); + + b.Property("BooleanProperty1") + .HasColumnType("bool") + .HasColumnName("bool_prop_1"); + + b.Property("BooleanProperty2") + .HasColumnType("bool") + .HasColumnName("bool_prop_2"); + + b.Property("DecimalProperty1") + .HasColumnType("numeric") + .HasColumnName("dec_prop_1"); + + b.Property("DecimalProperty2") + .HasColumnType("numeric") + .HasColumnName("dec_prop_2"); + + b.Property("IntegerProperty1") + .HasColumnType("integer") + .HasColumnName("int_prop_1"); + + b.Property("IntegerProperty2") + .HasColumnType("integer") + .HasColumnName("int_prop_2"); + + b.Property("LongProperty1") + .HasColumnType("bigint") + .HasColumnName("long_prop_1"); + + b.Property("LongProperty2") + .HasColumnType("bigint") + .HasColumnName("long_prop_2"); + + b.Property("StringProperty1") + .HasColumnType("text") + .HasColumnName("str_prop_1"); + + b.Property("StringProperty2") + .HasColumnType("text") + .HasColumnName("str_prop_2"); + + b.Property("StringProperty3") + .HasColumnType("text") + .HasColumnName("str_prop_3"); + + b.Property("TimeZoneId") + .HasColumnType("text") + .HasColumnName("time_zone_id"); + + b.HasKey("SchedulerName", "TriggerName", "TriggerGroup"); + + b.ToTable("qrtz_simprop_triggers", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSimpleTrigger", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("TriggerName") + .HasColumnType("text") + .HasColumnName("trigger_name"); + + b.Property("TriggerGroup") + .HasColumnType("text") + .HasColumnName("trigger_group"); + + b.Property("RepeatCount") + .HasColumnType("bigint") + .HasColumnName("repeat_count"); + + b.Property("RepeatInterval") + .HasColumnType("bigint") + .HasColumnName("repeat_interval"); + + b.Property("TimesTriggered") + .HasColumnType("bigint") + .HasColumnName("times_triggered"); + + b.HasKey("SchedulerName", "TriggerName", "TriggerGroup"); + + b.ToTable("qrtz_simple_triggers", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", b => + { + b.Property("SchedulerName") + .HasColumnType("text") + .HasColumnName("sched_name"); + + b.Property("TriggerName") + .HasColumnType("text") + .HasColumnName("trigger_name"); + + b.Property("TriggerGroup") + .HasColumnType("text") + .HasColumnName("trigger_group"); + + b.Property("CalendarName") + .HasColumnType("text") + .HasColumnName("calendar_name"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("EndTime") + .HasColumnType("bigint") + .HasColumnName("end_time"); + + b.Property("JobData") + .HasColumnType("bytea") + .HasColumnName("job_data"); + + b.Property("JobGroup") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_group"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("MisfireInstruction") + .HasColumnType("smallint") + .HasColumnName("misfire_instr"); + + b.Property("NextFireTime") + .HasColumnType("bigint") + .HasColumnName("next_fire_time"); + + b.Property("PreviousFireTime") + .HasColumnType("bigint") + .HasColumnName("prev_fire_time"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("StartTime") + .HasColumnType("bigint") + .HasColumnName("start_time"); + + b.Property("TriggerState") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trigger_state"); + + b.Property("TriggerType") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trigger_type"); + + b.HasKey("SchedulerName", "TriggerName", "TriggerGroup"); + + b.HasIndex("NextFireTime") + .HasDatabaseName("idx_qrtz_t_next_fire_time"); + + b.HasIndex("TriggerState") + .HasDatabaseName("idx_qrtz_t_state"); + + b.HasIndex("NextFireTime", "TriggerState") + .HasDatabaseName("idx_qrtz_t_nft_st"); + + b.HasIndex("SchedulerName", "JobName", "JobGroup"); + + b.ToTable("qrtz_triggers", (string)null); + }); + + modelBuilder.Entity("Unity.AI.Domain.AIPrompt", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("AIPrompts", "AI"); + }); + + modelBuilder.Entity("Unity.AI.Domain.AIPromptVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeveloperNotes") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeprecated") + .HasColumnType("boolean"); + + b.Property("IsPublished") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MaxTokens") + .HasColumnType("integer"); + + b.Property("MetadataJson") + .HasColumnType("jsonb"); + + b.Property("PromptId") + .HasColumnType("uuid"); + + b.Property("SystemPrompt") + .IsRequired() + .HasColumnType("text"); + + b.Property("TargetModel") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TargetProvider") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Temperature") + .HasColumnType("double precision"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserPromptTemplate") + .IsRequired() + .HasColumnType("text"); + + b.Property("VersionNumber") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PromptId", "VersionNumber") + .IsUnique(); + + b.ToTable("AIPromptVersions", "AI"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applicants.ApplicantTenantMap", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastUpdated") + .HasColumnType("timestamp without time zone"); + + b.Property("OidcSubUsername") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("TenantName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OidcSubUsername"); + + b.HasIndex("OidcSubUsername", "TenantId") + .IsUnique(); + + b.ToTable("ApplicantTenantMaps", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Integrations.CasClientCode", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientCode") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("ClientId") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialMinistry") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedTime") + .HasColumnType("timestamp with time zone"); + + b.Property("MinistryPrefix") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.HasKey("Id"); + + b.ToTable("CasClientCodes", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Integrations.DynamicUrl", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("KeyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DynamicUrls", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.Community", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrictCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Communities", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.EconomicRegion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EconomicRegionCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("EconomicRegionName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.ToTable("EconomicRegions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.ElectoralDistrict", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ElectoralDistrictCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ElectoralDistrictName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.ToTable("ElectoralDistricts", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.RegionalDistrict", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EconomicRegionCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("RegionalDistrictCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrictName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("RegionalDistricts", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.Sector", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SectorCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SectorName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Sectors", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.SubSector", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SectorId") + .HasColumnType("uuid"); + + b.Property("SubSectorCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubSectorName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("SectorId"); + + b.ToTable("SubSectors", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Messaging.InboxMessage", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DataType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Details") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MessageId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ProcessedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ReceivedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MessageId") + .IsUnique(); + + b.HasIndex("Source", "Status"); + + b.ToTable("InboxMessages", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Messaging.OutboxMessage", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AckStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DataType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Details") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("character varying(2000)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MessageId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("OriginalMessageId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("PublishedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Source", "Status"); + + b.ToTable("OutboxMessages", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Tokens.TenantToken", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TenantTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("text"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("integer") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uuid") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("integer") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("character varying(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuditLogId") + .HasColumnType("uuid") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("smallint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uuid"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("EntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EntityChangeId") + .HasColumnType("uuid"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("EntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("character varying(1048576)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("NextTryTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("BackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Features", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("FeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("FeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("ValueType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("SourceTenantId") + .HasColumnType("uuid"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("TargetTenantId") + .HasColumnType("uuid"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique(); + + b.ToTable("LinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("boolean") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("boolean") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("Roles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("character varying(96)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("SecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("LastAccessed") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("SignedIn") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("Sessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("OidcSub") + .HasColumnType("text"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("boolean"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("Users", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("EndTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SourceUserId") + .HasColumnType("uuid"); + + b.Property("StartTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TargetUserId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("UserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("character varying(196)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("UserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("UserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("UserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("character varying(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("OrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("OrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MultiTenancySide") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Permissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("PermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("PermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("Settings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExtraProperties") + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("boolean"); + + b.Property("IsInherited") + .HasColumnType("boolean"); + + b.Property("IsVisibleToClients") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("SettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EntityVersion") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("Tenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("TenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzBlobTrigger", b => + { + b.HasOne("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", "Trigger") + .WithMany("BlobTriggers") + .HasForeignKey("SchedulerName", "TriggerName", "TriggerGroup") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzCronTrigger", b => + { + b.HasOne("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", "Trigger") + .WithMany("CronTriggers") + .HasForeignKey("SchedulerName", "TriggerName", "TriggerGroup") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSimplePropertyTrigger", b => + { + b.HasOne("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", "Trigger") + .WithMany("SimplePropertyTriggers") + .HasForeignKey("SchedulerName", "TriggerName", "TriggerGroup") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzSimpleTrigger", b => + { + b.HasOne("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", "Trigger") + .WithMany("SimpleTriggers") + .HasForeignKey("SchedulerName", "TriggerName", "TriggerGroup") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", b => + { + b.HasOne("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzJobDetail", "JobDetail") + .WithMany("Triggers") + .HasForeignKey("SchedulerName", "JobName", "JobGroup") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JobDetail"); + }); + + modelBuilder.Entity("Unity.AI.Domain.AIPromptVersion", b => + { + b.HasOne("Unity.AI.Domain.AIPrompt", "Prompt") + .WithMany("Versions") + .HasForeignKey("PromptId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Prompt"); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.SubSector", b => + { + b.HasOne("Unity.GrantManager.Locality.Sector", "Sector") + .WithMany("SubSectors") + .HasForeignKey("SectorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Sector"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzJobDetail", b => + { + b.Navigation("Triggers"); + }); + + modelBuilder.Entity("AppAny.Quartz.EntityFrameworkCore.Migrations.QuartzTrigger", b => + { + b.Navigation("BlobTriggers"); + + b.Navigation("CronTriggers"); + + b.Navigation("SimplePropertyTriggers"); + + b.Navigation("SimpleTriggers"); + }); + + modelBuilder.Entity("Unity.AI.Domain.AIPrompt", b => + { + b.Navigation("Versions"); + }); + + modelBuilder.Entity("Unity.GrantManager.Locality.Sector", b => + { + b.Navigation("SubSectors"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260413232525_RenameAIPermissions.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260413232525_RenameAIPermissions.cs new file mode 100644 index 0000000000..cdbadef3db --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/HostMigrations/20260413232525_RenameAIPermissions.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.HostMigrations +{ + /// + public partial class RenameAIPermissions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + RenamePermissionGrant(migrationBuilder, "AI.ApplicationAnalysis", "AI.Analysis.ViewApplicationAnalysis"); + RenamePermissionGrant(migrationBuilder, "AI.AttachmentSummary", "AI.Analysis.ViewAttachmentSummary"); + RenamePermissionGrant(migrationBuilder, "AI.ScoringAssistant", "AI.Analysis.ViewScoringResult"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + RenamePermissionGrant(migrationBuilder, "AI.Analysis.ViewApplicationAnalysis", "AI.ApplicationAnalysis"); + RenamePermissionGrant(migrationBuilder, "AI.Analysis.ViewAttachmentSummary", "AI.AttachmentSummary"); + RenamePermissionGrant(migrationBuilder, "AI.Analysis.ViewScoringResult", "AI.ScoringAssistant"); + } + + private static void RenamePermissionGrant(MigrationBuilder migrationBuilder, string fromName, string toName) + { + migrationBuilder.Sql($@" +DELETE FROM public.""PermissionGrants"" target +USING public.""PermissionGrants"" source +WHERE target.""Name"" = '{toName}' + AND source.""Name"" = '{fromName}' + AND target.""TenantId"" IS NOT DISTINCT FROM source.""TenantId"" + AND target.""ProviderName"" IS NOT DISTINCT FROM source.""ProviderName"" + AND target.""ProviderKey"" IS NOT DISTINCT FROM source.""ProviderKey""; + +UPDATE public.""PermissionGrants"" +SET ""Name"" = '{toName}' +WHERE ""Name"" = '{fromName}'; +"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260328004721_AB9074_Add_Applicant_Comments.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260328004721_AB9074_Add_Applicant_Comments.Designer.cs new file mode 100644 index 0000000000..8408a892cd --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260328004721_AB9074_Add_Applicant_Comments.Designer.cs @@ -0,0 +1,4865 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + [DbContext(typeof(GrantTenantDbContext))] + [Migration("20260328004721_AB9074_Add_Applicant_Comments")] + partial class AB9074_Add_Applicant_Comments + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("QuestionId") + .HasColumnType("uuid"); + + b.Property("ScoresheetInstanceId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("ScoresheetInstanceId"); + + b.ToTable("Answers", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("Questions", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Scoresheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CustomFieldId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetInstanceId"); + + b.ToTable("CustomFieldValues", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetCorrelationId") + .HasColumnType("uuid"); + + b.Property("WorksheetCorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("WorksheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetLinks", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("CustomFields", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Worksheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantName") + .IsRequired() + .HasMaxLength(600) + .HasColumnType("character varying(600)"); + + b.Property("ApproxNumberOfEmployees") + .HasColumnType("text"); + + b.Property("AuditComments") + .HasColumnType("text"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("FundingHistoryComments") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + b.Property("IsDuplicated") + .HasColumnType("boolean"); + + b.Property("IssueTrackingComments") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MatchPercentage") + .HasColumnType("numeric"); + + b.Property("NonRegOrgName") + .HasColumnType("text"); + + b.Property("NonRegisteredBusinessName") + .HasColumnType("text"); + + b.Property("OrgName") + .HasColumnType("text"); + + b.Property("OrgNumber") + .HasColumnType("text"); + + b.Property("OrgStatus") + .HasColumnType("text"); + + b.Property("OrganizationSize") + .HasColumnType("text"); + + b.Property("OrganizationType") + .HasColumnType("text"); + + b.Property("RedStop") + .HasColumnType("boolean"); + + b.Property("Sector") + .HasColumnType("text"); + + b.Property("SectorSubSectorIndustryDesc") + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("StartedOperatingDate") + .HasColumnType("date"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SubSector") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UnityApplicantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantName"); + + b.ToTable("Applicants", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AddressType") + .HasColumnType("integer"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Postal") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("Street2") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Unit") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicantAddresses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BceidBusinessGuid") + .HasColumnType("uuid"); + + b.Property("BceidBusinessName") + .HasColumnType("text"); + + b.Property("BceidUserGuid") + .HasColumnType("uuid"); + + b.Property("BceidUserName") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactOrder") + .HasColumnType("integer"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IdentityEmail") + .HasColumnType("text"); + + b.Property("IdentityName") + .HasColumnType("text"); + + b.Property("IdentityProvider") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSubUser") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Phone2") + .HasColumnType("text"); + + b.Property("Phone2Extension") + .HasColumnType("text"); + + b.Property("PhoneExtension") + .HasColumnType("text"); + + b.Property("RoleForApplicant") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId") + .IsUnique(); + + b.ToTable("ApplicantAgents", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AIAnalysis") + .HasColumnType("text"); + + b.Property("AIScoresheetAnswers") + .HasColumnType("jsonb"); + + b.Property("Acquisition") + .HasColumnType("text"); + + b.Property("ApplicantElectoralDistrict") + .HasColumnType("text"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationStatusId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("AssessmentResultDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AssessmentResultStatus") + .HasColumnType("text"); + + b.Property("AssessmentStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Community") + .HasColumnType("text"); + + b.Property("CommunityPopulation") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractExecutionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ContractNumber") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeclineRational") + .HasColumnType("text"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DueDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DueDiligenceStatus") + .HasColumnType("text"); + + b.Property("EconomicRegion") + .HasColumnType("text"); + + b.Property("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinalDecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Forestry") + .HasColumnType("text"); + + b.Property("ForestryFocus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LikelihoodOfFunding") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("NotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("PercentageTotalProjectBudget") + .HasColumnType("double precision"); + + b.Property("Place") + .HasColumnType("text"); + + b.Property("ProjectEndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectFundingTotal") + .HasColumnType("numeric"); + + b.Property("ProjectName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ProjectStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectSummary") + .HasColumnType("text"); + + b.Property("ProposalDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecommendedAmount") + .HasColumnType("numeric"); + + b.Property("ReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrict") + .HasColumnType("text"); + + b.Property("RequestedAmount") + .HasColumnType("numeric"); + + b.Property("RiskRanking") + .HasColumnType("text"); + + b.Property("SigningAuthorityBusinessPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityCellPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityEmail") + .HasColumnType("text"); + + b.Property("SigningAuthorityFullName") + .HasColumnType("text"); + + b.Property("SigningAuthorityTitle") + .HasColumnType("text"); + + b.Property("SubStatus") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalProjectBudget") + .HasColumnType("numeric"); + + b.Property("TotalScore") + .HasColumnType("integer"); + + b.Property("UnityApplicationId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.HasIndex("ApplicationStatusId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Applications", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssigneeId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Duty") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssigneeId"); + + b.ToTable("ApplicationAssignments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AISummary") + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsFileId") + .HasColumnType("text"); + + b.Property("ChefsSubmissionId") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationChefsFileAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactEmail") + .HasColumnType("text"); + + b.Property("ContactFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactMobilePhone") + .HasColumnType("text"); + + b.Property("ContactTitle") + .HasColumnType("text"); + + b.Property("ContactType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactWorkPhone") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationContact", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasColumnType("text"); + + b.Property("ApplicationFormDescription") + .HasColumnType("text"); + + b.Property("ApplicationFormName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AttemptedConnectionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsCriteriaFormGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConnectionHttpStatus") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultPaymentGroup") + .HasColumnType("integer"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ElectoralDistrictAddressType") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormHierarchy") + .HasColumnType("integer"); + + b.Property("IntakeId") + .HasColumnType("uuid"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDirectApproval") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentFormId") + .HasColumnType("uuid"); + + b.Property("Payable") + .HasColumnType("boolean"); + + b.Property("PaymentApprovalThreshold") + .HasColumnType("numeric"); + + b.Property("Prefix") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PreventPayment") + .HasColumnType("boolean"); + + b.Property("RenderFormIoToHtml") + .HasColumnType("boolean"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("SuffixType") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IntakeId"); + + b.HasIndex("ParentFormId"); + + b.ToTable("ApplicationForms", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormVersionId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsSubmissionGuid") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormVersionId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("RenderedHTML") + .HasColumnType("text"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Submission") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormSubmissions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsFormVersionGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormSchema") + .HasColumnType("jsonb"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmissionHeaderMapping") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormVersion", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LinkType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("Related"); + + b.Property("LinkedApplicationId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StatusCode") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("StatusCode") + .IsUnique(); + + b.ToTable("ApplicationStatuses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("TagId"); + + b.ToTable("ApplicationTags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.ToTable("AssessmentAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("AuditDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AuditNote") + .HasColumnType("text"); + + b.Property("AuditTrackingNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("AuditHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FundingNotes") + .HasColumnType("text"); + + b.Property("FundingYear") + .HasColumnType("integer"); + + b.Property("GrantCategory") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReconsiderationAmount") + .HasColumnType("numeric"); + + b.Property("RenewedFunding") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalGrantAmount") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("FundingHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IssueDescription") + .HasColumnType("text"); + + b.Property("IssueHeading") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ResolutionNote") + .HasColumnType("text"); + + b.Property("Resolved") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Year") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("IssueTrackings", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ApprovalRecommended") + .HasColumnType("boolean"); + + b.Property("AssessorId") + .HasColumnType("uuid"); + + b.Property("CleanGrowth") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EconomicImpact") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialAnalysis") + .HasColumnType("integer"); + + b.Property("InclusiveGrowth") + .HasColumnType("integer"); + + b.Property("IsAiAssessment") + .HasColumnType("boolean"); + + b.Property("IsComplete") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssessorId"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicantComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicationComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CommenterId"); + + b.ToTable("AssessmentComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.Contact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HomePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MobilePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("WorkPhoneExtension") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WorkPhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Contacts", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("RelatedEntityId") + .HasColumnType("uuid"); + + b.Property("RelatedEntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Role") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RelatedEntityType", "RelatedEntityId"); + + b.HasIndex("ContactId", "RelatedEntityType", "RelatedEntityId"); + + b.ToTable("ContactLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.GlobalTag.Tag", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Tags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Identity.Person", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Badge") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcDisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("OidcSub"); + + b.ToTable("Persons", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Intakes.Intake", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Budget") + .HasColumnType("double precision"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Intakes", (string)null); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("EmailGroupUsers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CC") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesHttpStatusCode") + .HasColumnType("text"); + + b.Property("ChesMsgId") + .HasColumnType("uuid"); + + b.Property("ChesResponse") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestIds") + .IsRequired() + .HasColumnType("text"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryAttempts") + .HasColumnType("integer"); + + b.Property("SendOnDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SentDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ToAddress") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailLogs", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("EmailLogId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("EmailLogId"); + + b.HasIndex("S3ObjectKey"); + + b.ToTable("EmailLogAttachments", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BodyHTML") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyText") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SendFrom") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Subscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("SubscriptionGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriberId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.HasIndex("SubscriberId"); + + b.ToTable("SubscriptionGroupSubscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TemplateVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MapTo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TemplateVariables", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Triggers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriptionGroupId") + .HasColumnType("uuid"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SubscriptionGroupId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("TriggerId"); + + b.ToTable("TriggerSubscriptions", "Notifications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.AccountCodings.AccountCoding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(35) + .HasColumnType("character varying(35)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MinistryClient") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Responsibility") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServiceLine") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stob") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AccountCodings", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentConfigurations.PaymentConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultAccountCodingId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PaymentConfigurations", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DecisionUserId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("ExpenseApprovals", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BatchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BatchNumber") + .HasColumnType("numeric"); + + b.Property("CasHttpStatusCode") + .HasColumnType("integer"); + + b.Property("CasResponse") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FsbApNotified") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("FsbNotificationEmailLogId") + .HasColumnType("uuid"); + + b.Property("FsbNotificationSentDate") + .HasColumnType("timestamp without time zone"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("InvoiceStatus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRecon") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("PayeeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentDate") + .HasColumnType("text"); + + b.Property("PaymentNumber") + .HasColumnType("text"); + + b.Property("PaymentStatus") + .HasColumnType("text"); + + b.Property("ReferenceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequesterName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("SubmissionConfirmationCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SupplierName") + .HasColumnType("text"); + + b.Property("SupplierNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AccountCodingId"); + + b.HasIndex("FsbNotificationEmailLogId"); + + b.HasIndex("ReferenceNumber") + .IsUnique(); + + b.HasIndex("SiteId"); + + b.ToTable("PaymentRequests", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.HasIndex("TagId"); + + b.ToTable("PaymentTags", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentThresholds.PaymentThreshold", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Threshold") + .HasColumnType("numeric"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("PaymentThresholds", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressLine3") + .HasColumnType("text"); + + b.Property("BankAccount") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EFTAdvicePref") + .HasColumnType("text"); + + b.Property("EmailAddress") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCas") + .HasColumnType("timestamp without time zone"); + + b.Property("MarkDeletedInUse") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentGroup") + .HasColumnType("integer"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SiteProtected") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("Sites", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCAS") + .HasColumnType("timestamp without time zone"); + + b.Property("MailingAddress") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SIN") + .HasColumnType("text"); + + b.Property("StandardIndustryClassification") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Subcategory") + .HasColumnType("text"); + + b.Property("SupplierProtected") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Suppliers", "Payments"); + }); + + modelBuilder.Entity("Unity.Reporting.Domain.Configuration.ReportColumnsMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Mapping") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("RoleStatus") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ViewStatus") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ReportColumnsMaps", "Reporting"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Instances") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", null) + .WithMany("Answers") + .HasForeignKey("ScoresheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.ScoresheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Sections") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.HasOne("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", null) + .WithMany("Values") + .HasForeignKey("WorksheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Links") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.WorksheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Sections") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicationId"); + + b.Navigation("Applicant"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithOne("ApplicantAgent") + .HasForeignKey("Unity.GrantManager.Applications.ApplicantAgent", "ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", "ApplicationForm") + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationStatus", "ApplicationStatus") + .WithMany("Applications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Applicant"); + + b.Navigation("ApplicationForm"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationAssignments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Assignee") + .WithMany() + .HasForeignKey("AssigneeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Assignee"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.HasOne("Unity.GrantManager.Intakes.Intake", null) + .WithMany() + .HasForeignKey("IntakeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ParentFormId") + .OnDelete(DeleteBehavior.NoAction); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany("ApplicationLinks") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationTags") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("Assessments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("AssessorId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.HasOne("Unity.GrantManager.Contacts.Contact", null) + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.HasOne("Unity.Notifications.EmailGroups.EmailGroup", null) + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.HasOne("Unity.Notifications.Emails.EmailLog", null) + .WithMany() + .HasForeignKey("EmailLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("Unity.Notifications.Templates.Subscriber", "Subscriber") + .WithMany() + .HasForeignKey("SubscriberId"); + + b.Navigation("Subscriber"); + + b.Navigation("SubscriptionGroup"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("SubscriptionGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.EmailTemplate", "EmailTemplate") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmailTemplate"); + + b.Navigation("SubscriptionGroup"); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", "PaymentRequest") + .WithMany("ExpenseApprovals") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentRequest"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.HasOne("Unity.Payments.Domain.AccountCodings.AccountCoding", "AccountCoding") + .WithMany() + .HasForeignKey("AccountCodingId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("Unity.Payments.Domain.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("AccountCoding"); + + b.Navigation("Site"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", null) + .WithMany("PaymentTags") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.HasOne("Unity.Payments.Domain.Suppliers.Supplier", "Supplier") + .WithMany("Sites") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Navigation("Instances"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Navigation("Values"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Navigation("Links"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Navigation("ApplicantAddresses"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Navigation("ApplicantAddresses"); + + b.Navigation("ApplicantAgent"); + + b.Navigation("ApplicationAssignments"); + + b.Navigation("ApplicationLinks"); + + b.Navigation("ApplicationTags"); + + b.Navigation("Assessments"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Navigation("Applications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Navigation("ExpenseApprovals"); + + b.Navigation("PaymentTags"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Navigation("Sites"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260328004721_AB9074_Add_Applicant_Comments.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260328004721_AB9074_Add_Applicant_Comments.cs new file mode 100644 index 0000000000..efdde3de26 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260328004721_AB9074_Add_Applicant_Comments.cs @@ -0,0 +1,66 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class AB9074_Add_Applicant_Comments : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApplicantComments", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicantId = table.Column(type: "uuid", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + Comment = table.Column(type: "text", nullable: false), + CommenterId = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: true), + PinDateTime = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicantComments", x => x.Id); + table.ForeignKey( + name: "FK_ApplicantComments_Applicants_ApplicantId", + column: x => x.ApplicantId, + principalTable: "Applicants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ApplicantComments_Persons_CommenterId", + column: x => x.CommenterId, + principalTable: "Persons", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ApplicantComments_ApplicantId", + table: "ApplicantComments", + column: "ApplicantId"); + + migrationBuilder.CreateIndex( + name: "IX_ApplicantComments_CommenterId", + table: "ApplicantComments", + column: "CommenterId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApplicantComments"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260401222707_AddApplicantAttachments.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260401222707_AddApplicantAttachments.Designer.cs new file mode 100644 index 0000000000..678061b573 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260401222707_AddApplicantAttachments.Designer.cs @@ -0,0 +1,4938 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + [DbContext(typeof(GrantTenantDbContext))] + [Migration("20260401222707_AddApplicantAttachments")] + partial class AddApplicantAttachments + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("QuestionId") + .HasColumnType("uuid"); + + b.Property("ScoresheetInstanceId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("ScoresheetInstanceId"); + + b.ToTable("Answers", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("Questions", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Scoresheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CustomFieldId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetInstanceId"); + + b.ToTable("CustomFieldValues", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetCorrelationId") + .HasColumnType("uuid"); + + b.Property("WorksheetCorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("WorksheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetLinks", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("CustomFields", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Worksheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantName") + .IsRequired() + .HasMaxLength(600) + .HasColumnType("character varying(600)"); + + b.Property("ApproxNumberOfEmployees") + .HasColumnType("text"); + + b.Property("AuditComments") + .HasColumnType("text"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("FundingHistoryComments") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + b.Property("IsDuplicated") + .HasColumnType("boolean"); + + b.Property("IssueTrackingComments") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MatchPercentage") + .HasColumnType("numeric"); + + b.Property("NonRegOrgName") + .HasColumnType("text"); + + b.Property("NonRegisteredBusinessName") + .HasColumnType("text"); + + b.Property("OrgName") + .HasColumnType("text"); + + b.Property("OrgNumber") + .HasColumnType("text"); + + b.Property("OrgStatus") + .HasColumnType("text"); + + b.Property("OrganizationSize") + .HasColumnType("text"); + + b.Property("OrganizationType") + .HasColumnType("text"); + + b.Property("RedStop") + .HasColumnType("boolean"); + + b.Property("Sector") + .HasColumnType("text"); + + b.Property("SectorSubSectorIndustryDesc") + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("StartedOperatingDate") + .HasColumnType("date"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SubSector") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UnityApplicantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantName"); + + b.ToTable("Applicants", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AddressType") + .HasColumnType("integer"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Postal") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("Street2") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Unit") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicantAddresses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BceidBusinessGuid") + .HasColumnType("uuid"); + + b.Property("BceidBusinessName") + .HasColumnType("text"); + + b.Property("BceidUserGuid") + .HasColumnType("uuid"); + + b.Property("BceidUserName") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactOrder") + .HasColumnType("integer"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IdentityEmail") + .HasColumnType("text"); + + b.Property("IdentityName") + .HasColumnType("text"); + + b.Property("IdentityProvider") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSubUser") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Phone2") + .HasColumnType("text"); + + b.Property("Phone2Extension") + .HasColumnType("text"); + + b.Property("PhoneExtension") + .HasColumnType("text"); + + b.Property("RoleForApplicant") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId") + .IsUnique(); + + b.ToTable("ApplicantAgents", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("ApplicantAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AIAnalysis") + .HasColumnType("text"); + + b.Property("AIScoresheetAnswers") + .HasColumnType("jsonb"); + + b.Property("Acquisition") + .HasColumnType("text"); + + b.Property("ApplicantElectoralDistrict") + .HasColumnType("text"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationStatusId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("AssessmentResultDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AssessmentResultStatus") + .HasColumnType("text"); + + b.Property("AssessmentStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Community") + .HasColumnType("text"); + + b.Property("CommunityPopulation") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractExecutionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ContractNumber") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeclineRational") + .HasColumnType("text"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DueDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DueDiligenceStatus") + .HasColumnType("text"); + + b.Property("EconomicRegion") + .HasColumnType("text"); + + b.Property("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinalDecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Forestry") + .HasColumnType("text"); + + b.Property("ForestryFocus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LikelihoodOfFunding") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("NotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("PercentageTotalProjectBudget") + .HasColumnType("double precision"); + + b.Property("Place") + .HasColumnType("text"); + + b.Property("ProjectEndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectFundingTotal") + .HasColumnType("numeric"); + + b.Property("ProjectName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ProjectStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectSummary") + .HasColumnType("text"); + + b.Property("ProposalDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecommendedAmount") + .HasColumnType("numeric"); + + b.Property("ReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrict") + .HasColumnType("text"); + + b.Property("RequestedAmount") + .HasColumnType("numeric"); + + b.Property("RiskRanking") + .HasColumnType("text"); + + b.Property("SigningAuthorityBusinessPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityCellPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityEmail") + .HasColumnType("text"); + + b.Property("SigningAuthorityFullName") + .HasColumnType("text"); + + b.Property("SigningAuthorityTitle") + .HasColumnType("text"); + + b.Property("SubStatus") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalProjectBudget") + .HasColumnType("numeric"); + + b.Property("TotalScore") + .HasColumnType("integer"); + + b.Property("UnityApplicationId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.HasIndex("ApplicationStatusId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Applications", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssigneeId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Duty") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssigneeId"); + + b.ToTable("ApplicationAssignments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AISummary") + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsFileId") + .HasColumnType("text"); + + b.Property("ChefsSubmissionId") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationChefsFileAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactEmail") + .HasColumnType("text"); + + b.Property("ContactFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactMobilePhone") + .HasColumnType("text"); + + b.Property("ContactTitle") + .HasColumnType("text"); + + b.Property("ContactType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactWorkPhone") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationContact", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasColumnType("text"); + + b.Property("ApplicationFormDescription") + .HasColumnType("text"); + + b.Property("ApplicationFormName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AttemptedConnectionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsCriteriaFormGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConnectionHttpStatus") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultPaymentGroup") + .HasColumnType("integer"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ElectoralDistrictAddressType") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormHierarchy") + .HasColumnType("integer"); + + b.Property("IntakeId") + .HasColumnType("uuid"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDirectApproval") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentFormId") + .HasColumnType("uuid"); + + b.Property("Payable") + .HasColumnType("boolean"); + + b.Property("PaymentApprovalThreshold") + .HasColumnType("numeric"); + + b.Property("Prefix") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PreventPayment") + .HasColumnType("boolean"); + + b.Property("RenderFormIoToHtml") + .HasColumnType("boolean"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("SuffixType") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IntakeId"); + + b.HasIndex("ParentFormId"); + + b.ToTable("ApplicationForms", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormVersionId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsSubmissionGuid") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormVersionId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("RenderedHTML") + .HasColumnType("text"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Submission") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormSubmissions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsFormVersionGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormSchema") + .HasColumnType("jsonb"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmissionHeaderMapping") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormVersion", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LinkType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("Related"); + + b.Property("LinkedApplicationId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StatusCode") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("StatusCode") + .IsUnique(); + + b.ToTable("ApplicationStatuses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("TagId"); + + b.ToTable("ApplicationTags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.ToTable("AssessmentAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("AuditDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AuditNote") + .HasColumnType("text"); + + b.Property("AuditTrackingNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("AuditHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FundingNotes") + .HasColumnType("text"); + + b.Property("FundingYear") + .HasColumnType("text"); + + b.Property("GrantCategory") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReconsiderationAmount") + .HasColumnType("numeric"); + + b.Property("RenewedFunding") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalGrantAmount") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("FundingHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IssueDescription") + .HasColumnType("text"); + + b.Property("IssueHeading") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ResolutionNote") + .HasColumnType("text"); + + b.Property("Resolved") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Year") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("IssueTrackings", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ApprovalRecommended") + .HasColumnType("boolean"); + + b.Property("AssessorId") + .HasColumnType("uuid"); + + b.Property("CleanGrowth") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EconomicImpact") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialAnalysis") + .HasColumnType("integer"); + + b.Property("InclusiveGrowth") + .HasColumnType("integer"); + + b.Property("IsAiAssessment") + .HasColumnType("boolean"); + + b.Property("IsComplete") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssessorId"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicantComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicationComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CommenterId"); + + b.ToTable("AssessmentComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.Contact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HomePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MobilePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("WorkPhoneExtension") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WorkPhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Contacts", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("RelatedEntityId") + .HasColumnType("uuid"); + + b.Property("RelatedEntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Role") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RelatedEntityType", "RelatedEntityId"); + + b.HasIndex("ContactId", "RelatedEntityType", "RelatedEntityId"); + + b.ToTable("ContactLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.GlobalTag.Tag", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Tags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Identity.Person", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Badge") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcDisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("OidcSub"); + + b.ToTable("Persons", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Intakes.Intake", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Budget") + .HasColumnType("double precision"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Intakes", (string)null); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("EmailGroupUsers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CC") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesHttpStatusCode") + .HasColumnType("text"); + + b.Property("ChesMsgId") + .HasColumnType("uuid"); + + b.Property("ChesResponse") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestIds") + .IsRequired() + .HasColumnType("text"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryAttempts") + .HasColumnType("integer"); + + b.Property("SendOnDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SentDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ToAddress") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailLogs", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("EmailLogId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("EmailLogId"); + + b.HasIndex("S3ObjectKey"); + + b.ToTable("EmailLogAttachments", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BodyHTML") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyText") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SendFrom") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Subscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("SubscriptionGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriberId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.HasIndex("SubscriberId"); + + b.ToTable("SubscriptionGroupSubscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TemplateVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MapTo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TemplateVariables", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Triggers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriptionGroupId") + .HasColumnType("uuid"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SubscriptionGroupId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("TriggerId"); + + b.ToTable("TriggerSubscriptions", "Notifications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.AccountCodings.AccountCoding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(35) + .HasColumnType("character varying(35)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MinistryClient") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Responsibility") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServiceLine") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stob") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AccountCodings", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentConfigurations.PaymentConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultAccountCodingId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PaymentConfigurations", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DecisionUserId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("ExpenseApprovals", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BatchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BatchNumber") + .HasColumnType("numeric"); + + b.Property("CasHttpStatusCode") + .HasColumnType("integer"); + + b.Property("CasResponse") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FsbApNotified") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("FsbNotificationEmailLogId") + .HasColumnType("uuid"); + + b.Property("FsbNotificationSentDate") + .HasColumnType("timestamp without time zone"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("InvoiceStatus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRecon") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("PayeeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentDate") + .HasColumnType("text"); + + b.Property("PaymentNumber") + .HasColumnType("text"); + + b.Property("PaymentStatus") + .HasColumnType("text"); + + b.Property("ReferenceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequesterName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("SubmissionConfirmationCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SupplierName") + .HasColumnType("text"); + + b.Property("SupplierNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AccountCodingId"); + + b.HasIndex("FsbNotificationEmailLogId"); + + b.HasIndex("ReferenceNumber") + .IsUnique(); + + b.HasIndex("SiteId"); + + b.ToTable("PaymentRequests", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.HasIndex("TagId"); + + b.ToTable("PaymentTags", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentThresholds.PaymentThreshold", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Threshold") + .HasColumnType("numeric"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("PaymentThresholds", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressLine3") + .HasColumnType("text"); + + b.Property("BankAccount") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EFTAdvicePref") + .HasColumnType("text"); + + b.Property("EmailAddress") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCas") + .HasColumnType("timestamp without time zone"); + + b.Property("MarkDeletedInUse") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentGroup") + .HasColumnType("integer"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SiteProtected") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("Sites", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCAS") + .HasColumnType("timestamp without time zone"); + + b.Property("MailingAddress") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SIN") + .HasColumnType("text"); + + b.Property("StandardIndustryClassification") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Subcategory") + .HasColumnType("text"); + + b.Property("SupplierProtected") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Suppliers", "Payments"); + }); + + modelBuilder.Entity("Unity.Reporting.Domain.Configuration.ReportColumnsMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Mapping") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("RoleStatus") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ViewStatus") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ReportColumnsMaps", "Reporting"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Instances") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", null) + .WithMany("Answers") + .HasForeignKey("ScoresheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.ScoresheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Sections") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.HasOne("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", null) + .WithMany("Values") + .HasForeignKey("WorksheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Links") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.WorksheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Sections") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicationId"); + + b.Navigation("Applicant"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithOne("ApplicantAgent") + .HasForeignKey("Unity.GrantManager.Applications.ApplicantAgent", "ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", "ApplicationForm") + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationStatus", "ApplicationStatus") + .WithMany("Applications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Applicant"); + + b.Navigation("ApplicationForm"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationAssignments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Assignee") + .WithMany() + .HasForeignKey("AssigneeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Assignee"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.HasOne("Unity.GrantManager.Intakes.Intake", null) + .WithMany() + .HasForeignKey("IntakeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ParentFormId") + .OnDelete(DeleteBehavior.NoAction); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany("ApplicationLinks") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationTags") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("Assessments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("AssessorId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.HasOne("Unity.GrantManager.Contacts.Contact", null) + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.HasOne("Unity.Notifications.EmailGroups.EmailGroup", null) + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.HasOne("Unity.Notifications.Emails.EmailLog", null) + .WithMany() + .HasForeignKey("EmailLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("Unity.Notifications.Templates.Subscriber", "Subscriber") + .WithMany() + .HasForeignKey("SubscriberId"); + + b.Navigation("Subscriber"); + + b.Navigation("SubscriptionGroup"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("SubscriptionGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.EmailTemplate", "EmailTemplate") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmailTemplate"); + + b.Navigation("SubscriptionGroup"); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", "PaymentRequest") + .WithMany("ExpenseApprovals") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentRequest"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.HasOne("Unity.Payments.Domain.AccountCodings.AccountCoding", "AccountCoding") + .WithMany() + .HasForeignKey("AccountCodingId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("Unity.Payments.Domain.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("AccountCoding"); + + b.Navigation("Site"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", null) + .WithMany("PaymentTags") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.HasOne("Unity.Payments.Domain.Suppliers.Supplier", "Supplier") + .WithMany("Sites") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Navigation("Instances"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Navigation("Values"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Navigation("Links"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Navigation("ApplicantAddresses"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Navigation("ApplicantAddresses"); + + b.Navigation("ApplicantAgent"); + + b.Navigation("ApplicationAssignments"); + + b.Navigation("ApplicationLinks"); + + b.Navigation("ApplicationTags"); + + b.Navigation("Assessments"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Navigation("Applications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Navigation("ExpenseApprovals"); + + b.Navigation("PaymentTags"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Navigation("Sites"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260401222707_AddApplicantAttachments.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260401222707_AddApplicantAttachments.cs new file mode 100644 index 0000000000..fc1668edc0 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260401222707_AddApplicantAttachments.cs @@ -0,0 +1,57 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class AddApplicantAttachments : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApplicantAttachments", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ApplicantId = table.Column(type: "uuid", nullable: false), + ExtraProperties = table.Column(type: "text", nullable: false), + ConcurrencyStamp = table.Column(type: "character varying(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "timestamp without time zone", nullable: false), + CreatorId = table.Column(type: "uuid", nullable: true), + LastModificationTime = table.Column(type: "timestamp without time zone", nullable: true), + LastModifierId = table.Column(type: "uuid", nullable: true), + FileName = table.Column(type: "text", nullable: true), + DisplayName = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + TenantId = table.Column(type: "uuid", nullable: true), + S3ObjectKey = table.Column(type: "text", nullable: false), + Time = table.Column(type: "timestamp without time zone", nullable: false), + UserId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApplicantAttachments", x => x.Id); + table.ForeignKey( + name: "FK_ApplicantAttachments_Applicants_ApplicantId", + column: x => x.ApplicantId, + principalTable: "Applicants", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ApplicantAttachments_ApplicantId", + table: "ApplicantAttachments", + column: "ApplicantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApplicantAttachments"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260408213219_Backfill_UnityApplicationId_ABPP2025FallClaims.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260408213219_Backfill_UnityApplicationId_ABPP2025FallClaims.Designer.cs new file mode 100644 index 0000000000..da4021ce21 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260408213219_Backfill_UnityApplicationId_ABPP2025FallClaims.Designer.cs @@ -0,0 +1,4941 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + [DbContext(typeof(GrantTenantDbContext))] + [Migration("20260408213219_Backfill_UnityApplicationId_ABPP2025FallClaims")] + partial class Backfill_UnityApplicationId_ABPP2025FallClaims + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("QuestionId") + .HasColumnType("uuid"); + + b.Property("ScoresheetInstanceId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("ScoresheetInstanceId"); + + b.ToTable("Answers", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("Questions", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Scoresheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CustomFieldId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetInstanceId"); + + b.ToTable("CustomFieldValues", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetCorrelationId") + .HasColumnType("uuid"); + + b.Property("WorksheetCorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("WorksheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetLinks", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("CustomFields", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Worksheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantName") + .IsRequired() + .HasMaxLength(600) + .HasColumnType("character varying(600)"); + + b.Property("ApproxNumberOfEmployees") + .HasColumnType("text"); + + b.Property("AuditComments") + .HasColumnType("text"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("FundingHistoryComments") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + b.Property("IsDuplicated") + .HasColumnType("boolean"); + + b.Property("IssueTrackingComments") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MatchPercentage") + .HasColumnType("numeric"); + + b.Property("NonRegOrgName") + .HasColumnType("text"); + + b.Property("NonRegisteredBusinessName") + .HasColumnType("text"); + + b.Property("OrgName") + .HasColumnType("text"); + + b.Property("OrgNumber") + .HasColumnType("text"); + + b.Property("OrgStatus") + .HasColumnType("text"); + + b.Property("OrganizationSize") + .HasColumnType("text"); + + b.Property("OrganizationType") + .HasColumnType("text"); + + b.Property("RedStop") + .HasColumnType("boolean"); + + b.Property("Sector") + .HasColumnType("text"); + + b.Property("SectorSubSectorIndustryDesc") + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("StartedOperatingDate") + .HasColumnType("date"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SubSector") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UnityApplicantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantName"); + + b.ToTable("Applicants", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AddressType") + .HasColumnType("integer"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Postal") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("Street2") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Unit") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicantAddresses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BceidBusinessGuid") + .HasColumnType("uuid"); + + b.Property("BceidBusinessName") + .HasColumnType("text"); + + b.Property("BceidUserGuid") + .HasColumnType("uuid"); + + b.Property("BceidUserName") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactOrder") + .HasColumnType("integer"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IdentityEmail") + .HasColumnType("text"); + + b.Property("IdentityName") + .HasColumnType("text"); + + b.Property("IdentityProvider") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSubUser") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Phone2") + .HasColumnType("text"); + + b.Property("Phone2Extension") + .HasColumnType("text"); + + b.Property("PhoneExtension") + .HasColumnType("text"); + + b.Property("RoleForApplicant") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId") + .IsUnique(); + + b.ToTable("ApplicantAgents", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("ApplicantAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AIAnalysis") + .HasColumnType("text"); + + b.Property("AIScoresheetAnswers") + .HasColumnType("jsonb"); + + b.Property("Acquisition") + .HasColumnType("text"); + + b.Property("ApplicantElectoralDistrict") + .HasColumnType("text"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationStatusId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("AssessmentResultDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AssessmentResultStatus") + .HasColumnType("text"); + + b.Property("AssessmentStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Community") + .HasColumnType("text"); + + b.Property("CommunityPopulation") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractExecutionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ContractNumber") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeclineRational") + .HasColumnType("text"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DueDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DueDiligenceStatus") + .HasColumnType("text"); + + b.Property("EconomicRegion") + .HasColumnType("text"); + + b.Property("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinalDecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Forestry") + .HasColumnType("text"); + + b.Property("ForestryFocus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LikelihoodOfFunding") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("NotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("PercentageTotalProjectBudget") + .HasColumnType("double precision"); + + b.Property("Place") + .HasColumnType("text"); + + b.Property("ProjectEndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectFundingTotal") + .HasColumnType("numeric"); + + b.Property("ProjectName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ProjectStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectSummary") + .HasColumnType("text"); + + b.Property("ProposalDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecommendedAmount") + .HasColumnType("numeric"); + + b.Property("ReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrict") + .HasColumnType("text"); + + b.Property("RequestedAmount") + .HasColumnType("numeric"); + + b.Property("RiskRanking") + .HasColumnType("text"); + + b.Property("SigningAuthorityBusinessPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityCellPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityEmail") + .HasColumnType("text"); + + b.Property("SigningAuthorityFullName") + .HasColumnType("text"); + + b.Property("SigningAuthorityTitle") + .HasColumnType("text"); + + b.Property("SubStatus") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalProjectBudget") + .HasColumnType("numeric"); + + b.Property("TotalScore") + .HasColumnType("integer"); + + b.Property("UnityApplicationId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.HasIndex("ApplicationStatusId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Applications", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssigneeId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Duty") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssigneeId"); + + b.ToTable("ApplicationAssignments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AISummary") + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsFileId") + .HasColumnType("text"); + + b.Property("ChefsSubmissionId") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationChefsFileAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactEmail") + .HasColumnType("text"); + + b.Property("ContactFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactMobilePhone") + .HasColumnType("text"); + + b.Property("ContactTitle") + .HasColumnType("text"); + + b.Property("ContactType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactWorkPhone") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationContact", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasColumnType("text"); + + b.Property("ApplicationFormDescription") + .HasColumnType("text"); + + b.Property("ApplicationFormName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AttemptedConnectionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsCriteriaFormGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConnectionHttpStatus") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultPaymentGroup") + .HasColumnType("integer"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ElectoralDistrictAddressType") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormHierarchy") + .HasColumnType("integer"); + + b.Property("IntakeId") + .HasColumnType("uuid"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDirectApproval") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentFormId") + .HasColumnType("uuid"); + + b.Property("Payable") + .HasColumnType("boolean"); + + b.Property("PaymentApprovalThreshold") + .HasColumnType("numeric"); + + b.Property("Prefix") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PreventPayment") + .HasColumnType("boolean"); + + b.Property("RenderFormIoToHtml") + .HasColumnType("boolean"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("SuffixType") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IntakeId"); + + b.HasIndex("ParentFormId"); + + b.ToTable("ApplicationForms", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormVersionId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsSubmissionGuid") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormVersionId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("RenderedHTML") + .HasColumnType("text"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Submission") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormSubmissions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsFormVersionGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormSchema") + .HasColumnType("jsonb"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmissionHeaderMapping") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormVersion", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LinkType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("Related"); + + b.Property("LinkedApplicationId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StatusCode") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("StatusCode") + .IsUnique(); + + b.ToTable("ApplicationStatuses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("TagId"); + + b.ToTable("ApplicationTags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.ToTable("AssessmentAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("AuditDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AuditNote") + .HasColumnType("text"); + + b.Property("AuditTrackingNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("AuditHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FundingNotes") + .HasColumnType("text"); + + b.Property("FundingYear") + .HasColumnType("text"); + + b.Property("GrantCategory") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OneTimeConsideration") + .HasColumnType("numeric"); + + b.Property("ReconsiderationAmount") + .HasColumnType("numeric"); + + b.Property("RenewedFunding") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalGrantAmount") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("FundingHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IssueDescription") + .HasColumnType("text"); + + b.Property("IssueHeading") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ResolutionNote") + .HasColumnType("text"); + + b.Property("Resolved") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Year") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("IssueTrackings", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ApprovalRecommended") + .HasColumnType("boolean"); + + b.Property("AssessorId") + .HasColumnType("uuid"); + + b.Property("CleanGrowth") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EconomicImpact") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialAnalysis") + .HasColumnType("integer"); + + b.Property("InclusiveGrowth") + .HasColumnType("integer"); + + b.Property("IsAiAssessment") + .HasColumnType("boolean"); + + b.Property("IsComplete") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssessorId"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicantComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicationComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CommenterId"); + + b.ToTable("AssessmentComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.Contact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HomePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MobilePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("WorkPhoneExtension") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WorkPhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Contacts", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("RelatedEntityId") + .HasColumnType("uuid"); + + b.Property("RelatedEntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Role") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RelatedEntityType", "RelatedEntityId"); + + b.HasIndex("ContactId", "RelatedEntityType", "RelatedEntityId"); + + b.ToTable("ContactLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.GlobalTag.Tag", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Tags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Identity.Person", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Badge") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcDisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("OidcSub"); + + b.ToTable("Persons", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Intakes.Intake", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Budget") + .HasColumnType("double precision"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Intakes", (string)null); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("EmailGroupUsers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CC") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesHttpStatusCode") + .HasColumnType("text"); + + b.Property("ChesMsgId") + .HasColumnType("uuid"); + + b.Property("ChesResponse") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestIds") + .IsRequired() + .HasColumnType("text"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryAttempts") + .HasColumnType("integer"); + + b.Property("SendOnDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SentDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ToAddress") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailLogs", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("EmailLogId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("EmailLogId"); + + b.HasIndex("S3ObjectKey"); + + b.ToTable("EmailLogAttachments", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BodyHTML") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyText") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SendFrom") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Subscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("SubscriptionGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriberId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.HasIndex("SubscriberId"); + + b.ToTable("SubscriptionGroupSubscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TemplateVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MapTo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TemplateVariables", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Triggers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriptionGroupId") + .HasColumnType("uuid"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SubscriptionGroupId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("TriggerId"); + + b.ToTable("TriggerSubscriptions", "Notifications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.AccountCodings.AccountCoding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(35) + .HasColumnType("character varying(35)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MinistryClient") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Responsibility") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServiceLine") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stob") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AccountCodings", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentConfigurations.PaymentConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultAccountCodingId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PaymentConfigurations", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DecisionUserId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("ExpenseApprovals", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BatchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BatchNumber") + .HasColumnType("numeric"); + + b.Property("CasHttpStatusCode") + .HasColumnType("integer"); + + b.Property("CasResponse") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FsbApNotified") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("FsbNotificationEmailLogId") + .HasColumnType("uuid"); + + b.Property("FsbNotificationSentDate") + .HasColumnType("timestamp without time zone"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("InvoiceStatus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRecon") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("PayeeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentDate") + .HasColumnType("text"); + + b.Property("PaymentNumber") + .HasColumnType("text"); + + b.Property("PaymentStatus") + .HasColumnType("text"); + + b.Property("ReferenceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequesterName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("SubmissionConfirmationCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SupplierName") + .HasColumnType("text"); + + b.Property("SupplierNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AccountCodingId"); + + b.HasIndex("FsbNotificationEmailLogId"); + + b.HasIndex("ReferenceNumber") + .IsUnique(); + + b.HasIndex("SiteId"); + + b.ToTable("PaymentRequests", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.HasIndex("TagId"); + + b.ToTable("PaymentTags", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentThresholds.PaymentThreshold", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Threshold") + .HasColumnType("numeric"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("PaymentThresholds", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressLine3") + .HasColumnType("text"); + + b.Property("BankAccount") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EFTAdvicePref") + .HasColumnType("text"); + + b.Property("EmailAddress") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCas") + .HasColumnType("timestamp without time zone"); + + b.Property("MarkDeletedInUse") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentGroup") + .HasColumnType("integer"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SiteProtected") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("Sites", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCAS") + .HasColumnType("timestamp without time zone"); + + b.Property("MailingAddress") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SIN") + .HasColumnType("text"); + + b.Property("StandardIndustryClassification") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Subcategory") + .HasColumnType("text"); + + b.Property("SupplierProtected") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Suppliers", "Payments"); + }); + + modelBuilder.Entity("Unity.Reporting.Domain.Configuration.ReportColumnsMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Mapping") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("RoleStatus") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ViewStatus") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ReportColumnsMaps", "Reporting"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Instances") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", null) + .WithMany("Answers") + .HasForeignKey("ScoresheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.ScoresheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Sections") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.HasOne("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", null) + .WithMany("Values") + .HasForeignKey("WorksheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Links") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.WorksheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Sections") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicationId"); + + b.Navigation("Applicant"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithOne("ApplicantAgent") + .HasForeignKey("Unity.GrantManager.Applications.ApplicantAgent", "ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", "ApplicationForm") + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationStatus", "ApplicationStatus") + .WithMany("Applications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Applicant"); + + b.Navigation("ApplicationForm"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationAssignments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Assignee") + .WithMany() + .HasForeignKey("AssigneeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Assignee"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.HasOne("Unity.GrantManager.Intakes.Intake", null) + .WithMany() + .HasForeignKey("IntakeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ParentFormId") + .OnDelete(DeleteBehavior.NoAction); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany("ApplicationLinks") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationTags") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("Assessments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("AssessorId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.HasOne("Unity.GrantManager.Contacts.Contact", null) + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.HasOne("Unity.Notifications.EmailGroups.EmailGroup", null) + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.HasOne("Unity.Notifications.Emails.EmailLog", null) + .WithMany() + .HasForeignKey("EmailLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("Unity.Notifications.Templates.Subscriber", "Subscriber") + .WithMany() + .HasForeignKey("SubscriberId"); + + b.Navigation("Subscriber"); + + b.Navigation("SubscriptionGroup"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("SubscriptionGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.EmailTemplate", "EmailTemplate") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmailTemplate"); + + b.Navigation("SubscriptionGroup"); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", "PaymentRequest") + .WithMany("ExpenseApprovals") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentRequest"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.HasOne("Unity.Payments.Domain.AccountCodings.AccountCoding", "AccountCoding") + .WithMany() + .HasForeignKey("AccountCodingId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("Unity.Payments.Domain.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("AccountCoding"); + + b.Navigation("Site"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", null) + .WithMany("PaymentTags") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.HasOne("Unity.Payments.Domain.Suppliers.Supplier", "Supplier") + .WithMany("Sites") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Navigation("Instances"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Navigation("Values"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Navigation("Links"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Navigation("ApplicantAddresses"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Navigation("ApplicantAddresses"); + + b.Navigation("ApplicantAgent"); + + b.Navigation("ApplicationAssignments"); + + b.Navigation("ApplicationLinks"); + + b.Navigation("ApplicationTags"); + + b.Navigation("Assessments"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Navigation("Applications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Navigation("ExpenseApprovals"); + + b.Navigation("PaymentTags"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Navigation("Sites"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260408213219_Backfill_UnityApplicationId_ABPP2025FallClaims.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260408213219_Backfill_UnityApplicationId_ABPP2025FallClaims.cs new file mode 100644 index 0000000000..42aa0af0de --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260408213219_Backfill_UnityApplicationId_ABPP2025FallClaims.cs @@ -0,0 +1,113 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class Backfill_UnityApplicationId_ABPP2025FallClaims : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + // A: Assign sequential UnityApplicationIds to applications with NULL values + // belonging to the "ABPP 2025 - Fall Claim for Payment" form. + // + // Reads the current counter from unity_sequence_counters and adds ROW_NUMBER() + // per (tenant, form) partition ordered by SubmissionDate → CreationTime → Id, + // matching the stable ordering used by SequenceRepository. + migrationBuilder.Sql(@" + WITH target_forms AS ( + SELECT + af.""Id"" AS form_id, + af.""Prefix"", + COALESCE(af.""TenantId"", '00000000-0000-0000-0000-000000000000'::UUID) AS tenant_id + FROM ""ApplicationForms"" af + WHERE af.""Category"" = 'ABPP 2025 - Fall Claim for Payment' + AND af.""SuffixType"" = 1 + AND af.""Prefix"" IS NOT NULL + AND af.""Prefix"" <> '' + ), + counters AS ( + SELECT sc.""current_value"", tf.tenant_id, tf.""Prefix"" + FROM ""unity_sequence_counters"" sc + JOIN target_forms tf ON sc.""tenant_id"" = tf.tenant_id AND sc.""prefix"" = tf.""Prefix"" + ), + null_apps AS ( + SELECT + a.""Id"", + tf.form_id, + tf.""Prefix"", + tf.tenant_id, + ROW_NUMBER() OVER ( + PARTITION BY tf.tenant_id, tf.form_id + ORDER BY a.""SubmissionDate"" ASC, a.""CreationTime"" ASC, a.""Id"" ASC + ) AS rn + FROM ""Applications"" a + JOIN target_forms tf ON a.""ApplicationFormId"" = tf.form_id + WHERE a.""UnityApplicationId"" IS NULL + ), + assignments AS ( + SELECT + na.""Id"", + na.""Prefix"" || LPAD( + (c.""current_value"" + na.rn)::TEXT, + GREATEST(5, LENGTH((c.""current_value"" + na.rn)::TEXT)), + '0' + ) AS new_unity_id + FROM null_apps na + JOIN counters c ON c.tenant_id = na.tenant_id AND c.""Prefix"" = na.""Prefix"" + ) + UPDATE ""Applications"" a + SET ""UnityApplicationId"" = asgn.new_unity_id + FROM assignments asgn + WHERE a.""Id"" = asgn.""Id""; + "); + + // B: Sync unity_sequence_counters to the new maximum after the backfill. + // Uses GREATEST so the counter never moves backwards. + migrationBuilder.Sql(@" + WITH target_forms AS ( + SELECT + af.""Id"" AS form_id, + af.""Prefix"", + COALESCE(af.""TenantId"", '00000000-0000-0000-0000-000000000000'::UUID) AS tenant_id + FROM ""ApplicationForms"" af + WHERE af.""Category"" = 'ABPP 2025 - Fall Claim for Payment' + AND af.""SuffixType"" = 1 + AND af.""Prefix"" IS NOT NULL + AND af.""Prefix"" <> '' + ), + new_max AS ( + SELECT + tf.tenant_id, + tf.""Prefix"", + MAX( + CAST( + SUBSTRING(a.""UnityApplicationId"" FROM CHAR_LENGTH(tf.""Prefix"") + 1) + AS BIGINT + ) + ) AS max_seq + FROM ""Applications"" a + JOIN target_forms tf ON a.""ApplicationFormId"" = tf.form_id + WHERE a.""UnityApplicationId"" IS NOT NULL + AND LEFT(a.""UnityApplicationId"", CHAR_LENGTH(tf.""Prefix"")) = tf.""Prefix"" + AND SUBSTRING(a.""UnityApplicationId"" FROM CHAR_LENGTH(tf.""Prefix"") + 1) ~ '^[0-9]+$' + GROUP BY tf.tenant_id, tf.""Prefix"" + ) + UPDATE ""unity_sequence_counters"" sc + SET ""current_value"" = GREATEST(sc.""current_value"", nm.max_seq) + FROM new_max nm + WHERE sc.""tenant_id"" = nm.tenant_id + AND sc.""prefix"" = nm.""Prefix""; + "); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + // Un-assigning backfilled IDs is not supported. + // Rollback requires restoring from a pre-migration backup. + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260413203049_SafeDateTimeCasting.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260413203049_SafeDateTimeCasting.Designer.cs new file mode 100644 index 0000000000..3dd5548f12 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260413203049_SafeDateTimeCasting.Designer.cs @@ -0,0 +1,4941 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + [DbContext(typeof(GrantTenantDbContext))] + [Migration("20260413203049_SafeDateTimeCasting")] + partial class SafeDateTimeCasting + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("QuestionId") + .HasColumnType("uuid"); + + b.Property("ScoresheetInstanceId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("ScoresheetInstanceId"); + + b.ToTable("Answers", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("Questions", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Scoresheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CustomFieldId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetInstanceId"); + + b.ToTable("CustomFieldValues", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetCorrelationId") + .HasColumnType("uuid"); + + b.Property("WorksheetCorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("WorksheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetLinks", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("CustomFields", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Worksheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantName") + .IsRequired() + .HasMaxLength(600) + .HasColumnType("character varying(600)"); + + b.Property("ApproxNumberOfEmployees") + .HasColumnType("text"); + + b.Property("AuditComments") + .HasColumnType("text"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("FundingHistoryComments") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + b.Property("IsDuplicated") + .HasColumnType("boolean"); + + b.Property("IssueTrackingComments") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MatchPercentage") + .HasColumnType("numeric"); + + b.Property("NonRegOrgName") + .HasColumnType("text"); + + b.Property("NonRegisteredBusinessName") + .HasColumnType("text"); + + b.Property("OrgName") + .HasColumnType("text"); + + b.Property("OrgNumber") + .HasColumnType("text"); + + b.Property("OrgStatus") + .HasColumnType("text"); + + b.Property("OrganizationSize") + .HasColumnType("text"); + + b.Property("OrganizationType") + .HasColumnType("text"); + + b.Property("RedStop") + .HasColumnType("boolean"); + + b.Property("Sector") + .HasColumnType("text"); + + b.Property("SectorSubSectorIndustryDesc") + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("StartedOperatingDate") + .HasColumnType("date"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SubSector") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UnityApplicantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantName"); + + b.ToTable("Applicants", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AddressType") + .HasColumnType("integer"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Postal") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("Street2") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Unit") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicantAddresses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BceidBusinessGuid") + .HasColumnType("uuid"); + + b.Property("BceidBusinessName") + .HasColumnType("text"); + + b.Property("BceidUserGuid") + .HasColumnType("uuid"); + + b.Property("BceidUserName") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactOrder") + .HasColumnType("integer"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IdentityEmail") + .HasColumnType("text"); + + b.Property("IdentityName") + .HasColumnType("text"); + + b.Property("IdentityProvider") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSubUser") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Phone2") + .HasColumnType("text"); + + b.Property("Phone2Extension") + .HasColumnType("text"); + + b.Property("PhoneExtension") + .HasColumnType("text"); + + b.Property("RoleForApplicant") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId") + .IsUnique(); + + b.ToTable("ApplicantAgents", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("ApplicantAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AIAnalysis") + .HasColumnType("text"); + + b.Property("AIScoresheetAnswers") + .HasColumnType("jsonb"); + + b.Property("Acquisition") + .HasColumnType("text"); + + b.Property("ApplicantElectoralDistrict") + .HasColumnType("text"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationStatusId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("AssessmentResultDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AssessmentResultStatus") + .HasColumnType("text"); + + b.Property("AssessmentStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Community") + .HasColumnType("text"); + + b.Property("CommunityPopulation") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractExecutionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ContractNumber") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeclineRational") + .HasColumnType("text"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DueDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DueDiligenceStatus") + .HasColumnType("text"); + + b.Property("EconomicRegion") + .HasColumnType("text"); + + b.Property("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinalDecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Forestry") + .HasColumnType("text"); + + b.Property("ForestryFocus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LikelihoodOfFunding") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("NotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("PercentageTotalProjectBudget") + .HasColumnType("double precision"); + + b.Property("Place") + .HasColumnType("text"); + + b.Property("ProjectEndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectFundingTotal") + .HasColumnType("numeric"); + + b.Property("ProjectName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ProjectStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectSummary") + .HasColumnType("text"); + + b.Property("ProposalDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecommendedAmount") + .HasColumnType("numeric"); + + b.Property("ReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrict") + .HasColumnType("text"); + + b.Property("RequestedAmount") + .HasColumnType("numeric"); + + b.Property("RiskRanking") + .HasColumnType("text"); + + b.Property("SigningAuthorityBusinessPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityCellPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityEmail") + .HasColumnType("text"); + + b.Property("SigningAuthorityFullName") + .HasColumnType("text"); + + b.Property("SigningAuthorityTitle") + .HasColumnType("text"); + + b.Property("SubStatus") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalProjectBudget") + .HasColumnType("numeric"); + + b.Property("TotalScore") + .HasColumnType("integer"); + + b.Property("UnityApplicationId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.HasIndex("ApplicationStatusId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Applications", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssigneeId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Duty") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssigneeId"); + + b.ToTable("ApplicationAssignments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AISummary") + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsFileId") + .HasColumnType("text"); + + b.Property("ChefsSubmissionId") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationChefsFileAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactEmail") + .HasColumnType("text"); + + b.Property("ContactFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactMobilePhone") + .HasColumnType("text"); + + b.Property("ContactTitle") + .HasColumnType("text"); + + b.Property("ContactType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactWorkPhone") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationContact", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasColumnType("text"); + + b.Property("ApplicationFormDescription") + .HasColumnType("text"); + + b.Property("ApplicationFormName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AttemptedConnectionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsCriteriaFormGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConnectionHttpStatus") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultPaymentGroup") + .HasColumnType("integer"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ElectoralDistrictAddressType") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormHierarchy") + .HasColumnType("integer"); + + b.Property("IntakeId") + .HasColumnType("uuid"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDirectApproval") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ParentFormId") + .HasColumnType("uuid"); + + b.Property("Payable") + .HasColumnType("boolean"); + + b.Property("PaymentApprovalThreshold") + .HasColumnType("numeric"); + + b.Property("Prefix") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PreventPayment") + .HasColumnType("boolean"); + + b.Property("RenderFormIoToHtml") + .HasColumnType("boolean"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("SuffixType") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IntakeId"); + + b.HasIndex("ParentFormId"); + + b.ToTable("ApplicationForms", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormVersionId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsSubmissionGuid") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormVersionId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("RenderedHTML") + .HasColumnType("text"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Submission") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormSubmissions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsFormVersionGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormSchema") + .HasColumnType("jsonb"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmissionHeaderMapping") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormVersion", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LinkType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("Related"); + + b.Property("LinkedApplicationId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StatusCode") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("StatusCode") + .IsUnique(); + + b.ToTable("ApplicationStatuses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("TagId"); + + b.ToTable("ApplicationTags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.ToTable("AssessmentAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("AuditDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AuditNote") + .HasColumnType("text"); + + b.Property("AuditTrackingNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("AuditHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FundingNotes") + .HasColumnType("text"); + + b.Property("FundingYear") + .HasColumnType("text"); + + b.Property("GrantCategory") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OneTimeConsideration") + .HasColumnType("numeric"); + + b.Property("ReconsiderationAmount") + .HasColumnType("numeric"); + + b.Property("RenewedFunding") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalGrantAmount") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("FundingHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IssueDescription") + .HasColumnType("text"); + + b.Property("IssueHeading") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ResolutionNote") + .HasColumnType("text"); + + b.Property("Resolved") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Year") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("IssueTrackings", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ApprovalRecommended") + .HasColumnType("boolean"); + + b.Property("AssessorId") + .HasColumnType("uuid"); + + b.Property("CleanGrowth") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EconomicImpact") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialAnalysis") + .HasColumnType("integer"); + + b.Property("InclusiveGrowth") + .HasColumnType("integer"); + + b.Property("IsAiAssessment") + .HasColumnType("boolean"); + + b.Property("IsComplete") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssessorId"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicantComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicationComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CommenterId"); + + b.ToTable("AssessmentComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.Contact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HomePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MobilePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("WorkPhoneExtension") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WorkPhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Contacts", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("RelatedEntityId") + .HasColumnType("uuid"); + + b.Property("RelatedEntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Role") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RelatedEntityType", "RelatedEntityId"); + + b.HasIndex("ContactId", "RelatedEntityType", "RelatedEntityId"); + + b.ToTable("ContactLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.GlobalTag.Tag", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Tags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Identity.Person", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Badge") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcDisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("OidcSub"); + + b.ToTable("Persons", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Intakes.Intake", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Budget") + .HasColumnType("double precision"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Intakes", (string)null); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("EmailGroupUsers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CC") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesHttpStatusCode") + .HasColumnType("text"); + + b.Property("ChesMsgId") + .HasColumnType("uuid"); + + b.Property("ChesResponse") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestIds") + .IsRequired() + .HasColumnType("text"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryAttempts") + .HasColumnType("integer"); + + b.Property("SendOnDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SentDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ToAddress") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailLogs", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("EmailLogId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("EmailLogId"); + + b.HasIndex("S3ObjectKey"); + + b.ToTable("EmailLogAttachments", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BodyHTML") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyText") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SendFrom") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Subscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("SubscriptionGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriberId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.HasIndex("SubscriberId"); + + b.ToTable("SubscriptionGroupSubscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TemplateVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MapTo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TemplateVariables", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Triggers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriptionGroupId") + .HasColumnType("uuid"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SubscriptionGroupId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("TriggerId"); + + b.ToTable("TriggerSubscriptions", "Notifications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.AccountCodings.AccountCoding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(35) + .HasColumnType("character varying(35)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MinistryClient") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Responsibility") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServiceLine") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stob") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AccountCodings", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentConfigurations.PaymentConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultAccountCodingId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PaymentConfigurations", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DecisionUserId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("ExpenseApprovals", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BatchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BatchNumber") + .HasColumnType("numeric"); + + b.Property("CasHttpStatusCode") + .HasColumnType("integer"); + + b.Property("CasResponse") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FsbApNotified") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("FsbNotificationEmailLogId") + .HasColumnType("uuid"); + + b.Property("FsbNotificationSentDate") + .HasColumnType("timestamp without time zone"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("InvoiceStatus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRecon") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("PayeeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentDate") + .HasColumnType("text"); + + b.Property("PaymentNumber") + .HasColumnType("text"); + + b.Property("PaymentStatus") + .HasColumnType("text"); + + b.Property("ReferenceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequesterName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("SubmissionConfirmationCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SupplierName") + .HasColumnType("text"); + + b.Property("SupplierNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AccountCodingId"); + + b.HasIndex("FsbNotificationEmailLogId"); + + b.HasIndex("ReferenceNumber") + .IsUnique(); + + b.HasIndex("SiteId"); + + b.ToTable("PaymentRequests", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.HasIndex("TagId"); + + b.ToTable("PaymentTags", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentThresholds.PaymentThreshold", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Threshold") + .HasColumnType("numeric"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("PaymentThresholds", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressLine3") + .HasColumnType("text"); + + b.Property("BankAccount") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EFTAdvicePref") + .HasColumnType("text"); + + b.Property("EmailAddress") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCas") + .HasColumnType("timestamp without time zone"); + + b.Property("MarkDeletedInUse") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentGroup") + .HasColumnType("integer"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SiteProtected") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("Sites", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCAS") + .HasColumnType("timestamp without time zone"); + + b.Property("MailingAddress") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SIN") + .HasColumnType("text"); + + b.Property("StandardIndustryClassification") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Subcategory") + .HasColumnType("text"); + + b.Property("SupplierProtected") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Suppliers", "Payments"); + }); + + modelBuilder.Entity("Unity.Reporting.Domain.Configuration.ReportColumnsMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Mapping") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("RoleStatus") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ViewStatus") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ReportColumnsMaps", "Reporting"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Instances") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", null) + .WithMany("Answers") + .HasForeignKey("ScoresheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.ScoresheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Sections") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.HasOne("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", null) + .WithMany("Values") + .HasForeignKey("WorksheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Links") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.WorksheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Sections") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicationId"); + + b.Navigation("Applicant"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithOne("ApplicantAgent") + .HasForeignKey("Unity.GrantManager.Applications.ApplicantAgent", "ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", "ApplicationForm") + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationStatus", "ApplicationStatus") + .WithMany("Applications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Applicant"); + + b.Navigation("ApplicationForm"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationAssignments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Assignee") + .WithMany() + .HasForeignKey("AssigneeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Assignee"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.HasOne("Unity.GrantManager.Intakes.Intake", null) + .WithMany() + .HasForeignKey("IntakeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ParentFormId") + .OnDelete(DeleteBehavior.NoAction); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany("ApplicationLinks") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationTags") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("Assessments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("AssessorId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.HasOne("Unity.GrantManager.Contacts.Contact", null) + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.HasOne("Unity.Notifications.EmailGroups.EmailGroup", null) + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.HasOne("Unity.Notifications.Emails.EmailLog", null) + .WithMany() + .HasForeignKey("EmailLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("Unity.Notifications.Templates.Subscriber", "Subscriber") + .WithMany() + .HasForeignKey("SubscriberId"); + + b.Navigation("Subscriber"); + + b.Navigation("SubscriptionGroup"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("SubscriptionGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.EmailTemplate", "EmailTemplate") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmailTemplate"); + + b.Navigation("SubscriptionGroup"); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", "PaymentRequest") + .WithMany("ExpenseApprovals") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentRequest"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.HasOne("Unity.Payments.Domain.AccountCodings.AccountCoding", "AccountCoding") + .WithMany() + .HasForeignKey("AccountCodingId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("Unity.Payments.Domain.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("AccountCoding"); + + b.Navigation("Site"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", null) + .WithMany("PaymentTags") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.HasOne("Unity.Payments.Domain.Suppliers.Supplier", "Supplier") + .WithMany("Sites") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Navigation("Instances"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Navigation("Values"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Navigation("Links"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Navigation("ApplicantAddresses"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Navigation("ApplicantAddresses"); + + b.Navigation("ApplicantAgent"); + + b.Navigation("ApplicationAssignments"); + + b.Navigation("ApplicationLinks"); + + b.Navigation("ApplicationTags"); + + b.Navigation("Assessments"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Navigation("Applications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Navigation("ExpenseApprovals"); + + b.Navigation("PaymentTags"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Navigation("Sites"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260413203049_SafeDateTimeCasting.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260413203049_SafeDateTimeCasting.cs new file mode 100644 index 0000000000..1915e60563 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260413203049_SafeDateTimeCasting.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.IO; +using System.Reflection; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class SafeDateTimeCasting : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + var assembly = Assembly.GetExecutingAssembly(); + + // Create the safe_to_timestamp helper function + var safeTimestampResource = "Unity.GrantManager.Scripts.safe_to_timestamp.sql"; + using Stream stream1 = assembly.GetManifestResourceStream(safeTimestampResource) + ?? throw new InvalidOperationException($"Could not find embedded resource: {safeTimestampResource}"); + using StreamReader reader1 = new StreamReader(stream1); + string sql1 = reader1.ReadToEnd(); + migrationBuilder.Sql(sql1); + + // Create the safe_to_date helper function + var safeDateResource = "Unity.GrantManager.Scripts.safe_to_date.sql"; + using Stream stream2 = assembly.GetManifestResourceStream(safeDateResource) + ?? throw new InvalidOperationException($"Could not find embedded resource: {safeDateResource}"); + using StreamReader reader2 = new StreamReader(stream2); + string sql2 = reader2.ReadToEnd(); + migrationBuilder.Sql(sql2); + + // Update the get_worksheet_data function to use safe casting helpers + var worksheetDataResource = "Unity.GrantManager.Scripts.get_worksheet_data.sql"; + using Stream stream3 = assembly.GetManifestResourceStream(worksheetDataResource) + ?? throw new InvalidOperationException($"Could not find embedded resource: {worksheetDataResource}"); + using StreamReader reader3 = new StreamReader(stream3); + string sql3 = reader3.ReadToEnd(); + migrationBuilder.Sql(sql3); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS ""Reporting"".safe_to_timestamp(TEXT);"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS ""Reporting"".safe_to_date(TEXT);"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260415194927_AddApplicationFormAIConfiguration.Designer.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260415194927_AddApplicationFormAIConfiguration.Designer.cs new file mode 100644 index 0000000000..4ac5b2d15b --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260415194927_AddApplicationFormAIConfiguration.Designer.cs @@ -0,0 +1,4947 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + [DbContext(typeof(GrantTenantDbContext))] + [Migration("20260415194927_AddApplicationFormAIConfiguration")] + partial class AddApplicationFormAIConfiguration + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) + .HasAnnotation("ProductVersion", "9.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("QuestionId") + .HasColumnType("uuid"); + + b.Property("ScoresheetInstanceId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("QuestionId"); + + b.HasIndex("ScoresheetInstanceId"); + + b.ToTable("Answers", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("Questions", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Scoresheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ScoresheetId"); + + b.ToTable("ScoresheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("CustomFieldId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetInstanceId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetInstanceId"); + + b.ToTable("CustomFieldValues", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("CurrentValue") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetCorrelationId") + .HasColumnType("uuid"); + + b.Property("WorksheetCorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("WorksheetInstances", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UiAnchor") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetLinks", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Definition") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("SectionId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SectionId"); + + b.ToTable("CustomFields", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Worksheets", "Flex"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("WorksheetId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("WorksheetId"); + + b.ToTable("WorksheetSections", "Flex"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantName") + .IsRequired() + .HasMaxLength(600) + .HasColumnType("character varying(600)"); + + b.Property("ApproxNumberOfEmployees") + .HasColumnType("text"); + + b.Property("AuditComments") + .HasColumnType("text"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FiscalDay") + .HasColumnType("integer"); + + b.Property("FiscalMonth") + .HasColumnType("text"); + + b.Property("FundingHistoryComments") + .HasColumnType("text"); + + b.Property("IndigenousOrgInd") + .HasColumnType("text"); + + b.Property("IsDuplicated") + .HasColumnType("boolean"); + + b.Property("IssueTrackingComments") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MatchPercentage") + .HasColumnType("numeric"); + + b.Property("NonRegOrgName") + .HasColumnType("text"); + + b.Property("NonRegisteredBusinessName") + .HasColumnType("text"); + + b.Property("OrgName") + .HasColumnType("text"); + + b.Property("OrgNumber") + .HasColumnType("text"); + + b.Property("OrgStatus") + .HasColumnType("text"); + + b.Property("OrganizationSize") + .HasColumnType("text"); + + b.Property("OrganizationType") + .HasColumnType("text"); + + b.Property("RedStop") + .HasColumnType("boolean"); + + b.Property("Sector") + .HasColumnType("text"); + + b.Property("SectorSubSectorIndustryDesc") + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("StartedOperatingDate") + .HasColumnType("date"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SubSector") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UnityApplicantId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantName"); + + b.ToTable("Applicants", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AddressType") + .HasColumnType("integer"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Postal") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("Street") + .HasColumnType("text"); + + b.Property("Street2") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Unit") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicantAddresses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("BceidBusinessGuid") + .HasColumnType("uuid"); + + b.Property("BceidBusinessName") + .HasColumnType("text"); + + b.Property("BceidUserGuid") + .HasColumnType("uuid"); + + b.Property("BceidUserName") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactOrder") + .HasColumnType("integer"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IdentityEmail") + .HasColumnType("text"); + + b.Property("IdentityName") + .HasColumnType("text"); + + b.Property("IdentityProvider") + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSubUser") + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("Phone2") + .HasColumnType("text"); + + b.Property("Phone2Extension") + .HasColumnType("text"); + + b.Property("PhoneExtension") + .HasColumnType("text"); + + b.Property("RoleForApplicant") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationId") + .IsUnique(); + + b.ToTable("ApplicantAgents", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("ApplicantAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AIAnalysis") + .HasColumnType("text"); + + b.Property("AIScoresheetAnswers") + .HasColumnType("jsonb"); + + b.Property("Acquisition") + .HasColumnType("text"); + + b.Property("ApplicantElectoralDistrict") + .HasColumnType("text"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationStatusId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("AssessmentResultDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AssessmentResultStatus") + .HasColumnType("text"); + + b.Property("AssessmentStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Community") + .HasColumnType("text"); + + b.Property("CommunityPopulation") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractExecutionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ContractNumber") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeclineRational") + .HasColumnType("text"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("DueDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DueDiligenceStatus") + .HasColumnType("text"); + + b.Property("EconomicRegion") + .HasColumnType("text"); + + b.Property("ElectoralDistrict") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinalDecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Forestry") + .HasColumnType("text"); + + b.Property("ForestryFocus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LikelihoodOfFunding") + .HasColumnType("text"); + + b.Property("Notes") + .HasColumnType("text"); + + b.Property("NotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OwnerId") + .HasColumnType("uuid"); + + b.Property("Payload") + .HasColumnType("jsonb"); + + b.Property("PercentageTotalProjectBudget") + .HasColumnType("double precision"); + + b.Property("Place") + .HasColumnType("text"); + + b.Property("ProjectEndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectFundingTotal") + .HasColumnType("numeric"); + + b.Property("ProjectName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ProjectStartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ProjectSummary") + .HasColumnType("text"); + + b.Property("ProposalDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecommendedAmount") + .HasColumnType("numeric"); + + b.Property("ReferenceNo") + .IsRequired() + .HasColumnType("text"); + + b.Property("RegionalDistrict") + .HasColumnType("text"); + + b.Property("RequestedAmount") + .HasColumnType("numeric"); + + b.Property("RiskRanking") + .HasColumnType("text"); + + b.Property("SigningAuthorityBusinessPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityCellPhone") + .HasColumnType("text"); + + b.Property("SigningAuthorityEmail") + .HasColumnType("text"); + + b.Property("SigningAuthorityFullName") + .HasColumnType("text"); + + b.Property("SigningAuthorityTitle") + .HasColumnType("text"); + + b.Property("SubStatus") + .HasColumnType("text"); + + b.Property("SubmissionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalProjectBudget") + .HasColumnType("numeric"); + + b.Property("TotalScore") + .HasColumnType("integer"); + + b.Property("UnityApplicationId") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.HasIndex("ApplicationStatusId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Applications", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssigneeId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Duty") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssigneeId"); + + b.ToTable("ApplicationAssignments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AISummary") + .HasColumnType("text"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsFileId") + .HasColumnType("text"); + + b.Property("ChefsSubmissionId") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationChefsFileAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactEmail") + .HasColumnType("text"); + + b.Property("ContactFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactMobilePhone") + .HasColumnType("text"); + + b.Property("ContactTitle") + .HasColumnType("text"); + + b.Property("ContactType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContactWorkPhone") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationContact", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasColumnType("text"); + + b.Property("ApplicationFormDescription") + .HasColumnType("text"); + + b.Property("ApplicationFormName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("AttemptedConnectionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AutomaticallyGenerateAIAnalysis") + .HasColumnType("boolean"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsCriteriaFormGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConnectionHttpStatus") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultPaymentGroup") + .HasColumnType("integer"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ElectoralDistrictAddressType") + .HasColumnType("integer"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormHierarchy") + .HasColumnType("integer"); + + b.Property("IntakeId") + .HasColumnType("uuid"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDirectApproval") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ManuallyInitiateAIAnalysis") + .HasColumnType("boolean"); + + b.Property("ParentFormId") + .HasColumnType("uuid"); + + b.Property("Payable") + .HasColumnType("boolean"); + + b.Property("PaymentApprovalThreshold") + .HasColumnType("numeric"); + + b.Property("Prefix") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PreventPayment") + .HasColumnType("boolean"); + + b.Property("RenderFormIoToHtml") + .HasColumnType("boolean"); + + b.Property("ScoresheetId") + .HasColumnType("uuid"); + + b.Property("SuffixType") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("IntakeId"); + + b.HasIndex("ParentFormId"); + + b.ToTable("ApplicationForms", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("ApplicationFormVersionId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ChefsSubmissionGuid") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormVersionId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("RenderedHTML") + .HasColumnType("text"); + + b.Property("ReportData") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Submission") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormSubmissions", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationFormId") + .HasColumnType("uuid"); + + b.Property("AvailableChefsFields") + .HasColumnType("text"); + + b.Property("ChefsApplicationFormGuid") + .HasColumnType("text"); + + b.Property("ChefsFormVersionGuid") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FormSchema") + .HasColumnType("jsonb"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Published") + .HasColumnType("boolean"); + + b.Property("ReportColumns") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportKeys") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReportViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SubmissionHeaderMapping") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationFormId"); + + b.ToTable("ApplicationFormVersion", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LinkType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue("Related"); + + b.Property("LinkedApplicationId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.ToTable("ApplicationLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StatusCode") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("StatusCode") + .IsUnique(); + + b.ToTable("ApplicationStatuses", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("TagId"); + + b.ToTable("ApplicationTags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.ToTable("AssessmentAttachments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("AuditDate") + .HasColumnType("timestamp without time zone"); + + b.Property("AuditNote") + .HasColumnType("text"); + + b.Property("AuditTrackingNumber") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("AuditHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApprovedAmount") + .HasColumnType("numeric"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FundingNotes") + .HasColumnType("text"); + + b.Property("FundingYear") + .HasColumnType("text"); + + b.Property("GrantCategory") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OneTimeConsideration") + .HasColumnType("numeric"); + + b.Property("ReconsiderationAmount") + .HasColumnType("numeric"); + + b.Property("RenewedFunding") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TotalGrantAmount") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("FundingHistories", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IssueDescription") + .HasColumnType("text"); + + b.Property("IssueHeading") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("ResolutionNote") + .HasColumnType("text"); + + b.Property("Resolved") + .HasColumnType("boolean"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Year") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("IssueTrackings", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("ApprovalRecommended") + .HasColumnType("boolean"); + + b.Property("AssessorId") + .HasColumnType("uuid"); + + b.Property("CleanGrowth") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("EconomicImpact") + .HasColumnType("integer"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FinancialAnalysis") + .HasColumnType("integer"); + + b.Property("InclusiveGrowth") + .HasColumnType("integer"); + + b.Property("IsAiAssessment") + .HasColumnType("boolean"); + + b.Property("IsComplete") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("AssessorId"); + + b.ToTable("Assessments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicantComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicationComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AssessmentId"); + + b.HasIndex("CommenterId"); + + b.ToTable("AssessmentComments", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.Contact", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("HomePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MobilePhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Title") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("WorkPhoneExtension") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("WorkPhoneNumber") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Contacts", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContactId") + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("RelatedEntityId") + .HasColumnType("uuid"); + + b.Property("RelatedEntityType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Role") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RelatedEntityType", "RelatedEntityId"); + + b.HasIndex("ContactId", "RelatedEntityType", "RelatedEntityId"); + + b.ToTable("ContactLinks", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.GlobalTag.Tag", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Tags", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Identity.Person", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Badge") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("OidcDisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("OidcSub") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("OidcSub"); + + b.ToTable("Persons", (string)null); + }); + + modelBuilder.Entity("Unity.GrantManager.Intakes.Intake", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Budget") + .HasColumnType("double precision"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EndDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IntakeName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Intakes", (string)null); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("EmailGroupUsers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ApplicationId") + .HasColumnType("uuid"); + + b.Property("AssessmentId") + .HasColumnType("uuid"); + + b.Property("BCC") + .IsRequired() + .HasColumnType("text"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CC") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesHttpStatusCode") + .HasColumnType("text"); + + b.Property("ChesMsgId") + .HasColumnType("uuid"); + + b.Property("ChesResponse") + .IsRequired() + .HasColumnType("text"); + + b.Property("ChesStatus") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FromAddress") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestIds") + .IsRequired() + .HasColumnType("text"); + + b.Property("Priority") + .IsRequired() + .HasColumnType("text"); + + b.Property("RetryAttempts") + .HasColumnType("integer"); + + b.Property("SendOnDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("SentDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text"); + + b.Property("TemplateName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ToAddress") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EmailLogs", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("EmailLogId") + .HasColumnType("uuid"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("EmailLogId"); + + b.HasIndex("S3ObjectKey"); + + b.ToTable("EmailLogAttachments", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.EmailTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BodyHTML") + .IsRequired() + .HasColumnType("text"); + + b.Property("BodyText") + .IsRequired() + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SendFrom") + .IsRequired() + .HasColumnType("text"); + + b.Property("Subject") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("EmailTemplates", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Subscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("SubscriptionGroups", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriberId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.HasIndex("SubscriberId"); + + b.ToTable("SubscriptionGroupSubscribers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TemplateVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MapTo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Token") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TemplateVariables", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("InternalName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Triggers", "Notifications"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("SubscriptionGroupId") + .HasColumnType("uuid"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SubscriptionGroupId"); + + b.HasIndex("TemplateId"); + + b.HasIndex("TriggerId"); + + b.ToTable("TriggerSubscriptions", "Notifications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.AccountCodings.AccountCoding", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("Description") + .HasMaxLength(35) + .HasColumnType("character varying(35)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("MinistryClient") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProjectNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("Responsibility") + .IsRequired() + .HasColumnType("text"); + + b.Property("ServiceLine") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stob") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AccountCodings", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentConfigurations.PaymentConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DefaultAccountCodingId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentIdPrefix") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PaymentConfigurations", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DecisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("DecisionUserId") + .HasColumnType("uuid"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.ToTable("ExpenseApprovals", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountCodingId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("BatchName") + .IsRequired() + .HasColumnType("text"); + + b.Property("BatchNumber") + .HasColumnType("numeric"); + + b.Property("CasHttpStatusCode") + .HasColumnType("integer"); + + b.Property("CasResponse") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContractNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FsbApNotified") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("FsbNotificationEmailLogId") + .HasColumnType("uuid"); + + b.Property("FsbNotificationSentDate") + .HasColumnType("timestamp without time zone"); + + b.Property("InvoiceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("InvoiceStatus") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRecon") + .HasColumnType("boolean"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("PayeeName") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentDate") + .HasColumnType("text"); + + b.Property("PaymentNumber") + .HasColumnType("text"); + + b.Property("PaymentStatus") + .HasColumnType("text"); + + b.Property("ReferenceNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequesterName") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("SubmissionConfirmationCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("SupplierName") + .HasColumnType("text"); + + b.Property("SupplierNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AccountCodingId"); + + b.HasIndex("FsbNotificationEmailLogId"); + + b.HasIndex("ReferenceNumber") + .IsUnique(); + + b.HasIndex("SiteId"); + + b.ToTable("PaymentRequests", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PaymentRequestId") + .HasColumnType("uuid"); + + b.Property("TagId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("PaymentRequestId"); + + b.HasIndex("TagId"); + + b.ToTable("PaymentTags", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentThresholds.PaymentThreshold", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Threshold") + .HasColumnType("numeric"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("PaymentThresholds", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressLine1") + .HasColumnType("text"); + + b.Property("AddressLine2") + .HasColumnType("text"); + + b.Property("AddressLine3") + .HasColumnType("text"); + + b.Property("BankAccount") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("Country") + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("EFTAdvicePref") + .HasColumnType("text"); + + b.Property("EmailAddress") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCas") + .HasColumnType("timestamp without time zone"); + + b.Property("MarkDeletedInUse") + .HasColumnType("boolean"); + + b.Property("Number") + .IsRequired() + .HasColumnType("text"); + + b.Property("PaymentGroup") + .HasColumnType("integer"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SiteProtected") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("SupplierId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("Sites", "Payments"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BusinessNumber") + .HasColumnType("text"); + + b.Property("City") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uuid") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdatedInCAS") + .HasColumnType("timestamp without time zone"); + + b.Property("MailingAddress") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("text"); + + b.Property("PostalCode") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("text"); + + b.Property("Province") + .HasColumnType("text"); + + b.Property("SIN") + .HasColumnType("text"); + + b.Property("StandardIndustryClassification") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Subcategory") + .HasColumnType("text"); + + b.Property("SupplierProtected") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("Suppliers", "Payments"); + }); + + modelBuilder.Entity("Unity.Reporting.Domain.Configuration.ReportColumnsMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("CorrelationProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("Mapping") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("RoleStatus") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("ViewName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ViewStatus") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ReportColumnsMaps", "Reporting"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Instances") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Answer", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Question", "Question") + .WithMany("Answers") + .HasForeignKey("QuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", null) + .WithMany("Answers") + .HasForeignKey("ScoresheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Question"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.ScoresheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Scoresheets.Scoresheet", "Scoresheet") + .WithMany("Sections") + .HasForeignKey("ScoresheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Scoresheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.CustomFieldValue", b => + { + b.HasOne("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", null) + .WithMany("Values") + .HasForeignKey("WorksheetInstanceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetLinks.WorksheetLink", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Links") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.CustomField", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.WorksheetSection", "Section") + .WithMany("Fields") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Section"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.HasOne("Unity.Flex.Domain.Worksheets.Worksheet", "Worksheet") + .WithMany("Sections") + .HasForeignKey("WorksheetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Worksheet"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAddress", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicantAddresses") + .HasForeignKey("ApplicationId"); + + b.Navigation("Applicant"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAgent", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithOne("ApplicantAgent") + .HasForeignKey("Unity.GrantManager.Applications.ApplicantAgent", "ApplicationId"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", "ApplicationForm") + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationStatus", "ApplicationStatus") + .WithMany("Applications") + .HasForeignKey("ApplicationStatusId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Applicant"); + + b.Navigation("ApplicationForm"); + + b.Navigation("ApplicationStatus"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAssignment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationAssignments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", "Assignee") + .WithMany() + .HasForeignKey("AssigneeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Assignee"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationChefsFileAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationContact", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationForm", b => + { + b.HasOne("Unity.GrantManager.Intakes.Intake", null) + .WithMany() + .HasForeignKey("IntakeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ParentFormId") + .OnDelete(DeleteBehavior.NoAction); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormSubmission", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationFormVersion", b => + { + b.HasOne("Unity.GrantManager.Applications.ApplicationForm", null) + .WithMany() + .HasForeignKey("ApplicationFormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationLink", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany("ApplicationLinks") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationTags", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("ApplicationTags") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AssessmentAttachment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.AuditHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.FundingHistory", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.IssueTracking", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId"); + }); + + modelBuilder.Entity("Unity.GrantManager.Assessments.Assessment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", "Application") + .WithMany("Assessments") + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("AssessorId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Application", null) + .WithMany() + .HasForeignKey("ApplicationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Comments.AssessmentComment", b => + { + b.HasOne("Unity.GrantManager.Assessments.Assessment", null) + .WithMany() + .HasForeignKey("AssessmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.GrantManager.Contacts.ContactLink", b => + { + b.HasOne("Unity.GrantManager.Contacts.Contact", null) + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.EmailGroups.EmailGroupUser", b => + { + b.HasOne("Unity.Notifications.EmailGroups.EmailGroup", null) + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Emails.EmailLogAttachment", b => + { + b.HasOne("Unity.Notifications.Emails.EmailLog", null) + .WithMany() + .HasForeignKey("EmailLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.SubscriptionGroupSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("GroupId"); + + b.HasOne("Unity.Notifications.Templates.Subscriber", "Subscriber") + .WithMany() + .HasForeignKey("SubscriberId"); + + b.Navigation("Subscriber"); + + b.Navigation("SubscriptionGroup"); + }); + + modelBuilder.Entity("Unity.Notifications.Templates.TriggerSubscription", b => + { + b.HasOne("Unity.Notifications.Templates.SubscriptionGroup", "SubscriptionGroup") + .WithMany() + .HasForeignKey("SubscriptionGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.EmailTemplate", "EmailTemplate") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.Notifications.Templates.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmailTemplate"); + + b.Navigation("SubscriptionGroup"); + + b.Navigation("Trigger"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.ExpenseApproval", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", "PaymentRequest") + .WithMany("ExpenseApprovals") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PaymentRequest"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.HasOne("Unity.Payments.Domain.AccountCodings.AccountCoding", "AccountCoding") + .WithMany() + .HasForeignKey("AccountCodingId") + .OnDelete(DeleteBehavior.NoAction); + + b.HasOne("Unity.Payments.Domain.Suppliers.Site", "Site") + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("AccountCoding"); + + b.Navigation("Site"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentTags.PaymentTag", b => + { + b.HasOne("Unity.Payments.Domain.PaymentRequests.PaymentRequest", null) + .WithMany("PaymentTags") + .HasForeignKey("PaymentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.GlobalTag.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Site", b => + { + b.HasOne("Unity.Payments.Domain.Suppliers.Supplier", "Supplier") + .WithMany("Sites") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.ScoresheetInstances.ScoresheetInstance", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Question", b => + { + b.Navigation("Answers"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.Scoresheet", b => + { + b.Navigation("Instances"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Scoresheets.ScoresheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.WorksheetInstances.WorksheetInstance", b => + { + b.Navigation("Values"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.Worksheet", b => + { + b.Navigation("Links"); + + b.Navigation("Sections"); + }); + + modelBuilder.Entity("Unity.Flex.Domain.Worksheets.WorksheetSection", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Applicant", b => + { + b.Navigation("ApplicantAddresses"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => + { + b.Navigation("ApplicantAddresses"); + + b.Navigation("ApplicantAgent"); + + b.Navigation("ApplicationAssignments"); + + b.Navigation("ApplicationLinks"); + + b.Navigation("ApplicationTags"); + + b.Navigation("Assessments"); + }); + + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicationStatus", b => + { + b.Navigation("Applications"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.PaymentRequests.PaymentRequest", b => + { + b.Navigation("ExpenseApprovals"); + + b.Navigation("PaymentTags"); + }); + + modelBuilder.Entity("Unity.Payments.Domain.Suppliers.Supplier", b => + { + b.Navigation("Sites"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260415194927_AddApplicationFormAIConfiguration.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260415194927_AddApplicationFormAIConfiguration.cs new file mode 100644 index 0000000000..5e3d6eef33 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/20260415194927_AddApplicationFormAIConfiguration.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Unity.GrantManager.Migrations.TenantMigrations +{ + /// + public partial class AddApplicationFormAIConfiguration : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AutomaticallyGenerateAIAnalysis", + table: "ApplicationForms", + type: "boolean", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "ManuallyInitiateAIAnalysis", + table: "ApplicationForms", + type: "boolean", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AutomaticallyGenerateAIAnalysis", + table: "ApplicationForms"); + + migrationBuilder.DropColumn( + name: "ManuallyInitiateAIAnalysis", + table: "ApplicationForms"); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs index d3860e166c..a810161028 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Migrations/TenantMigrations/GrantTenantDbContextModelSnapshot.cs @@ -1100,6 +1100,70 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ApplicantAgents", (string)null); }); + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("DisplayName") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .HasColumnType("text"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("S3ObjectKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.Property("Time") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.ToTable("ApplicantAttachments", (string)null); + }); + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => { b.Property("Id") @@ -1594,6 +1658,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("AttemptedConnectionDate") .HasColumnType("timestamp without time zone"); + b.Property("AutomaticallyGenerateAIAnalysis") + .HasColumnType("boolean"); + b.Property("AvailableChefsFields") .HasColumnType("text"); @@ -1666,6 +1733,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("LastModifierId"); + b.Property("ManuallyInitiateAIAnalysis") + .HasColumnType("boolean"); + b.Property("ParentFormId") .HasColumnType("uuid"); @@ -2201,6 +2271,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("LastModifierId"); + b.Property("OneTimeConsideration") + .HasColumnType("numeric"); + b.Property("ReconsiderationAmount") .HasColumnType("numeric"); @@ -2364,6 +2437,65 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Assessments", (string)null); }); + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApplicantId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CommenterId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("character varying(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("text") + .HasColumnName("ExtraProperties"); + + b.Property("LastModificationTime") + .HasColumnType("timestamp without time zone") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uuid") + .HasColumnName("LastModifierId"); + + b.Property("PinDateTime") + .HasColumnType("timestamp without time zone"); + + b.Property("TenantId") + .HasColumnType("uuid") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ApplicantId"); + + b.HasIndex("CommenterId"); + + b.ToTable("ApplicantComments", (string)null); + }); + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => { b.Property("Id") @@ -4358,6 +4490,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Application"); }); + modelBuilder.Entity("Unity.GrantManager.Applications.ApplicantAttachment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Unity.GrantManager.Applications.Application", b => { b.HasOne("Unity.GrantManager.Applications.Applicant", "Applicant") @@ -4551,6 +4692,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Application"); }); + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicantComment", b => + { + b.HasOne("Unity.GrantManager.Applications.Applicant", null) + .WithMany() + .HasForeignKey("ApplicantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Unity.GrantManager.Identity.Person", null) + .WithMany() + .HasForeignKey("CommenterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Unity.GrantManager.Comments.ApplicationComment", b => { b.HasOne("Unity.GrantManager.Applications.Application", null) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantAttachmentRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantAttachmentRepository.cs new file mode 100644 index 0000000000..a1addbb62d --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantAttachmentRepository.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading.Tasks; +using Unity.GrantManager.Applications; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + + +namespace Unity.GrantManager.Repositories +{ + [Dependency(ReplaceServices = true)] + [ExposeServices(typeof(IApplicantAttachmentRepository))] +#pragma warning disable CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. + // This pattern is an implementation ontop of ABP framework, will not change this + public class ApplicantAttachmentRepository : EfCoreRepository, IApplicantAttachmentRepository +#pragma warning restore CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. + { + public ApplicantAttachmentRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + public async Task> GetListAsync(int skipCount, int maxResultCount, string sorting, string filter) + { + var dbSet = await GetDbSetAsync(); + return await dbSet + .WhereIf( + !filter.IsNullOrWhiteSpace(), + attachment => attachment!=null && attachment.FileName!=null && attachment.FileName.Contains(filter) + ) + .OrderBy(sorting) + .Skip(skipCount) + .Take(maxResultCount) + .ToListAsync(); + } + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantCommentsRepository.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantCommentsRepository.cs new file mode 100644 index 0000000000..2b85b38ace --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Repositories/ApplicantCommentsRepository.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; +using Unity.GrantManager.EntityFrameworkCore; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Unity.GrantManager.Comments; + +namespace Unity.GrantManager.Repositories; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(ICommentsRepository))] +#pragma warning disable CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. +// This pattern is an implementation built on top of the ABP framework and will not be changed. +public class ApplicantCommentsRepository : EfCoreRepository, ICommentsRepository +#pragma warning restore CS8613 // Nullability of reference types in return type doesn't match implicitly implemented member. +{ + public ApplicantCommentsRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public async Task> GetListAsync(int skipCount, int maxResultCount, string sorting, string filter) + { + var dbSet = await GetDbSetAsync(); + return await dbSet + .WhereIf( + !filter.IsNullOrWhiteSpace(), + applicantComment => applicantComment.Comment.Contains(filter) + ) + .OrderBy(sorting) + .Skip(skipCount) + .Take(maxResultCount) + .ToListAsync(); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/get_worksheet_data.sql b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/get_worksheet_data.sql index 16e5e65112..98d5f5ec33 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/get_worksheet_data.sql +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/get_worksheet_data.sql @@ -100,11 +100,11 @@ BEGIN format('(CASE WHEN ((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) IS NULL THEN NULL WHEN ((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) ~ ''^-?[0-9]+\.?[0-9]*$'' THEN ((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L))::NUMERIC ELSE NULL END) AS %I', um.field_name, um.field_name, um.field_name, um.column_name) WHEN 'date' THEN - format('(CASE WHEN ((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) IS NULL OR trim((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) = '''' THEN NULL ELSE ((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L))::DATE END) AS %I', - um.field_name, um.field_name, um.field_name, um.column_name) + format('"Reporting".safe_to_date((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) AS %I', + um.field_name, um.column_name) WHEN 'datetime' THEN - format('(CASE WHEN ((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) IS NULL OR trim((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) = '''' THEN NULL ELSE ((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L))::TIMESTAMP END) AS %I', - um.field_name, um.field_name, um.field_name, um.column_name) + format('"Reporting".safe_to_timestamp((SELECT cell_elem->>''value'' FROM jsonb_array_elements(dg_tbl.dg_data->''cells'') AS cell_elem WHERE cell_elem->>''key'' = %L)) AS %I', + um.field_name, um.column_name) WHEN 'checkbox' THEN -- Check if this is a checkbox group field by looking at the type_path CASE @@ -189,15 +189,11 @@ BEGIN COALESCE(um.clean_data_path, um.property_name), um.column_name) WHEN 'date' THEN - format('(CASE WHEN ((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L)) IS NULL OR trim((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L)) = '''' THEN NULL ELSE ((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L))::DATE END) AS %I', - COALESCE(um.clean_data_path, um.property_name), - COALESCE(um.clean_data_path, um.property_name), + format('"Reporting".safe_to_date((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L)) AS %I', COALESCE(um.clean_data_path, um.property_name), um.column_name) WHEN 'datetime' THEN - format('(CASE WHEN ((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L)) IS NULL OR trim((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L)) = '''' THEN NULL ELSE ((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L))::TIMESTAMP END) AS %I', - COALESCE(um.clean_data_path, um.property_name), - COALESCE(um.clean_data_path, um.property_name), + format('"Reporting".safe_to_timestamp((SELECT v_elem->>''value'' FROM jsonb_array_elements(wi."CurrentValue"->''values'') AS v_elem WHERE v_elem->>''key'' = %L)) AS %I', COALESCE(um.clean_data_path, um.property_name), um.column_name) WHEN 'checkbox' THEN diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/safe_to_date.sql b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/safe_to_date.sql new file mode 100644 index 0000000000..e143639416 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/safe_to_date.sql @@ -0,0 +1,75 @@ +CREATE OR REPLACE FUNCTION "Reporting".safe_to_date(val text) + RETURNS date + LANGUAGE plpgsql + STABLE +AS $function$ +DECLARE + normalized text; + result date; + parts text[]; + p1 int; + p2 int; + p3 int; +BEGIN + IF val IS NULL OR trim(val) = '' THEN + RETURN NULL; + END IF; + + normalized := trim(val); + + -- Direct cast handles ISO 8601 (YYYY-MM-DD) and is strict about invalid dates + BEGIN + RETURN normalized::date; + EXCEPTION WHEN OTHERS THEN + NULL; + END; + + -- Branch by detected layout; validate parsed results to reject + -- silently-wrapped invalid dates (e.g., month 13 rolling into next year) + IF normalized ~ '^\d{4}/' THEN + -- Year-first: YYYY/MM/DD + BEGIN + parts := string_to_array(normalized, '/'); + p1 := parts[1]::int; p2 := parts[2]::int; p3 := parts[3]::int; + result := to_date(normalized, 'YYYY/MM/DD'); + EXCEPTION WHEN OTHERS THEN + RETURN NULL; + END; + IF EXTRACT(year FROM result) = p1 + AND EXTRACT(month FROM result) = p2 + AND EXTRACT(day FROM result) = p3 THEN + RETURN result; + END IF; + + ELSIF normalized ~ '^\d{1,2}/\d{1,2}/\d{4}' THEN + -- Extract date parts once (regex guarantees slash-separated integers) + BEGIN + parts := string_to_array(normalized, '/'); + p1 := parts[1]::int; p2 := parts[2]::int; p3 := parts[3]::int; + EXCEPTION WHEN OTHERS THEN + RETURN NULL; + END; + + -- Try MM/DD/YYYY (North American locale used in BC) + BEGIN result := to_date(normalized, 'MM/DD/YYYY'); EXCEPTION WHEN OTHERS THEN result := NULL; END; + IF result IS NOT NULL + AND EXTRACT(month FROM result) = p1 + AND EXTRACT(day FROM result) = p2 + AND EXTRACT(year FROM result) = p3 THEN + RETURN result; + END IF; + + -- Try DD/MM/YYYY + BEGIN result := to_date(normalized, 'DD/MM/YYYY'); EXCEPTION WHEN OTHERS THEN result := NULL; END; + IF result IS NOT NULL + AND EXTRACT(day FROM result) = p1 + AND EXTRACT(month FROM result) = p2 + AND EXTRACT(year FROM result) = p3 THEN + RETURN result; + END IF; + END IF; + + -- All attempts failed, return NULL gracefully + RETURN NULL; +END; +$function$; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/safe_to_timestamp.sql b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/safe_to_timestamp.sql new file mode 100644 index 0000000000..f7733f3c6d --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Scripts/safe_to_timestamp.sql @@ -0,0 +1,124 @@ +CREATE OR REPLACE FUNCTION "Reporting".safe_to_timestamp(val text) + RETURNS timestamp without time zone + LANGUAGE plpgsql + STABLE +AS $function$ +DECLARE + normalized text; + has_meridian boolean; + has_seconds boolean; + has_time boolean; + result timestamp; + date_part text; + parts text[]; + p1 int; + p2 int; + p3 int; + fmt text; + fmt_mdy text; + fmt_dmy text; +BEGIN + IF val IS NULL OR trim(val) = '' THEN + RETURN NULL; + END IF; + + -- Normalize: trim whitespace and handle dotted meridian indicators + normalized := trim(val); + normalized := regexp_replace(normalized, '\s*[aA]\.[mM]\.', ' AM', 'g'); + normalized := regexp_replace(normalized, '\s*[pP]\.[mM]\.', ' PM', 'g'); + + -- Try direct cast first (handles ISO 8601, YYYY-MM-DD HH24:MI:SS, etc.) + BEGIN + RETURN normalized::timestamp; + EXCEPTION WHEN OTHERS THEN + NULL; + END; + + -- Pre-detect format characteristics via regex to select the right parse + -- branch and avoid entering unnecessary BEGIN...EXCEPTION blocks + has_meridian := normalized ~* '\s+(AM|PM)\s*$'; + has_time := normalized ~ '\s+\d{1,2}:\d{2}'; + has_seconds := normalized ~ '\d{1,2}:\d{2}:\d{2}'; + + -- Year-first with slash: YYYY/MM/DD variants + IF normalized ~ '^\d{4}/' THEN + date_part := split_part(normalized, ' ', 1); + BEGIN + parts := string_to_array(date_part, '/'); + p1 := parts[1]::int; p2 := parts[2]::int; p3 := parts[3]::int; + EXCEPTION WHEN OTHERS THEN + RETURN NULL; + END; + + IF has_time AND has_seconds THEN + fmt := 'YYYY/MM/DD HH24:MI:SS'; + ELSIF has_time THEN + fmt := 'YYYY/MM/DD HH24:MI'; + ELSE + fmt := 'YYYY/MM/DD'; + END IF; + + BEGIN result := to_timestamp(normalized, fmt); EXCEPTION WHEN OTHERS THEN result := NULL; END; + IF result IS NOT NULL + AND EXTRACT(year FROM result) = p1 + AND EXTRACT(month FROM result) = p2 + AND EXTRACT(day FROM result) = p3 THEN + RETURN result; + END IF; + RETURN NULL; + END IF; + + -- Slash-separated with year last: MM/DD/YYYY or DD/MM/YYYY + -- MM/DD is tried first (North American locale used in BC) + IF normalized ~ '^\d{1,2}/\d{1,2}/\d{4}' THEN + date_part := split_part(normalized, ' ', 1); + BEGIN + parts := string_to_array(date_part, '/'); + p1 := parts[1]::int; p2 := parts[2]::int; p3 := parts[3]::int; + EXCEPTION WHEN OTHERS THEN + RETURN NULL; + END; + + -- Select format strings based on detected time characteristics + IF has_time AND has_seconds AND has_meridian THEN + fmt_mdy := 'MM/DD/YYYY HH12:MI:SS AM'; + fmt_dmy := 'DD/MM/YYYY HH12:MI:SS AM'; + ELSIF has_time AND has_seconds THEN + fmt_mdy := 'MM/DD/YYYY HH24:MI:SS'; + fmt_dmy := 'DD/MM/YYYY HH24:MI:SS'; + ELSIF has_time AND has_meridian THEN + fmt_mdy := 'MM/DD/YYYY HH12:MI AM'; + fmt_dmy := 'DD/MM/YYYY HH12:MI AM'; + ELSIF has_time THEN + fmt_mdy := 'MM/DD/YYYY HH24:MI'; + fmt_dmy := 'DD/MM/YYYY HH24:MI'; + ELSE + fmt_mdy := 'MM/DD/YYYY'; + fmt_dmy := 'DD/MM/YYYY'; + END IF; + + -- Try MM/DD/YYYY, validate parsed date parts match input + BEGIN result := to_timestamp(normalized, fmt_mdy); EXCEPTION WHEN OTHERS THEN result := NULL; END; + IF result IS NOT NULL + AND EXTRACT(month FROM result) = p1 + AND EXTRACT(day FROM result) = p2 + AND EXTRACT(year FROM result) = p3 THEN + RETURN result; + END IF; + + -- Try DD/MM/YYYY, validate parsed date parts match input + BEGIN result := to_timestamp(normalized, fmt_dmy); EXCEPTION WHEN OTHERS THEN result := NULL; END; + IF result IS NOT NULL + AND EXTRACT(day FROM result) = p1 + AND EXTRACT(month FROM result) = p2 + AND EXTRACT(year FROM result) = p3 THEN + RETURN result; + END IF; + + RETURN NULL; + END IF; + + -- All attempts failed, return NULL gracefully + RETURN NULL; +END; +$function$; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Unity.GrantManager.EntityFrameworkCore.csproj b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Unity.GrantManager.EntityFrameworkCore.csproj index af8cbd315a..02e6a2f93a 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Unity.GrantManager.EntityFrameworkCore.csproj +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.EntityFrameworkCore/Unity.GrantManager.EntityFrameworkCore.csproj @@ -16,6 +16,8 @@ + + @@ -35,7 +37,13 @@ Never - Never + Never + + + Never + + + Never diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi.Client/GrantManagerHttpApiClientModule.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi.Client/GrantManagerHttpApiClientModule.cs index ac9bbde1e2..5ecae6c8bf 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi.Client/GrantManagerHttpApiClientModule.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi.Client/GrantManagerHttpApiClientModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Unity.AI; using Volo.Abp.FeatureManagement; using Volo.Abp.Identity; using Volo.Abp.Modularity; @@ -19,7 +20,8 @@ namespace Unity.GrantManager; typeof(UnityTenantManagementHttpApiClientModule), typeof(AbpFeatureManagementHttpApiClientModule), typeof(AbpSettingManagementHttpApiClientModule), - typeof(NotificationsHttpApiClientModule) + typeof(NotificationsHttpApiClientModule), + typeof(AIApplicationContractsModule) )] public class GrantManagerHttpApiClientModule : AbpModule { @@ -31,6 +33,10 @@ public override void ConfigureServices(ServiceConfigurationContext context) typeof(GrantManagerApplicationContractsModule).Assembly, RemoteServiceName ); + context.Services.AddHttpClientProxies( + typeof(AIApplicationContractsModule).Assembly, + AIRemoteServiceConsts.RemoteServiceName + ); // Register Geocoder API client context.Services.AddHttpClient(client => diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs index cd74758f62..e0825c7dc2 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/AttachmentController.cs @@ -17,9 +17,36 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Unity.GrantManager.Models; +using System.Threading; namespace Unity.GrantManager.Controllers { + internal static class LibreOfficeInstallationCache + { + private static int _hasCachedValue; + private static bool _isInstalled; + private static readonly object SyncRoot = new(); + + public static bool IsInstalled(Func installationCheck) + { + if (Volatile.Read(ref _hasCachedValue) == 1) + { + return _isInstalled; + } + + lock (SyncRoot) + { + if (_hasCachedValue == 0) + { + _isInstalled = installationCheck(); + Volatile.Write(ref _hasCachedValue, 1); + } + } + + return _isInstalled; + } + } + [Route("api/app/attachment")] public class AttachmentController : AbpController { @@ -28,24 +55,81 @@ public class AttachmentController : AbpController private readonly ISubmissionAppService _submissionAppService; private readonly IEmailLogAttachmentUploadService _emailLogAttachmentUploadService; private readonly ICurrentTenant _currentTenant; + private readonly ILibreOfficeConversionService _libreOfficeConversionService; + private readonly IAttachmentPreviewAppService _attachmentPreviewAppService; private ILogger logger => LazyServiceProvider.LazyGetService(provider => LoggerFactory?.CreateLogger(GetType().FullName!) ?? NullLogger.Instance); private const string badRequestFileMsg = "File name must be provided."; private const string NotFoundFileMsg = "File not found."; private const string errorFileMsg = "An error occurred while downloading the file."; private const string chefsApiAccessError = "You do not have access to this resource"; + private const string fileProvidedError = "At least one file must be provided."; + private const string libreOfficeNotInstalledMsg = "LibreOffice is not installed on the server. File preview is unavailable."; + private const string ErrorCodeKey = "ErrorCode"; + private const string PdfContentType = "application/pdf"; public AttachmentController( IFileAppService fileAppService, IConfiguration configuration, ISubmissionAppService submissionAppService, IEmailLogAttachmentUploadService emailLogAttachmentUploadService, - ICurrentTenant currentTenant) + ICurrentTenant currentTenant, + ILibreOfficeConversionService libreOfficeConversionService, + IAttachmentPreviewAppService attachmentPreviewAppService) { _fileAppService = fileAppService; _configuration = configuration; _submissionAppService = submissionAppService; _emailLogAttachmentUploadService = emailLogAttachmentUploadService; _currentTenant = currentTenant; + _libreOfficeConversionService = libreOfficeConversionService; + _attachmentPreviewAppService = attachmentPreviewAppService; + } + + [HttpGet("applicant/{applicantId}/download/{fileName}")] + public async Task DownloadApplicantAttachment(string applicantId, string fileName) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + if (string.IsNullOrWhiteSpace(applicantId)) + { + return BadRequest("Applicant ID must be provided."); + } + + if (string.IsNullOrWhiteSpace(fileName)) + { + return BadRequest(badRequestFileMsg); + } + + var folder = _configuration["S3:ApplicantS3Folder"] ?? throw new AbpValidationException("Missing server configuration: S3:ApplicantS3Folder"); + + if (!folder.EndsWith('/')) + { + folder += "/"; + } + + folder += applicantId; + var key = folder + "/" + fileName; + + try + { + var fileDto = await _fileAppService.GetBlobAsync(new GetBlobRequestDto { S3ObjectKey = key, Name = fileName }); + + if (fileDto == null || fileDto.Content == null) + { + return NotFound(NotFoundFileMsg); + } + + return File(fileDto.Content, fileDto.ContentType, fileDto.Name); + } + catch (Exception ex) + { + string ExceptionMessage = ex.Message; + logger.LogError(ex, "AttachmentController->DownloadApplicantAttachment: {ExceptionMessage}", ExceptionMessage); + return StatusCode(500, errorFileMsg); + } } [HttpGet("application/{applicationId}/download/{fileName}")] @@ -170,7 +254,7 @@ public async Task DownloadChefsAttachment(Guid formSubmissionId, { string ExceptionMessage = ex.Message; logger.LogError(ex, "AttachmentController->DownloadChefsAttachment: {ExceptionMessage}", ExceptionMessage); - var errorCode = ex.Data.Contains("ErrorCode") ? Convert.ToInt32(ex.Data["ErrorCode"]) : 500; + var errorCode = ex.Data.Contains(ErrorCodeKey) ? Convert.ToInt32(ex.Data[ErrorCodeKey]) : 500; return StatusCode(errorCode, ExceptionMessage); } } @@ -225,6 +309,108 @@ public async Task DownloadAllChefsAttachment([FromBody] List PreviewApplicationAttachment(string applicationId, string fileName) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + if (string.IsNullOrWhiteSpace(applicationId)) return BadRequest("Application ID must be provided."); + if (!Guid.TryParse(applicationId, out var parsedApplicationId)) return BadRequest("Application ID must be a valid GUID."); + if (string.IsNullOrWhiteSpace(fileName)) return BadRequest(badRequestFileMsg); + if (!LibreOfficeInstallationCache.IsInstalled(() => _libreOfficeConversionService.IsInstalled())) return StatusCode(503, new { error = libreOfficeNotInstalledMsg }); + try + { + var blob = await _attachmentPreviewAppService.GetOrCreatePreviewPdfAsync(AttachmentType.APPLICATION, parsedApplicationId, fileName); + if (blob?.Content == null) return NotFound(NotFoundFileMsg); + return File(blob.Content, PdfContentType); + } + catch (Exception ex) + { + logger.LogError(ex, "AttachmentController->PreviewApplicationAttachment: {Message}", ex.Message); + return StatusCode(500, errorFileMsg); + } + } + + [HttpGet("assessment/{assessmentId}/preview-pdf/{fileName}")] + public async Task PreviewAssessmentAttachment(string assessmentId, string fileName) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + if (string.IsNullOrWhiteSpace(assessmentId)) return BadRequest("Assessment ID must be provided."); + if (!Guid.TryParse(assessmentId, out var parsedAssessmentId)) return BadRequest("Assessment ID must be a valid GUID."); + if (string.IsNullOrWhiteSpace(fileName)) return BadRequest(badRequestFileMsg); + if (!LibreOfficeInstallationCache.IsInstalled(() => _libreOfficeConversionService.IsInstalled())) return StatusCode(503, new { error = libreOfficeNotInstalledMsg }); + try + { + var blob = await _attachmentPreviewAppService.GetOrCreatePreviewPdfAsync(AttachmentType.ASSESSMENT, parsedAssessmentId, fileName); + if (blob?.Content == null) return NotFound(NotFoundFileMsg); + return File(blob.Content, PdfContentType); + } + catch (Exception ex) + { + logger.LogError(ex, "AttachmentController->PreviewAssessmentAttachment: {Message}", ex.Message); + return StatusCode(500, errorFileMsg); + } + } + + [HttpGet("applicant/{applicantId}/preview-pdf/{fileName}")] + public async Task PreviewApplicantAttachment(string applicantId, string fileName) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + if (string.IsNullOrWhiteSpace(applicantId)) return BadRequest("Applicant ID must be provided."); + if (string.IsNullOrWhiteSpace(fileName)) return BadRequest(badRequestFileMsg); + if (!_libreOfficeConversionService.IsInstalled()) return StatusCode(503, new { error = libreOfficeNotInstalledMsg }); + try + { + var blob = await _attachmentPreviewAppService.GetOrCreatePreviewPdfAsync(AttachmentType.APPLICANT, Guid.Parse(applicantId), fileName); + if (blob?.Content == null) return NotFound(NotFoundFileMsg); + return File(blob.Content, PdfContentType); + } + catch (Exception ex) + { + logger.LogError(ex, "AttachmentController->PreviewApplicantAttachment: {Message}", ex.Message); + return StatusCode(500, errorFileMsg); + } + } + + [HttpGet("chefs/{formSubmissionId}/preview-pdf/{chefsFileId}/{fileName}")] + public async Task PreviewChefsAttachment(Guid formSubmissionId, Guid chefsFileId, string fileName) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + if (string.IsNullOrWhiteSpace(fileName)) return BadRequest(badRequestFileMsg); + if (!_libreOfficeConversionService.IsInstalled()) return StatusCode(503, new { error = libreOfficeNotInstalledMsg }); + try + { + var chefsBlob = await _submissionAppService.GetChefsFileAttachment(formSubmissionId, chefsFileId, fileName); + if (chefsBlob?.Content == null) return NotFound(NotFoundFileMsg); + var blob = await _attachmentPreviewAppService.GetOrCreateChefsPreviewPdfAsync(formSubmissionId, chefsFileId, fileName, chefsBlob.Content); + if (blob?.Content == null) return NotFound(NotFoundFileMsg); + return File(blob.Content, PdfContentType); + } + catch (Exception ex) + { + logger.LogError(ex, "AttachmentController->PreviewChefsAttachment: {Message}", ex.Message); + var errorCode = ex.Data.Contains(ErrorCodeKey) ? Convert.ToInt32(ex.Data[ErrorCodeKey]) : 500; + return StatusCode(errorCode, errorFileMsg); + } + } + + [HttpPost("applicant/{applicantId}/upload")] +#pragma warning disable IDE0060 // Remove unused parameter + public async Task UploadApplicantAttachments(Guid applicantId, IList files, string userId, string userName) +#pragma warning restore IDE0060 // Remove unused parameter + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + if (files == null || files.Count == 0) + { + return BadRequest(fileProvidedError); + } + + return await UploadFiles(files); + } + [HttpPost("assessment/{assessmentId}/upload")] #pragma warning disable IDE0060 // Remove unused parameter public async Task UploadAssessmentAttachments(Guid assessmentId, IList files) @@ -237,7 +423,7 @@ public async Task UploadAssessmentAttachments(Guid assessmentId, if (files == null || files.Count == 0) { - return BadRequest("At least one file must be provided."); + return BadRequest(fileProvidedError); } return await UploadFiles(files); @@ -255,7 +441,7 @@ public async Task UploadApplicationAttachments(Guid applicationId if (files == null || files.Count == 0) { - return BadRequest("At least one file must be provided."); + return BadRequest(fileProvidedError); } return await UploadFiles(files); @@ -271,7 +457,7 @@ public async Task UploadEmailAttachments(Guid emailLogId, IList invalidFileTypes = GetInvalidFileTypes(files); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/FormController.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/FormController.cs index bf90e94248..5a90cbd0a5 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/FormController.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.HttpApi/Controllers/FormController.cs @@ -10,6 +10,7 @@ using Volo.Abp.Domain.Entities; using Microsoft.Extensions.Logging; using Unity.GrantManager.Integrations.Chefs; +using Newtonsoft.Json.Linq; namespace Unity.GrantManager.Controllers { @@ -51,14 +52,16 @@ public async Task SynchronizeChefsAvailableFields(string formId, throw new BusinessException("Application Form API Key is Required"); } + // Check if the application form name is current + var updatedApplicationFormName = await SyncApplicationFormNameAsync(formId, applicationForm); + var chefsFormVersion = await _formsApiService.GetFormDataAsync(formId, formVersionId) ?? throw new BusinessException("Chefs Form Version data could not be retrieved."); - var result = await _applicationFormVersionAppService .UpdateOrCreateApplicationFormVersion(formId, formVersionId, applicationForm.Id, chefsFormVersion); - return Ok(result); + return Ok(new { formVersion = result, updatedFormName = updatedApplicationFormName }); } catch (EntityNotFoundException ex) { @@ -77,6 +80,25 @@ public async Task SynchronizeChefsAvailableFields(string formId, } + private async Task SyncApplicationFormNameAsync(string formId, ApplicationForm applicationForm) + { + var chefsForm = await _formsApiService.GetForm( + Guid.Parse(formId), + formId, + applicationForm.ApiKey!) ?? throw new BusinessException("Unable to retrieve Chefs Form."); + + if (chefsForm is not JObject formObject) + return null; + + var formName = formObject.SelectToken("name")?.ToString(); + if (string.IsNullOrWhiteSpace(formName) || formName == applicationForm.ApplicationFormName) + return null; + + applicationForm.ApplicationFormName = formName; + await _applicationFormRepository.UpdateAsync(applicationForm); + return formName; + } + public class ApplicationSubmission { public string InnerHTML { set; get; } = string.Empty; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/AI/AIPromptToolViewOptionsProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/AI/AIPromptToolViewOptionsProvider.cs deleted file mode 100644 index 7e9f1a5620..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/AI/AIPromptToolViewOptionsProvider.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Volo.Abp.DependencyInjection; - -namespace Unity.GrantManager.Web.AI -{ - public class AIPromptToolViewOptionsProvider( - IWebHostEnvironment webHostEnvironment, - IConfiguration configuration) : IAIPromptToolViewOptionsProvider, ITransientDependency - { - public bool IsDevPromptControlsEnabled => - string.Equals(webHostEnvironment.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase); - - public string DefaultPromptVersion - { - get - { - var configuredPromptVersion = configuration["Azure:Operations:Defaults:PromptVersion"]; - if (string.IsNullOrWhiteSpace(configuredPromptVersion)) - { - configuredPromptVersion = configuration["Azure:OpenAI:PromptVersion"]; - } - - return string.IsNullOrWhiteSpace(configuredPromptVersion) - ? "v1" - : configuredPromptVersion.Trim().ToLowerInvariant(); - } - } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/AI/IAIPromptToolViewOptionsProvider.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/AI/IAIPromptToolViewOptionsProvider.cs deleted file mode 100644 index f6e2242194..0000000000 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/AI/IAIPromptToolViewOptionsProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Unity.GrantManager.Web.AI -{ - public interface IAIPromptToolViewOptionsProvider - { - bool IsDevPromptControlsEnabled { get; } - - string DefaultPromptVersion { get; } - } -} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Dockerfile b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Dockerfile index a2ce3d25c8..b83c1f36fe 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Dockerfile +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Dockerfile @@ -73,9 +73,9 @@ RUN mkdir -p /.aspnet && \ mkdir -p /app/logs && \ chmod 755 /.aspnet && \ chmod 755 /.dotnet && \ - chmod 755 /app/logs && \ + chmod 755 /app/logs && \ chmod 644 /usr/local/share/ca-certificates/cas2024inter.crt && \ - chmod 644 /usr/local/share/ca-certificates/cas2024root.crt && \ + chmod 644 /usr/local/share/ca-certificates/cas2024root.crt && \ chmod 644 /usr/local/share/ca-certificates/cas2025inter.crt && \ chmod 644 /usr/local/share/ca-certificates/cas2025root.crt && \ chmod 644 /usr/local/share/ca-certificates/cas2025top.crt && \ @@ -83,7 +83,10 @@ RUN mkdir -p /.aspnet && \ chmod 644 /usr/local/share/ca-certificates/casroot.crt && \ chmod 644 /usr/local/share/ca-certificates/sslcomroot.crt && \ chmod 644 /usr/local/share/ca-certificates/ssoroot.crt && \ - update-ca-certificates + update-ca-certificates && \ + apt-get update && \ + apt-get install -y --no-install-recommends libreoffice-nogui && \ + rm -rf /var/lib/apt/lists/* COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "Unity.GrantManager.Web.dll"] diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Menus/GrantManagerMenus.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Menus/GrantManagerMenus.cs index 809d901ccf..5151503b1b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Menus/GrantManagerMenus.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Menus/GrantManagerMenus.cs @@ -19,4 +19,5 @@ public static class GrantManagerMenus public const string EndpointManagement = Prefix + ".EndpointManagement"; public const string AIReporting = Prefix + ".AIReporting"; public const string Applicants = Prefix + ".Applicants"; + public const string UnityAdmin = Prefix + ".UnityAdmin"; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.cshtml new file mode 100644 index 0000000000..8f8b093fd2 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.cshtml @@ -0,0 +1,89 @@ +@page +@using Microsoft.Extensions.Localization +@using Unity.GrantManager.Localization +@using Unity.GrantManager.GrantApplications +@using Volo.Abp.AspNetCore.Mvc.UI.Layout + +@model Unity.GrantManager.Web.Pages.ApplicantPortalSettings.IndexModel + +@inject IStringLocalizer L +@inject IPageLayout PageLayout + +@{ + PageLayout.Content.Title = L["ApplicantPortalSettings:Title"].Value; + ViewBag.PageTitle = L["ApplicantPortalSettings:Title"].Value; +} + +@section styles { + +} +@section scripts { + +} + + +
+ +
+
+
+
+
@L["ApplicantPortalSettings:PortalStatusHeading"]
+
+ +
+ + + + + + + + + @for (var i = 0; i < Model.Statuses.Count; i++) + { + var status = Model.Statuses[i]; + + + + + } + +
@L["ApplicantPortalSettings:InternalStatus"]@L["ApplicantPortalSettings:PortalStatusLabel"]
+ + + + +
+
+
+ + +
+ +
+
+
+
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.cshtml.cs new file mode 100644 index 0000000000..41c12d5819 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.cshtml.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Authorization; +using System.Collections.Generic; +using System.Threading.Tasks; +using Unity.GrantManager.GrantApplications; + +namespace Unity.GrantManager.Web.Pages.ApplicantPortalSettings; + +[Authorize] +public class IndexModel(IApplicationStatusService applicationStatusService) : GrantManagerPageModel +{ + public IList Statuses { get; set; } = []; + + public async Task OnGetAsync() + { + Statuses = await applicationStatusService.GetListAsync(); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.css new file mode 100644 index 0000000000..113b93d7f2 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.css @@ -0,0 +1,68 @@ +.unity-app-main-container { + margin: auto; + display: block; +} + +.portal-settings-layout { + min-height: calc(100vh - 200px); +} + +#PortalSettingsSideMenu.side-menu { + position: sticky; + top: 150px; +} + +#PortalSettingsSideMenu ul { + padding-left: 0; +} + +#PortalSettingsSideMenu li { + height: 40px; + padding: 10px; + border-radius: 0 100em 100em 0; +} + +#PortalSettingsSideMenu .nav-item { + justify-content: left; +} + +.portal-settings-config { + overflow: auto; + max-width: 750px; + max-height: calc(100vh - 180px); + width: 100%; +} + +.portal-settings-actions { + background: #fff; +} + +.portal-status-table th { + font-weight: 600; + border-bottom: 2px solid #dee2e6; +} + +.portal-status-table td { + vertical-align: middle; +} + +.portal-status-table label { + margin-bottom: 0; + font-weight: 400; +} + +.portal-status-table .form-control { + max-width: 300px; +} + +#PortalStatusForm .dt-container { + max-height: none !important; +} + +.breadcrumb-container { + background-color: #fff; + margin: 0 -0.5rem; + padding: 0.75rem 1rem; + display: flex; + margin-top: 1px; +} \ No newline at end of file diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.js new file mode 100644 index 0000000000..fede36f39c --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicantPortalSettings/Index.js @@ -0,0 +1,143 @@ +(function ($) { + + const l = abp.localization.getResource('GrantManager'); + + const $form = $('#PortalStatusForm'); + const $saveButton = $('#SaveButton'); + const $resetButton = $('#ResetButton'); + + // Store original values on page load + const originalValues = new Map(); + + let portalStatusTable = new DataTable("#PortalStatusTable", { + paging: false, + ordering: false, + info: false + }); + + // Capture original values after DataTable initialization + // Use DataTable's rows().every() to ensure all rows are captured, even if dynamically loaded + portalStatusTable.rows().every(function () { + const $row = $(this.node()); + const id = $row.find('input[type="hidden"]').val(); + const externalStatus = $row.find('input[type="text"]').val().trim(); + originalValues.set(id, externalStatus); + }); + + // Check if any values have changed + function hasChanges() { + let changed = false; + portalStatusTable.$('tbody tr').each(function () { + const $row = $(this); + const id = $row.find('input[type="hidden"]').val(); + const currentValue = $row.find('input[type="text"]').val().trim(); + if (originalValues.get(id) !== currentValue) { + changed = true; + return false; + } + }); + return changed; + } + + // Update button states + function updateButtonStates() { + const changed = hasChanges(); + $saveButton.prop('disabled', !changed); + $resetButton.prop('disabled', !changed); + } + + // Debounce utility to limit how often updateButtonStates is called + function debounce(func, wait) { + let timeout; + return function () { + clearTimeout(timeout); + timeout = setTimeout(func, wait); + }; + } + + // Debounced version of updateButtonStates + const debouncedUpdateButtonStates = debounce(updateButtonStates, 150); + + // Listen for input changes, using debounced handler + $form.on('input', '#PortalStatusTable input[type="text"]', function () { + debouncedUpdateButtonStates(); + }); + + // Reset button handler + $resetButton.on('click', function (e) { + e.preventDefault(); + + portalStatusTable.$('tbody tr').each(function () { + const $row = $(this); + const id = $row.find('input[type="hidden"]').val(); + const originalValue = originalValues.get(id); + $row.find('input[type="text"]').val(originalValue); + }); + + updateButtonStates(); + abp.notify.info(l('ApplicantPortalSettings:ChangesReset')); + }); + + // Initialize button states + updateButtonStates(); + + $form.on('submit', function (e) { + e.preventDefault(); + + const statuses = []; + let hasValidationError = false; + + portalStatusTable.$('tbody tr').each(function () { + const $row = $(this); + const id = $row.find('input[type="hidden"]').val(); + const externalStatus = $row.find('input[type="text"]').val().trim(); + + if (!externalStatus) { + abp.notify.warn(l('ApplicantPortalSettings:ValidationRequired')); + hasValidationError = true; + return false; + } + + // Only include if value has changed + if (originalValues.get(id) !== externalStatus) { + statuses.push({ + id: id, + externalStatus: externalStatus + }); + } + }); + + if (hasValidationError) { + return; + } + + // Check if there are any changes + if (statuses.length === 0) { + abp.notify.info(l('ApplicantPortalSettings:NoChanges')); + return; + } + + abp.ui.setBusy($form); + + unity.grantManager.grantApplications.applicationStatus + .updateExternalStatusLabels({ statuses: statuses }) + .then(function () { + abp.notify.success(l('ApplicantPortalSettings:SaveSuccess')); + + // Update original values after successful save + statuses.forEach(function(status) { + originalValues.set(status.id, status.externalStatus); + }); + + // Update button states after save + updateButtonStates(); + }) + .catch(function (error) { + abp.notify.error(error.message || l('ApplicantPortalSettings:SaveError')); + }) + .always(function () { + abp.ui.clearBusy($form); + }); + }); + +})(jQuery); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml index 5e9f9aefa3..de3a5fd5ce 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml @@ -26,6 +26,10 @@ + + + +
@@ -51,8 +55,16 @@ @*-------- Organization Info Section END ---------*@ + @*-------- Contacts Section ---------*@ + +
+ @await Component.InvokeAsync("ApplicantContacts", new { applicantId = Model.ApplicantId }) +
+
+ @*-------- Contacts Section END ---------*@ + @*-------- Addresses Section ---------*@ - +
@await Component.InvokeAsync("ApplicantAddresses", new { applicantId = Model.ApplicantId })
@@ -91,16 +103,15 @@ - @if (aiApplicationAnalysisEnabled) { } @if (Model.IsDevPromptControlsEnabled) @@ -352,7 +362,7 @@
Comments
- @await Component.InvokeAsync("CommentsWidget", new { commentType = 1 }) + @await Component.InvokeAsync("CommentsWidget", new { commentType = Unity.GrantManager.Comments.CommentType.AssessmentComment })
@@ -380,7 +390,10 @@
Comments
- @await Component.InvokeAsync("CommentsWidget", new { ownerId = Model.ApplicationId, commentType = 0, currentUserId = Model.CurrentUserId }) + @await Component.InvokeAsync("CommentsWidget", new { + ownerId = Model.ApplicationId, + commentType = Unity.GrantManager.Comments.CommentType.ApplicationComment, + currentUserId = Model.CurrentUserId })
@*-------- Comments Tab Section END ---------*@ @@ -389,7 +402,7 @@
@await Component.InvokeAsync("ApplicationAttachments") - @await Component.InvokeAsync("ChefsAttachments") + @await Component.InvokeAsync("ChefsAttachments", new { applicationFormId = Model.ApplicationFormId })
@*-------- Attachments Tab Section END ---------*@ @@ -414,38 +427,63 @@ {
-
AI Application Analysis
- +
Application Analysis
+ @if (aiApplicationAnalysisGenerateEnabled) + { + + }
@* Default message when no analysis data is available *@
-
- -
No AI Analysis Available
-

AI analysis results will appear here when available.

-
-
-
- @* Analysis sections will be dynamically generated here *@ +
+ +
No AI Analysis Available
+

AI analysis results will appear here when available.

+
+
+ @* Analysis sections will be dynamically generated here *@ +
+
@* Hidden HTML templates for AI analysis items *@
- + +
+
+ +
- -
@@ -455,18 +493,18 @@
-
-
+
-
@@ -494,15 +532,12 @@ } - @if (aiAttachmentSummariesEnabled && aiApplicationAnalysisEnabled && aiScoringEnabled) - { - - } +
@@ -511,19 +546,12 @@
Attachment Summary
- @if (aiAttachmentSummariesEnabled) - { - - } - else - { - Unavailable: feature or permission not enabled - } +
@@ -538,19 +566,12 @@
Application Analysis
- @if (aiApplicationAnalysisEnabled) - { - - } - else - { - Unavailable: feature or permission not enabled - } +
@@ -565,19 +586,12 @@
Application Scoring
- @if (aiScoringEnabled) - { - - } - else - { - Unavailable: feature or permission not enabled - } +
diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs index 092b831c63..499f338e15 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.cshtml.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; @@ -16,7 +16,7 @@ using Unity.GrantManager.Applications; using Unity.GrantManager.Flex; using Unity.GrantManager.GrantApplications; -using Unity.GrantManager.Web.AI; +using Unity.AI.Web.PromptTools; using Unity.GrantManager.Zones; using Unity.Modules.Shared.Correlation; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css index 20cfb5b527..2721db382e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.css @@ -60,104 +60,104 @@ border-bottom: 3px solid #003366; } -.spinner-loader { - display: flex; - align-items: center; - justify-content: center; -} - -.ai-button-content { - display: inline-flex; - align-items: center; - gap: 0.5rem; -} - -.ai-dev-output { - min-height: 10rem; - max-height: 24rem; - overflow: auto; - resize: vertical; - white-space: pre; - font-family: Consolas, "Courier New", monospace; - line-height: 1.35; - padding-top: 0.75rem; - padding-right: 2.5rem; -} - -.ai-dev-output-container { - position: relative; -} - -.ai-dev-output-actions { - position: absolute; - top: 0.375rem; - right: 0.5rem; - display: inline-flex; - align-items: center; - gap: 0.25rem; - z-index: 1; - padding: 0 0.25rem; - background: #ffffff; - border-radius: 999px; -} - -.ai-dev-output-actions .btn-icon { - width: 2rem; - height: 2rem; - padding: 0; - color: #5c6b7a; -} - -.ai-dev-output-timestamp { - font-weight: 400; - color: #5c6b7a; -} - -.dev-prompt-section { - margin-bottom: 1rem; - padding-bottom: 1rem; - border-bottom: 1px solid #e7ebef; -} - -.dev-tools-header { - display: flex; - justify-content: space-between; - align-items: center; - gap: 1rem; - flex-wrap: wrap; -} - -.dev-prompt-toolbar-row { - display: inline-flex; - align-items: center; - gap: 0.75rem; -} - -.dev-prompt-toolbar-inline { - display: inline-flex; - align-items: center; - gap: 0.75rem; -} - -.dev-prompt-toolbar-row .form-select { - width: auto; - min-width: 5rem; -} - -.dev-prompt-section:last-child { - margin-bottom: 0; - padding-bottom: 0; - border-bottom: 0; -} - -.dev-prompt-section-header { - margin-bottom: 0.5rem; - display: flex; - justify-content: space-between; - align-items: center; - gap: 0.75rem; - flex-wrap: wrap; -} +.spinner-loader { + display: flex; + align-items: center; + justify-content: center; +} + +.ai-button-content { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.ai-dev-output { + min-height: 10rem; + max-height: 24rem; + overflow: auto; + resize: vertical; + white-space: pre; + font-family: Consolas, "Courier New", monospace; + line-height: 1.35; + padding-top: 0.75rem; + padding-right: 2.5rem; +} + +.ai-dev-output-container { + position: relative; +} + +.ai-dev-output-actions { + position: absolute; + top: 0.375rem; + right: 0.5rem; + display: inline-flex; + align-items: center; + gap: 0.25rem; + z-index: 1; + padding: 0 0.25rem; + background: #ffffff; + border-radius: 999px; +} + +.ai-dev-output-actions .btn-icon { + width: 2rem; + height: 2rem; + padding: 0; + color: #5c6b7a; +} + +.ai-dev-output-timestamp { + font-weight: 400; + color: #5c6b7a; +} + +.dev-prompt-section { + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 1px solid #e7ebef; +} + +.dev-tools-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 1rem; + flex-wrap: wrap; +} + +.dev-prompt-toolbar-row { + display: inline-flex; + align-items: center; + gap: 0.75rem; +} + +.dev-prompt-toolbar-inline { + display: inline-flex; + align-items: center; + gap: 0.75rem; +} + +.dev-prompt-toolbar-row .form-select { + width: auto; + min-width: 5rem; +} + +.dev-prompt-section:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: 0; +} + +.dev-prompt-section-header { + margin-bottom: 0.5rem; + display: flex; + justify-content: space-between; + align-items: center; + gap: 0.75rem; + flex-wrap: wrap; +} .left-card { border-right: 1px solid #dddddd; @@ -374,6 +374,7 @@ select.selected { overflow-x: hidden; height: calc(100vh - 276px); margin-right: -6px; + position: relative; } #detailsTabContent { @@ -484,152 +485,162 @@ form label.error { } /* AI Analysis Tab Styles */ -.ai-analysis-container { - padding: 0; -} - -.ai-analysis-status-badge { - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 999px; - padding: 4px 10px; - font-size: 12px; - font-weight: 700; - width: auto; - min-width: 0; - border: 1px solid transparent; - background-image: none; -} - -.ai-analysis-status-badge.proceed { - background-color: #d1e7dd; - color: #0f5132; -} - -.ai-analysis-status-badge.hold { - background-color: #f8d7da; - color: #842029; -} - -.ai-analysis-recommendation-rationale { - color: #495057; - font-size: 14px; - line-height: 1.6; +.ai-analysis-container { + padding: 0; +} + +.ai-analysis-status-badge { + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + padding: 4px 10px; + font-size: 12px; + font-weight: 700; + width: auto; + min-width: 0; + border: 1px solid transparent; + background-image: none; +} + +.ai-analysis-status-badge.proceed { + background-color: #d1e7dd; + color: #0f5132; +} + +.ai-analysis-status-badge.hold { + background-color: #f8d7da; + color: #842029; +} + +.ai-analysis-recommendation-rationale { + color: #495057; + font-size: 14px; + line-height: 1.6; +} + +.ai-analysis-sections { + margin-top: 16px; +} + +.ai-analysis-section { + border: 1px solid #dce3ec; + border-radius: 8px; + overflow: hidden; + margin-bottom: 16px; +} + +.ai-analysis-section-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 12px; + border-left: 4px solid; + min-height: 52px; +} + +.ai-analysis-section.error .ai-analysis-section-header { + border-left-color: #dc3545; + background-color: #f8d7da; +} + +.ai-analysis-section.warning .ai-analysis-section-header { + border-left-color: #ffc107; + background-color: #fff3cd; +} + +.ai-analysis-section.summary .ai-analysis-section-header { + border-left-color: #0dcaf0; + background-color: #cff4fc; +} + +.ai-analysis-section.next-steps .ai-analysis-section-header { + border-left-color: #198754; + background-color: #d1e7dd; +} + +.ai-analysis-section.recommendation .ai-analysis-section-header { + border-left-color: #6c757d; + background-color: #f8f9fa; +} + +.ai-analysis-section-title-row { + display: flex; + align-items: center; + gap: 8px; +} + +.ai-analysis-section-icon { + margin-right: 0; + font-size: 16px; + flex-shrink: 0; +} + +.ai-analysis-section.error .ai-analysis-section-icon { + color: #721c24; +} + +.ai-analysis-section.warning .ai-analysis-section-icon { + color: #856404; +} + +.ai-analysis-section.summary .ai-analysis-section-icon { + color: #055160; +} + +.ai-analysis-section.next-steps .ai-analysis-section-icon { + color: #0f5132; +} + +.ai-analysis-section.recommendation .ai-analysis-section-icon { + color: #5c6b7a; +} + +.ai-analysis-section-title { + font-weight: 650; + font-size: 16px; + color: #212529; +} + +.ai-analysis-section-body { + padding: 12px 14px; + background-color: #ffffff; + border-top: 1px solid #dee2e6; + color: #495057; + font-size: 14px; + line-height: 1.6; +} + +.ai-analysis-section.compact .ai-analysis-section-body { + padding-top: 10px; + padding-bottom: 10px; +} + +.ai-analysis-section.header-only .ai-analysis-section-body { + display: none; } -.ai-analysis-sections { - margin-top: 16px; +.ai-analysis-section.collapsed .ai-analysis-section-body { + display: none; } -.ai-analysis-section { - border: 1px solid #dce3ec; - border-radius: 8px; - overflow: hidden; +.ai-analysis-detail-item { margin-bottom: 16px; + padding-bottom: 16px; + border-bottom: 1px solid #e9ecef; } - -.ai-analysis-section-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 12px 12px; - border-left: 4px solid; - min-height: 52px; -} - -.ai-analysis-section.error .ai-analysis-section-header { - border-left-color: #dc3545; - background-color: #f8d7da; -} - -.ai-analysis-section.warning .ai-analysis-section-header { - border-left-color: #ffc107; - background-color: #fff3cd; -} - -.ai-analysis-section.summary .ai-analysis-section-header { - border-left-color: #0dcaf0; - background-color: #cff4fc; -} - -.ai-analysis-section.next-steps .ai-analysis-section-header { - border-left-color: #198754; - background-color: #d1e7dd; -} - -.ai-analysis-section.recommendation .ai-analysis-section-header { - border-left-color: #6c757d; - background-color: #f8f9fa; -} - -.ai-analysis-section-title-row { - display: flex; - align-items: center; - gap: 8px; -} - -.ai-analysis-section-icon { - margin-right: 0; - font-size: 16px; - flex-shrink: 0; -} - -.ai-analysis-section.error .ai-analysis-section-icon { - color: #721c24; -} - -.ai-analysis-section.warning .ai-analysis-section-icon { - color: #856404; -} - -.ai-analysis-section.summary .ai-analysis-section-icon { - color: #055160; -} - -.ai-analysis-section.next-steps .ai-analysis-section-icon { - color: #0f5132; -} - -.ai-analysis-section.recommendation .ai-analysis-section-icon { - color: #5c6b7a; -} - -.ai-analysis-section-title { - font-weight: 650; - font-size: 16px; - color: #212529; -} - -.ai-analysis-section-body { - padding: 12px 14px; - background-color: #ffffff; - border-top: 1px solid #dee2e6; - color: #495057; - font-size: 14px; - line-height: 1.6; -} - -.ai-analysis-section.compact .ai-analysis-section-body { - padding-top: 10px; - padding-bottom: 10px; + +.ai-analysis-detail-item:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; } -.ai-analysis-section.header-only .ai-analysis-section-body { - display: none; +.ai-analysis-detail-item.last-visible { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; } - -.ai-analysis-detail-item { - margin-bottom: 16px; - padding-bottom: 16px; - border-bottom: 1px solid #e9ecef; -} - -.ai-analysis-detail-item:last-child { - margin-bottom: 0; - padding-bottom: 0; - border-bottom: none; -} .ai-analysis-detail-category { font-weight: 700; @@ -656,95 +667,133 @@ form label.error { margin-bottom: 6px; } -.ai-analysis-detail-item.hidden-item { +.ai-analysis-detail-item.dismissed-item { opacity: 0.6; } - -.ai-analysis-section-toggle { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 132px; - padding: 4px 10px; - font-size: 13px; - font-weight: 600; - color: #4b5563; - background-color: #ffffff; - border: 1px solid #d1d5db; - border-radius: 6px; - text-decoration: none; -} - -.ai-analysis-section-toggle:disabled { - cursor: default; - pointer-events: none; - opacity: 1; -} - + +.ai-analysis-section-toggle { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 132px; + padding: 4px 10px; + font-size: 13px; + font-weight: 600; + color: #4b5563; + background-color: #ffffff; + border: 1px solid #d1d5db; + border-radius: 6px; + text-decoration: none; +} + +.ai-analysis-section-toggle:disabled { + cursor: default; + pointer-events: none; + opacity: 1; +} + .ai-analysis-section-toggle:hover { color: #1f2937; background-color: #f9fafb; border-color: #9ca3af; } -.ai-analysis-status-chip { +.ai-analysis-collapse-toggle { display: inline-flex; align-items: center; justify-content: center; - padding: 4px 10px; - font-size: 12px; - font-weight: 700; - color: #5c6b7a; - background-color: #eef2f6; - border: 1px solid #dce3ec; + width: 2rem; + height: 2rem; + padding: 0; + border: 0; + background: transparent; + box-shadow: none; + color: #4b5563; border-radius: 999px; + transition: color 0.2s, background-color 0.2s, border-color 0.2s, transform 0.2s; } -#ai-analysis-tab { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 6px; +.ai-analysis-collapse-toggle:hover { + color: #1f2937; + background-color: #eef2f6; +} + +.ai-analysis-collapse-toggle:focus, +.ai-analysis-collapse-toggle:focus-visible { + outline: none; + box-shadow: none; } -.ai-analysis-tab-icon-wrap { +.ai-analysis-status-chip { display: inline-flex; align-items: center; justify-content: center; -} - -.ai-analysis-tab-indicator { - width: 8px; - height: 8px; + padding: 4px 10px; + font-size: 12px; + font-weight: 700; + color: #5c6b7a; + background-color: #eef2f6; + border: 1px solid #dce3ec; border-radius: 999px; - background-color: #adb5bd; - flex-shrink: 0; -} - -.ai-analysis-tab-indicator.proceed { - background-color: #198754; -} - -.ai-analysis-tab-indicator.hold { - background-color: #dc3545; } -.ai-analysis-action-btn { - background: #ffffff; - border: 1px solid #d1d5db; - padding: 4px 10px; - cursor: pointer; - color: #4b5563; - font-size: 13px; - font-weight: 600; - transition: color 0.2s, background-color 0.2s, border-color 0.2s; - border-radius: 6px; - flex-shrink: 0; - line-height: 1.2; +.ai-analysis-status-chip.proceed { + color: #0f5132; + background-color: #d1e7dd; + border-color: #badbcc; } -.ai-analysis-action-btn:hover { - color: #1f2937; - background-color: #f9fafb; - border-color: #9ca3af; +.ai-analysis-status-chip.hold { + color: #842029; + background-color: #f8d7da; + border-color: #f5c2c7; } + +#ai-analysis-tab { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; +} + +.ai-analysis-tab-icon-wrap { + display: inline-flex; + align-items: center; + justify-content: center; +} + +.ai-analysis-tab-indicator { + width: 8px; + height: 8px; + border-radius: 999px; + background-color: #adb5bd; + flex-shrink: 0; +} + +.ai-analysis-tab-indicator.proceed { + background-color: #198754; +} + +.ai-analysis-tab-indicator.hold { + background-color: #dc3545; +} + +.ai-analysis-action-btn { + background: #ffffff; + border: 1px solid #d1d5db; + padding: 4px 10px; + cursor: pointer; + color: #4b5563; + font-size: 13px; + font-weight: 600; + transition: color 0.2s, background-color 0.2s, border-color 0.2s; + border-radius: 6px; + flex-shrink: 0; + line-height: 1.2; +} + +.ai-analysis-action-btn:hover { + color: #1f2937; + background-color: #f9fafb; + border-color: #9ca3af; +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js index efac448661..41ecd22540 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Details.js @@ -465,17 +465,22 @@ $(function () { // Create shadow DOM with open mode (allows external JS access) const shadowRoot = formioContainer.attachShadow({mode: 'open'}); - // Load form.io CSS inside shadow DOM - const formioStyle = document.createElement('link'); - formioStyle.rel = 'stylesheet'; - formioStyle.href = '/libs/formiojs/formio.form.css'; - shadowRoot.appendChild(formioStyle); - - // Load bootstrap CSS - const bootstrapStyle = document.createElement('link'); - bootstrapStyle.rel = 'stylesheet'; - bootstrapStyle.href = '/libs/bootstrap-4/dist/css/bootstrap.min.css'; - shadowRoot.appendChild(bootstrapStyle); + // Load CHEFS CSS (replaces Bootstrap and formio CSS — CHEFS bundles both inside their index CSS) + const chefsIndexStyle = document.createElement('link'); + chefsIndexStyle.rel = 'stylesheet'; + chefsIndexStyle.href = '/Pages/GrantApplications/chefs-index.css'; + shadowRoot.appendChild(chefsIndexStyle); + + const chefsFormViewerStyle = document.createElement('link'); + chefsFormViewerStyle.rel = 'stylesheet'; + chefsFormViewerStyle.href = '/Pages/GrantApplications/chefs-form-viewer.css'; + shadowRoot.appendChild(chefsFormViewerStyle); + + // Override Bootstrap bg-* classes with CHEFS BC Government theme colors + const chefsVuetifyBsBridge = document.createElement('link'); + chefsVuetifyBsBridge.rel = 'stylesheet'; + chefsVuetifyBsBridge.href = '/Pages/GrantApplications/chefs-vuetify-bs-bridge.css'; + shadowRoot.appendChild(chefsVuetifyBsBridge); // Load Details-shadow-dom.css into shadow DOM (CRITICAL for accordion, styling, etc.) const detailsStyle = document.createElement('link'); @@ -1025,20 +1030,6 @@ $(function () { ); }); - PubSub.subscribe('update_ai_analysis_status', (msg, data) => { - const $indicator = $('#ai_analysis_status'); - const status = data?.status; - - $indicator.removeClass('proceed hold'); - - if (status === 'proceed' || status === 'hold') { - $indicator.addClass(status).show(); - return; - } - - $indicator.hide(); - }); - PubSub.subscribe('update_application_emails_count', (msg, data) => { if (data.itemCount || data.itemCount === 0) { tabCounters.emails = data.itemCount; @@ -1502,7 +1493,7 @@ function updateCommentsCounters() { $('#' + $(this).data('counttag')).html($(this).data('count')); }) .get(); - }, 100); + }, 500); } function updateLinksCounters() { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js index 344c647be8..e039b477e1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/Index.js @@ -90,10 +90,18 @@ $(function () { }) dt.colReorder.order(orderedIndexes); - $('#search, .custom-filter-input').val(''); - dt.columns().search(''); - dt.search(''); - dt.order(initialSortOrder); + if (typeof dt.filterRow === 'function') { + const filterRowApi = dt.filterRow(); + if (filterRowApi && typeof filterRowApi?.clearFilters === 'function') { + filterRowApi.clearFilters(); + } + } + else { + $('#search, .custom-filter-input').val(''); + dt.columns().search(''); + dt.search(''); + dt.order(initialSortOrder); + } // Reset date range filters const range = getDateRange(defaultQuickDateRange); @@ -185,12 +193,12 @@ $(function () { let isCustomRange = savedQuickRange === 'custom'; toggleCustomDateInputs(isCustomRange); - let range = !isCustomRange - ? getDateRange(savedQuickRange) - : { + let range = isCustomRange + ? { fromDate: savedFromDate || '', toDate: savedToDate || '' - }; + } + : getDateRange(savedQuickRange); if (!isCustomRange && !range) { savedQuickRange = defaultQuickDateRange; @@ -471,12 +479,12 @@ $(function () { let isCustomRange = filters.quickDateRange === 'custom'; toggleCustomDateInputs(isCustomRange); - let range = !isCustomRange - ? getDateRange(quickRange) - : { + let range = isCustomRange + ? { fromDate: filters.submittedFromDate || '', toDate: filters.submittedToDate || '' - }; + } + : getDateRange(quickRange); if (!isCustomRange && !range) { quickRange = defaultQuickDateRange; @@ -579,14 +587,15 @@ $(function () { className: 'data-table-header', index: columnIndex, render: function(data, type, row) { - let applicantName = (typeof data !== 'string' || data.trim() === '') ? '(Unknown Applicant)' : data; + let applicantName = (typeof data !== 'string' || data.trim() === '') ? 'Applicant Name' : data; if (type === 'sort' || type === 'filter') { return applicantName; } + const safeApplicantName = $.fn.dataTable.render.text().display(applicantName); + if (type === 'display' && abp.auth.isGranted('GrantApplicationManagement.Applicants.ViewList')) { - const safeApplicantName = $.fn.dataTable.render.text().display(applicantName); const applicantId = row?.applicant?.id; const isGuid = applicantId && guidPattern.test(applicantId); @@ -696,9 +705,9 @@ $(function () { render: function (data, type, row) { let displayText = ' '; - if (data != null && data.length == 1) { + if (data?.length === 1) { displayText = type === 'fullName' ? getNames(data) : (data[0].fullName + getDutyText(data[0])); - } else if (data.length > 1) { + } else if (data?.length > 1) { displayText = getNames(data); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ai-analysis.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ai-analysis.js index dfd5d2abb1..254595cbdd 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ai-analysis.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/ai-analysis.js @@ -3,13 +3,36 @@ * Renders a stable sectioned view for AI-generated analysis results. */ -const hiddenSectionVisibility = { +const dismissedSectionVisibility = { error: false, warning: false, summary: false, - nextStep: false + recommendation: false }; +function getAnalysisLabels() { + const labels = document.getElementById('aiAnalysisLabels')?.dataset ?? {}; + + return { + errors: labels.errors || 'Errors', + warnings: labels.warnings || 'Warnings', + summaries: labels.summaries || 'Summaries', + recommendation: labels.recommendation || labels.recommendations || 'Recommendation', + proceed: labels.proceed || 'Proceed', + hold: labels.hold || 'Hold', + noErrors: labels.noErrors || 'No errors', + noWarnings: labels.noWarnings || 'No warnings', + showDismissed: labels.showDismissed || 'Show dismissed items', + hideDismissed: labels.hideDismissed || 'Hide dismissed items', + dismiss: labels.dismiss || 'Dismiss', + restore: labels.restore || 'Restore', + dismissTitle: labels.dismissTitle || 'Dismiss this item', + restoreTitle: labels.restoreTitle || 'Restore this item', + collapseTitle: labels.collapseTitle || 'Collapse section', + expandTitle: labels.expandTitle || 'Expand section' + }; +} + function bindTemplateAction($element, actionData) { $element.attr('data-id', actionData.id).attr('data-type', actionData.type); } @@ -20,16 +43,11 @@ function bindTemplateValue($item, key, value) { return; } - if (key === 'hide-btn' || key === 'show-btn') { + if (key === 'dismiss-btn' || key === 'restore-btn') { bindTemplateAction($element, value); return; } - if (key === 'icon') { - $element.addClass(value); - return; - } - $element.text(value); } @@ -59,15 +77,15 @@ function getFindingDetailText(item) { } } -function updateAnalysisTabStatus(recommendation) { - let status = ''; - if (recommendation) { - status = recommendation.decision === 'PROCEED' ? 'proceed' : 'hold'; +function normalizeDecision(decision) { + if (typeof decision !== 'string') { + return ''; } - PubSub.publish('update_ai_analysis_status', { - status: status - }); + const normalized = decision.trim().toUpperCase(); + return normalized === 'PROCEED' || normalized === 'HOLD' + ? normalized + : ''; } function normalizeFindings(items, fallbackType) { @@ -75,7 +93,7 @@ function normalizeFindings(items, fallbackType) { error: 'Error', warning: 'Warning', summary: 'Summary', - nextStep: 'Next step' + recommendation: 'Recommendation' }; return (items || []) @@ -83,246 +101,249 @@ function normalizeFindings(items, fallbackType) { .map((item, index) => ({ ...item, id: item.id || `${fallbackType}-${index}`, - hidden: item.hidden === true, + dismissed: item.dismissed === true, title: item.title || item.category || fallbackTitles[fallbackType] || 'Item', detail: item.detail || item.message || '' })); } -function normalizeRecommendation(recommendation) { - if (!recommendation || typeof recommendation !== 'object') { - return null; - } - - const decision = typeof recommendation.decision === 'string' - ? recommendation.decision.trim().toUpperCase() - : ''; - const rationale = typeof recommendation.rationale === 'string' - ? recommendation.rationale.trim() - : ''; - - if (decision !== 'PROCEED' && decision !== 'HOLD') { - return null; - } - - return { - decision: decision, - rationale: rationale - }; -} - function createFindingItem(item, type, hidden) { - const templateName = hidden ? 'hidden-item' : 'active-item'; - const actionKey = hidden ? 'show-btn' : 'hide-btn'; - return createItemFromTemplate(templateName, { + const labels = getAnalysisLabels(); + const templateName = hidden ? 'dismissed-item' : 'active-item'; + const actionKey = hidden ? 'restore-btn' : 'dismiss-btn'; + const $item = createItemFromTemplate(templateName, { category: item.title, message: getFindingDetailText(item), [actionKey]: { id: item.id, type: type } }); + + if (hidden) { + $item.find('[data-element="restore-text"]').text(labels.restore); + $item.find('[data-element="restore-btn"]').attr('title', labels.restoreTitle); + } else { + $item.find('[data-element="dismiss-text"]').text(labels.dismiss); + $item.find('[data-element="dismiss-btn"]').attr('title', labels.dismissTitle); + } + + return $item; } -function renderSection(section) { - const $section = createItemFromTemplate('section', { - icon: section.icon, - title: section.title +function updateVisibleItemLayout($items) { + const $allItems = $items.children('.ai-analysis-detail-item'); + const $visibleItems = $allItems.filter(function() { + return this.style.display !== 'none'; }); - $section.addClass(section.sectionClass); - if (section.activeItems.length === 0) { - $section.addClass('compact'); + $allItems.removeClass('last-visible'); + $visibleItems.last().addClass('last-visible'); +} + +function formatSectionTitle(title, count) { + return `${title} (${count})`; +} + +function configureSectionStatus($status, text, statusClass) { + if (!text) { + return; } - const $items = $section.find('[data-element="items"]'); - const $status = $section.find('[data-element="status-chip"]'); - const $toggle = $section.find('[data-element="hidden-toggle"]'); - const hiddenCount = section.hiddenItems.length; - const isHiddenVisible = hiddenSectionVisibility[section.itemType] === true; + $status + .removeClass('proceed hold') + .addClass('ai-analysis-status-chip'); - if (section.headerOnlyText) { - $section.addClass('header-only'); - $status - .addClass('ai-analysis-status-chip') - .text(section.headerOnlyText) - .show(); - $toggle.hide(); - return $section; + if (statusClass) { + $status.addClass(statusClass); } - if (section.activeItems.length > 0 || hiddenCount > 0) { - section.allItems.forEach(item => { - const isHidden = item.hidden === true; - const $item = createFindingItem(item, section.itemType, isHidden); - if (isHidden && !isHiddenVisible) { - $item.hide(); - } + $status + .text(text) + .show(); +} - $items.append($item); +function configureCollapseToggle($section, $collapseToggle) { + const labels = getAnalysisLabels(); + $collapseToggle + .off('click') + .on('click', function() { + const isCollapsed = $section.toggleClass('collapsed').hasClass('collapsed'); + const $icon = $(this).find('i'); + + $(this) + .attr('aria-expanded', (!isCollapsed).toString()) + .attr('title', isCollapsed ? labels.expandTitle : labels.collapseTitle); + + $icon + .toggleClass('fa-chevron-down', !isCollapsed) + .toggleClass('fa-chevron-up', isCollapsed); }); +} + +function createAnalysisSection(config) { + const groups = splitFindingsByVisibility(config.items); + const hasItems = config.items.length > 0; + + return { + ...config, + activeItems: groups.activeItems, + allItems: config.items, + hiddenItems: groups.hiddenItems, + hasItems + }; +} + +function appendSectionItems($items, section, isDismissedVisible) { + if (section.activeItems.length === 0 && section.hiddenItems.length === 0) { + return; } - if (hiddenCount > 0) { - $toggle - .css('visibility', 'visible') - .text(isHiddenVisible - ? 'Hide hidden items' - : 'Show hidden items') - .prop('disabled', false) - .show() - .off('click') - .on('click', function() { - const shouldShow = hiddenSectionVisibility[section.itemType] !== true; - hiddenSectionVisibility[section.itemType] = shouldShow; - $items.find('.hidden-item').toggle(shouldShow); - $toggle.text( - shouldShow - ? 'Hide hidden items' - : 'Show hidden items' - ); - }); - } else { - hiddenSectionVisibility[section.itemType] = false; + section.allItems.forEach(item => { + const isHidden = item.dismissed === true; + const $item = createFindingItem(item, section.itemType, isHidden); + + if (isHidden && !isDismissedVisible) { + $item.hide(); + } + + $items.append($item); + }); + + updateVisibleItemLayout($items); +} + +function configureDismissedItemsToggle($items, $toggle, section, isDismissedVisible) { + const labels = getAnalysisLabels(); + const hiddenCount = section.hiddenItems.length; + + if (hiddenCount === 0) { + dismissedSectionVisibility[section.itemType] = false; $toggle - .text('Show hidden items') + .text(labels.showDismissed) .css('visibility', 'hidden') .prop('disabled', true) .show(); + return; } - return $section; + $toggle + .css('visibility', 'visible') + .text(isDismissedVisible ? labels.hideDismissed : labels.showDismissed) + .prop('disabled', false) + .show() + .off('click') + .on('click', function() { + const shouldShow = dismissedSectionVisibility[section.itemType] !== true; + dismissedSectionVisibility[section.itemType] = shouldShow; + $items.find('.dismissed-item').toggle(shouldShow); + updateVisibleItemLayout($items); + $toggle.text(shouldShow ? labels.hideDismissed : labels.showDismissed); + }); } -function renderRecommendationSection(recommendation) { - if (!recommendation) { - return null; - } - - const shouldProceed = recommendation.decision === 'PROCEED'; +function renderSection(section) { const $section = createItemFromTemplate('section', { - icon: 'fl-info-circle', - title: 'Recommendation' + title: section.title }); - $section.addClass('recommendation compact'); - $section.find('[data-element="status-chip"]') - .addClass('ai-analysis-status-badge') - .addClass(shouldProceed ? 'proceed' : 'hold') - .text(shouldProceed ? 'Proceed' : 'Hold') - .show(); - $section.find('[data-element="hidden-toggle"]').remove(); - $section.find('[data-element="items"]').append( - $('
') - .text(recommendation.rationale || 'No rationale provided.') - ); + $section + .addClass(section.sectionClass) + .toggleClass('compact', section.activeItems.length === 0) + .toggleClass('header-only', !section.hasItems); + + const $items = $section.find('[data-element="items"]'); + const $status = $section.find('[data-element="status-chip"]'); + const $toggle = $section.find('[data-element="hidden-toggle"]'); + const $collapseToggle = $section.find('[data-element="collapse-toggle"]'); + const isDismissedVisible = dismissedSectionVisibility[section.itemType] === true; + + configureSectionStatus($status, section.statusText, section.statusClass); + configureCollapseToggle($section, $collapseToggle); + $collapseToggle.toggle(section.hasItems); + + appendSectionItems($items, section, isDismissedVisible); + configureDismissedItemsToggle($items, $toggle, section, isDismissedVisible); return $section; } function splitFindingsByVisibility(items) { return { - activeItems: items.filter(item => item.hidden !== true), - hiddenItems: items.filter(item => item.hidden === true) + activeItems: items.filter(item => item.dismissed !== true), + hiddenItems: items.filter(item => item.dismissed === true) }; } function buildAnalysisSections(analysisData) { - const recommendation = normalizeRecommendation(analysisData.recommendation); + const labels = getAnalysisLabels(); + const decision = normalizeDecision(analysisData.decision); const errors = normalizeFindings(analysisData.errors, 'error'); const warnings = normalizeFindings(analysisData.warnings, 'warning'); - const summaries = normalizeFindings(analysisData.summaries || analysisData.recommendations, 'summary'); - const nextSteps = normalizeFindings(analysisData.nextSteps, 'nextStep'); - const errorGroups = splitFindingsByVisibility(errors); - const warningGroups = splitFindingsByVisibility(warnings); - const summaryGroups = splitFindingsByVisibility(summaries); - const nextStepGroups = splitFindingsByVisibility(nextSteps); + const summaries = normalizeFindings(analysisData.summaries, 'summary'); + const recommendations = normalizeFindings(analysisData.recommendations, 'recommendation'); + let recommendationStatusText = ''; + if (decision === 'PROCEED') { + recommendationStatusText = labels.proceed; + } else if (decision === 'HOLD') { + recommendationStatusText = labels.hold; + } return { - recommendation, sections: [ - { - title: 'Errors', - icon: 'fl-times-circle', + createAnalysisSection({ + title: formatSectionTitle(labels.errors, errors.length), sectionClass: 'error', itemType: 'error', - headerOnlyText: errorGroups.activeItems.length === 0 && errorGroups.hiddenItems.length === 0 ? 'No errors' : null, - activeItems: errorGroups.activeItems, - allItems: errors, - hiddenItems: errorGroups.hiddenItems - }, - { - title: 'Warnings', - icon: 'fl-exclamation-triangle', + items: errors + }), + createAnalysisSection({ + title: formatSectionTitle(labels.warnings, warnings.length), sectionClass: 'warning', itemType: 'warning', - headerOnlyText: warningGroups.activeItems.length === 0 && warningGroups.hiddenItems.length === 0 ? 'No warnings' : null, - activeItems: warningGroups.activeItems, - allItems: warnings, - hiddenItems: warningGroups.hiddenItems - }, - { - title: 'Summary', - icon: 'fl-info-circle', + items: warnings + }), + createAnalysisSection({ + title: formatSectionTitle(labels.summaries, summaries.length), sectionClass: 'summary', itemType: 'summary', - headerOnlyText: summaryGroups.activeItems.length === 0 && summaryGroups.hiddenItems.length === 0 ? 'No summary' : null, - activeItems: summaryGroups.activeItems, - allItems: summaries, - hiddenItems: summaryGroups.hiddenItems - }, - { - title: 'Next Steps', - icon: 'fl-check-square', - sectionClass: 'next-steps', - itemType: 'nextStep', - headerOnlyText: nextStepGroups.activeItems.length === 0 && nextStepGroups.hiddenItems.length === 0 ? 'No next steps' : null, - activeItems: nextStepGroups.activeItems, - allItems: nextSteps, - hiddenItems: nextStepGroups.hiddenItems - } + items: summaries + }), + createAnalysisSection({ + title: labels.recommendation, + sectionClass: 'recommendation', + itemType: 'recommendation', + statusText: recommendationStatusText, + statusClass: decision ? decision.toLowerCase() : '', + items: recommendations + }) ] }; } -function hasAnyAnalysisContent(recommendation, sections) { - if (recommendation) { - return true; - } - - return sections.some(section => section.allItems.length > 0); -} - function bindAnalysisItemActions($sections) { $sections.off('click'); - $sections.on('click', '[data-element="hide-btn"]', function(e) { + $sections.on('click', '[data-element="dismiss-btn"]', function(e) { e.preventDefault(); const itemId = $(this).data('id'); - hideAnalysisItem(itemId); + dismissAnalysisItem(itemId); }); - $sections.on('click', '[data-element="show-btn"]', function(e) { + $sections.on('click', '[data-element="restore-btn"]', function(e) { e.preventDefault(); const itemId = $(this).data('id'); - showAnalysisItem(itemId); + restoreAnalysisItem(itemId); }); } function renderRealAIAnalysis(analysisData) { - const { recommendation, sections } = buildAnalysisSections(analysisData); + const { sections } = buildAnalysisSections(analysisData); const $sections = $('#aiAnalysisSections'); $sections.empty(); - const $recommendationSection = renderRecommendationSection(recommendation); - const hasRecommendation = $recommendationSection !== null; - if ($recommendationSection) { - $sections.append($recommendationSection); - } sections.forEach(section => { $sections.append(renderSection(section)); }); - updateAnalysisTabStatus(recommendation); - const $noDataMessage = $('#aiAnalysisNoData'); - if (!hasRecommendation && !hasAnyAnalysisContent(recommendation, sections)) { + if ($sections.children().length === 0) { $noDataMessage.show(); $sections.hide(); } else { @@ -333,36 +354,35 @@ function renderRealAIAnalysis(analysisData) { bindAnalysisItemActions($sections); } -globalThis.hideAnalysisItem = function(itemId) { +globalThis.dismissAnalysisItem = function(itemId) { const applicationId = $('#DetailsViewApplicationId').val(); unity.grantManager.grantApplications.grantApplication - .hideAIAnalysisItem(applicationId, itemId) + .dismissAIAnalysisItem(applicationId, itemId) .then(function() { loadAIAnalysis(); }) .catch(function() { - abp.message.error('Failed to hide the item. Please try again.'); + abp.message.error('Failed to dismiss the item. Please try again.'); }); } -globalThis.showAnalysisItem = function(itemId) { +globalThis.restoreAnalysisItem = function(itemId) { const applicationId = $('#DetailsViewApplicationId').val(); unity.grantManager.grantApplications.grantApplication - .showAIAnalysisItem(applicationId, itemId) + .restoreAIAnalysisItem(applicationId, itemId) .then(function() { loadAIAnalysis(); }) .catch(function() { - abp.message.error('Failed to show the item. Please try again.'); + abp.message.error('Failed to restore the item. Please try again.'); }); } function resetAnalysisView() { $('#aiAnalysisSections').empty().hide(); $('#aiAnalysisNoData').show(); - updateAnalysisTabStatus(null); } function tryParseRawAnalysis(analysisJson) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-form-viewer.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-form-viewer.css new file mode 100644 index 0000000000..c21dae009d --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-form-viewer.css @@ -0,0 +1 @@ +.more-info-link[data-v-f199d3d1]{color:gray;text-decoration:none;align-items:center;margin-top:4px}.more-info-link[data-v-f199d3d1]:hover{text-decoration:underline}.flex-container[data-v-f199d3d1]{display:flex;justify-content:flex-start}.v-btn--icon[data-v-f199d3d1]{border-radius:0}.displayNone[data-v-5901bc38],.formio-error-wrapper[data-v-5901bc38]{display:none!important;height:1px;width:1px}.loading[data-v-5901bc38]{background-color:#5072a6;border-color:#036}.loading strong[data-v-5901bc38]{color:#fff;font-size:13px}.file-upload[data-v-5901bc38]{position:relative;width:100%;display:block;margin-top:3%}.file-upload h3[data-v-5901bc38]{width:100%;color:#38598a}.file-upload .link[data-v-5901bc38]{cursor:pointer;color:#036}.file-upload .worker-zone[data-v-5901bc38]{width:380px;min-height:150px;text-align:center;font-family:Quicksand,sans-serif;font-size:16px;border:.5px solid #003366;border-radius:10px;box-shadow:-4px 18px 126px -71px #0000009e;-webkit-box-shadow:-4px 18px 126px -71px rgba(0,0,0,.62);-moz-box-shadow:-4px 18px 126px -71px rgba(0,0,0,.62);display:inline-block}.file-upload .worker-zone .wz-top[data-v-5901bc38]{position:relative;width:370px;min-height:40px;margin-left:auto;margin-right:auto;display:inline-block;padding:1% 0 0}.file-upload .worker-zone .wz-top .fileinfo[data-v-5901bc38]{margin-top:.5%;padding-top:.5px}.file-upload .worker-zone .wz-top .fileinfo label[data-v-5901bc38]{font-size:12px;color:#38598a;line-height:100%}.file-upload .worker-zone .wz-top .fileinfo .label-right[data-v-5901bc38]{text-align:right;float:right}.file-upload .worker-zone .wz-top .fileinfo .label-right p[data-v-5901bc38]{color:#38598a}.file-upload .worker-zone .wz-top .fileinfo .label-left[data-v-5901bc38]{text-align:left;float:left}.file-upload .worker-zone .message-block[data-v-5901bc38]{width:100%;height:auto;display:inline;margin-bottom:-5%}.file-upload .worker-zone .message-block hr[data-v-5901bc38]{margin:none;margin-top:-4%;margin-bottom:3%}.file-upload .worker-zone .message-block .success-text[data-v-5901bc38]{color:#38598a}.file-upload .worker-zone .message-block .fail-text[data-v-5901bc38]{color:#e9324e}.file-upload .worker-zone .message-block span[data-v-5901bc38]{font-weight:700;color:#036;float:left;width:12%;padding:none;font-size:15px}.file-upload .worker-zone .message-block p[data-v-5901bc38]{float:right;width:84%;margin-top:-.5%;text-align:left;padding:0;font-size:15px}.file-upload .worker-zone .message-block p i[data-v-5901bc38]{position:relative;margin:-.5% 0 0;padding:0;line-height:100%;font-size:20px}.file-upload .drop-zone[data-v-5901bc38]{position:relative;max-width:380px;min-height:200px;padding:3%;text-align:center;font-family:Quicksand,sans-serif;font-size:17px;cursor:pointer;color:#ccc;border:1.5px dashed #053667;border-radius:10px;background-color:#eef1ff}.file-upload .drop-zone i[data-v-5901bc38]{font-size:50px}.file-upload .drop-zone h1[data-v-5901bc38]{position:relative;width:100%;text-align:center;font-size:25px;font-weight:small;color:#036;display:block}.file-upload .drop-zone p[data-v-5901bc38]{position:relative;width:100%;text-align:center;font-size:15px;display:block;font-weight:700}.file-upload .drop-zone[data-v-5901bc38]:hover{background-color:#d5d9ea}.file-upload .drop-zone--over[data-v-5901bc38]{border-style:solid}.file-upload .drop-zone__input[data-v-5901bc38]{display:none}.form-wrapper[data-v-bbd05c12] .formio-form.formio-read-only .form-control,.form-wrapper[data-v-bbd05c12] .formio-form.formio-read-only .formio-component-simpletextarea .card-body.bg-light,.form-wrapper[data-v-bbd05c12] .formio-form.formio-read-only .choices.is-disabled .choices__input{background-color:#e9ecef!important}.form-wrapper[data-v-bbd05c12] .formio-form.formio-read-only .formio-component-simpletextarea .card-body.bg-light{border:1px solid #606060} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-index.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-index.css new file mode 100644 index 0000000000..fbfd368247 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-index.css @@ -0,0 +1,12 @@ +@charset "UTF-8";@import"https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900";@import"https://fonts.googleapis.com/css?family=Material+Icons";#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .spinner,.nprogress-custom-parent #nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@font-face{src:url(/app/assets/BCSans-Regular-D1GWWdtt.woff) format("woff");font-weight:400;font-style:normal;font-family:BCSans}@font-face{src:url(/app/assets/BCSans-BoldItalic-B1wzMjUl.woff) format("woff");font-weight:700;font-style:italic;font-family:BCSans}@font-face{src:url(/app/assets/BCSans-Italic-DrCEB72l.woff) format("woff");font-weight:400;font-style:italic;font-family:BCSans}@font-face{src:url(/app/assets/BCSans-Bold-DLThXedW.woff) format("woff");font-weight:700;font-style:normal;font-family:BCSans}@font-face{font-family:Material Design Icons;src:url(/app/assets/materialdesignicons-webfont-Cd51xsCA.eot?v=7.2.96);src:url(/app/assets/materialdesignicons-webfont-Cd51xsCA.eot?#iefix&v=7.2.96) format("embedded-opentype"),url(/app/assets/materialdesignicons-webfont-DsMmahHu.woff2?v=7.2.96) format("woff2"),url(/app/assets/materialdesignicons-webfont-BqTIB9TP.woff?v=7.2.96) format("woff"),url(/app/assets/materialdesignicons-webfont-CfT4HAkQ.ttf?v=7.2.96) format("truetype");font-weight:400;font-style:normal}.mdi:before,.mdi-set{display:inline-block;font: 24px/1 Material Design Icons;font-size:inherit;text-rendering:auto;line-height:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mdi-ab-testing:before{content:"󰇉"}.mdi-abacus:before{content:"󱛠"}.mdi-abjad-arabic:before{content:"󱌨"}.mdi-abjad-hebrew:before{content:"󱌩"}.mdi-abugida-devanagari:before{content:"󱌪"}.mdi-abugida-thai:before{content:"󱌫"}.mdi-access-point:before{content:"󰀃"}.mdi-access-point-check:before{content:"󱔸"}.mdi-access-point-minus:before{content:"󱔹"}.mdi-access-point-network:before{content:"󰀂"}.mdi-access-point-network-off:before{content:"󰯡"}.mdi-access-point-off:before{content:"󱔑"}.mdi-access-point-plus:before{content:"󱔺"}.mdi-access-point-remove:before{content:"󱔻"}.mdi-account:before{content:"󰀄"}.mdi-account-alert:before{content:"󰀅"}.mdi-account-alert-outline:before{content:"󰭐"}.mdi-account-arrow-down:before{content:"󱡨"}.mdi-account-arrow-down-outline:before{content:"󱡩"}.mdi-account-arrow-left:before{content:"󰭑"}.mdi-account-arrow-left-outline:before{content:"󰭒"}.mdi-account-arrow-right:before{content:"󰭓"}.mdi-account-arrow-right-outline:before{content:"󰭔"}.mdi-account-arrow-up:before{content:"󱡧"}.mdi-account-arrow-up-outline:before{content:"󱡪"}.mdi-account-badge:before{content:"󱬊"}.mdi-account-badge-outline:before{content:"󱬋"}.mdi-account-box:before{content:"󰀆"}.mdi-account-box-multiple:before{content:"󰤴"}.mdi-account-box-multiple-outline:before{content:"󱀊"}.mdi-account-box-outline:before{content:"󰀇"}.mdi-account-cancel:before{content:"󱋟"}.mdi-account-cancel-outline:before{content:"󱋠"}.mdi-account-card:before{content:"󱮤"}.mdi-account-card-outline:before{content:"󱮥"}.mdi-account-cash:before{content:"󱂗"}.mdi-account-cash-outline:before{content:"󱂘"}.mdi-account-check:before{content:"󰀈"}.mdi-account-check-outline:before{content:"󰯢"}.mdi-account-child:before{content:"󰪉"}.mdi-account-child-circle:before{content:"󰪊"}.mdi-account-child-outline:before{content:"󱃈"}.mdi-account-circle:before{content:"󰀉"}.mdi-account-circle-outline:before{content:"󰭕"}.mdi-account-clock:before{content:"󰭖"}.mdi-account-clock-outline:before{content:"󰭗"}.mdi-account-cog:before{content:"󱍰"}.mdi-account-cog-outline:before{content:"󱍱"}.mdi-account-convert:before{content:"󰀊"}.mdi-account-convert-outline:before{content:"󱌁"}.mdi-account-cowboy-hat:before{content:"󰺛"}.mdi-account-cowboy-hat-outline:before{content:"󱟳"}.mdi-account-credit-card:before{content:"󱮦"}.mdi-account-credit-card-outline:before{content:"󱮧"}.mdi-account-details:before{content:"󰘱"}.mdi-account-details-outline:before{content:"󱍲"}.mdi-account-edit:before{content:"󰚼"}.mdi-account-edit-outline:before{content:"󰿻"}.mdi-account-eye:before{content:"󰐠"}.mdi-account-eye-outline:before{content:"󱉻"}.mdi-account-filter:before{content:"󰤶"}.mdi-account-filter-outline:before{content:"󰾝"}.mdi-account-group:before{content:"󰡉"}.mdi-account-group-outline:before{content:"󰭘"}.mdi-account-hard-hat:before{content:"󰖵"}.mdi-account-hard-hat-outline:before{content:"󱨟"}.mdi-account-heart:before{content:"󰢙"}.mdi-account-heart-outline:before{content:"󰯣"}.mdi-account-injury:before{content:"󱠕"}.mdi-account-injury-outline:before{content:"󱠖"}.mdi-account-key:before{content:"󰀋"}.mdi-account-key-outline:before{content:"󰯤"}.mdi-account-lock:before{content:"󱅞"}.mdi-account-lock-open:before{content:"󱥠"}.mdi-account-lock-open-outline:before{content:"󱥡"}.mdi-account-lock-outline:before{content:"󱅟"}.mdi-account-minus:before{content:"󰀍"}.mdi-account-minus-outline:before{content:"󰫬"}.mdi-account-multiple:before{content:"󰀎"}.mdi-account-multiple-check:before{content:"󰣅"}.mdi-account-multiple-check-outline:before{content:"󱇾"}.mdi-account-multiple-minus:before{content:"󰗓"}.mdi-account-multiple-minus-outline:before{content:"󰯥"}.mdi-account-multiple-outline:before{content:"󰀏"}.mdi-account-multiple-plus:before{content:"󰀐"}.mdi-account-multiple-plus-outline:before{content:"󰠀"}.mdi-account-multiple-remove:before{content:"󱈊"}.mdi-account-multiple-remove-outline:before{content:"󱈋"}.mdi-account-music:before{content:"󰠃"}.mdi-account-music-outline:before{content:"󰳩"}.mdi-account-network:before{content:"󰀑"}.mdi-account-network-off:before{content:"󱫱"}.mdi-account-network-off-outline:before{content:"󱫲"}.mdi-account-network-outline:before{content:"󰯦"}.mdi-account-off:before{content:"󰀒"}.mdi-account-off-outline:before{content:"󰯧"}.mdi-account-outline:before{content:"󰀓"}.mdi-account-plus:before{content:"󰀔"}.mdi-account-plus-outline:before{content:"󰠁"}.mdi-account-question:before{content:"󰭙"}.mdi-account-question-outline:before{content:"󰭚"}.mdi-account-reactivate:before{content:"󱔫"}.mdi-account-reactivate-outline:before{content:"󱔬"}.mdi-account-remove:before{content:"󰀕"}.mdi-account-remove-outline:before{content:"󰫭"}.mdi-account-school:before{content:"󱨠"}.mdi-account-school-outline:before{content:"󱨡"}.mdi-account-search:before{content:"󰀖"}.mdi-account-search-outline:before{content:"󰤵"}.mdi-account-settings:before{content:"󰘰"}.mdi-account-settings-outline:before{content:"󱃉"}.mdi-account-star:before{content:"󰀗"}.mdi-account-star-outline:before{content:"󰯨"}.mdi-account-supervisor:before{content:"󰪋"}.mdi-account-supervisor-circle:before{content:"󰪌"}.mdi-account-supervisor-circle-outline:before{content:"󱓬"}.mdi-account-supervisor-outline:before{content:"󱄭"}.mdi-account-switch:before{content:"󰀙"}.mdi-account-switch-outline:before{content:"󰓋"}.mdi-account-sync:before{content:"󱤛"}.mdi-account-sync-outline:before{content:"󱤜"}.mdi-account-tag:before{content:"󱰛"}.mdi-account-tag-outline:before{content:"󱰜"}.mdi-account-tie:before{content:"󰳣"}.mdi-account-tie-hat:before{content:"󱢘"}.mdi-account-tie-hat-outline:before{content:"󱢙"}.mdi-account-tie-outline:before{content:"󱃊"}.mdi-account-tie-voice:before{content:"󱌈"}.mdi-account-tie-voice-off:before{content:"󱌊"}.mdi-account-tie-voice-off-outline:before{content:"󱌋"}.mdi-account-tie-voice-outline:before{content:"󱌉"}.mdi-account-tie-woman:before{content:"󱪌"}.mdi-account-voice:before{content:"󰗋"}.mdi-account-voice-off:before{content:"󰻔"}.mdi-account-wrench:before{content:"󱢚"}.mdi-account-wrench-outline:before{content:"󱢛"}.mdi-adjust:before{content:"󰀚"}.mdi-advertisements:before{content:"󱤪"}.mdi-advertisements-off:before{content:"󱤫"}.mdi-air-conditioner:before{content:"󰀛"}.mdi-air-filter:before{content:"󰵃"}.mdi-air-horn:before{content:"󰶬"}.mdi-air-humidifier:before{content:"󱂙"}.mdi-air-humidifier-off:before{content:"󱑦"}.mdi-air-purifier:before{content:"󰵄"}.mdi-air-purifier-off:before{content:"󱭗"}.mdi-airbag:before{content:"󰯩"}.mdi-airballoon:before{content:"󰀜"}.mdi-airballoon-outline:before{content:"󱀋"}.mdi-airplane:before{content:"󰀝"}.mdi-airplane-alert:before{content:"󱡺"}.mdi-airplane-check:before{content:"󱡻"}.mdi-airplane-clock:before{content:"󱡼"}.mdi-airplane-cog:before{content:"󱡽"}.mdi-airplane-edit:before{content:"󱡾"}.mdi-airplane-landing:before{content:"󰗔"}.mdi-airplane-marker:before{content:"󱡿"}.mdi-airplane-minus:before{content:"󱢀"}.mdi-airplane-off:before{content:"󰀞"}.mdi-airplane-plus:before{content:"󱢁"}.mdi-airplane-remove:before{content:"󱢂"}.mdi-airplane-search:before{content:"󱢃"}.mdi-airplane-settings:before{content:"󱢄"}.mdi-airplane-takeoff:before{content:"󰗕"}.mdi-airport:before{content:"󰡋"}.mdi-alarm:before{content:"󰀠"}.mdi-alarm-bell:before{content:"󰞎"}.mdi-alarm-check:before{content:"󰀡"}.mdi-alarm-light:before{content:"󰞏"}.mdi-alarm-light-off:before{content:"󱜞"}.mdi-alarm-light-off-outline:before{content:"󱜟"}.mdi-alarm-light-outline:before{content:"󰯪"}.mdi-alarm-multiple:before{content:"󰀢"}.mdi-alarm-note:before{content:"󰹱"}.mdi-alarm-note-off:before{content:"󰹲"}.mdi-alarm-off:before{content:"󰀣"}.mdi-alarm-panel:before{content:"󱗄"}.mdi-alarm-panel-outline:before{content:"󱗅"}.mdi-alarm-plus:before{content:"󰀤"}.mdi-alarm-snooze:before{content:"󰚎"}.mdi-album:before{content:"󰀥"}.mdi-alert:before{content:"󰀦"}.mdi-alert-box:before{content:"󰀧"}.mdi-alert-box-outline:before{content:"󰳤"}.mdi-alert-circle:before{content:"󰀨"}.mdi-alert-circle-check:before{content:"󱇭"}.mdi-alert-circle-check-outline:before{content:"󱇮"}.mdi-alert-circle-outline:before{content:"󰗖"}.mdi-alert-decagram:before{content:"󰚽"}.mdi-alert-decagram-outline:before{content:"󰳥"}.mdi-alert-minus:before{content:"󱒻"}.mdi-alert-minus-outline:before{content:"󱒾"}.mdi-alert-octagon:before{content:"󰀩"}.mdi-alert-octagon-outline:before{content:"󰳦"}.mdi-alert-octagram:before{content:"󰝧"}.mdi-alert-octagram-outline:before{content:"󰳧"}.mdi-alert-outline:before{content:"󰀪"}.mdi-alert-plus:before{content:"󱒺"}.mdi-alert-plus-outline:before{content:"󱒽"}.mdi-alert-remove:before{content:"󱒼"}.mdi-alert-remove-outline:before{content:"󱒿"}.mdi-alert-rhombus:before{content:"󱇎"}.mdi-alert-rhombus-outline:before{content:"󱇏"}.mdi-alien:before{content:"󰢚"}.mdi-alien-outline:before{content:"󱃋"}.mdi-align-horizontal-center:before{content:"󱇃"}.mdi-align-horizontal-distribute:before{content:"󱥢"}.mdi-align-horizontal-left:before{content:"󱇂"}.mdi-align-horizontal-right:before{content:"󱇄"}.mdi-align-vertical-bottom:before{content:"󱇅"}.mdi-align-vertical-center:before{content:"󱇆"}.mdi-align-vertical-distribute:before{content:"󱥣"}.mdi-align-vertical-top:before{content:"󱇇"}.mdi-all-inclusive:before{content:"󰚾"}.mdi-all-inclusive-box:before{content:"󱢍"}.mdi-all-inclusive-box-outline:before{content:"󱢎"}.mdi-allergy:before{content:"󱉘"}.mdi-alpha:before{content:"󰀫"}.mdi-alpha-a:before{content:"󰫮"}.mdi-alpha-a-box:before{content:"󰬈"}.mdi-alpha-a-box-outline:before{content:"󰯫"}.mdi-alpha-a-circle:before{content:"󰯬"}.mdi-alpha-a-circle-outline:before{content:"󰯭"}.mdi-alpha-b:before{content:"󰫯"}.mdi-alpha-b-box:before{content:"󰬉"}.mdi-alpha-b-box-outline:before{content:"󰯮"}.mdi-alpha-b-circle:before{content:"󰯯"}.mdi-alpha-b-circle-outline:before{content:"󰯰"}.mdi-alpha-c:before{content:"󰫰"}.mdi-alpha-c-box:before{content:"󰬊"}.mdi-alpha-c-box-outline:before{content:"󰯱"}.mdi-alpha-c-circle:before{content:"󰯲"}.mdi-alpha-c-circle-outline:before{content:"󰯳"}.mdi-alpha-d:before{content:"󰫱"}.mdi-alpha-d-box:before{content:"󰬋"}.mdi-alpha-d-box-outline:before{content:"󰯴"}.mdi-alpha-d-circle:before{content:"󰯵"}.mdi-alpha-d-circle-outline:before{content:"󰯶"}.mdi-alpha-e:before{content:"󰫲"}.mdi-alpha-e-box:before{content:"󰬌"}.mdi-alpha-e-box-outline:before{content:"󰯷"}.mdi-alpha-e-circle:before{content:"󰯸"}.mdi-alpha-e-circle-outline:before{content:"󰯹"}.mdi-alpha-f:before{content:"󰫳"}.mdi-alpha-f-box:before{content:"󰬍"}.mdi-alpha-f-box-outline:before{content:"󰯺"}.mdi-alpha-f-circle:before{content:"󰯻"}.mdi-alpha-f-circle-outline:before{content:"󰯼"}.mdi-alpha-g:before{content:"󰫴"}.mdi-alpha-g-box:before{content:"󰬎"}.mdi-alpha-g-box-outline:before{content:"󰯽"}.mdi-alpha-g-circle:before{content:"󰯾"}.mdi-alpha-g-circle-outline:before{content:"󰯿"}.mdi-alpha-h:before{content:"󰫵"}.mdi-alpha-h-box:before{content:"󰬏"}.mdi-alpha-h-box-outline:before{content:"󰰀"}.mdi-alpha-h-circle:before{content:"󰰁"}.mdi-alpha-h-circle-outline:before{content:"󰰂"}.mdi-alpha-i:before{content:"󰫶"}.mdi-alpha-i-box:before{content:"󰬐"}.mdi-alpha-i-box-outline:before{content:"󰰃"}.mdi-alpha-i-circle:before{content:"󰰄"}.mdi-alpha-i-circle-outline:before{content:"󰰅"}.mdi-alpha-j:before{content:"󰫷"}.mdi-alpha-j-box:before{content:"󰬑"}.mdi-alpha-j-box-outline:before{content:"󰰆"}.mdi-alpha-j-circle:before{content:"󰰇"}.mdi-alpha-j-circle-outline:before{content:"󰰈"}.mdi-alpha-k:before{content:"󰫸"}.mdi-alpha-k-box:before{content:"󰬒"}.mdi-alpha-k-box-outline:before{content:"󰰉"}.mdi-alpha-k-circle:before{content:"󰰊"}.mdi-alpha-k-circle-outline:before{content:"󰰋"}.mdi-alpha-l:before{content:"󰫹"}.mdi-alpha-l-box:before{content:"󰬓"}.mdi-alpha-l-box-outline:before{content:"󰰌"}.mdi-alpha-l-circle:before{content:"󰰍"}.mdi-alpha-l-circle-outline:before{content:"󰰎"}.mdi-alpha-m:before{content:"󰫺"}.mdi-alpha-m-box:before{content:"󰬔"}.mdi-alpha-m-box-outline:before{content:"󰰏"}.mdi-alpha-m-circle:before{content:"󰰐"}.mdi-alpha-m-circle-outline:before{content:"󰰑"}.mdi-alpha-n:before{content:"󰫻"}.mdi-alpha-n-box:before{content:"󰬕"}.mdi-alpha-n-box-outline:before{content:"󰰒"}.mdi-alpha-n-circle:before{content:"󰰓"}.mdi-alpha-n-circle-outline:before{content:"󰰔"}.mdi-alpha-o:before{content:"󰫼"}.mdi-alpha-o-box:before{content:"󰬖"}.mdi-alpha-o-box-outline:before{content:"󰰕"}.mdi-alpha-o-circle:before{content:"󰰖"}.mdi-alpha-o-circle-outline:before{content:"󰰗"}.mdi-alpha-p:before{content:"󰫽"}.mdi-alpha-p-box:before{content:"󰬗"}.mdi-alpha-p-box-outline:before{content:"󰰘"}.mdi-alpha-p-circle:before{content:"󰰙"}.mdi-alpha-p-circle-outline:before{content:"󰰚"}.mdi-alpha-q:before{content:"󰫾"}.mdi-alpha-q-box:before{content:"󰬘"}.mdi-alpha-q-box-outline:before{content:"󰰛"}.mdi-alpha-q-circle:before{content:"󰰜"}.mdi-alpha-q-circle-outline:before{content:"󰰝"}.mdi-alpha-r:before{content:"󰫿"}.mdi-alpha-r-box:before{content:"󰬙"}.mdi-alpha-r-box-outline:before{content:"󰰞"}.mdi-alpha-r-circle:before{content:"󰰟"}.mdi-alpha-r-circle-outline:before{content:"󰰠"}.mdi-alpha-s:before{content:"󰬀"}.mdi-alpha-s-box:before{content:"󰬚"}.mdi-alpha-s-box-outline:before{content:"󰰡"}.mdi-alpha-s-circle:before{content:"󰰢"}.mdi-alpha-s-circle-outline:before{content:"󰰣"}.mdi-alpha-t:before{content:"󰬁"}.mdi-alpha-t-box:before{content:"󰬛"}.mdi-alpha-t-box-outline:before{content:"󰰤"}.mdi-alpha-t-circle:before{content:"󰰥"}.mdi-alpha-t-circle-outline:before{content:"󰰦"}.mdi-alpha-u:before{content:"󰬂"}.mdi-alpha-u-box:before{content:"󰬜"}.mdi-alpha-u-box-outline:before{content:"󰰧"}.mdi-alpha-u-circle:before{content:"󰰨"}.mdi-alpha-u-circle-outline:before{content:"󰰩"}.mdi-alpha-v:before{content:"󰬃"}.mdi-alpha-v-box:before{content:"󰬝"}.mdi-alpha-v-box-outline:before{content:"󰰪"}.mdi-alpha-v-circle:before{content:"󰰫"}.mdi-alpha-v-circle-outline:before{content:"󰰬"}.mdi-alpha-w:before{content:"󰬄"}.mdi-alpha-w-box:before{content:"󰬞"}.mdi-alpha-w-box-outline:before{content:"󰰭"}.mdi-alpha-w-circle:before{content:"󰰮"}.mdi-alpha-w-circle-outline:before{content:"󰰯"}.mdi-alpha-x:before{content:"󰬅"}.mdi-alpha-x-box:before{content:"󰬟"}.mdi-alpha-x-box-outline:before{content:"󰰰"}.mdi-alpha-x-circle:before{content:"󰰱"}.mdi-alpha-x-circle-outline:before{content:"󰰲"}.mdi-alpha-y:before{content:"󰬆"}.mdi-alpha-y-box:before{content:"󰬠"}.mdi-alpha-y-box-outline:before{content:"󰰳"}.mdi-alpha-y-circle:before{content:"󰰴"}.mdi-alpha-y-circle-outline:before{content:"󰰵"}.mdi-alpha-z:before{content:"󰬇"}.mdi-alpha-z-box:before{content:"󰬡"}.mdi-alpha-z-box-outline:before{content:"󰰶"}.mdi-alpha-z-circle:before{content:"󰰷"}.mdi-alpha-z-circle-outline:before{content:"󰰸"}.mdi-alphabet-aurebesh:before{content:"󱌬"}.mdi-alphabet-cyrillic:before{content:"󱌭"}.mdi-alphabet-greek:before{content:"󱌮"}.mdi-alphabet-latin:before{content:"󱌯"}.mdi-alphabet-piqad:before{content:"󱌰"}.mdi-alphabet-tengwar:before{content:"󱌷"}.mdi-alphabetical:before{content:"󰀬"}.mdi-alphabetical-off:before{content:"󱀌"}.mdi-alphabetical-variant:before{content:"󱀍"}.mdi-alphabetical-variant-off:before{content:"󱀎"}.mdi-altimeter:before{content:"󰗗"}.mdi-ambulance:before{content:"󰀯"}.mdi-ammunition:before{content:"󰳨"}.mdi-ampersand:before{content:"󰪍"}.mdi-amplifier:before{content:"󰀰"}.mdi-amplifier-off:before{content:"󱆵"}.mdi-anchor:before{content:"󰀱"}.mdi-android:before{content:"󰀲"}.mdi-android-studio:before{content:"󰀴"}.mdi-angle-acute:before{content:"󰤷"}.mdi-angle-obtuse:before{content:"󰤸"}.mdi-angle-right:before{content:"󰤹"}.mdi-angular:before{content:"󰚲"}.mdi-angularjs:before{content:"󰚿"}.mdi-animation:before{content:"󰗘"}.mdi-animation-outline:before{content:"󰪏"}.mdi-animation-play:before{content:"󰤺"}.mdi-animation-play-outline:before{content:"󰪐"}.mdi-ansible:before{content:"󱂚"}.mdi-antenna:before{content:"󱄙"}.mdi-anvil:before{content:"󰢛"}.mdi-apache-kafka:before{content:"󱀏"}.mdi-api:before{content:"󱂛"}.mdi-api-off:before{content:"󱉗"}.mdi-apple:before{content:"󰀵"}.mdi-apple-finder:before{content:"󰀶"}.mdi-apple-icloud:before{content:"󰀸"}.mdi-apple-ios:before{content:"󰀷"}.mdi-apple-keyboard-caps:before{content:"󰘲"}.mdi-apple-keyboard-command:before{content:"󰘳"}.mdi-apple-keyboard-control:before{content:"󰘴"}.mdi-apple-keyboard-option:before{content:"󰘵"}.mdi-apple-keyboard-shift:before{content:"󰘶"}.mdi-apple-safari:before{content:"󰀹"}.mdi-application:before{content:"󰣆"}.mdi-application-array:before{content:"󱃵"}.mdi-application-array-outline:before{content:"󱃶"}.mdi-application-braces:before{content:"󱃷"}.mdi-application-braces-outline:before{content:"󱃸"}.mdi-application-brackets:before{content:"󰲋"}.mdi-application-brackets-outline:before{content:"󰲌"}.mdi-application-cog:before{content:"󰙵"}.mdi-application-cog-outline:before{content:"󱕷"}.mdi-application-edit:before{content:"󰂮"}.mdi-application-edit-outline:before{content:"󰘙"}.mdi-application-export:before{content:"󰶭"}.mdi-application-import:before{content:"󰶮"}.mdi-application-outline:before{content:"󰘔"}.mdi-application-parentheses:before{content:"󱃹"}.mdi-application-parentheses-outline:before{content:"󱃺"}.mdi-application-settings:before{content:"󰭠"}.mdi-application-settings-outline:before{content:"󱕕"}.mdi-application-variable:before{content:"󱃻"}.mdi-application-variable-outline:before{content:"󱃼"}.mdi-approximately-equal:before{content:"󰾞"}.mdi-approximately-equal-box:before{content:"󰾟"}.mdi-apps:before{content:"󰀻"}.mdi-apps-box:before{content:"󰵆"}.mdi-arch:before{content:"󰣇"}.mdi-archive:before{content:"󰀼"}.mdi-archive-alert:before{content:"󱓽"}.mdi-archive-alert-outline:before{content:"󱓾"}.mdi-archive-arrow-down:before{content:"󱉙"}.mdi-archive-arrow-down-outline:before{content:"󱉚"}.mdi-archive-arrow-up:before{content:"󱉛"}.mdi-archive-arrow-up-outline:before{content:"󱉜"}.mdi-archive-cancel:before{content:"󱝋"}.mdi-archive-cancel-outline:before{content:"󱝌"}.mdi-archive-check:before{content:"󱝍"}.mdi-archive-check-outline:before{content:"󱝎"}.mdi-archive-clock:before{content:"󱝏"}.mdi-archive-clock-outline:before{content:"󱝐"}.mdi-archive-cog:before{content:"󱝑"}.mdi-archive-cog-outline:before{content:"󱝒"}.mdi-archive-edit:before{content:"󱝓"}.mdi-archive-edit-outline:before{content:"󱝔"}.mdi-archive-eye:before{content:"󱝕"}.mdi-archive-eye-outline:before{content:"󱝖"}.mdi-archive-lock:before{content:"󱝗"}.mdi-archive-lock-open:before{content:"󱝘"}.mdi-archive-lock-open-outline:before{content:"󱝙"}.mdi-archive-lock-outline:before{content:"󱝚"}.mdi-archive-marker:before{content:"󱝛"}.mdi-archive-marker-outline:before{content:"󱝜"}.mdi-archive-minus:before{content:"󱝝"}.mdi-archive-minus-outline:before{content:"󱝞"}.mdi-archive-music:before{content:"󱝟"}.mdi-archive-music-outline:before{content:"󱝠"}.mdi-archive-off:before{content:"󱝡"}.mdi-archive-off-outline:before{content:"󱝢"}.mdi-archive-outline:before{content:"󱈎"}.mdi-archive-plus:before{content:"󱝣"}.mdi-archive-plus-outline:before{content:"󱝤"}.mdi-archive-refresh:before{content:"󱝥"}.mdi-archive-refresh-outline:before{content:"󱝦"}.mdi-archive-remove:before{content:"󱝧"}.mdi-archive-remove-outline:before{content:"󱝨"}.mdi-archive-search:before{content:"󱝩"}.mdi-archive-search-outline:before{content:"󱝪"}.mdi-archive-settings:before{content:"󱝫"}.mdi-archive-settings-outline:before{content:"󱝬"}.mdi-archive-star:before{content:"󱝭"}.mdi-archive-star-outline:before{content:"󱝮"}.mdi-archive-sync:before{content:"󱝯"}.mdi-archive-sync-outline:before{content:"󱝰"}.mdi-arm-flex:before{content:"󰿗"}.mdi-arm-flex-outline:before{content:"󰿖"}.mdi-arrange-bring-forward:before{content:"󰀽"}.mdi-arrange-bring-to-front:before{content:"󰀾"}.mdi-arrange-send-backward:before{content:"󰀿"}.mdi-arrange-send-to-back:before{content:"󰁀"}.mdi-arrow-all:before{content:"󰁁"}.mdi-arrow-bottom-left:before{content:"󰁂"}.mdi-arrow-bottom-left-bold-box:before{content:"󱥤"}.mdi-arrow-bottom-left-bold-box-outline:before{content:"󱥥"}.mdi-arrow-bottom-left-bold-outline:before{content:"󰦷"}.mdi-arrow-bottom-left-thick:before{content:"󰦸"}.mdi-arrow-bottom-left-thin:before{content:"󱦶"}.mdi-arrow-bottom-left-thin-circle-outline:before{content:"󱖖"}.mdi-arrow-bottom-right:before{content:"󰁃"}.mdi-arrow-bottom-right-bold-box:before{content:"󱥦"}.mdi-arrow-bottom-right-bold-box-outline:before{content:"󱥧"}.mdi-arrow-bottom-right-bold-outline:before{content:"󰦹"}.mdi-arrow-bottom-right-thick:before{content:"󰦺"}.mdi-arrow-bottom-right-thin:before{content:"󱦷"}.mdi-arrow-bottom-right-thin-circle-outline:before{content:"󱖕"}.mdi-arrow-collapse:before{content:"󰘕"}.mdi-arrow-collapse-all:before{content:"󰁄"}.mdi-arrow-collapse-down:before{content:"󰞒"}.mdi-arrow-collapse-horizontal:before{content:"󰡌"}.mdi-arrow-collapse-left:before{content:"󰞓"}.mdi-arrow-collapse-right:before{content:"󰞔"}.mdi-arrow-collapse-up:before{content:"󰞕"}.mdi-arrow-collapse-vertical:before{content:"󰡍"}.mdi-arrow-decision:before{content:"󰦻"}.mdi-arrow-decision-auto:before{content:"󰦼"}.mdi-arrow-decision-auto-outline:before{content:"󰦽"}.mdi-arrow-decision-outline:before{content:"󰦾"}.mdi-arrow-down:before{content:"󰁅"}.mdi-arrow-down-bold:before{content:"󰜮"}.mdi-arrow-down-bold-box:before{content:"󰜯"}.mdi-arrow-down-bold-box-outline:before{content:"󰜰"}.mdi-arrow-down-bold-circle:before{content:"󰁇"}.mdi-arrow-down-bold-circle-outline:before{content:"󰁈"}.mdi-arrow-down-bold-hexagon-outline:before{content:"󰁉"}.mdi-arrow-down-bold-outline:before{content:"󰦿"}.mdi-arrow-down-box:before{content:"󰛀"}.mdi-arrow-down-circle:before{content:"󰳛"}.mdi-arrow-down-circle-outline:before{content:"󰳜"}.mdi-arrow-down-drop-circle:before{content:"󰁊"}.mdi-arrow-down-drop-circle-outline:before{content:"󰁋"}.mdi-arrow-down-left:before{content:"󱞡"}.mdi-arrow-down-left-bold:before{content:"󱞢"}.mdi-arrow-down-right:before{content:"󱞣"}.mdi-arrow-down-right-bold:before{content:"󱞤"}.mdi-arrow-down-thick:before{content:"󰁆"}.mdi-arrow-down-thin:before{content:"󱦳"}.mdi-arrow-down-thin-circle-outline:before{content:"󱖙"}.mdi-arrow-expand:before{content:"󰘖"}.mdi-arrow-expand-all:before{content:"󰁌"}.mdi-arrow-expand-down:before{content:"󰞖"}.mdi-arrow-expand-horizontal:before{content:"󰡎"}.mdi-arrow-expand-left:before{content:"󰞗"}.mdi-arrow-expand-right:before{content:"󰞘"}.mdi-arrow-expand-up:before{content:"󰞙"}.mdi-arrow-expand-vertical:before{content:"󰡏"}.mdi-arrow-horizontal-lock:before{content:"󱅛"}.mdi-arrow-left:before{content:"󰁍"}.mdi-arrow-left-bold:before{content:"󰜱"}.mdi-arrow-left-bold-box:before{content:"󰜲"}.mdi-arrow-left-bold-box-outline:before{content:"󰜳"}.mdi-arrow-left-bold-circle:before{content:"󰁏"}.mdi-arrow-left-bold-circle-outline:before{content:"󰁐"}.mdi-arrow-left-bold-hexagon-outline:before{content:"󰁑"}.mdi-arrow-left-bold-outline:before{content:"󰧀"}.mdi-arrow-left-bottom:before{content:"󱞥"}.mdi-arrow-left-bottom-bold:before{content:"󱞦"}.mdi-arrow-left-box:before{content:"󰛁"}.mdi-arrow-left-circle:before{content:"󰳝"}.mdi-arrow-left-circle-outline:before{content:"󰳞"}.mdi-arrow-left-drop-circle:before{content:"󰁒"}.mdi-arrow-left-drop-circle-outline:before{content:"󰁓"}.mdi-arrow-left-right:before{content:"󰹳"}.mdi-arrow-left-right-bold:before{content:"󰹴"}.mdi-arrow-left-right-bold-outline:before{content:"󰧁"}.mdi-arrow-left-thick:before{content:"󰁎"}.mdi-arrow-left-thin:before{content:"󱦱"}.mdi-arrow-left-thin-circle-outline:before{content:"󱖚"}.mdi-arrow-left-top:before{content:"󱞧"}.mdi-arrow-left-top-bold:before{content:"󱞨"}.mdi-arrow-projectile:before{content:"󱡀"}.mdi-arrow-projectile-multiple:before{content:"󱠿"}.mdi-arrow-right:before{content:"󰁔"}.mdi-arrow-right-bold:before{content:"󰜴"}.mdi-arrow-right-bold-box:before{content:"󰜵"}.mdi-arrow-right-bold-box-outline:before{content:"󰜶"}.mdi-arrow-right-bold-circle:before{content:"󰁖"}.mdi-arrow-right-bold-circle-outline:before{content:"󰁗"}.mdi-arrow-right-bold-hexagon-outline:before{content:"󰁘"}.mdi-arrow-right-bold-outline:before{content:"󰧂"}.mdi-arrow-right-bottom:before{content:"󱞩"}.mdi-arrow-right-bottom-bold:before{content:"󱞪"}.mdi-arrow-right-box:before{content:"󰛂"}.mdi-arrow-right-circle:before{content:"󰳟"}.mdi-arrow-right-circle-outline:before{content:"󰳠"}.mdi-arrow-right-drop-circle:before{content:"󰁙"}.mdi-arrow-right-drop-circle-outline:before{content:"󰁚"}.mdi-arrow-right-thick:before{content:"󰁕"}.mdi-arrow-right-thin:before{content:"󱦰"}.mdi-arrow-right-thin-circle-outline:before{content:"󱖘"}.mdi-arrow-right-top:before{content:"󱞫"}.mdi-arrow-right-top-bold:before{content:"󱞬"}.mdi-arrow-split-horizontal:before{content:"󰤻"}.mdi-arrow-split-vertical:before{content:"󰤼"}.mdi-arrow-top-left:before{content:"󰁛"}.mdi-arrow-top-left-bold-box:before{content:"󱥨"}.mdi-arrow-top-left-bold-box-outline:before{content:"󱥩"}.mdi-arrow-top-left-bold-outline:before{content:"󰧃"}.mdi-arrow-top-left-bottom-right:before{content:"󰹵"}.mdi-arrow-top-left-bottom-right-bold:before{content:"󰹶"}.mdi-arrow-top-left-thick:before{content:"󰧄"}.mdi-arrow-top-left-thin:before{content:"󱦵"}.mdi-arrow-top-left-thin-circle-outline:before{content:"󱖓"}.mdi-arrow-top-right:before{content:"󰁜"}.mdi-arrow-top-right-bold-box:before{content:"󱥪"}.mdi-arrow-top-right-bold-box-outline:before{content:"󱥫"}.mdi-arrow-top-right-bold-outline:before{content:"󰧅"}.mdi-arrow-top-right-bottom-left:before{content:"󰹷"}.mdi-arrow-top-right-bottom-left-bold:before{content:"󰹸"}.mdi-arrow-top-right-thick:before{content:"󰧆"}.mdi-arrow-top-right-thin:before{content:"󱦴"}.mdi-arrow-top-right-thin-circle-outline:before{content:"󱖔"}.mdi-arrow-u-down-left:before{content:"󱞭"}.mdi-arrow-u-down-left-bold:before{content:"󱞮"}.mdi-arrow-u-down-right:before{content:"󱞯"}.mdi-arrow-u-down-right-bold:before{content:"󱞰"}.mdi-arrow-u-left-bottom:before{content:"󱞱"}.mdi-arrow-u-left-bottom-bold:before{content:"󱞲"}.mdi-arrow-u-left-top:before{content:"󱞳"}.mdi-arrow-u-left-top-bold:before{content:"󱞴"}.mdi-arrow-u-right-bottom:before{content:"󱞵"}.mdi-arrow-u-right-bottom-bold:before{content:"󱞶"}.mdi-arrow-u-right-top:before{content:"󱞷"}.mdi-arrow-u-right-top-bold:before{content:"󱞸"}.mdi-arrow-u-up-left:before{content:"󱞹"}.mdi-arrow-u-up-left-bold:before{content:"󱞺"}.mdi-arrow-u-up-right:before{content:"󱞻"}.mdi-arrow-u-up-right-bold:before{content:"󱞼"}.mdi-arrow-up:before{content:"󰁝"}.mdi-arrow-up-bold:before{content:"󰜷"}.mdi-arrow-up-bold-box:before{content:"󰜸"}.mdi-arrow-up-bold-box-outline:before{content:"󰜹"}.mdi-arrow-up-bold-circle:before{content:"󰁟"}.mdi-arrow-up-bold-circle-outline:before{content:"󰁠"}.mdi-arrow-up-bold-hexagon-outline:before{content:"󰁡"}.mdi-arrow-up-bold-outline:before{content:"󰧇"}.mdi-arrow-up-box:before{content:"󰛃"}.mdi-arrow-up-circle:before{content:"󰳡"}.mdi-arrow-up-circle-outline:before{content:"󰳢"}.mdi-arrow-up-down:before{content:"󰹹"}.mdi-arrow-up-down-bold:before{content:"󰹺"}.mdi-arrow-up-down-bold-outline:before{content:"󰧈"}.mdi-arrow-up-drop-circle:before{content:"󰁢"}.mdi-arrow-up-drop-circle-outline:before{content:"󰁣"}.mdi-arrow-up-left:before{content:"󱞽"}.mdi-arrow-up-left-bold:before{content:"󱞾"}.mdi-arrow-up-right:before{content:"󱞿"}.mdi-arrow-up-right-bold:before{content:"󱟀"}.mdi-arrow-up-thick:before{content:"󰁞"}.mdi-arrow-up-thin:before{content:"󱦲"}.mdi-arrow-up-thin-circle-outline:before{content:"󱖗"}.mdi-arrow-vertical-lock:before{content:"󱅜"}.mdi-artboard:before{content:"󱮚"}.mdi-artstation:before{content:"󰭛"}.mdi-aspect-ratio:before{content:"󰨤"}.mdi-assistant:before{content:"󰁤"}.mdi-asterisk:before{content:"󰛄"}.mdi-asterisk-circle-outline:before{content:"󱨧"}.mdi-at:before{content:"󰁥"}.mdi-atlassian:before{content:"󰠄"}.mdi-atm:before{content:"󰵇"}.mdi-atom:before{content:"󰝨"}.mdi-atom-variant:before{content:"󰹻"}.mdi-attachment:before{content:"󰁦"}.mdi-attachment-check:before{content:"󱫁"}.mdi-attachment-lock:before{content:"󱧄"}.mdi-attachment-minus:before{content:"󱫂"}.mdi-attachment-off:before{content:"󱫃"}.mdi-attachment-plus:before{content:"󱫄"}.mdi-attachment-remove:before{content:"󱫅"}.mdi-atv:before{content:"󱭰"}.mdi-audio-input-rca:before{content:"󱡫"}.mdi-audio-input-stereo-minijack:before{content:"󱡬"}.mdi-audio-input-xlr:before{content:"󱡭"}.mdi-audio-video:before{content:"󰤽"}.mdi-audio-video-off:before{content:"󱆶"}.mdi-augmented-reality:before{content:"󰡐"}.mdi-aurora:before{content:"󱮹"}.mdi-auto-download:before{content:"󱍾"}.mdi-auto-fix:before{content:"󰁨"}.mdi-auto-mode:before{content:"󱰠"}.mdi-auto-upload:before{content:"󰁩"}.mdi-autorenew:before{content:"󰁪"}.mdi-autorenew-off:before{content:"󱧧"}.mdi-av-timer:before{content:"󰁫"}.mdi-awning:before{content:"󱮇"}.mdi-awning-outline:before{content:"󱮈"}.mdi-aws:before{content:"󰸏"}.mdi-axe:before{content:"󰣈"}.mdi-axe-battle:before{content:"󱡂"}.mdi-axis:before{content:"󰵈"}.mdi-axis-arrow:before{content:"󰵉"}.mdi-axis-arrow-info:before{content:"󱐎"}.mdi-axis-arrow-lock:before{content:"󰵊"}.mdi-axis-lock:before{content:"󰵋"}.mdi-axis-x-arrow:before{content:"󰵌"}.mdi-axis-x-arrow-lock:before{content:"󰵍"}.mdi-axis-x-rotate-clockwise:before{content:"󰵎"}.mdi-axis-x-rotate-counterclockwise:before{content:"󰵏"}.mdi-axis-x-y-arrow-lock:before{content:"󰵐"}.mdi-axis-y-arrow:before{content:"󰵑"}.mdi-axis-y-arrow-lock:before{content:"󰵒"}.mdi-axis-y-rotate-clockwise:before{content:"󰵓"}.mdi-axis-y-rotate-counterclockwise:before{content:"󰵔"}.mdi-axis-z-arrow:before{content:"󰵕"}.mdi-axis-z-arrow-lock:before{content:"󰵖"}.mdi-axis-z-rotate-clockwise:before{content:"󰵗"}.mdi-axis-z-rotate-counterclockwise:before{content:"󰵘"}.mdi-babel:before{content:"󰨥"}.mdi-baby:before{content:"󰁬"}.mdi-baby-bottle:before{content:"󰼹"}.mdi-baby-bottle-outline:before{content:"󰼺"}.mdi-baby-buggy:before{content:"󱏠"}.mdi-baby-buggy-off:before{content:"󱫳"}.mdi-baby-carriage:before{content:"󰚏"}.mdi-baby-carriage-off:before{content:"󰾠"}.mdi-baby-face:before{content:"󰹼"}.mdi-baby-face-outline:before{content:"󰹽"}.mdi-backburger:before{content:"󰁭"}.mdi-backspace:before{content:"󰁮"}.mdi-backspace-outline:before{content:"󰭜"}.mdi-backspace-reverse:before{content:"󰹾"}.mdi-backspace-reverse-outline:before{content:"󰹿"}.mdi-backup-restore:before{content:"󰁯"}.mdi-bacteria:before{content:"󰻕"}.mdi-bacteria-outline:before{content:"󰻖"}.mdi-badge-account:before{content:"󰶧"}.mdi-badge-account-alert:before{content:"󰶨"}.mdi-badge-account-alert-outline:before{content:"󰶩"}.mdi-badge-account-horizontal:before{content:"󰸍"}.mdi-badge-account-horizontal-outline:before{content:"󰸎"}.mdi-badge-account-outline:before{content:"󰶪"}.mdi-badminton:before{content:"󰡑"}.mdi-bag-carry-on:before{content:"󰼻"}.mdi-bag-carry-on-check:before{content:"󰵥"}.mdi-bag-carry-on-off:before{content:"󰼼"}.mdi-bag-checked:before{content:"󰼽"}.mdi-bag-personal:before{content:"󰸐"}.mdi-bag-personal-off:before{content:"󰸑"}.mdi-bag-personal-off-outline:before{content:"󰸒"}.mdi-bag-personal-outline:before{content:"󰸓"}.mdi-bag-personal-tag:before{content:"󱬌"}.mdi-bag-personal-tag-outline:before{content:"󱬍"}.mdi-bag-suitcase:before{content:"󱖋"}.mdi-bag-suitcase-off:before{content:"󱖍"}.mdi-bag-suitcase-off-outline:before{content:"󱖎"}.mdi-bag-suitcase-outline:before{content:"󱖌"}.mdi-baguette:before{content:"󰼾"}.mdi-balcony:before{content:"󱠗"}.mdi-balloon:before{content:"󰨦"}.mdi-ballot:before{content:"󰧉"}.mdi-ballot-outline:before{content:"󰧊"}.mdi-ballot-recount:before{content:"󰰹"}.mdi-ballot-recount-outline:before{content:"󰰺"}.mdi-bandage:before{content:"󰶯"}.mdi-bank:before{content:"󰁰"}.mdi-bank-check:before{content:"󱙕"}.mdi-bank-circle:before{content:"󱰃"}.mdi-bank-circle-outline:before{content:"󱰄"}.mdi-bank-minus:before{content:"󰶰"}.mdi-bank-off:before{content:"󱙖"}.mdi-bank-off-outline:before{content:"󱙗"}.mdi-bank-outline:before{content:"󰺀"}.mdi-bank-plus:before{content:"󰶱"}.mdi-bank-remove:before{content:"󰶲"}.mdi-bank-transfer:before{content:"󰨧"}.mdi-bank-transfer-in:before{content:"󰨨"}.mdi-bank-transfer-out:before{content:"󰨩"}.mdi-barcode:before{content:"󰁱"}.mdi-barcode-off:before{content:"󱈶"}.mdi-barcode-scan:before{content:"󰁲"}.mdi-barley:before{content:"󰁳"}.mdi-barley-off:before{content:"󰭝"}.mdi-barn:before{content:"󰭞"}.mdi-barrel:before{content:"󰁴"}.mdi-barrel-outline:before{content:"󱨨"}.mdi-baseball:before{content:"󰡒"}.mdi-baseball-bat:before{content:"󰡓"}.mdi-baseball-diamond:before{content:"󱗬"}.mdi-baseball-diamond-outline:before{content:"󱗭"}.mdi-baseball-outline:before{content:"󱱚"}.mdi-bash:before{content:"󱆃"}.mdi-basket:before{content:"󰁶"}.mdi-basket-check:before{content:"󱣥"}.mdi-basket-check-outline:before{content:"󱣦"}.mdi-basket-fill:before{content:"󰁷"}.mdi-basket-minus:before{content:"󱔣"}.mdi-basket-minus-outline:before{content:"󱔤"}.mdi-basket-off:before{content:"󱔥"}.mdi-basket-off-outline:before{content:"󱔦"}.mdi-basket-outline:before{content:"󱆁"}.mdi-basket-plus:before{content:"󱔧"}.mdi-basket-plus-outline:before{content:"󱔨"}.mdi-basket-remove:before{content:"󱔩"}.mdi-basket-remove-outline:before{content:"󱔪"}.mdi-basket-unfill:before{content:"󰁸"}.mdi-basketball:before{content:"󰠆"}.mdi-basketball-hoop:before{content:"󰰻"}.mdi-basketball-hoop-outline:before{content:"󰰼"}.mdi-bat:before{content:"󰭟"}.mdi-bathtub:before{content:"󱠘"}.mdi-bathtub-outline:before{content:"󱠙"}.mdi-battery:before{content:"󰁹"}.mdi-battery-10:before{content:"󰁺"}.mdi-battery-10-bluetooth:before{content:"󰤾"}.mdi-battery-20:before{content:"󰁻"}.mdi-battery-20-bluetooth:before{content:"󰤿"}.mdi-battery-30:before{content:"󰁼"}.mdi-battery-30-bluetooth:before{content:"󰥀"}.mdi-battery-40:before{content:"󰁽"}.mdi-battery-40-bluetooth:before{content:"󰥁"}.mdi-battery-50:before{content:"󰁾"}.mdi-battery-50-bluetooth:before{content:"󰥂"}.mdi-battery-60:before{content:"󰁿"}.mdi-battery-60-bluetooth:before{content:"󰥃"}.mdi-battery-70:before{content:"󰂀"}.mdi-battery-70-bluetooth:before{content:"󰥄"}.mdi-battery-80:before{content:"󰂁"}.mdi-battery-80-bluetooth:before{content:"󰥅"}.mdi-battery-90:before{content:"󰂂"}.mdi-battery-90-bluetooth:before{content:"󰥆"}.mdi-battery-alert:before{content:"󰂃"}.mdi-battery-alert-bluetooth:before{content:"󰥇"}.mdi-battery-alert-variant:before{content:"󱃌"}.mdi-battery-alert-variant-outline:before{content:"󱃍"}.mdi-battery-arrow-down:before{content:"󱟞"}.mdi-battery-arrow-down-outline:before{content:"󱟟"}.mdi-battery-arrow-up:before{content:"󱟠"}.mdi-battery-arrow-up-outline:before{content:"󱟡"}.mdi-battery-bluetooth:before{content:"󰥈"}.mdi-battery-bluetooth-variant:before{content:"󰥉"}.mdi-battery-charging:before{content:"󰂄"}.mdi-battery-charging-10:before{content:"󰢜"}.mdi-battery-charging-100:before{content:"󰂅"}.mdi-battery-charging-20:before{content:"󰂆"}.mdi-battery-charging-30:before{content:"󰂇"}.mdi-battery-charging-40:before{content:"󰂈"}.mdi-battery-charging-50:before{content:"󰢝"}.mdi-battery-charging-60:before{content:"󰂉"}.mdi-battery-charging-70:before{content:"󰢞"}.mdi-battery-charging-80:before{content:"󰂊"}.mdi-battery-charging-90:before{content:"󰂋"}.mdi-battery-charging-high:before{content:"󱊦"}.mdi-battery-charging-low:before{content:"󱊤"}.mdi-battery-charging-medium:before{content:"󱊥"}.mdi-battery-charging-outline:before{content:"󰢟"}.mdi-battery-charging-wireless:before{content:"󰠇"}.mdi-battery-charging-wireless-10:before{content:"󰠈"}.mdi-battery-charging-wireless-20:before{content:"󰠉"}.mdi-battery-charging-wireless-30:before{content:"󰠊"}.mdi-battery-charging-wireless-40:before{content:"󰠋"}.mdi-battery-charging-wireless-50:before{content:"󰠌"}.mdi-battery-charging-wireless-60:before{content:"󰠍"}.mdi-battery-charging-wireless-70:before{content:"󰠎"}.mdi-battery-charging-wireless-80:before{content:"󰠏"}.mdi-battery-charging-wireless-90:before{content:"󰠐"}.mdi-battery-charging-wireless-alert:before{content:"󰠑"}.mdi-battery-charging-wireless-outline:before{content:"󰠒"}.mdi-battery-check:before{content:"󱟢"}.mdi-battery-check-outline:before{content:"󱟣"}.mdi-battery-clock:before{content:"󱧥"}.mdi-battery-clock-outline:before{content:"󱧦"}.mdi-battery-heart:before{content:"󱈏"}.mdi-battery-heart-outline:before{content:"󱈐"}.mdi-battery-heart-variant:before{content:"󱈑"}.mdi-battery-high:before{content:"󱊣"}.mdi-battery-lock:before{content:"󱞜"}.mdi-battery-lock-open:before{content:"󱞝"}.mdi-battery-low:before{content:"󱊡"}.mdi-battery-medium:before{content:"󱊢"}.mdi-battery-minus:before{content:"󱟤"}.mdi-battery-minus-outline:before{content:"󱟥"}.mdi-battery-minus-variant:before{content:"󰂌"}.mdi-battery-negative:before{content:"󰂍"}.mdi-battery-off:before{content:"󱉝"}.mdi-battery-off-outline:before{content:"󱉞"}.mdi-battery-outline:before{content:"󰂎"}.mdi-battery-plus:before{content:"󱟦"}.mdi-battery-plus-outline:before{content:"󱟧"}.mdi-battery-plus-variant:before{content:"󰂏"}.mdi-battery-positive:before{content:"󰂐"}.mdi-battery-remove:before{content:"󱟨"}.mdi-battery-remove-outline:before{content:"󱟩"}.mdi-battery-sync:before{content:"󱠴"}.mdi-battery-sync-outline:before{content:"󱠵"}.mdi-battery-unknown:before{content:"󰂑"}.mdi-battery-unknown-bluetooth:before{content:"󰥊"}.mdi-beach:before{content:"󰂒"}.mdi-beaker:before{content:"󰳪"}.mdi-beaker-alert:before{content:"󱈩"}.mdi-beaker-alert-outline:before{content:"󱈪"}.mdi-beaker-check:before{content:"󱈫"}.mdi-beaker-check-outline:before{content:"󱈬"}.mdi-beaker-minus:before{content:"󱈭"}.mdi-beaker-minus-outline:before{content:"󱈮"}.mdi-beaker-outline:before{content:"󰚐"}.mdi-beaker-plus:before{content:"󱈯"}.mdi-beaker-plus-outline:before{content:"󱈰"}.mdi-beaker-question:before{content:"󱈱"}.mdi-beaker-question-outline:before{content:"󱈲"}.mdi-beaker-remove:before{content:"󱈳"}.mdi-beaker-remove-outline:before{content:"󱈴"}.mdi-bed:before{content:"󰋣"}.mdi-bed-clock:before{content:"󱮔"}.mdi-bed-double:before{content:"󰿔"}.mdi-bed-double-outline:before{content:"󰿓"}.mdi-bed-empty:before{content:"󰢠"}.mdi-bed-king:before{content:"󰿒"}.mdi-bed-king-outline:before{content:"󰿑"}.mdi-bed-outline:before{content:"󰂙"}.mdi-bed-queen:before{content:"󰿐"}.mdi-bed-queen-outline:before{content:"󰿛"}.mdi-bed-single:before{content:"󱁭"}.mdi-bed-single-outline:before{content:"󱁮"}.mdi-bee:before{content:"󰾡"}.mdi-bee-flower:before{content:"󰾢"}.mdi-beehive-off-outline:before{content:"󱏭"}.mdi-beehive-outline:before{content:"󱃎"}.mdi-beekeeper:before{content:"󱓢"}.mdi-beer:before{content:"󰂘"}.mdi-beer-outline:before{content:"󱌌"}.mdi-bell:before{content:"󰂚"}.mdi-bell-alert:before{content:"󰵙"}.mdi-bell-alert-outline:before{content:"󰺁"}.mdi-bell-badge:before{content:"󱅫"}.mdi-bell-badge-outline:before{content:"󰅸"}.mdi-bell-cancel:before{content:"󱏧"}.mdi-bell-cancel-outline:before{content:"󱏨"}.mdi-bell-check:before{content:"󱇥"}.mdi-bell-check-outline:before{content:"󱇦"}.mdi-bell-circle:before{content:"󰵚"}.mdi-bell-circle-outline:before{content:"󰵛"}.mdi-bell-cog:before{content:"󱨩"}.mdi-bell-cog-outline:before{content:"󱨪"}.mdi-bell-minus:before{content:"󱏩"}.mdi-bell-minus-outline:before{content:"󱏪"}.mdi-bell-off:before{content:"󰂛"}.mdi-bell-off-outline:before{content:"󰪑"}.mdi-bell-outline:before{content:"󰂜"}.mdi-bell-plus:before{content:"󰂝"}.mdi-bell-plus-outline:before{content:"󰪒"}.mdi-bell-remove:before{content:"󱏫"}.mdi-bell-remove-outline:before{content:"󱏬"}.mdi-bell-ring:before{content:"󰂞"}.mdi-bell-ring-outline:before{content:"󰂟"}.mdi-bell-sleep:before{content:"󰂠"}.mdi-bell-sleep-outline:before{content:"󰪓"}.mdi-bench:before{content:"󱰡"}.mdi-bench-back:before{content:"󱰢"}.mdi-beta:before{content:"󰂡"}.mdi-betamax:before{content:"󰧋"}.mdi-biathlon:before{content:"󰸔"}.mdi-bicycle:before{content:"󱂜"}.mdi-bicycle-basket:before{content:"󱈵"}.mdi-bicycle-cargo:before{content:"󱢜"}.mdi-bicycle-electric:before{content:"󱖴"}.mdi-bicycle-penny-farthing:before{content:"󱗩"}.mdi-bike:before{content:"󰂣"}.mdi-bike-fast:before{content:"󱄟"}.mdi-bike-pedal:before{content:"󱰣"}.mdi-bike-pedal-clipless:before{content:"󱰤"}.mdi-bike-pedal-mountain:before{content:"󱰥"}.mdi-billboard:before{content:"󱀐"}.mdi-billiards:before{content:"󰭡"}.mdi-billiards-rack:before{content:"󰭢"}.mdi-binoculars:before{content:"󰂥"}.mdi-bio:before{content:"󰂦"}.mdi-biohazard:before{content:"󰂧"}.mdi-bird:before{content:"󱗆"}.mdi-bitbucket:before{content:"󰂨"}.mdi-bitcoin:before{content:"󰠓"}.mdi-black-mesa:before{content:"󰂩"}.mdi-blender:before{content:"󰳫"}.mdi-blender-outline:before{content:"󱠚"}.mdi-blender-software:before{content:"󰂫"}.mdi-blinds:before{content:"󰂬"}.mdi-blinds-horizontal:before{content:"󱨫"}.mdi-blinds-horizontal-closed:before{content:"󱨬"}.mdi-blinds-open:before{content:"󱀑"}.mdi-blinds-vertical:before{content:"󱨭"}.mdi-blinds-vertical-closed:before{content:"󱨮"}.mdi-block-helper:before{content:"󰂭"}.mdi-blood-bag:before{content:"󰳬"}.mdi-bluetooth:before{content:"󰂯"}.mdi-bluetooth-audio:before{content:"󰂰"}.mdi-bluetooth-connect:before{content:"󰂱"}.mdi-bluetooth-off:before{content:"󰂲"}.mdi-bluetooth-settings:before{content:"󰂳"}.mdi-bluetooth-transfer:before{content:"󰂴"}.mdi-blur:before{content:"󰂵"}.mdi-blur-linear:before{content:"󰂶"}.mdi-blur-off:before{content:"󰂷"}.mdi-blur-radial:before{content:"󰂸"}.mdi-bolt:before{content:"󰶳"}.mdi-bomb:before{content:"󰚑"}.mdi-bomb-off:before{content:"󰛅"}.mdi-bone:before{content:"󰂹"}.mdi-bone-off:before{content:"󱧠"}.mdi-book:before{content:"󰂺"}.mdi-book-account:before{content:"󱎭"}.mdi-book-account-outline:before{content:"󱎮"}.mdi-book-alert:before{content:"󱙼"}.mdi-book-alert-outline:before{content:"󱙽"}.mdi-book-alphabet:before{content:"󰘝"}.mdi-book-arrow-down:before{content:"󱙾"}.mdi-book-arrow-down-outline:before{content:"󱙿"}.mdi-book-arrow-left:before{content:"󱚀"}.mdi-book-arrow-left-outline:before{content:"󱚁"}.mdi-book-arrow-right:before{content:"󱚂"}.mdi-book-arrow-right-outline:before{content:"󱚃"}.mdi-book-arrow-up:before{content:"󱚄"}.mdi-book-arrow-up-outline:before{content:"󱚅"}.mdi-book-cancel:before{content:"󱚆"}.mdi-book-cancel-outline:before{content:"󱚇"}.mdi-book-check:before{content:"󱓳"}.mdi-book-check-outline:before{content:"󱓴"}.mdi-book-clock:before{content:"󱚈"}.mdi-book-clock-outline:before{content:"󱚉"}.mdi-book-cog:before{content:"󱚊"}.mdi-book-cog-outline:before{content:"󱚋"}.mdi-book-cross:before{content:"󰂢"}.mdi-book-edit:before{content:"󱚌"}.mdi-book-edit-outline:before{content:"󱚍"}.mdi-book-education:before{content:"󱛉"}.mdi-book-education-outline:before{content:"󱛊"}.mdi-book-heart:before{content:"󱨝"}.mdi-book-heart-outline:before{content:"󱨞"}.mdi-book-information-variant:before{content:"󱁯"}.mdi-book-lock:before{content:"󰞚"}.mdi-book-lock-open:before{content:"󰞛"}.mdi-book-lock-open-outline:before{content:"󱚎"}.mdi-book-lock-outline:before{content:"󱚏"}.mdi-book-marker:before{content:"󱚐"}.mdi-book-marker-outline:before{content:"󱚑"}.mdi-book-minus:before{content:"󰗙"}.mdi-book-minus-multiple:before{content:"󰪔"}.mdi-book-minus-multiple-outline:before{content:"󰤋"}.mdi-book-minus-outline:before{content:"󱚒"}.mdi-book-multiple:before{content:"󰂻"}.mdi-book-multiple-outline:before{content:"󰐶"}.mdi-book-music:before{content:"󰁧"}.mdi-book-music-outline:before{content:"󱚓"}.mdi-book-off:before{content:"󱚔"}.mdi-book-off-outline:before{content:"󱚕"}.mdi-book-open:before{content:"󰂽"}.mdi-book-open-blank-variant:before{content:"󰂾"}.mdi-book-open-outline:before{content:"󰭣"}.mdi-book-open-page-variant:before{content:"󰗚"}.mdi-book-open-page-variant-outline:before{content:"󱗖"}.mdi-book-open-variant:before{content:"󱓷"}.mdi-book-outline:before{content:"󰭤"}.mdi-book-play:before{content:"󰺂"}.mdi-book-play-outline:before{content:"󰺃"}.mdi-book-plus:before{content:"󰗛"}.mdi-book-plus-multiple:before{content:"󰪕"}.mdi-book-plus-multiple-outline:before{content:"󰫞"}.mdi-book-plus-outline:before{content:"󱚖"}.mdi-book-refresh:before{content:"󱚗"}.mdi-book-refresh-outline:before{content:"󱚘"}.mdi-book-remove:before{content:"󰪗"}.mdi-book-remove-multiple:before{content:"󰪖"}.mdi-book-remove-multiple-outline:before{content:"󰓊"}.mdi-book-remove-outline:before{content:"󱚙"}.mdi-book-search:before{content:"󰺄"}.mdi-book-search-outline:before{content:"󰺅"}.mdi-book-settings:before{content:"󱚚"}.mdi-book-settings-outline:before{content:"󱚛"}.mdi-book-sync:before{content:"󱚜"}.mdi-book-sync-outline:before{content:"󱛈"}.mdi-book-variant:before{content:"󰂿"}.mdi-bookmark:before{content:"󰃀"}.mdi-bookmark-box:before{content:"󱭵"}.mdi-bookmark-box-multiple:before{content:"󱥬"}.mdi-bookmark-box-multiple-outline:before{content:"󱥭"}.mdi-bookmark-box-outline:before{content:"󱭶"}.mdi-bookmark-check:before{content:"󰃁"}.mdi-bookmark-check-outline:before{content:"󱍻"}.mdi-bookmark-minus:before{content:"󰧌"}.mdi-bookmark-minus-outline:before{content:"󰧍"}.mdi-bookmark-multiple:before{content:"󰸕"}.mdi-bookmark-multiple-outline:before{content:"󰸖"}.mdi-bookmark-music:before{content:"󰃂"}.mdi-bookmark-music-outline:before{content:"󱍹"}.mdi-bookmark-off:before{content:"󰧎"}.mdi-bookmark-off-outline:before{content:"󰧏"}.mdi-bookmark-outline:before{content:"󰃃"}.mdi-bookmark-plus:before{content:"󰃅"}.mdi-bookmark-plus-outline:before{content:"󰃄"}.mdi-bookmark-remove:before{content:"󰃆"}.mdi-bookmark-remove-outline:before{content:"󱍺"}.mdi-bookshelf:before{content:"󱉟"}.mdi-boom-gate:before{content:"󰺆"}.mdi-boom-gate-alert:before{content:"󰺇"}.mdi-boom-gate-alert-outline:before{content:"󰺈"}.mdi-boom-gate-arrow-down:before{content:"󰺉"}.mdi-boom-gate-arrow-down-outline:before{content:"󰺊"}.mdi-boom-gate-arrow-up:before{content:"󰺌"}.mdi-boom-gate-arrow-up-outline:before{content:"󰺍"}.mdi-boom-gate-outline:before{content:"󰺋"}.mdi-boom-gate-up:before{content:"󱟹"}.mdi-boom-gate-up-outline:before{content:"󱟺"}.mdi-boombox:before{content:"󰗜"}.mdi-boomerang:before{content:"󱃏"}.mdi-bootstrap:before{content:"󰛆"}.mdi-border-all:before{content:"󰃇"}.mdi-border-all-variant:before{content:"󰢡"}.mdi-border-bottom:before{content:"󰃈"}.mdi-border-bottom-variant:before{content:"󰢢"}.mdi-border-color:before{content:"󰃉"}.mdi-border-horizontal:before{content:"󰃊"}.mdi-border-inside:before{content:"󰃋"}.mdi-border-left:before{content:"󰃌"}.mdi-border-left-variant:before{content:"󰢣"}.mdi-border-none:before{content:"󰃍"}.mdi-border-none-variant:before{content:"󰢤"}.mdi-border-outside:before{content:"󰃎"}.mdi-border-radius:before{content:"󱫴"}.mdi-border-right:before{content:"󰃏"}.mdi-border-right-variant:before{content:"󰢥"}.mdi-border-style:before{content:"󰃐"}.mdi-border-top:before{content:"󰃑"}.mdi-border-top-variant:before{content:"󰢦"}.mdi-border-vertical:before{content:"󰃒"}.mdi-bottle-soda:before{content:"󱁰"}.mdi-bottle-soda-classic:before{content:"󱁱"}.mdi-bottle-soda-classic-outline:before{content:"󱍣"}.mdi-bottle-soda-outline:before{content:"󱁲"}.mdi-bottle-tonic:before{content:"󱄮"}.mdi-bottle-tonic-outline:before{content:"󱄯"}.mdi-bottle-tonic-plus:before{content:"󱄰"}.mdi-bottle-tonic-plus-outline:before{content:"󱄱"}.mdi-bottle-tonic-skull:before{content:"󱄲"}.mdi-bottle-tonic-skull-outline:before{content:"󱄳"}.mdi-bottle-wine:before{content:"󰡔"}.mdi-bottle-wine-outline:before{content:"󱌐"}.mdi-bow-arrow:before{content:"󱡁"}.mdi-bow-tie:before{content:"󰙸"}.mdi-bowl:before{content:"󰊎"}.mdi-bowl-mix:before{content:"󰘗"}.mdi-bowl-mix-outline:before{content:"󰋤"}.mdi-bowl-outline:before{content:"󰊩"}.mdi-bowling:before{content:"󰃓"}.mdi-box:before{content:"󰃔"}.mdi-box-cutter:before{content:"󰃕"}.mdi-box-cutter-off:before{content:"󰭊"}.mdi-box-shadow:before{content:"󰘷"}.mdi-boxing-glove:before{content:"󰭥"}.mdi-braille:before{content:"󰧐"}.mdi-brain:before{content:"󰧑"}.mdi-bread-slice:before{content:"󰳮"}.mdi-bread-slice-outline:before{content:"󰳯"}.mdi-bridge:before{content:"󰘘"}.mdi-briefcase:before{content:"󰃖"}.mdi-briefcase-account:before{content:"󰳰"}.mdi-briefcase-account-outline:before{content:"󰳱"}.mdi-briefcase-arrow-left-right:before{content:"󱪍"}.mdi-briefcase-arrow-left-right-outline:before{content:"󱪎"}.mdi-briefcase-arrow-up-down:before{content:"󱪏"}.mdi-briefcase-arrow-up-down-outline:before{content:"󱪐"}.mdi-briefcase-check:before{content:"󰃗"}.mdi-briefcase-check-outline:before{content:"󱌞"}.mdi-briefcase-clock:before{content:"󱃐"}.mdi-briefcase-clock-outline:before{content:"󱃑"}.mdi-briefcase-download:before{content:"󰃘"}.mdi-briefcase-download-outline:before{content:"󰰽"}.mdi-briefcase-edit:before{content:"󰪘"}.mdi-briefcase-edit-outline:before{content:"󰰾"}.mdi-briefcase-eye:before{content:"󱟙"}.mdi-briefcase-eye-outline:before{content:"󱟚"}.mdi-briefcase-minus:before{content:"󰨪"}.mdi-briefcase-minus-outline:before{content:"󰰿"}.mdi-briefcase-off:before{content:"󱙘"}.mdi-briefcase-off-outline:before{content:"󱙙"}.mdi-briefcase-outline:before{content:"󰠔"}.mdi-briefcase-plus:before{content:"󰨫"}.mdi-briefcase-plus-outline:before{content:"󰱀"}.mdi-briefcase-remove:before{content:"󰨬"}.mdi-briefcase-remove-outline:before{content:"󰱁"}.mdi-briefcase-search:before{content:"󰨭"}.mdi-briefcase-search-outline:before{content:"󰱂"}.mdi-briefcase-upload:before{content:"󰃙"}.mdi-briefcase-upload-outline:before{content:"󰱃"}.mdi-briefcase-variant:before{content:"󱒔"}.mdi-briefcase-variant-off:before{content:"󱙚"}.mdi-briefcase-variant-off-outline:before{content:"󱙛"}.mdi-briefcase-variant-outline:before{content:"󱒕"}.mdi-brightness-1:before{content:"󰃚"}.mdi-brightness-2:before{content:"󰃛"}.mdi-brightness-3:before{content:"󰃜"}.mdi-brightness-4:before{content:"󰃝"}.mdi-brightness-5:before{content:"󰃞"}.mdi-brightness-6:before{content:"󰃟"}.mdi-brightness-7:before{content:"󰃠"}.mdi-brightness-auto:before{content:"󰃡"}.mdi-brightness-percent:before{content:"󰳲"}.mdi-broadcast:before{content:"󱜠"}.mdi-broadcast-off:before{content:"󱜡"}.mdi-broom:before{content:"󰃢"}.mdi-brush:before{content:"󰃣"}.mdi-brush-off:before{content:"󱝱"}.mdi-brush-outline:before{content:"󱨍"}.mdi-brush-variant:before{content:"󱠓"}.mdi-bucket:before{content:"󱐕"}.mdi-bucket-outline:before{content:"󱐖"}.mdi-buffet:before{content:"󰕸"}.mdi-bug:before{content:"󰃤"}.mdi-bug-check:before{content:"󰨮"}.mdi-bug-check-outline:before{content:"󰨯"}.mdi-bug-outline:before{content:"󰨰"}.mdi-bug-pause:before{content:"󱫵"}.mdi-bug-pause-outline:before{content:"󱫶"}.mdi-bug-play:before{content:"󱫷"}.mdi-bug-play-outline:before{content:"󱫸"}.mdi-bug-stop:before{content:"󱫹"}.mdi-bug-stop-outline:before{content:"󱫺"}.mdi-bugle:before{content:"󰶴"}.mdi-bulkhead-light:before{content:"󱨯"}.mdi-bulldozer:before{content:"󰬢"}.mdi-bullet:before{content:"󰳳"}.mdi-bulletin-board:before{content:"󰃥"}.mdi-bullhorn:before{content:"󰃦"}.mdi-bullhorn-outline:before{content:"󰬣"}.mdi-bullhorn-variant:before{content:"󱥮"}.mdi-bullhorn-variant-outline:before{content:"󱥯"}.mdi-bullseye:before{content:"󰗝"}.mdi-bullseye-arrow:before{content:"󰣉"}.mdi-bulma:before{content:"󱋧"}.mdi-bunk-bed:before{content:"󱌂"}.mdi-bunk-bed-outline:before{content:"󰂗"}.mdi-bus:before{content:"󰃧"}.mdi-bus-alert:before{content:"󰪙"}.mdi-bus-articulated-end:before{content:"󰞜"}.mdi-bus-articulated-front:before{content:"󰞝"}.mdi-bus-clock:before{content:"󰣊"}.mdi-bus-double-decker:before{content:"󰞞"}.mdi-bus-electric:before{content:"󱤝"}.mdi-bus-marker:before{content:"󱈒"}.mdi-bus-multiple:before{content:"󰼿"}.mdi-bus-school:before{content:"󰞟"}.mdi-bus-side:before{content:"󰞠"}.mdi-bus-stop:before{content:"󱀒"}.mdi-bus-stop-covered:before{content:"󱀓"}.mdi-bus-stop-uncovered:before{content:"󱀔"}.mdi-butterfly:before{content:"󱖉"}.mdi-butterfly-outline:before{content:"󱖊"}.mdi-button-cursor:before{content:"󱭏"}.mdi-button-pointer:before{content:"󱭐"}.mdi-cabin-a-frame:before{content:"󱢌"}.mdi-cable-data:before{content:"󱎔"}.mdi-cached:before{content:"󰃨"}.mdi-cactus:before{content:"󰶵"}.mdi-cake:before{content:"󰃩"}.mdi-cake-layered:before{content:"󰃪"}.mdi-cake-variant:before{content:"󰃫"}.mdi-cake-variant-outline:before{content:"󱟰"}.mdi-calculator:before{content:"󰃬"}.mdi-calculator-variant:before{content:"󰪚"}.mdi-calculator-variant-outline:before{content:"󱖦"}.mdi-calendar:before{content:"󰃭"}.mdi-calendar-account:before{content:"󰻗"}.mdi-calendar-account-outline:before{content:"󰻘"}.mdi-calendar-alert:before{content:"󰨱"}.mdi-calendar-alert-outline:before{content:"󱭢"}.mdi-calendar-arrow-left:before{content:"󱄴"}.mdi-calendar-arrow-right:before{content:"󱄵"}.mdi-calendar-badge:before{content:"󱮝"}.mdi-calendar-badge-outline:before{content:"󱮞"}.mdi-calendar-blank:before{content:"󰃮"}.mdi-calendar-blank-multiple:before{content:"󱁳"}.mdi-calendar-blank-outline:before{content:"󰭦"}.mdi-calendar-check:before{content:"󰃯"}.mdi-calendar-check-outline:before{content:"󰱄"}.mdi-calendar-clock:before{content:"󰃰"}.mdi-calendar-clock-outline:before{content:"󱛡"}.mdi-calendar-collapse-horizontal:before{content:"󱢝"}.mdi-calendar-collapse-horizontal-outline:before{content:"󱭣"}.mdi-calendar-cursor:before{content:"󱕻"}.mdi-calendar-cursor-outline:before{content:"󱭤"}.mdi-calendar-edit:before{content:"󰢧"}.mdi-calendar-edit-outline:before{content:"󱭥"}.mdi-calendar-end:before{content:"󱙬"}.mdi-calendar-end-outline:before{content:"󱭦"}.mdi-calendar-expand-horizontal:before{content:"󱢞"}.mdi-calendar-expand-horizontal-outline:before{content:"󱭧"}.mdi-calendar-export:before{content:"󰬤"}.mdi-calendar-export-outline:before{content:"󱭨"}.mdi-calendar-filter:before{content:"󱨲"}.mdi-calendar-filter-outline:before{content:"󱨳"}.mdi-calendar-heart:before{content:"󰧒"}.mdi-calendar-heart-outline:before{content:"󱭩"}.mdi-calendar-import:before{content:"󰬥"}.mdi-calendar-import-outline:before{content:"󱭪"}.mdi-calendar-lock:before{content:"󱙁"}.mdi-calendar-lock-open:before{content:"󱭛"}.mdi-calendar-lock-open-outline:before{content:"󱭜"}.mdi-calendar-lock-outline:before{content:"󱙂"}.mdi-calendar-minus:before{content:"󰵜"}.mdi-calendar-minus-outline:before{content:"󱭫"}.mdi-calendar-month:before{content:"󰸗"}.mdi-calendar-month-outline:before{content:"󰸘"}.mdi-calendar-multiple:before{content:"󰃱"}.mdi-calendar-multiple-check:before{content:"󰃲"}.mdi-calendar-multiselect:before{content:"󰨲"}.mdi-calendar-multiselect-outline:before{content:"󱭕"}.mdi-calendar-outline:before{content:"󰭧"}.mdi-calendar-plus:before{content:"󰃳"}.mdi-calendar-plus-outline:before{content:"󱭬"}.mdi-calendar-question:before{content:"󰚒"}.mdi-calendar-question-outline:before{content:"󱭭"}.mdi-calendar-range:before{content:"󰙹"}.mdi-calendar-range-outline:before{content:"󰭨"}.mdi-calendar-refresh:before{content:"󰇡"}.mdi-calendar-refresh-outline:before{content:"󰈃"}.mdi-calendar-remove:before{content:"󰃴"}.mdi-calendar-remove-outline:before{content:"󰱅"}.mdi-calendar-search:before{content:"󰥌"}.mdi-calendar-search-outline:before{content:"󱭮"}.mdi-calendar-star:before{content:"󰧓"}.mdi-calendar-star-four-points:before{content:"󱰟"}.mdi-calendar-star-outline:before{content:"󱭓"}.mdi-calendar-start:before{content:"󱙭"}.mdi-calendar-start-outline:before{content:"󱭯"}.mdi-calendar-sync:before{content:"󰺎"}.mdi-calendar-sync-outline:before{content:"󰺏"}.mdi-calendar-text:before{content:"󰃵"}.mdi-calendar-text-outline:before{content:"󰱆"}.mdi-calendar-today:before{content:"󰃶"}.mdi-calendar-today-outline:before{content:"󱨰"}.mdi-calendar-week:before{content:"󰨳"}.mdi-calendar-week-begin:before{content:"󰨴"}.mdi-calendar-week-begin-outline:before{content:"󱨱"}.mdi-calendar-week-outline:before{content:"󱨴"}.mdi-calendar-weekend:before{content:"󰻙"}.mdi-calendar-weekend-outline:before{content:"󰻚"}.mdi-call-made:before{content:"󰃷"}.mdi-call-merge:before{content:"󰃸"}.mdi-call-missed:before{content:"󰃹"}.mdi-call-received:before{content:"󰃺"}.mdi-call-split:before{content:"󰃻"}.mdi-camcorder:before{content:"󰃼"}.mdi-camcorder-off:before{content:"󰃿"}.mdi-camera:before{content:"󰄀"}.mdi-camera-account:before{content:"󰣋"}.mdi-camera-burst:before{content:"󰚓"}.mdi-camera-control:before{content:"󰭩"}.mdi-camera-document:before{content:"󱡱"}.mdi-camera-document-off:before{content:"󱡲"}.mdi-camera-enhance:before{content:"󰄁"}.mdi-camera-enhance-outline:before{content:"󰭪"}.mdi-camera-flip:before{content:"󱗙"}.mdi-camera-flip-outline:before{content:"󱗚"}.mdi-camera-front:before{content:"󰄂"}.mdi-camera-front-variant:before{content:"󰄃"}.mdi-camera-gopro:before{content:"󰞡"}.mdi-camera-image:before{content:"󰣌"}.mdi-camera-iris:before{content:"󰄄"}.mdi-camera-lock:before{content:"󱨔"}.mdi-camera-lock-open:before{content:"󱰍"}.mdi-camera-lock-open-outline:before{content:"󱰎"}.mdi-camera-lock-outline:before{content:"󱨕"}.mdi-camera-marker:before{content:"󱦧"}.mdi-camera-marker-outline:before{content:"󱦨"}.mdi-camera-metering-center:before{content:"󰞢"}.mdi-camera-metering-matrix:before{content:"󰞣"}.mdi-camera-metering-partial:before{content:"󰞤"}.mdi-camera-metering-spot:before{content:"󰞥"}.mdi-camera-off:before{content:"󰗟"}.mdi-camera-off-outline:before{content:"󱦿"}.mdi-camera-outline:before{content:"󰵝"}.mdi-camera-party-mode:before{content:"󰄅"}.mdi-camera-plus:before{content:"󰻛"}.mdi-camera-plus-outline:before{content:"󰻜"}.mdi-camera-rear:before{content:"󰄆"}.mdi-camera-rear-variant:before{content:"󰄇"}.mdi-camera-retake:before{content:"󰸙"}.mdi-camera-retake-outline:before{content:"󰸚"}.mdi-camera-switch:before{content:"󰄈"}.mdi-camera-switch-outline:before{content:"󰡊"}.mdi-camera-timer:before{content:"󰄉"}.mdi-camera-wireless:before{content:"󰶶"}.mdi-camera-wireless-outline:before{content:"󰶷"}.mdi-campfire:before{content:"󰻝"}.mdi-cancel:before{content:"󰜺"}.mdi-candelabra:before{content:"󱟒"}.mdi-candelabra-fire:before{content:"󱟓"}.mdi-candle:before{content:"󰗢"}.mdi-candy:before{content:"󱥰"}.mdi-candy-off:before{content:"󱥱"}.mdi-candy-off-outline:before{content:"󱥲"}.mdi-candy-outline:before{content:"󱥳"}.mdi-candycane:before{content:"󰄊"}.mdi-cannabis:before{content:"󰞦"}.mdi-cannabis-off:before{content:"󱙮"}.mdi-caps-lock:before{content:"󰪛"}.mdi-car:before{content:"󰄋"}.mdi-car-2-plus:before{content:"󱀕"}.mdi-car-3-plus:before{content:"󱀖"}.mdi-car-arrow-left:before{content:"󱎲"}.mdi-car-arrow-right:before{content:"󱎳"}.mdi-car-back:before{content:"󰸛"}.mdi-car-battery:before{content:"󰄌"}.mdi-car-brake-abs:before{content:"󰱇"}.mdi-car-brake-alert:before{content:"󰱈"}.mdi-car-brake-fluid-level:before{content:"󱤉"}.mdi-car-brake-hold:before{content:"󰵞"}.mdi-car-brake-low-pressure:before{content:"󱤊"}.mdi-car-brake-parking:before{content:"󰵟"}.mdi-car-brake-retarder:before{content:"󱀗"}.mdi-car-brake-temperature:before{content:"󱤋"}.mdi-car-brake-worn-linings:before{content:"󱤌"}.mdi-car-child-seat:before{content:"󰾣"}.mdi-car-clock:before{content:"󱥴"}.mdi-car-clutch:before{content:"󱀘"}.mdi-car-cog:before{content:"󱏌"}.mdi-car-connected:before{content:"󰄍"}.mdi-car-convertible:before{content:"󰞧"}.mdi-car-coolant-level:before{content:"󱀙"}.mdi-car-cruise-control:before{content:"󰵠"}.mdi-car-defrost-front:before{content:"󰵡"}.mdi-car-defrost-rear:before{content:"󰵢"}.mdi-car-door:before{content:"󰭫"}.mdi-car-door-lock:before{content:"󱂝"}.mdi-car-electric:before{content:"󰭬"}.mdi-car-electric-outline:before{content:"󱖵"}.mdi-car-emergency:before{content:"󱘏"}.mdi-car-esp:before{content:"󰱉"}.mdi-car-estate:before{content:"󰞨"}.mdi-car-hatchback:before{content:"󰞩"}.mdi-car-info:before{content:"󱆾"}.mdi-car-key:before{content:"󰭭"}.mdi-car-lifted-pickup:before{content:"󱔭"}.mdi-car-light-alert:before{content:"󱤍"}.mdi-car-light-dimmed:before{content:"󰱊"}.mdi-car-light-fog:before{content:"󰱋"}.mdi-car-light-high:before{content:"󰱌"}.mdi-car-limousine:before{content:"󰣍"}.mdi-car-multiple:before{content:"󰭮"}.mdi-car-off:before{content:"󰸜"}.mdi-car-outline:before{content:"󱓭"}.mdi-car-parking-lights:before{content:"󰵣"}.mdi-car-pickup:before{content:"󰞪"}.mdi-car-search:before{content:"󱮍"}.mdi-car-search-outline:before{content:"󱮎"}.mdi-car-seat:before{content:"󰾤"}.mdi-car-seat-cooler:before{content:"󰾥"}.mdi-car-seat-heater:before{content:"󰾦"}.mdi-car-select:before{content:"󱡹"}.mdi-car-settings:before{content:"󱏍"}.mdi-car-shift-pattern:before{content:"󰽀"}.mdi-car-side:before{content:"󰞫"}.mdi-car-speed-limiter:before{content:"󱤎"}.mdi-car-sports:before{content:"󰞬"}.mdi-car-tire-alert:before{content:"󰱍"}.mdi-car-traction-control:before{content:"󰵤"}.mdi-car-turbocharger:before{content:"󱀚"}.mdi-car-wash:before{content:"󰄎"}.mdi-car-windshield:before{content:"󱀛"}.mdi-car-windshield-outline:before{content:"󱀜"}.mdi-car-wireless:before{content:"󱡸"}.mdi-car-wrench:before{content:"󱠔"}.mdi-carabiner:before{content:"󱓀"}.mdi-caravan:before{content:"󰞭"}.mdi-card:before{content:"󰭯"}.mdi-card-account-details:before{content:"󰗒"}.mdi-card-account-details-outline:before{content:"󰶫"}.mdi-card-account-details-star:before{content:"󰊣"}.mdi-card-account-details-star-outline:before{content:"󰛛"}.mdi-card-account-mail:before{content:"󰆎"}.mdi-card-account-mail-outline:before{content:"󰺘"}.mdi-card-account-phone:before{content:"󰺙"}.mdi-card-account-phone-outline:before{content:"󰺚"}.mdi-card-bulleted:before{content:"󰭰"}.mdi-card-bulleted-off:before{content:"󰭱"}.mdi-card-bulleted-off-outline:before{content:"󰭲"}.mdi-card-bulleted-outline:before{content:"󰭳"}.mdi-card-bulleted-settings:before{content:"󰭴"}.mdi-card-bulleted-settings-outline:before{content:"󰭵"}.mdi-card-minus:before{content:"󱘀"}.mdi-card-minus-outline:before{content:"󱘁"}.mdi-card-multiple:before{content:"󱟱"}.mdi-card-multiple-outline:before{content:"󱟲"}.mdi-card-off:before{content:"󱘂"}.mdi-card-off-outline:before{content:"󱘃"}.mdi-card-outline:before{content:"󰭶"}.mdi-card-plus:before{content:"󱇿"}.mdi-card-plus-outline:before{content:"󱈀"}.mdi-card-remove:before{content:"󱘄"}.mdi-card-remove-outline:before{content:"󱘅"}.mdi-card-search:before{content:"󱁴"}.mdi-card-search-outline:before{content:"󱁵"}.mdi-card-text:before{content:"󰭷"}.mdi-card-text-outline:before{content:"󰭸"}.mdi-cards:before{content:"󰘸"}.mdi-cards-club:before{content:"󰣎"}.mdi-cards-club-outline:before{content:"󱢟"}.mdi-cards-diamond:before{content:"󰣏"}.mdi-cards-diamond-outline:before{content:"󱀝"}.mdi-cards-heart:before{content:"󰣐"}.mdi-cards-heart-outline:before{content:"󱢠"}.mdi-cards-outline:before{content:"󰘹"}.mdi-cards-playing:before{content:"󱢡"}.mdi-cards-playing-club:before{content:"󱢢"}.mdi-cards-playing-club-multiple:before{content:"󱢣"}.mdi-cards-playing-club-multiple-outline:before{content:"󱢤"}.mdi-cards-playing-club-outline:before{content:"󱢥"}.mdi-cards-playing-diamond:before{content:"󱢦"}.mdi-cards-playing-diamond-multiple:before{content:"󱢧"}.mdi-cards-playing-diamond-multiple-outline:before{content:"󱢨"}.mdi-cards-playing-diamond-outline:before{content:"󱢩"}.mdi-cards-playing-heart:before{content:"󱢪"}.mdi-cards-playing-heart-multiple:before{content:"󱢫"}.mdi-cards-playing-heart-multiple-outline:before{content:"󱢬"}.mdi-cards-playing-heart-outline:before{content:"󱢭"}.mdi-cards-playing-outline:before{content:"󰘺"}.mdi-cards-playing-spade:before{content:"󱢮"}.mdi-cards-playing-spade-multiple:before{content:"󱢯"}.mdi-cards-playing-spade-multiple-outline:before{content:"󱢰"}.mdi-cards-playing-spade-outline:before{content:"󱢱"}.mdi-cards-spade:before{content:"󰣑"}.mdi-cards-spade-outline:before{content:"󱢲"}.mdi-cards-variant:before{content:"󰛇"}.mdi-carrot:before{content:"󰄏"}.mdi-cart:before{content:"󰄐"}.mdi-cart-arrow-down:before{content:"󰵦"}.mdi-cart-arrow-right:before{content:"󰱎"}.mdi-cart-arrow-up:before{content:"󰵧"}.mdi-cart-check:before{content:"󱗪"}.mdi-cart-heart:before{content:"󱣠"}.mdi-cart-minus:before{content:"󰵨"}.mdi-cart-off:before{content:"󰙫"}.mdi-cart-outline:before{content:"󰄑"}.mdi-cart-percent:before{content:"󱮮"}.mdi-cart-plus:before{content:"󰄒"}.mdi-cart-remove:before{content:"󰵩"}.mdi-cart-variant:before{content:"󱗫"}.mdi-case-sensitive-alt:before{content:"󰄓"}.mdi-cash:before{content:"󰄔"}.mdi-cash-100:before{content:"󰄕"}.mdi-cash-check:before{content:"󱓮"}.mdi-cash-clock:before{content:"󱪑"}.mdi-cash-fast:before{content:"󱡜"}.mdi-cash-lock:before{content:"󱓪"}.mdi-cash-lock-open:before{content:"󱓫"}.mdi-cash-marker:before{content:"󰶸"}.mdi-cash-minus:before{content:"󱉠"}.mdi-cash-multiple:before{content:"󰄖"}.mdi-cash-off:before{content:"󱱹"}.mdi-cash-plus:before{content:"󱉡"}.mdi-cash-refund:before{content:"󰪜"}.mdi-cash-register:before{content:"󰳴"}.mdi-cash-remove:before{content:"󱉢"}.mdi-cash-sync:before{content:"󱪒"}.mdi-cassette:before{content:"󰧔"}.mdi-cast:before{content:"󰄘"}.mdi-cast-audio:before{content:"󱀞"}.mdi-cast-audio-variant:before{content:"󱝉"}.mdi-cast-connected:before{content:"󰄙"}.mdi-cast-education:before{content:"󰸝"}.mdi-cast-off:before{content:"󰞊"}.mdi-cast-variant:before{content:"󰀟"}.mdi-castle:before{content:"󰄚"}.mdi-cat:before{content:"󰄛"}.mdi-cctv:before{content:"󰞮"}.mdi-cctv-off:before{content:"󱡟"}.mdi-ceiling-fan:before{content:"󱞗"}.mdi-ceiling-fan-light:before{content:"󱞘"}.mdi-ceiling-light:before{content:"󰝩"}.mdi-ceiling-light-multiple:before{content:"󱣝"}.mdi-ceiling-light-multiple-outline:before{content:"󱣞"}.mdi-ceiling-light-outline:before{content:"󱟇"}.mdi-cellphone:before{content:"󰄜"}.mdi-cellphone-arrow-down:before{content:"󰧕"}.mdi-cellphone-arrow-down-variant:before{content:"󱧅"}.mdi-cellphone-basic:before{content:"󰄞"}.mdi-cellphone-charging:before{content:"󱎗"}.mdi-cellphone-check:before{content:"󱟽"}.mdi-cellphone-cog:before{content:"󰥑"}.mdi-cellphone-dock:before{content:"󰄟"}.mdi-cellphone-information:before{content:"󰽁"}.mdi-cellphone-key:before{content:"󰥎"}.mdi-cellphone-link:before{content:"󰄡"}.mdi-cellphone-link-off:before{content:"󰄢"}.mdi-cellphone-lock:before{content:"󰥏"}.mdi-cellphone-marker:before{content:"󱠺"}.mdi-cellphone-message:before{content:"󰣓"}.mdi-cellphone-message-off:before{content:"󱃒"}.mdi-cellphone-nfc:before{content:"󰺐"}.mdi-cellphone-nfc-off:before{content:"󱋘"}.mdi-cellphone-off:before{content:"󰥐"}.mdi-cellphone-play:before{content:"󱀟"}.mdi-cellphone-remove:before{content:"󰥍"}.mdi-cellphone-screenshot:before{content:"󰨵"}.mdi-cellphone-settings:before{content:"󰄣"}.mdi-cellphone-sound:before{content:"󰥒"}.mdi-cellphone-text:before{content:"󰣒"}.mdi-cellphone-wireless:before{content:"󰠕"}.mdi-centos:before{content:"󱄚"}.mdi-certificate:before{content:"󰄤"}.mdi-certificate-outline:before{content:"󱆈"}.mdi-chair-rolling:before{content:"󰽈"}.mdi-chair-school:before{content:"󰄥"}.mdi-chandelier:before{content:"󱞓"}.mdi-charity:before{content:"󰱏"}.mdi-chart-arc:before{content:"󰄦"}.mdi-chart-areaspline:before{content:"󰄧"}.mdi-chart-areaspline-variant:before{content:"󰺑"}.mdi-chart-bar:before{content:"󰄨"}.mdi-chart-bar-stacked:before{content:"󰝪"}.mdi-chart-bell-curve:before{content:"󰱐"}.mdi-chart-bell-curve-cumulative:before{content:"󰾧"}.mdi-chart-box:before{content:"󱕍"}.mdi-chart-box-outline:before{content:"󱕎"}.mdi-chart-box-plus-outline:before{content:"󱕏"}.mdi-chart-bubble:before{content:"󰗣"}.mdi-chart-donut:before{content:"󰞯"}.mdi-chart-donut-variant:before{content:"󰞰"}.mdi-chart-gantt:before{content:"󰙬"}.mdi-chart-histogram:before{content:"󰄩"}.mdi-chart-line:before{content:"󰄪"}.mdi-chart-line-stacked:before{content:"󰝫"}.mdi-chart-line-variant:before{content:"󰞱"}.mdi-chart-multiline:before{content:"󰣔"}.mdi-chart-multiple:before{content:"󱈓"}.mdi-chart-pie:before{content:"󰄫"}.mdi-chart-pie-outline:before{content:"󱯟"}.mdi-chart-ppf:before{content:"󱎀"}.mdi-chart-sankey:before{content:"󱇟"}.mdi-chart-sankey-variant:before{content:"󱇠"}.mdi-chart-scatter-plot:before{content:"󰺒"}.mdi-chart-scatter-plot-hexbin:before{content:"󰙭"}.mdi-chart-timeline:before{content:"󰙮"}.mdi-chart-timeline-variant:before{content:"󰺓"}.mdi-chart-timeline-variant-shimmer:before{content:"󱖶"}.mdi-chart-tree:before{content:"󰺔"}.mdi-chart-waterfall:before{content:"󱤘"}.mdi-chat:before{content:"󰭹"}.mdi-chat-alert:before{content:"󰭺"}.mdi-chat-alert-outline:before{content:"󱋉"}.mdi-chat-minus:before{content:"󱐐"}.mdi-chat-minus-outline:before{content:"󱐓"}.mdi-chat-outline:before{content:"󰻞"}.mdi-chat-plus:before{content:"󱐏"}.mdi-chat-plus-outline:before{content:"󱐒"}.mdi-chat-processing:before{content:"󰭻"}.mdi-chat-processing-outline:before{content:"󱋊"}.mdi-chat-question:before{content:"󱜸"}.mdi-chat-question-outline:before{content:"󱜹"}.mdi-chat-remove:before{content:"󱐑"}.mdi-chat-remove-outline:before{content:"󱐔"}.mdi-chat-sleep:before{content:"󱋑"}.mdi-chat-sleep-outline:before{content:"󱋒"}.mdi-check:before{content:"󰄬"}.mdi-check-all:before{content:"󰄭"}.mdi-check-bold:before{content:"󰸞"}.mdi-check-circle:before{content:"󰗠"}.mdi-check-circle-outline:before{content:"󰗡"}.mdi-check-decagram:before{content:"󰞑"}.mdi-check-decagram-outline:before{content:"󱝀"}.mdi-check-network:before{content:"󰱓"}.mdi-check-network-outline:before{content:"󰱔"}.mdi-check-outline:before{content:"󰡕"}.mdi-check-underline:before{content:"󰸟"}.mdi-check-underline-circle:before{content:"󰸠"}.mdi-check-underline-circle-outline:before{content:"󰸡"}.mdi-checkbook:before{content:"󰪝"}.mdi-checkbook-arrow-left:before{content:"󱰝"}.mdi-checkbook-arrow-right:before{content:"󱰞"}.mdi-checkbox-blank:before{content:"󰄮"}.mdi-checkbox-blank-badge:before{content:"󱅶"}.mdi-checkbox-blank-badge-outline:before{content:"󰄗"}.mdi-checkbox-blank-circle:before{content:"󰄯"}.mdi-checkbox-blank-circle-outline:before{content:"󰄰"}.mdi-checkbox-blank-off:before{content:"󱋬"}.mdi-checkbox-blank-off-outline:before{content:"󱋭"}.mdi-checkbox-blank-outline:before{content:"󰄱"}.mdi-checkbox-intermediate:before{content:"󰡖"}.mdi-checkbox-intermediate-variant:before{content:"󱭔"}.mdi-checkbox-marked:before{content:"󰄲"}.mdi-checkbox-marked-circle:before{content:"󰄳"}.mdi-checkbox-marked-circle-auto-outline:before{content:"󱰦"}.mdi-checkbox-marked-circle-minus-outline:before{content:"󱰧"}.mdi-checkbox-marked-circle-outline:before{content:"󰄴"}.mdi-checkbox-marked-circle-plus-outline:before{content:"󱤧"}.mdi-checkbox-marked-outline:before{content:"󰄵"}.mdi-checkbox-multiple-blank:before{content:"󰄶"}.mdi-checkbox-multiple-blank-circle:before{content:"󰘻"}.mdi-checkbox-multiple-blank-circle-outline:before{content:"󰘼"}.mdi-checkbox-multiple-blank-outline:before{content:"󰄷"}.mdi-checkbox-multiple-marked:before{content:"󰄸"}.mdi-checkbox-multiple-marked-circle:before{content:"󰘽"}.mdi-checkbox-multiple-marked-circle-outline:before{content:"󰘾"}.mdi-checkbox-multiple-marked-outline:before{content:"󰄹"}.mdi-checkbox-multiple-outline:before{content:"󰱑"}.mdi-checkbox-outline:before{content:"󰱒"}.mdi-checkerboard:before{content:"󰄺"}.mdi-checkerboard-minus:before{content:"󱈂"}.mdi-checkerboard-plus:before{content:"󱈁"}.mdi-checkerboard-remove:before{content:"󱈃"}.mdi-cheese:before{content:"󱊹"}.mdi-cheese-off:before{content:"󱏮"}.mdi-chef-hat:before{content:"󰭼"}.mdi-chemical-weapon:before{content:"󰄻"}.mdi-chess-bishop:before{content:"󰡜"}.mdi-chess-king:before{content:"󰡗"}.mdi-chess-knight:before{content:"󰡘"}.mdi-chess-pawn:before{content:"󰡙"}.mdi-chess-queen:before{content:"󰡚"}.mdi-chess-rook:before{content:"󰡛"}.mdi-chevron-double-down:before{content:"󰄼"}.mdi-chevron-double-left:before{content:"󰄽"}.mdi-chevron-double-right:before{content:"󰄾"}.mdi-chevron-double-up:before{content:"󰄿"}.mdi-chevron-down:before{content:"󰅀"}.mdi-chevron-down-box:before{content:"󰧖"}.mdi-chevron-down-box-outline:before{content:"󰧗"}.mdi-chevron-down-circle:before{content:"󰬦"}.mdi-chevron-down-circle-outline:before{content:"󰬧"}.mdi-chevron-left:before{content:"󰅁"}.mdi-chevron-left-box:before{content:"󰧘"}.mdi-chevron-left-box-outline:before{content:"󰧙"}.mdi-chevron-left-circle:before{content:"󰬨"}.mdi-chevron-left-circle-outline:before{content:"󰬩"}.mdi-chevron-right:before{content:"󰅂"}.mdi-chevron-right-box:before{content:"󰧚"}.mdi-chevron-right-box-outline:before{content:"󰧛"}.mdi-chevron-right-circle:before{content:"󰬪"}.mdi-chevron-right-circle-outline:before{content:"󰬫"}.mdi-chevron-triple-down:before{content:"󰶹"}.mdi-chevron-triple-left:before{content:"󰶺"}.mdi-chevron-triple-right:before{content:"󰶻"}.mdi-chevron-triple-up:before{content:"󰶼"}.mdi-chevron-up:before{content:"󰅃"}.mdi-chevron-up-box:before{content:"󰧜"}.mdi-chevron-up-box-outline:before{content:"󰧝"}.mdi-chevron-up-circle:before{content:"󰬬"}.mdi-chevron-up-circle-outline:before{content:"󰬭"}.mdi-chili-alert:before{content:"󱟪"}.mdi-chili-alert-outline:before{content:"󱟫"}.mdi-chili-hot:before{content:"󰞲"}.mdi-chili-hot-outline:before{content:"󱟬"}.mdi-chili-medium:before{content:"󰞳"}.mdi-chili-medium-outline:before{content:"󱟭"}.mdi-chili-mild:before{content:"󰞴"}.mdi-chili-mild-outline:before{content:"󱟮"}.mdi-chili-off:before{content:"󱑧"}.mdi-chili-off-outline:before{content:"󱟯"}.mdi-chip:before{content:"󰘚"}.mdi-church:before{content:"󰅄"}.mdi-church-outline:before{content:"󱬂"}.mdi-cigar:before{content:"󱆉"}.mdi-cigar-off:before{content:"󱐛"}.mdi-circle:before{content:"󰝥"}.mdi-circle-box:before{content:"󱗜"}.mdi-circle-box-outline:before{content:"󱗝"}.mdi-circle-double:before{content:"󰺕"}.mdi-circle-edit-outline:before{content:"󰣕"}.mdi-circle-expand:before{content:"󰺖"}.mdi-circle-half:before{content:"󱎕"}.mdi-circle-half-full:before{content:"󱎖"}.mdi-circle-medium:before{content:"󰧞"}.mdi-circle-multiple:before{content:"󰬸"}.mdi-circle-multiple-outline:before{content:"󰚕"}.mdi-circle-off-outline:before{content:"󱃓"}.mdi-circle-opacity:before{content:"󱡓"}.mdi-circle-outline:before{content:"󰝦"}.mdi-circle-slice-1:before{content:"󰪞"}.mdi-circle-slice-2:before{content:"󰪟"}.mdi-circle-slice-3:before{content:"󰪠"}.mdi-circle-slice-4:before{content:"󰪡"}.mdi-circle-slice-5:before{content:"󰪢"}.mdi-circle-slice-6:before{content:"󰪣"}.mdi-circle-slice-7:before{content:"󰪤"}.mdi-circle-slice-8:before{content:"󰪥"}.mdi-circle-small:before{content:"󰧟"}.mdi-circular-saw:before{content:"󰸢"}.mdi-city:before{content:"󰅆"}.mdi-city-switch:before{content:"󱰨"}.mdi-city-variant:before{content:"󰨶"}.mdi-city-variant-outline:before{content:"󰨷"}.mdi-clipboard:before{content:"󰅇"}.mdi-clipboard-account:before{content:"󰅈"}.mdi-clipboard-account-outline:before{content:"󰱕"}.mdi-clipboard-alert:before{content:"󰅉"}.mdi-clipboard-alert-outline:before{content:"󰳷"}.mdi-clipboard-arrow-down:before{content:"󰅊"}.mdi-clipboard-arrow-down-outline:before{content:"󰱖"}.mdi-clipboard-arrow-left:before{content:"󰅋"}.mdi-clipboard-arrow-left-outline:before{content:"󰳸"}.mdi-clipboard-arrow-right:before{content:"󰳹"}.mdi-clipboard-arrow-right-outline:before{content:"󰳺"}.mdi-clipboard-arrow-up:before{content:"󰱗"}.mdi-clipboard-arrow-up-outline:before{content:"󰱘"}.mdi-clipboard-check:before{content:"󰅎"}.mdi-clipboard-check-multiple:before{content:"󱉣"}.mdi-clipboard-check-multiple-outline:before{content:"󱉤"}.mdi-clipboard-check-outline:before{content:"󰢨"}.mdi-clipboard-clock:before{content:"󱛢"}.mdi-clipboard-clock-outline:before{content:"󱛣"}.mdi-clipboard-edit:before{content:"󱓥"}.mdi-clipboard-edit-outline:before{content:"󱓦"}.mdi-clipboard-file:before{content:"󱉥"}.mdi-clipboard-file-outline:before{content:"󱉦"}.mdi-clipboard-flow:before{content:"󰛈"}.mdi-clipboard-flow-outline:before{content:"󱄗"}.mdi-clipboard-list:before{content:"󱃔"}.mdi-clipboard-list-outline:before{content:"󱃕"}.mdi-clipboard-minus:before{content:"󱘘"}.mdi-clipboard-minus-outline:before{content:"󱘙"}.mdi-clipboard-multiple:before{content:"󱉧"}.mdi-clipboard-multiple-outline:before{content:"󱉨"}.mdi-clipboard-off:before{content:"󱘚"}.mdi-clipboard-off-outline:before{content:"󱘛"}.mdi-clipboard-outline:before{content:"󰅌"}.mdi-clipboard-play:before{content:"󰱙"}.mdi-clipboard-play-multiple:before{content:"󱉩"}.mdi-clipboard-play-multiple-outline:before{content:"󱉪"}.mdi-clipboard-play-outline:before{content:"󰱚"}.mdi-clipboard-plus:before{content:"󰝑"}.mdi-clipboard-plus-outline:before{content:"󱌟"}.mdi-clipboard-pulse:before{content:"󰡝"}.mdi-clipboard-pulse-outline:before{content:"󰡞"}.mdi-clipboard-remove:before{content:"󱘜"}.mdi-clipboard-remove-outline:before{content:"󱘝"}.mdi-clipboard-search:before{content:"󱘞"}.mdi-clipboard-search-outline:before{content:"󱘟"}.mdi-clipboard-text:before{content:"󰅍"}.mdi-clipboard-text-clock:before{content:"󱣹"}.mdi-clipboard-text-clock-outline:before{content:"󱣺"}.mdi-clipboard-text-multiple:before{content:"󱉫"}.mdi-clipboard-text-multiple-outline:before{content:"󱉬"}.mdi-clipboard-text-off:before{content:"󱘠"}.mdi-clipboard-text-off-outline:before{content:"󱘡"}.mdi-clipboard-text-outline:before{content:"󰨸"}.mdi-clipboard-text-play:before{content:"󰱛"}.mdi-clipboard-text-play-outline:before{content:"󰱜"}.mdi-clipboard-text-search:before{content:"󱘢"}.mdi-clipboard-text-search-outline:before{content:"󱘣"}.mdi-clippy:before{content:"󰅏"}.mdi-clock:before{content:"󰥔"}.mdi-clock-alert:before{content:"󰥕"}.mdi-clock-alert-outline:before{content:"󰗎"}.mdi-clock-check:before{content:"󰾨"}.mdi-clock-check-outline:before{content:"󰾩"}.mdi-clock-digital:before{content:"󰺗"}.mdi-clock-edit:before{content:"󱦺"}.mdi-clock-edit-outline:before{content:"󱦻"}.mdi-clock-end:before{content:"󰅑"}.mdi-clock-fast:before{content:"󰅒"}.mdi-clock-in:before{content:"󰅓"}.mdi-clock-minus:before{content:"󱡣"}.mdi-clock-minus-outline:before{content:"󱡤"}.mdi-clock-out:before{content:"󰅔"}.mdi-clock-outline:before{content:"󰅐"}.mdi-clock-plus:before{content:"󱡡"}.mdi-clock-plus-outline:before{content:"󱡢"}.mdi-clock-remove:before{content:"󱡥"}.mdi-clock-remove-outline:before{content:"󱡦"}.mdi-clock-star-four-points:before{content:"󱰩"}.mdi-clock-star-four-points-outline:before{content:"󱰪"}.mdi-clock-start:before{content:"󰅕"}.mdi-clock-time-eight:before{content:"󱑆"}.mdi-clock-time-eight-outline:before{content:"󱑒"}.mdi-clock-time-eleven:before{content:"󱑉"}.mdi-clock-time-eleven-outline:before{content:"󱑕"}.mdi-clock-time-five:before{content:"󱑃"}.mdi-clock-time-five-outline:before{content:"󱑏"}.mdi-clock-time-four:before{content:"󱑂"}.mdi-clock-time-four-outline:before{content:"󱑎"}.mdi-clock-time-nine:before{content:"󱑇"}.mdi-clock-time-nine-outline:before{content:"󱑓"}.mdi-clock-time-one:before{content:"󱐿"}.mdi-clock-time-one-outline:before{content:"󱑋"}.mdi-clock-time-seven:before{content:"󱑅"}.mdi-clock-time-seven-outline:before{content:"󱑑"}.mdi-clock-time-six:before{content:"󱑄"}.mdi-clock-time-six-outline:before{content:"󱑐"}.mdi-clock-time-ten:before{content:"󱑈"}.mdi-clock-time-ten-outline:before{content:"󱑔"}.mdi-clock-time-three:before{content:"󱑁"}.mdi-clock-time-three-outline:before{content:"󱑍"}.mdi-clock-time-twelve:before{content:"󱑊"}.mdi-clock-time-twelve-outline:before{content:"󱑖"}.mdi-clock-time-two:before{content:"󱑀"}.mdi-clock-time-two-outline:before{content:"󱑌"}.mdi-close:before{content:"󰅖"}.mdi-close-box:before{content:"󰅗"}.mdi-close-box-multiple:before{content:"󰱝"}.mdi-close-box-multiple-outline:before{content:"󰱞"}.mdi-close-box-outline:before{content:"󰅘"}.mdi-close-circle:before{content:"󰅙"}.mdi-close-circle-multiple:before{content:"󰘪"}.mdi-close-circle-multiple-outline:before{content:"󰢃"}.mdi-close-circle-outline:before{content:"󰅚"}.mdi-close-network:before{content:"󰅛"}.mdi-close-network-outline:before{content:"󰱟"}.mdi-close-octagon:before{content:"󰅜"}.mdi-close-octagon-outline:before{content:"󰅝"}.mdi-close-outline:before{content:"󰛉"}.mdi-close-thick:before{content:"󱎘"}.mdi-closed-caption:before{content:"󰅞"}.mdi-closed-caption-outline:before{content:"󰶽"}.mdi-cloud:before{content:"󰅟"}.mdi-cloud-alert:before{content:"󰧠"}.mdi-cloud-alert-outline:before{content:"󱯠"}.mdi-cloud-arrow-down:before{content:"󱯡"}.mdi-cloud-arrow-down-outline:before{content:"󱯢"}.mdi-cloud-arrow-left:before{content:"󱯣"}.mdi-cloud-arrow-left-outline:before{content:"󱯤"}.mdi-cloud-arrow-right:before{content:"󱯥"}.mdi-cloud-arrow-right-outline:before{content:"󱯦"}.mdi-cloud-arrow-up:before{content:"󱯧"}.mdi-cloud-arrow-up-outline:before{content:"󱯨"}.mdi-cloud-braces:before{content:"󰞵"}.mdi-cloud-cancel:before{content:"󱯩"}.mdi-cloud-cancel-outline:before{content:"󱯪"}.mdi-cloud-check:before{content:"󱯫"}.mdi-cloud-check-outline:before{content:"󱯬"}.mdi-cloud-check-variant:before{content:"󰅠"}.mdi-cloud-check-variant-outline:before{content:"󱋌"}.mdi-cloud-circle:before{content:"󰅡"}.mdi-cloud-circle-outline:before{content:"󱯭"}.mdi-cloud-clock:before{content:"󱯮"}.mdi-cloud-clock-outline:before{content:"󱯯"}.mdi-cloud-cog:before{content:"󱯰"}.mdi-cloud-cog-outline:before{content:"󱯱"}.mdi-cloud-download:before{content:"󰅢"}.mdi-cloud-download-outline:before{content:"󰭽"}.mdi-cloud-lock:before{content:"󱇱"}.mdi-cloud-lock-open:before{content:"󱯲"}.mdi-cloud-lock-open-outline:before{content:"󱯳"}.mdi-cloud-lock-outline:before{content:"󱇲"}.mdi-cloud-minus:before{content:"󱯴"}.mdi-cloud-minus-outline:before{content:"󱯵"}.mdi-cloud-off:before{content:"󱯶"}.mdi-cloud-off-outline:before{content:"󰅤"}.mdi-cloud-outline:before{content:"󰅣"}.mdi-cloud-percent:before{content:"󱨵"}.mdi-cloud-percent-outline:before{content:"󱨶"}.mdi-cloud-plus:before{content:"󱯷"}.mdi-cloud-plus-outline:before{content:"󱯸"}.mdi-cloud-print:before{content:"󰅥"}.mdi-cloud-print-outline:before{content:"󰅦"}.mdi-cloud-question:before{content:"󰨹"}.mdi-cloud-question-outline:before{content:"󱯹"}.mdi-cloud-refresh:before{content:"󱯺"}.mdi-cloud-refresh-outline:before{content:"󱯻"}.mdi-cloud-refresh-variant:before{content:"󰔪"}.mdi-cloud-refresh-variant-outline:before{content:"󱯼"}.mdi-cloud-remove:before{content:"󱯽"}.mdi-cloud-remove-outline:before{content:"󱯾"}.mdi-cloud-search:before{content:"󰥖"}.mdi-cloud-search-outline:before{content:"󰥗"}.mdi-cloud-sync:before{content:"󰘿"}.mdi-cloud-sync-outline:before{content:"󱋖"}.mdi-cloud-tags:before{content:"󰞶"}.mdi-cloud-upload:before{content:"󰅧"}.mdi-cloud-upload-outline:before{content:"󰭾"}.mdi-clouds:before{content:"󱮕"}.mdi-clover:before{content:"󰠖"}.mdi-clover-outline:before{content:"󱱢"}.mdi-coach-lamp:before{content:"󱀠"}.mdi-coach-lamp-variant:before{content:"󱨷"}.mdi-coat-rack:before{content:"󱂞"}.mdi-code-array:before{content:"󰅨"}.mdi-code-braces:before{content:"󰅩"}.mdi-code-braces-box:before{content:"󱃖"}.mdi-code-brackets:before{content:"󰅪"}.mdi-code-equal:before{content:"󰅫"}.mdi-code-greater-than:before{content:"󰅬"}.mdi-code-greater-than-or-equal:before{content:"󰅭"}.mdi-code-json:before{content:"󰘦"}.mdi-code-less-than:before{content:"󰅮"}.mdi-code-less-than-or-equal:before{content:"󰅯"}.mdi-code-not-equal:before{content:"󰅰"}.mdi-code-not-equal-variant:before{content:"󰅱"}.mdi-code-parentheses:before{content:"󰅲"}.mdi-code-parentheses-box:before{content:"󱃗"}.mdi-code-string:before{content:"󰅳"}.mdi-code-tags:before{content:"󰅴"}.mdi-code-tags-check:before{content:"󰚔"}.mdi-codepen:before{content:"󰅵"}.mdi-coffee:before{content:"󰅶"}.mdi-coffee-maker:before{content:"󱂟"}.mdi-coffee-maker-check:before{content:"󱤱"}.mdi-coffee-maker-check-outline:before{content:"󱤲"}.mdi-coffee-maker-outline:before{content:"󱠛"}.mdi-coffee-off:before{content:"󰾪"}.mdi-coffee-off-outline:before{content:"󰾫"}.mdi-coffee-outline:before{content:"󰛊"}.mdi-coffee-to-go:before{content:"󰅷"}.mdi-coffee-to-go-outline:before{content:"󱌎"}.mdi-coffin:before{content:"󰭿"}.mdi-cog:before{content:"󰒓"}.mdi-cog-box:before{content:"󰒔"}.mdi-cog-clockwise:before{content:"󱇝"}.mdi-cog-counterclockwise:before{content:"󱇞"}.mdi-cog-off:before{content:"󱏎"}.mdi-cog-off-outline:before{content:"󱏏"}.mdi-cog-outline:before{content:"󰢻"}.mdi-cog-pause:before{content:"󱤳"}.mdi-cog-pause-outline:before{content:"󱤴"}.mdi-cog-play:before{content:"󱤵"}.mdi-cog-play-outline:before{content:"󱤶"}.mdi-cog-refresh:before{content:"󱑞"}.mdi-cog-refresh-outline:before{content:"󱑟"}.mdi-cog-stop:before{content:"󱤷"}.mdi-cog-stop-outline:before{content:"󱤸"}.mdi-cog-sync:before{content:"󱑠"}.mdi-cog-sync-outline:before{content:"󱑡"}.mdi-cog-transfer:before{content:"󱁛"}.mdi-cog-transfer-outline:before{content:"󱁜"}.mdi-cogs:before{content:"󰣖"}.mdi-collage:before{content:"󰙀"}.mdi-collapse-all:before{content:"󰪦"}.mdi-collapse-all-outline:before{content:"󰪧"}.mdi-color-helper:before{content:"󰅹"}.mdi-comma:before{content:"󰸣"}.mdi-comma-box:before{content:"󰸫"}.mdi-comma-box-outline:before{content:"󰸤"}.mdi-comma-circle:before{content:"󰸥"}.mdi-comma-circle-outline:before{content:"󰸦"}.mdi-comment:before{content:"󰅺"}.mdi-comment-account:before{content:"󰅻"}.mdi-comment-account-outline:before{content:"󰅼"}.mdi-comment-alert:before{content:"󰅽"}.mdi-comment-alert-outline:before{content:"󰅾"}.mdi-comment-arrow-left:before{content:"󰧡"}.mdi-comment-arrow-left-outline:before{content:"󰧢"}.mdi-comment-arrow-right:before{content:"󰧣"}.mdi-comment-arrow-right-outline:before{content:"󰧤"}.mdi-comment-bookmark:before{content:"󱖮"}.mdi-comment-bookmark-outline:before{content:"󱖯"}.mdi-comment-check:before{content:"󰅿"}.mdi-comment-check-outline:before{content:"󰆀"}.mdi-comment-edit:before{content:"󱆿"}.mdi-comment-edit-outline:before{content:"󱋄"}.mdi-comment-eye:before{content:"󰨺"}.mdi-comment-eye-outline:before{content:"󰨻"}.mdi-comment-flash:before{content:"󱖰"}.mdi-comment-flash-outline:before{content:"󱖱"}.mdi-comment-minus:before{content:"󱗟"}.mdi-comment-minus-outline:before{content:"󱗠"}.mdi-comment-multiple:before{content:"󰡟"}.mdi-comment-multiple-outline:before{content:"󰆁"}.mdi-comment-off:before{content:"󱗡"}.mdi-comment-off-outline:before{content:"󱗢"}.mdi-comment-outline:before{content:"󰆂"}.mdi-comment-plus:before{content:"󰧥"}.mdi-comment-plus-outline:before{content:"󰆃"}.mdi-comment-processing:before{content:"󰆄"}.mdi-comment-processing-outline:before{content:"󰆅"}.mdi-comment-question:before{content:"󰠗"}.mdi-comment-question-outline:before{content:"󰆆"}.mdi-comment-quote:before{content:"󱀡"}.mdi-comment-quote-outline:before{content:"󱀢"}.mdi-comment-remove:before{content:"󰗞"}.mdi-comment-remove-outline:before{content:"󰆇"}.mdi-comment-search:before{content:"󰨼"}.mdi-comment-search-outline:before{content:"󰨽"}.mdi-comment-text:before{content:"󰆈"}.mdi-comment-text-multiple:before{content:"󰡠"}.mdi-comment-text-multiple-outline:before{content:"󰡡"}.mdi-comment-text-outline:before{content:"󰆉"}.mdi-compare:before{content:"󰆊"}.mdi-compare-horizontal:before{content:"󱒒"}.mdi-compare-remove:before{content:"󱢳"}.mdi-compare-vertical:before{content:"󱒓"}.mdi-compass:before{content:"󰆋"}.mdi-compass-off:before{content:"󰮀"}.mdi-compass-off-outline:before{content:"󰮁"}.mdi-compass-outline:before{content:"󰆌"}.mdi-compass-rose:before{content:"󱎂"}.mdi-compost:before{content:"󱨸"}.mdi-cone:before{content:"󱥌"}.mdi-cone-off:before{content:"󱥍"}.mdi-connection:before{content:"󱘖"}.mdi-console:before{content:"󰆍"}.mdi-console-line:before{content:"󰞷"}.mdi-console-network:before{content:"󰢩"}.mdi-console-network-outline:before{content:"󰱠"}.mdi-consolidate:before{content:"󱃘"}.mdi-contactless-payment:before{content:"󰵪"}.mdi-contactless-payment-circle:before{content:"󰌡"}.mdi-contactless-payment-circle-outline:before{content:"󰐈"}.mdi-contacts:before{content:"󰛋"}.mdi-contacts-outline:before{content:"󰖸"}.mdi-contain:before{content:"󰨾"}.mdi-contain-end:before{content:"󰨿"}.mdi-contain-start:before{content:"󰩀"}.mdi-content-copy:before{content:"󰆏"}.mdi-content-cut:before{content:"󰆐"}.mdi-content-duplicate:before{content:"󰆑"}.mdi-content-paste:before{content:"󰆒"}.mdi-content-save:before{content:"󰆓"}.mdi-content-save-alert:before{content:"󰽂"}.mdi-content-save-alert-outline:before{content:"󰽃"}.mdi-content-save-all:before{content:"󰆔"}.mdi-content-save-all-outline:before{content:"󰽄"}.mdi-content-save-check:before{content:"󱣪"}.mdi-content-save-check-outline:before{content:"󱣫"}.mdi-content-save-cog:before{content:"󱑛"}.mdi-content-save-cog-outline:before{content:"󱑜"}.mdi-content-save-edit:before{content:"󰳻"}.mdi-content-save-edit-outline:before{content:"󰳼"}.mdi-content-save-minus:before{content:"󱭃"}.mdi-content-save-minus-outline:before{content:"󱭄"}.mdi-content-save-move:before{content:"󰸧"}.mdi-content-save-move-outline:before{content:"󰸨"}.mdi-content-save-off:before{content:"󱙃"}.mdi-content-save-off-outline:before{content:"󱙄"}.mdi-content-save-outline:before{content:"󰠘"}.mdi-content-save-plus:before{content:"󱭁"}.mdi-content-save-plus-outline:before{content:"󱭂"}.mdi-content-save-settings:before{content:"󰘛"}.mdi-content-save-settings-outline:before{content:"󰬮"}.mdi-contrast:before{content:"󰆕"}.mdi-contrast-box:before{content:"󰆖"}.mdi-contrast-circle:before{content:"󰆗"}.mdi-controller:before{content:"󰊴"}.mdi-controller-classic:before{content:"󰮂"}.mdi-controller-classic-outline:before{content:"󰮃"}.mdi-controller-off:before{content:"󰊵"}.mdi-cookie:before{content:"󰆘"}.mdi-cookie-alert:before{content:"󱛐"}.mdi-cookie-alert-outline:before{content:"󱛑"}.mdi-cookie-check:before{content:"󱛒"}.mdi-cookie-check-outline:before{content:"󱛓"}.mdi-cookie-clock:before{content:"󱛤"}.mdi-cookie-clock-outline:before{content:"󱛥"}.mdi-cookie-cog:before{content:"󱛔"}.mdi-cookie-cog-outline:before{content:"󱛕"}.mdi-cookie-edit:before{content:"󱛦"}.mdi-cookie-edit-outline:before{content:"󱛧"}.mdi-cookie-lock:before{content:"󱛨"}.mdi-cookie-lock-outline:before{content:"󱛩"}.mdi-cookie-minus:before{content:"󱛚"}.mdi-cookie-minus-outline:before{content:"󱛛"}.mdi-cookie-off:before{content:"󱛪"}.mdi-cookie-off-outline:before{content:"󱛫"}.mdi-cookie-outline:before{content:"󱛞"}.mdi-cookie-plus:before{content:"󱛖"}.mdi-cookie-plus-outline:before{content:"󱛗"}.mdi-cookie-refresh:before{content:"󱛬"}.mdi-cookie-refresh-outline:before{content:"󱛭"}.mdi-cookie-remove:before{content:"󱛘"}.mdi-cookie-remove-outline:before{content:"󱛙"}.mdi-cookie-settings:before{content:"󱛜"}.mdi-cookie-settings-outline:before{content:"󱛝"}.mdi-coolant-temperature:before{content:"󰏈"}.mdi-copyleft:before{content:"󱤹"}.mdi-copyright:before{content:"󰗦"}.mdi-cordova:before{content:"󰥘"}.mdi-corn:before{content:"󰞸"}.mdi-corn-off:before{content:"󱏯"}.mdi-cosine-wave:before{content:"󱑹"}.mdi-counter:before{content:"󰆙"}.mdi-countertop:before{content:"󱠜"}.mdi-countertop-outline:before{content:"󱠝"}.mdi-cow:before{content:"󰆚"}.mdi-cow-off:before{content:"󱣼"}.mdi-cpu-32-bit:before{content:"󰻟"}.mdi-cpu-64-bit:before{content:"󰻠"}.mdi-cradle:before{content:"󱦋"}.mdi-cradle-outline:before{content:"󱦑"}.mdi-crane:before{content:"󰡢"}.mdi-creation:before{content:"󰙴"}.mdi-creation-outline:before{content:"󱰫"}.mdi-creative-commons:before{content:"󰵫"}.mdi-credit-card:before{content:"󰿯"}.mdi-credit-card-check:before{content:"󱏐"}.mdi-credit-card-check-outline:before{content:"󱏑"}.mdi-credit-card-chip:before{content:"󱤏"}.mdi-credit-card-chip-outline:before{content:"󱤐"}.mdi-credit-card-clock:before{content:"󰻡"}.mdi-credit-card-clock-outline:before{content:"󰻢"}.mdi-credit-card-edit:before{content:"󱟗"}.mdi-credit-card-edit-outline:before{content:"󱟘"}.mdi-credit-card-fast:before{content:"󱤑"}.mdi-credit-card-fast-outline:before{content:"󱤒"}.mdi-credit-card-lock:before{content:"󱣧"}.mdi-credit-card-lock-outline:before{content:"󱣨"}.mdi-credit-card-marker:before{content:"󰚨"}.mdi-credit-card-marker-outline:before{content:"󰶾"}.mdi-credit-card-minus:before{content:"󰾬"}.mdi-credit-card-minus-outline:before{content:"󰾭"}.mdi-credit-card-multiple:before{content:"󰿰"}.mdi-credit-card-multiple-outline:before{content:"󰆜"}.mdi-credit-card-off:before{content:"󰿱"}.mdi-credit-card-off-outline:before{content:"󰗤"}.mdi-credit-card-outline:before{content:"󰆛"}.mdi-credit-card-plus:before{content:"󰿲"}.mdi-credit-card-plus-outline:before{content:"󰙶"}.mdi-credit-card-refresh:before{content:"󱙅"}.mdi-credit-card-refresh-outline:before{content:"󱙆"}.mdi-credit-card-refund:before{content:"󰿳"}.mdi-credit-card-refund-outline:before{content:"󰪨"}.mdi-credit-card-remove:before{content:"󰾮"}.mdi-credit-card-remove-outline:before{content:"󰾯"}.mdi-credit-card-scan:before{content:"󰿴"}.mdi-credit-card-scan-outline:before{content:"󰆝"}.mdi-credit-card-search:before{content:"󱙇"}.mdi-credit-card-search-outline:before{content:"󱙈"}.mdi-credit-card-settings:before{content:"󰿵"}.mdi-credit-card-settings-outline:before{content:"󰣗"}.mdi-credit-card-sync:before{content:"󱙉"}.mdi-credit-card-sync-outline:before{content:"󱙊"}.mdi-credit-card-wireless:before{content:"󰠂"}.mdi-credit-card-wireless-off:before{content:"󰕺"}.mdi-credit-card-wireless-off-outline:before{content:"󰕻"}.mdi-credit-card-wireless-outline:before{content:"󰵬"}.mdi-cricket:before{content:"󰵭"}.mdi-crop:before{content:"󰆞"}.mdi-crop-free:before{content:"󰆟"}.mdi-crop-landscape:before{content:"󰆠"}.mdi-crop-portrait:before{content:"󰆡"}.mdi-crop-rotate:before{content:"󰚖"}.mdi-crop-square:before{content:"󰆢"}.mdi-cross:before{content:"󰥓"}.mdi-cross-bolnisi:before{content:"󰳭"}.mdi-cross-celtic:before{content:"󰳵"}.mdi-cross-outline:before{content:"󰳶"}.mdi-crosshairs:before{content:"󰆣"}.mdi-crosshairs-gps:before{content:"󰆤"}.mdi-crosshairs-off:before{content:"󰽅"}.mdi-crosshairs-question:before{content:"󱄶"}.mdi-crowd:before{content:"󱥵"}.mdi-crown:before{content:"󰆥"}.mdi-crown-circle:before{content:"󱟜"}.mdi-crown-circle-outline:before{content:"󱟝"}.mdi-crown-outline:before{content:"󱇐"}.mdi-cryengine:before{content:"󰥙"}.mdi-crystal-ball:before{content:"󰬯"}.mdi-cube:before{content:"󰆦"}.mdi-cube-off:before{content:"󱐜"}.mdi-cube-off-outline:before{content:"󱐝"}.mdi-cube-outline:before{content:"󰆧"}.mdi-cube-scan:before{content:"󰮄"}.mdi-cube-send:before{content:"󰆨"}.mdi-cube-unfolded:before{content:"󰆩"}.mdi-cup:before{content:"󰆪"}.mdi-cup-off:before{content:"󰗥"}.mdi-cup-off-outline:before{content:"󱍽"}.mdi-cup-outline:before{content:"󱌏"}.mdi-cup-water:before{content:"󰆫"}.mdi-cupboard:before{content:"󰽆"}.mdi-cupboard-outline:before{content:"󰽇"}.mdi-cupcake:before{content:"󰥚"}.mdi-curling:before{content:"󰡣"}.mdi-currency-bdt:before{content:"󰡤"}.mdi-currency-brl:before{content:"󰮅"}.mdi-currency-btc:before{content:"󰆬"}.mdi-currency-cny:before{content:"󰞺"}.mdi-currency-eth:before{content:"󰞻"}.mdi-currency-eur:before{content:"󰆭"}.mdi-currency-eur-off:before{content:"󱌕"}.mdi-currency-fra:before{content:"󱨹"}.mdi-currency-gbp:before{content:"󰆮"}.mdi-currency-ils:before{content:"󰱡"}.mdi-currency-inr:before{content:"󰆯"}.mdi-currency-jpy:before{content:"󰞼"}.mdi-currency-krw:before{content:"󰞽"}.mdi-currency-kzt:before{content:"󰡥"}.mdi-currency-mnt:before{content:"󱔒"}.mdi-currency-ngn:before{content:"󰆰"}.mdi-currency-php:before{content:"󰧦"}.mdi-currency-rial:before{content:"󰺜"}.mdi-currency-rub:before{content:"󰆱"}.mdi-currency-rupee:before{content:"󱥶"}.mdi-currency-sign:before{content:"󰞾"}.mdi-currency-thb:before{content:"󱰅"}.mdi-currency-try:before{content:"󰆲"}.mdi-currency-twd:before{content:"󰞿"}.mdi-currency-uah:before{content:"󱮛"}.mdi-currency-usd:before{content:"󰇁"}.mdi-currency-usd-off:before{content:"󰙺"}.mdi-current-ac:before{content:"󱒀"}.mdi-current-dc:before{content:"󰥜"}.mdi-cursor-default:before{content:"󰇀"}.mdi-cursor-default-click:before{content:"󰳽"}.mdi-cursor-default-click-outline:before{content:"󰳾"}.mdi-cursor-default-gesture:before{content:"󱄧"}.mdi-cursor-default-gesture-outline:before{content:"󱄨"}.mdi-cursor-default-outline:before{content:"󰆿"}.mdi-cursor-move:before{content:"󰆾"}.mdi-cursor-pointer:before{content:"󰆽"}.mdi-cursor-text:before{content:"󰗧"}.mdi-curtains:before{content:"󱡆"}.mdi-curtains-closed:before{content:"󱡇"}.mdi-cylinder:before{content:"󱥎"}.mdi-cylinder-off:before{content:"󱥏"}.mdi-dance-ballroom:before{content:"󱗻"}.mdi-dance-pole:before{content:"󱕸"}.mdi-data-matrix:before{content:"󱔼"}.mdi-data-matrix-edit:before{content:"󱔽"}.mdi-data-matrix-minus:before{content:"󱔾"}.mdi-data-matrix-plus:before{content:"󱔿"}.mdi-data-matrix-remove:before{content:"󱕀"}.mdi-data-matrix-scan:before{content:"󱕁"}.mdi-database:before{content:"󰆼"}.mdi-database-alert:before{content:"󱘺"}.mdi-database-alert-outline:before{content:"󱘤"}.mdi-database-arrow-down:before{content:"󱘻"}.mdi-database-arrow-down-outline:before{content:"󱘥"}.mdi-database-arrow-left:before{content:"󱘼"}.mdi-database-arrow-left-outline:before{content:"󱘦"}.mdi-database-arrow-right:before{content:"󱘽"}.mdi-database-arrow-right-outline:before{content:"󱘧"}.mdi-database-arrow-up:before{content:"󱘾"}.mdi-database-arrow-up-outline:before{content:"󱘨"}.mdi-database-check:before{content:"󰪩"}.mdi-database-check-outline:before{content:"󱘩"}.mdi-database-clock:before{content:"󱘿"}.mdi-database-clock-outline:before{content:"󱘪"}.mdi-database-cog:before{content:"󱙋"}.mdi-database-cog-outline:before{content:"󱙌"}.mdi-database-edit:before{content:"󰮆"}.mdi-database-edit-outline:before{content:"󱘫"}.mdi-database-export:before{content:"󰥞"}.mdi-database-export-outline:before{content:"󱘬"}.mdi-database-eye:before{content:"󱤟"}.mdi-database-eye-off:before{content:"󱤠"}.mdi-database-eye-off-outline:before{content:"󱤡"}.mdi-database-eye-outline:before{content:"󱤢"}.mdi-database-import:before{content:"󰥝"}.mdi-database-import-outline:before{content:"󱘭"}.mdi-database-lock:before{content:"󰪪"}.mdi-database-lock-outline:before{content:"󱘮"}.mdi-database-marker:before{content:"󱋶"}.mdi-database-marker-outline:before{content:"󱘯"}.mdi-database-minus:before{content:"󰆻"}.mdi-database-minus-outline:before{content:"󱘰"}.mdi-database-off:before{content:"󱙀"}.mdi-database-off-outline:before{content:"󱘱"}.mdi-database-outline:before{content:"󱘲"}.mdi-database-plus:before{content:"󰆺"}.mdi-database-plus-outline:before{content:"󱘳"}.mdi-database-refresh:before{content:"󰗂"}.mdi-database-refresh-outline:before{content:"󱘴"}.mdi-database-remove:before{content:"󰴀"}.mdi-database-remove-outline:before{content:"󱘵"}.mdi-database-search:before{content:"󰡦"}.mdi-database-search-outline:before{content:"󱘶"}.mdi-database-settings:before{content:"󰴁"}.mdi-database-settings-outline:before{content:"󱘷"}.mdi-database-sync:before{content:"󰳿"}.mdi-database-sync-outline:before{content:"󱘸"}.mdi-death-star:before{content:"󰣘"}.mdi-death-star-variant:before{content:"󰣙"}.mdi-deathly-hallows:before{content:"󰮇"}.mdi-debian:before{content:"󰣚"}.mdi-debug-step-into:before{content:"󰆹"}.mdi-debug-step-out:before{content:"󰆸"}.mdi-debug-step-over:before{content:"󰆷"}.mdi-decagram:before{content:"󰝬"}.mdi-decagram-outline:before{content:"󰝭"}.mdi-decimal:before{content:"󱂡"}.mdi-decimal-comma:before{content:"󱂢"}.mdi-decimal-comma-decrease:before{content:"󱂣"}.mdi-decimal-comma-increase:before{content:"󱂤"}.mdi-decimal-decrease:before{content:"󰆶"}.mdi-decimal-increase:before{content:"󰆵"}.mdi-delete:before{content:"󰆴"}.mdi-delete-alert:before{content:"󱂥"}.mdi-delete-alert-outline:before{content:"󱂦"}.mdi-delete-circle:before{content:"󰚃"}.mdi-delete-circle-outline:before{content:"󰮈"}.mdi-delete-clock:before{content:"󱕖"}.mdi-delete-clock-outline:before{content:"󱕗"}.mdi-delete-empty:before{content:"󰛌"}.mdi-delete-empty-outline:before{content:"󰺝"}.mdi-delete-forever:before{content:"󰗨"}.mdi-delete-forever-outline:before{content:"󰮉"}.mdi-delete-off:before{content:"󱂧"}.mdi-delete-off-outline:before{content:"󱂨"}.mdi-delete-outline:before{content:"󰧧"}.mdi-delete-restore:before{content:"󰠙"}.mdi-delete-sweep:before{content:"󰗩"}.mdi-delete-sweep-outline:before{content:"󰱢"}.mdi-delete-variant:before{content:"󰆳"}.mdi-delta:before{content:"󰇂"}.mdi-desk:before{content:"󱈹"}.mdi-desk-lamp:before{content:"󰥟"}.mdi-desk-lamp-off:before{content:"󱬟"}.mdi-desk-lamp-on:before{content:"󱬠"}.mdi-deskphone:before{content:"󰇃"}.mdi-desktop-classic:before{content:"󰟀"}.mdi-desktop-tower:before{content:"󰇅"}.mdi-desktop-tower-monitor:before{content:"󰪫"}.mdi-details:before{content:"󰇆"}.mdi-dev-to:before{content:"󰵮"}.mdi-developer-board:before{content:"󰚗"}.mdi-deviantart:before{content:"󰇇"}.mdi-devices:before{content:"󰾰"}.mdi-dharmachakra:before{content:"󰥋"}.mdi-diabetes:before{content:"󱄦"}.mdi-dialpad:before{content:"󰘜"}.mdi-diameter:before{content:"󰱣"}.mdi-diameter-outline:before{content:"󰱤"}.mdi-diameter-variant:before{content:"󰱥"}.mdi-diamond:before{content:"󰮊"}.mdi-diamond-outline:before{content:"󰮋"}.mdi-diamond-stone:before{content:"󰇈"}.mdi-dice-1:before{content:"󰇊"}.mdi-dice-1-outline:before{content:"󱅊"}.mdi-dice-2:before{content:"󰇋"}.mdi-dice-2-outline:before{content:"󱅋"}.mdi-dice-3:before{content:"󰇌"}.mdi-dice-3-outline:before{content:"󱅌"}.mdi-dice-4:before{content:"󰇍"}.mdi-dice-4-outline:before{content:"󱅍"}.mdi-dice-5:before{content:"󰇎"}.mdi-dice-5-outline:before{content:"󱅎"}.mdi-dice-6:before{content:"󰇏"}.mdi-dice-6-outline:before{content:"󱅏"}.mdi-dice-d10:before{content:"󱅓"}.mdi-dice-d10-outline:before{content:"󰝯"}.mdi-dice-d12:before{content:"󱅔"}.mdi-dice-d12-outline:before{content:"󰡧"}.mdi-dice-d20:before{content:"󱅕"}.mdi-dice-d20-outline:before{content:"󰗪"}.mdi-dice-d4:before{content:"󱅐"}.mdi-dice-d4-outline:before{content:"󰗫"}.mdi-dice-d6:before{content:"󱅑"}.mdi-dice-d6-outline:before{content:"󰗭"}.mdi-dice-d8:before{content:"󱅒"}.mdi-dice-d8-outline:before{content:"󰗬"}.mdi-dice-multiple:before{content:"󰝮"}.mdi-dice-multiple-outline:before{content:"󱅖"}.mdi-digital-ocean:before{content:"󱈷"}.mdi-dip-switch:before{content:"󰟁"}.mdi-directions:before{content:"󰇐"}.mdi-directions-fork:before{content:"󰙁"}.mdi-disc:before{content:"󰗮"}.mdi-disc-alert:before{content:"󰇑"}.mdi-disc-player:before{content:"󰥠"}.mdi-dishwasher:before{content:"󰪬"}.mdi-dishwasher-alert:before{content:"󱆸"}.mdi-dishwasher-off:before{content:"󱆹"}.mdi-disqus:before{content:"󰇒"}.mdi-distribute-horizontal-center:before{content:"󱇉"}.mdi-distribute-horizontal-left:before{content:"󱇈"}.mdi-distribute-horizontal-right:before{content:"󱇊"}.mdi-distribute-vertical-bottom:before{content:"󱇋"}.mdi-distribute-vertical-center:before{content:"󱇌"}.mdi-distribute-vertical-top:before{content:"󱇍"}.mdi-diversify:before{content:"󱡷"}.mdi-diving:before{content:"󱥷"}.mdi-diving-flippers:before{content:"󰶿"}.mdi-diving-helmet:before{content:"󰷀"}.mdi-diving-scuba:before{content:"󱭷"}.mdi-diving-scuba-flag:before{content:"󰷂"}.mdi-diving-scuba-mask:before{content:"󰷁"}.mdi-diving-scuba-tank:before{content:"󰷃"}.mdi-diving-scuba-tank-multiple:before{content:"󰷄"}.mdi-diving-snorkel:before{content:"󰷅"}.mdi-division:before{content:"󰇔"}.mdi-division-box:before{content:"󰇕"}.mdi-dlna:before{content:"󰩁"}.mdi-dna:before{content:"󰚄"}.mdi-dns:before{content:"󰇖"}.mdi-dns-outline:before{content:"󰮌"}.mdi-dock-bottom:before{content:"󱂩"}.mdi-dock-left:before{content:"󱂪"}.mdi-dock-right:before{content:"󱂫"}.mdi-dock-top:before{content:"󱔓"}.mdi-dock-window:before{content:"󱂬"}.mdi-docker:before{content:"󰡨"}.mdi-doctor:before{content:"󰩂"}.mdi-dog:before{content:"󰩃"}.mdi-dog-service:before{content:"󰪭"}.mdi-dog-side:before{content:"󰩄"}.mdi-dog-side-off:before{content:"󱛮"}.mdi-dolby:before{content:"󰚳"}.mdi-dolly:before{content:"󰺞"}.mdi-dolphin:before{content:"󱢴"}.mdi-domain:before{content:"󰇗"}.mdi-domain-off:before{content:"󰵯"}.mdi-domain-plus:before{content:"󱂭"}.mdi-domain-remove:before{content:"󱂮"}.mdi-domain-switch:before{content:"󱰬"}.mdi-dome-light:before{content:"󱐞"}.mdi-domino-mask:before{content:"󱀣"}.mdi-donkey:before{content:"󰟂"}.mdi-door:before{content:"󰠚"}.mdi-door-closed:before{content:"󰠛"}.mdi-door-closed-lock:before{content:"󱂯"}.mdi-door-open:before{content:"󰠜"}.mdi-door-sliding:before{content:"󱠞"}.mdi-door-sliding-lock:before{content:"󱠟"}.mdi-door-sliding-open:before{content:"󱠠"}.mdi-doorbell:before{content:"󱋦"}.mdi-doorbell-video:before{content:"󰡩"}.mdi-dot-net:before{content:"󰪮"}.mdi-dots-circle:before{content:"󱥸"}.mdi-dots-grid:before{content:"󱗼"}.mdi-dots-hexagon:before{content:"󱗿"}.mdi-dots-horizontal:before{content:"󰇘"}.mdi-dots-horizontal-circle:before{content:"󰟃"}.mdi-dots-horizontal-circle-outline:before{content:"󰮍"}.mdi-dots-square:before{content:"󱗽"}.mdi-dots-triangle:before{content:"󱗾"}.mdi-dots-vertical:before{content:"󰇙"}.mdi-dots-vertical-circle:before{content:"󰟄"}.mdi-dots-vertical-circle-outline:before{content:"󰮎"}.mdi-download:before{content:"󰇚"}.mdi-download-box:before{content:"󱑢"}.mdi-download-box-outline:before{content:"󱑣"}.mdi-download-circle:before{content:"󱑤"}.mdi-download-circle-outline:before{content:"󱑥"}.mdi-download-lock:before{content:"󱌠"}.mdi-download-lock-outline:before{content:"󱌡"}.mdi-download-multiple:before{content:"󰧩"}.mdi-download-network:before{content:"󰛴"}.mdi-download-network-outline:before{content:"󰱦"}.mdi-download-off:before{content:"󱂰"}.mdi-download-off-outline:before{content:"󱂱"}.mdi-download-outline:before{content:"󰮏"}.mdi-drag:before{content:"󰇛"}.mdi-drag-horizontal:before{content:"󰇜"}.mdi-drag-horizontal-variant:before{content:"󱋰"}.mdi-drag-variant:before{content:"󰮐"}.mdi-drag-vertical:before{content:"󰇝"}.mdi-drag-vertical-variant:before{content:"󱋱"}.mdi-drama-masks:before{content:"󰴂"}.mdi-draw:before{content:"󰽉"}.mdi-draw-pen:before{content:"󱦹"}.mdi-drawing:before{content:"󰇞"}.mdi-drawing-box:before{content:"󰇟"}.mdi-dresser:before{content:"󰽊"}.mdi-dresser-outline:before{content:"󰽋"}.mdi-drone:before{content:"󰇢"}.mdi-dropbox:before{content:"󰇣"}.mdi-drupal:before{content:"󰇤"}.mdi-duck:before{content:"󰇥"}.mdi-dumbbell:before{content:"󰇦"}.mdi-dump-truck:before{content:"󰱧"}.mdi-ear-hearing:before{content:"󰟅"}.mdi-ear-hearing-loop:before{content:"󱫮"}.mdi-ear-hearing-off:before{content:"󰩅"}.mdi-earbuds:before{content:"󱡏"}.mdi-earbuds-off:before{content:"󱡐"}.mdi-earbuds-off-outline:before{content:"󱡑"}.mdi-earbuds-outline:before{content:"󱡒"}.mdi-earth:before{content:"󰇧"}.mdi-earth-arrow-right:before{content:"󱌑"}.mdi-earth-box:before{content:"󰛍"}.mdi-earth-box-minus:before{content:"󱐇"}.mdi-earth-box-off:before{content:"󰛎"}.mdi-earth-box-plus:before{content:"󱐆"}.mdi-earth-box-remove:before{content:"󱐈"}.mdi-earth-minus:before{content:"󱐄"}.mdi-earth-off:before{content:"󰇨"}.mdi-earth-plus:before{content:"󱐃"}.mdi-earth-remove:before{content:"󱐅"}.mdi-egg:before{content:"󰪯"}.mdi-egg-easter:before{content:"󰪰"}.mdi-egg-fried:before{content:"󱡊"}.mdi-egg-off:before{content:"󱏰"}.mdi-egg-off-outline:before{content:"󱏱"}.mdi-egg-outline:before{content:"󱏲"}.mdi-eiffel-tower:before{content:"󱕫"}.mdi-eight-track:before{content:"󰧪"}.mdi-eject:before{content:"󰇪"}.mdi-eject-circle:before{content:"󱬣"}.mdi-eject-circle-outline:before{content:"󱬤"}.mdi-eject-outline:before{content:"󰮑"}.mdi-electric-switch:before{content:"󰺟"}.mdi-electric-switch-closed:before{content:"󱃙"}.mdi-electron-framework:before{content:"󱀤"}.mdi-elephant:before{content:"󰟆"}.mdi-elevation-decline:before{content:"󰇫"}.mdi-elevation-rise:before{content:"󰇬"}.mdi-elevator:before{content:"󰇭"}.mdi-elevator-down:before{content:"󱋂"}.mdi-elevator-passenger:before{content:"󱎁"}.mdi-elevator-passenger-off:before{content:"󱥹"}.mdi-elevator-passenger-off-outline:before{content:"󱥺"}.mdi-elevator-passenger-outline:before{content:"󱥻"}.mdi-elevator-up:before{content:"󱋁"}.mdi-ellipse:before{content:"󰺠"}.mdi-ellipse-outline:before{content:"󰺡"}.mdi-email:before{content:"󰇮"}.mdi-email-alert:before{content:"󰛏"}.mdi-email-alert-outline:before{content:"󰵂"}.mdi-email-arrow-left:before{content:"󱃚"}.mdi-email-arrow-left-outline:before{content:"󱃛"}.mdi-email-arrow-right:before{content:"󱃜"}.mdi-email-arrow-right-outline:before{content:"󱃝"}.mdi-email-box:before{content:"󰴃"}.mdi-email-check:before{content:"󰪱"}.mdi-email-check-outline:before{content:"󰪲"}.mdi-email-edit:before{content:"󰻣"}.mdi-email-edit-outline:before{content:"󰻤"}.mdi-email-fast:before{content:"󱡯"}.mdi-email-fast-outline:before{content:"󱡰"}.mdi-email-heart-outline:before{content:"󱱛"}.mdi-email-lock:before{content:"󰇱"}.mdi-email-lock-outline:before{content:"󱭡"}.mdi-email-mark-as-unread:before{content:"󰮒"}.mdi-email-minus:before{content:"󰻥"}.mdi-email-minus-outline:before{content:"󰻦"}.mdi-email-multiple:before{content:"󰻧"}.mdi-email-multiple-outline:before{content:"󰻨"}.mdi-email-newsletter:before{content:"󰾱"}.mdi-email-off:before{content:"󱏣"}.mdi-email-off-outline:before{content:"󱏤"}.mdi-email-open:before{content:"󰇯"}.mdi-email-open-heart-outline:before{content:"󱱜"}.mdi-email-open-multiple:before{content:"󰻩"}.mdi-email-open-multiple-outline:before{content:"󰻪"}.mdi-email-open-outline:before{content:"󰗯"}.mdi-email-outline:before{content:"󰇰"}.mdi-email-plus:before{content:"󰧫"}.mdi-email-plus-outline:before{content:"󰧬"}.mdi-email-remove:before{content:"󱙡"}.mdi-email-remove-outline:before{content:"󱙢"}.mdi-email-seal:before{content:"󱥛"}.mdi-email-seal-outline:before{content:"󱥜"}.mdi-email-search:before{content:"󰥡"}.mdi-email-search-outline:before{content:"󰥢"}.mdi-email-sync:before{content:"󱋇"}.mdi-email-sync-outline:before{content:"󱋈"}.mdi-email-variant:before{content:"󰗰"}.mdi-ember:before{content:"󰬰"}.mdi-emby:before{content:"󰚴"}.mdi-emoticon:before{content:"󰱨"}.mdi-emoticon-angry:before{content:"󰱩"}.mdi-emoticon-angry-outline:before{content:"󰱪"}.mdi-emoticon-confused:before{content:"󱃞"}.mdi-emoticon-confused-outline:before{content:"󱃟"}.mdi-emoticon-cool:before{content:"󰱫"}.mdi-emoticon-cool-outline:before{content:"󰇳"}.mdi-emoticon-cry:before{content:"󰱬"}.mdi-emoticon-cry-outline:before{content:"󰱭"}.mdi-emoticon-dead:before{content:"󰱮"}.mdi-emoticon-dead-outline:before{content:"󰚛"}.mdi-emoticon-devil:before{content:"󰱯"}.mdi-emoticon-devil-outline:before{content:"󰇴"}.mdi-emoticon-excited:before{content:"󰱰"}.mdi-emoticon-excited-outline:before{content:"󰚜"}.mdi-emoticon-frown:before{content:"󰽌"}.mdi-emoticon-frown-outline:before{content:"󰽍"}.mdi-emoticon-happy:before{content:"󰱱"}.mdi-emoticon-happy-outline:before{content:"󰇵"}.mdi-emoticon-kiss:before{content:"󰱲"}.mdi-emoticon-kiss-outline:before{content:"󰱳"}.mdi-emoticon-lol:before{content:"󱈔"}.mdi-emoticon-lol-outline:before{content:"󱈕"}.mdi-emoticon-neutral:before{content:"󰱴"}.mdi-emoticon-neutral-outline:before{content:"󰇶"}.mdi-emoticon-outline:before{content:"󰇲"}.mdi-emoticon-poop:before{content:"󰇷"}.mdi-emoticon-poop-outline:before{content:"󰱵"}.mdi-emoticon-sad:before{content:"󰱶"}.mdi-emoticon-sad-outline:before{content:"󰇸"}.mdi-emoticon-sick:before{content:"󱕼"}.mdi-emoticon-sick-outline:before{content:"󱕽"}.mdi-emoticon-tongue:before{content:"󰇹"}.mdi-emoticon-tongue-outline:before{content:"󰱷"}.mdi-emoticon-wink:before{content:"󰱸"}.mdi-emoticon-wink-outline:before{content:"󰱹"}.mdi-engine:before{content:"󰇺"}.mdi-engine-off:before{content:"󰩆"}.mdi-engine-off-outline:before{content:"󰩇"}.mdi-engine-outline:before{content:"󰇻"}.mdi-epsilon:before{content:"󱃠"}.mdi-equal:before{content:"󰇼"}.mdi-equal-box:before{content:"󰇽"}.mdi-equalizer:before{content:"󰺢"}.mdi-equalizer-outline:before{content:"󰺣"}.mdi-eraser:before{content:"󰇾"}.mdi-eraser-variant:before{content:"󰙂"}.mdi-escalator:before{content:"󰇿"}.mdi-escalator-box:before{content:"󱎙"}.mdi-escalator-down:before{content:"󱋀"}.mdi-escalator-up:before{content:"󱊿"}.mdi-eslint:before{content:"󰱺"}.mdi-et:before{content:"󰪳"}.mdi-ethereum:before{content:"󰡪"}.mdi-ethernet:before{content:"󰈀"}.mdi-ethernet-cable:before{content:"󰈁"}.mdi-ethernet-cable-off:before{content:"󰈂"}.mdi-ev-plug-ccs1:before{content:"󱔙"}.mdi-ev-plug-ccs2:before{content:"󱔚"}.mdi-ev-plug-chademo:before{content:"󱔛"}.mdi-ev-plug-tesla:before{content:"󱔜"}.mdi-ev-plug-type1:before{content:"󱔝"}.mdi-ev-plug-type2:before{content:"󱔞"}.mdi-ev-station:before{content:"󰗱"}.mdi-evernote:before{content:"󰈄"}.mdi-excavator:before{content:"󱀥"}.mdi-exclamation:before{content:"󰈅"}.mdi-exclamation-thick:before{content:"󱈸"}.mdi-exit-run:before{content:"󰩈"}.mdi-exit-to-app:before{content:"󰈆"}.mdi-expand-all:before{content:"󰪴"}.mdi-expand-all-outline:before{content:"󰪵"}.mdi-expansion-card:before{content:"󰢮"}.mdi-expansion-card-variant:before{content:"󰾲"}.mdi-exponent:before{content:"󰥣"}.mdi-exponent-box:before{content:"󰥤"}.mdi-export:before{content:"󰈇"}.mdi-export-variant:before{content:"󰮓"}.mdi-eye:before{content:"󰈈"}.mdi-eye-arrow-left:before{content:"󱣽"}.mdi-eye-arrow-left-outline:before{content:"󱣾"}.mdi-eye-arrow-right:before{content:"󱣿"}.mdi-eye-arrow-right-outline:before{content:"󱤀"}.mdi-eye-check:before{content:"󰴄"}.mdi-eye-check-outline:before{content:"󰴅"}.mdi-eye-circle:before{content:"󰮔"}.mdi-eye-circle-outline:before{content:"󰮕"}.mdi-eye-lock:before{content:"󱰆"}.mdi-eye-lock-open:before{content:"󱰇"}.mdi-eye-lock-open-outline:before{content:"󱰈"}.mdi-eye-lock-outline:before{content:"󱰉"}.mdi-eye-minus:before{content:"󱀦"}.mdi-eye-minus-outline:before{content:"󱀧"}.mdi-eye-off:before{content:"󰈉"}.mdi-eye-off-outline:before{content:"󰛑"}.mdi-eye-outline:before{content:"󰛐"}.mdi-eye-plus:before{content:"󰡫"}.mdi-eye-plus-outline:before{content:"󰡬"}.mdi-eye-refresh:before{content:"󱥼"}.mdi-eye-refresh-outline:before{content:"󱥽"}.mdi-eye-remove:before{content:"󱗣"}.mdi-eye-remove-outline:before{content:"󱗤"}.mdi-eye-settings:before{content:"󰡭"}.mdi-eye-settings-outline:before{content:"󰡮"}.mdi-eyedropper:before{content:"󰈊"}.mdi-eyedropper-minus:before{content:"󱏝"}.mdi-eyedropper-off:before{content:"󱏟"}.mdi-eyedropper-plus:before{content:"󱏜"}.mdi-eyedropper-remove:before{content:"󱏞"}.mdi-eyedropper-variant:before{content:"󰈋"}.mdi-face-agent:before{content:"󰵰"}.mdi-face-man:before{content:"󰙃"}.mdi-face-man-outline:before{content:"󰮖"}.mdi-face-man-profile:before{content:"󰙄"}.mdi-face-man-shimmer:before{content:"󱗌"}.mdi-face-man-shimmer-outline:before{content:"󱗍"}.mdi-face-mask:before{content:"󱖆"}.mdi-face-mask-outline:before{content:"󱖇"}.mdi-face-recognition:before{content:"󰱻"}.mdi-face-woman:before{content:"󱁷"}.mdi-face-woman-outline:before{content:"󱁸"}.mdi-face-woman-profile:before{content:"󱁶"}.mdi-face-woman-shimmer:before{content:"󱗎"}.mdi-face-woman-shimmer-outline:before{content:"󱗏"}.mdi-facebook:before{content:"󰈌"}.mdi-facebook-gaming:before{content:"󰟝"}.mdi-facebook-messenger:before{content:"󰈎"}.mdi-facebook-workplace:before{content:"󰬱"}.mdi-factory:before{content:"󰈏"}.mdi-family-tree:before{content:"󱘎"}.mdi-fan:before{content:"󰈐"}.mdi-fan-alert:before{content:"󱑬"}.mdi-fan-auto:before{content:"󱜝"}.mdi-fan-chevron-down:before{content:"󱑭"}.mdi-fan-chevron-up:before{content:"󱑮"}.mdi-fan-clock:before{content:"󱨺"}.mdi-fan-minus:before{content:"󱑰"}.mdi-fan-off:before{content:"󰠝"}.mdi-fan-plus:before{content:"󱑯"}.mdi-fan-remove:before{content:"󱑱"}.mdi-fan-speed-1:before{content:"󱑲"}.mdi-fan-speed-2:before{content:"󱑳"}.mdi-fan-speed-3:before{content:"󱑴"}.mdi-fast-forward:before{content:"󰈑"}.mdi-fast-forward-10:before{content:"󰵱"}.mdi-fast-forward-15:before{content:"󱤺"}.mdi-fast-forward-30:before{content:"󰴆"}.mdi-fast-forward-45:before{content:"󱬒"}.mdi-fast-forward-5:before{content:"󱇸"}.mdi-fast-forward-60:before{content:"󱘋"}.mdi-fast-forward-outline:before{content:"󰛒"}.mdi-faucet:before{content:"󱬩"}.mdi-faucet-variant:before{content:"󱬪"}.mdi-fax:before{content:"󰈒"}.mdi-feather:before{content:"󰛓"}.mdi-feature-search:before{content:"󰩉"}.mdi-feature-search-outline:before{content:"󰩊"}.mdi-fedora:before{content:"󰣛"}.mdi-fence:before{content:"󱞚"}.mdi-fence-electric:before{content:"󱟶"}.mdi-fencing:before{content:"󱓁"}.mdi-ferris-wheel:before{content:"󰺤"}.mdi-ferry:before{content:"󰈓"}.mdi-file:before{content:"󰈔"}.mdi-file-account:before{content:"󰜻"}.mdi-file-account-outline:before{content:"󱀨"}.mdi-file-alert:before{content:"󰩋"}.mdi-file-alert-outline:before{content:"󰩌"}.mdi-file-arrow-left-right:before{content:"󱪓"}.mdi-file-arrow-left-right-outline:before{content:"󱪔"}.mdi-file-arrow-up-down:before{content:"󱪕"}.mdi-file-arrow-up-down-outline:before{content:"󱪖"}.mdi-file-cabinet:before{content:"󰪶"}.mdi-file-cad:before{content:"󰻫"}.mdi-file-cad-box:before{content:"󰻬"}.mdi-file-cancel:before{content:"󰷆"}.mdi-file-cancel-outline:before{content:"󰷇"}.mdi-file-certificate:before{content:"󱆆"}.mdi-file-certificate-outline:before{content:"󱆇"}.mdi-file-chart:before{content:"󰈕"}.mdi-file-chart-check:before{content:"󱧆"}.mdi-file-chart-check-outline:before{content:"󱧇"}.mdi-file-chart-outline:before{content:"󱀩"}.mdi-file-check:before{content:"󰈖"}.mdi-file-check-outline:before{content:"󰸩"}.mdi-file-clock:before{content:"󱋡"}.mdi-file-clock-outline:before{content:"󱋢"}.mdi-file-cloud:before{content:"󰈗"}.mdi-file-cloud-outline:before{content:"󱀪"}.mdi-file-code:before{content:"󰈮"}.mdi-file-code-outline:before{content:"󱀫"}.mdi-file-cog:before{content:"󱁻"}.mdi-file-cog-outline:before{content:"󱁼"}.mdi-file-compare:before{content:"󰢪"}.mdi-file-delimited:before{content:"󰈘"}.mdi-file-delimited-outline:before{content:"󰺥"}.mdi-file-document:before{content:"󰈙"}.mdi-file-document-alert:before{content:"󱪗"}.mdi-file-document-alert-outline:before{content:"󱪘"}.mdi-file-document-arrow-right:before{content:"󱰏"}.mdi-file-document-arrow-right-outline:before{content:"󱰐"}.mdi-file-document-check:before{content:"󱪙"}.mdi-file-document-check-outline:before{content:"󱪚"}.mdi-file-document-edit:before{content:"󰷈"}.mdi-file-document-edit-outline:before{content:"󰷉"}.mdi-file-document-minus:before{content:"󱪛"}.mdi-file-document-minus-outline:before{content:"󱪜"}.mdi-file-document-multiple:before{content:"󱔗"}.mdi-file-document-multiple-outline:before{content:"󱔘"}.mdi-file-document-outline:before{content:"󰧮"}.mdi-file-document-plus:before{content:"󱪝"}.mdi-file-document-plus-outline:before{content:"󱪞"}.mdi-file-document-refresh:before{content:"󱱺"}.mdi-file-document-refresh-outline:before{content:"󱱻"}.mdi-file-document-remove:before{content:"󱪟"}.mdi-file-document-remove-outline:before{content:"󱪠"}.mdi-file-download:before{content:"󰥥"}.mdi-file-download-outline:before{content:"󰥦"}.mdi-file-edit:before{content:"󱇧"}.mdi-file-edit-outline:before{content:"󱇨"}.mdi-file-excel:before{content:"󰈛"}.mdi-file-excel-box:before{content:"󰈜"}.mdi-file-excel-box-outline:before{content:"󱀬"}.mdi-file-excel-outline:before{content:"󱀭"}.mdi-file-export:before{content:"󰈝"}.mdi-file-export-outline:before{content:"󱀮"}.mdi-file-eye:before{content:"󰷊"}.mdi-file-eye-outline:before{content:"󰷋"}.mdi-file-find:before{content:"󰈞"}.mdi-file-find-outline:before{content:"󰮗"}.mdi-file-gif-box:before{content:"󰵸"}.mdi-file-hidden:before{content:"󰘓"}.mdi-file-image:before{content:"󰈟"}.mdi-file-image-marker:before{content:"󱝲"}.mdi-file-image-marker-outline:before{content:"󱝳"}.mdi-file-image-minus:before{content:"󱤻"}.mdi-file-image-minus-outline:before{content:"󱤼"}.mdi-file-image-outline:before{content:"󰺰"}.mdi-file-image-plus:before{content:"󱤽"}.mdi-file-image-plus-outline:before{content:"󱤾"}.mdi-file-image-remove:before{content:"󱤿"}.mdi-file-image-remove-outline:before{content:"󱥀"}.mdi-file-import:before{content:"󰈠"}.mdi-file-import-outline:before{content:"󱀯"}.mdi-file-jpg-box:before{content:"󰈥"}.mdi-file-key:before{content:"󱆄"}.mdi-file-key-outline:before{content:"󱆅"}.mdi-file-link:before{content:"󱅷"}.mdi-file-link-outline:before{content:"󱅸"}.mdi-file-lock:before{content:"󰈡"}.mdi-file-lock-open:before{content:"󱧈"}.mdi-file-lock-open-outline:before{content:"󱧉"}.mdi-file-lock-outline:before{content:"󱀰"}.mdi-file-marker:before{content:"󱝴"}.mdi-file-marker-outline:before{content:"󱝵"}.mdi-file-minus:before{content:"󱪡"}.mdi-file-minus-outline:before{content:"󱪢"}.mdi-file-move:before{content:"󰪹"}.mdi-file-move-outline:before{content:"󱀱"}.mdi-file-multiple:before{content:"󰈢"}.mdi-file-multiple-outline:before{content:"󱀲"}.mdi-file-music:before{content:"󰈣"}.mdi-file-music-outline:before{content:"󰸪"}.mdi-file-outline:before{content:"󰈤"}.mdi-file-pdf-box:before{content:"󰈦"}.mdi-file-percent:before{content:"󰠞"}.mdi-file-percent-outline:before{content:"󱀳"}.mdi-file-phone:before{content:"󱅹"}.mdi-file-phone-outline:before{content:"󱅺"}.mdi-file-plus:before{content:"󰝒"}.mdi-file-plus-outline:before{content:"󰻭"}.mdi-file-png-box:before{content:"󰸭"}.mdi-file-powerpoint:before{content:"󰈧"}.mdi-file-powerpoint-box:before{content:"󰈨"}.mdi-file-powerpoint-box-outline:before{content:"󱀴"}.mdi-file-powerpoint-outline:before{content:"󱀵"}.mdi-file-presentation-box:before{content:"󰈩"}.mdi-file-question:before{content:"󰡯"}.mdi-file-question-outline:before{content:"󱀶"}.mdi-file-refresh:before{content:"󰤘"}.mdi-file-refresh-outline:before{content:"󰕁"}.mdi-file-remove:before{content:"󰮘"}.mdi-file-remove-outline:before{content:"󱀷"}.mdi-file-replace:before{content:"󰬲"}.mdi-file-replace-outline:before{content:"󰬳"}.mdi-file-restore:before{content:"󰙰"}.mdi-file-restore-outline:before{content:"󱀸"}.mdi-file-rotate-left:before{content:"󱨻"}.mdi-file-rotate-left-outline:before{content:"󱨼"}.mdi-file-rotate-right:before{content:"󱨽"}.mdi-file-rotate-right-outline:before{content:"󱨾"}.mdi-file-search:before{content:"󰱼"}.mdi-file-search-outline:before{content:"󰱽"}.mdi-file-send:before{content:"󰈪"}.mdi-file-send-outline:before{content:"󱀹"}.mdi-file-settings:before{content:"󱁹"}.mdi-file-settings-outline:before{content:"󱁺"}.mdi-file-sign:before{content:"󱧃"}.mdi-file-star:before{content:"󱀺"}.mdi-file-star-four-points:before{content:"󱰭"}.mdi-file-star-four-points-outline:before{content:"󱰮"}.mdi-file-star-outline:before{content:"󱀻"}.mdi-file-swap:before{content:"󰾴"}.mdi-file-swap-outline:before{content:"󰾵"}.mdi-file-sync:before{content:"󱈖"}.mdi-file-sync-outline:before{content:"󱈗"}.mdi-file-table:before{content:"󰱾"}.mdi-file-table-box:before{content:"󱃡"}.mdi-file-table-box-multiple:before{content:"󱃢"}.mdi-file-table-box-multiple-outline:before{content:"󱃣"}.mdi-file-table-box-outline:before{content:"󱃤"}.mdi-file-table-outline:before{content:"󰱿"}.mdi-file-tree:before{content:"󰙅"}.mdi-file-tree-outline:before{content:"󱏒"}.mdi-file-undo:before{content:"󰣜"}.mdi-file-undo-outline:before{content:"󱀼"}.mdi-file-upload:before{content:"󰩍"}.mdi-file-upload-outline:before{content:"󰩎"}.mdi-file-video:before{content:"󰈫"}.mdi-file-video-outline:before{content:"󰸬"}.mdi-file-word:before{content:"󰈬"}.mdi-file-word-box:before{content:"󰈭"}.mdi-file-word-box-outline:before{content:"󱀽"}.mdi-file-word-outline:before{content:"󱀾"}.mdi-file-xml-box:before{content:"󱭋"}.mdi-film:before{content:"󰈯"}.mdi-filmstrip:before{content:"󰈰"}.mdi-filmstrip-box:before{content:"󰌲"}.mdi-filmstrip-box-multiple:before{content:"󰴘"}.mdi-filmstrip-off:before{content:"󰈱"}.mdi-filter:before{content:"󰈲"}.mdi-filter-check:before{content:"󱣬"}.mdi-filter-check-outline:before{content:"󱣭"}.mdi-filter-cog:before{content:"󱪣"}.mdi-filter-cog-outline:before{content:"󱪤"}.mdi-filter-menu:before{content:"󱃥"}.mdi-filter-menu-outline:before{content:"󱃦"}.mdi-filter-minus:before{content:"󰻮"}.mdi-filter-minus-outline:before{content:"󰻯"}.mdi-filter-multiple:before{content:"󱨿"}.mdi-filter-multiple-outline:before{content:"󱩀"}.mdi-filter-off:before{content:"󱓯"}.mdi-filter-off-outline:before{content:"󱓰"}.mdi-filter-outline:before{content:"󰈳"}.mdi-filter-plus:before{content:"󰻰"}.mdi-filter-plus-outline:before{content:"󰻱"}.mdi-filter-remove:before{content:"󰈴"}.mdi-filter-remove-outline:before{content:"󰈵"}.mdi-filter-settings:before{content:"󱪥"}.mdi-filter-settings-outline:before{content:"󱪦"}.mdi-filter-variant:before{content:"󰈶"}.mdi-filter-variant-minus:before{content:"󱄒"}.mdi-filter-variant-plus:before{content:"󱄓"}.mdi-filter-variant-remove:before{content:"󱀿"}.mdi-finance:before{content:"󰠟"}.mdi-find-replace:before{content:"󰛔"}.mdi-fingerprint:before{content:"󰈷"}.mdi-fingerprint-off:before{content:"󰺱"}.mdi-fire:before{content:"󰈸"}.mdi-fire-alert:before{content:"󱗗"}.mdi-fire-circle:before{content:"󱠇"}.mdi-fire-extinguisher:before{content:"󰻲"}.mdi-fire-hydrant:before{content:"󱄷"}.mdi-fire-hydrant-alert:before{content:"󱄸"}.mdi-fire-hydrant-off:before{content:"󱄹"}.mdi-fire-off:before{content:"󱜢"}.mdi-fire-truck:before{content:"󰢫"}.mdi-firebase:before{content:"󰥧"}.mdi-firefox:before{content:"󰈹"}.mdi-fireplace:before{content:"󰸮"}.mdi-fireplace-off:before{content:"󰸯"}.mdi-firewire:before{content:"󰖾"}.mdi-firework:before{content:"󰸰"}.mdi-firework-off:before{content:"󱜣"}.mdi-fish:before{content:"󰈺"}.mdi-fish-off:before{content:"󱏳"}.mdi-fishbowl:before{content:"󰻳"}.mdi-fishbowl-outline:before{content:"󰻴"}.mdi-fit-to-page:before{content:"󰻵"}.mdi-fit-to-page-outline:before{content:"󰻶"}.mdi-fit-to-screen:before{content:"󱣴"}.mdi-fit-to-screen-outline:before{content:"󱣵"}.mdi-flag:before{content:"󰈻"}.mdi-flag-checkered:before{content:"󰈼"}.mdi-flag-minus:before{content:"󰮙"}.mdi-flag-minus-outline:before{content:"󱂲"}.mdi-flag-off:before{content:"󱣮"}.mdi-flag-off-outline:before{content:"󱣯"}.mdi-flag-outline:before{content:"󰈽"}.mdi-flag-plus:before{content:"󰮚"}.mdi-flag-plus-outline:before{content:"󱂳"}.mdi-flag-remove:before{content:"󰮛"}.mdi-flag-remove-outline:before{content:"󱂴"}.mdi-flag-triangle:before{content:"󰈿"}.mdi-flag-variant:before{content:"󰉀"}.mdi-flag-variant-minus:before{content:"󱮴"}.mdi-flag-variant-minus-outline:before{content:"󱮵"}.mdi-flag-variant-off:before{content:"󱮰"}.mdi-flag-variant-off-outline:before{content:"󱮱"}.mdi-flag-variant-outline:before{content:"󰈾"}.mdi-flag-variant-plus:before{content:"󱮲"}.mdi-flag-variant-plus-outline:before{content:"󱮳"}.mdi-flag-variant-remove:before{content:"󱮶"}.mdi-flag-variant-remove-outline:before{content:"󱮷"}.mdi-flare:before{content:"󰵲"}.mdi-flash:before{content:"󰉁"}.mdi-flash-alert:before{content:"󰻷"}.mdi-flash-alert-outline:before{content:"󰻸"}.mdi-flash-auto:before{content:"󰉂"}.mdi-flash-off:before{content:"󰉃"}.mdi-flash-off-outline:before{content:"󱭅"}.mdi-flash-outline:before{content:"󰛕"}.mdi-flash-red-eye:before{content:"󰙻"}.mdi-flash-triangle:before{content:"󱬝"}.mdi-flash-triangle-outline:before{content:"󱬞"}.mdi-flashlight:before{content:"󰉄"}.mdi-flashlight-off:before{content:"󰉅"}.mdi-flask:before{content:"󰂓"}.mdi-flask-empty:before{content:"󰂔"}.mdi-flask-empty-minus:before{content:"󱈺"}.mdi-flask-empty-minus-outline:before{content:"󱈻"}.mdi-flask-empty-off:before{content:"󱏴"}.mdi-flask-empty-off-outline:before{content:"󱏵"}.mdi-flask-empty-outline:before{content:"󰂕"}.mdi-flask-empty-plus:before{content:"󱈼"}.mdi-flask-empty-plus-outline:before{content:"󱈽"}.mdi-flask-empty-remove:before{content:"󱈾"}.mdi-flask-empty-remove-outline:before{content:"󱈿"}.mdi-flask-minus:before{content:"󱉀"}.mdi-flask-minus-outline:before{content:"󱉁"}.mdi-flask-off:before{content:"󱏶"}.mdi-flask-off-outline:before{content:"󱏷"}.mdi-flask-outline:before{content:"󰂖"}.mdi-flask-plus:before{content:"󱉂"}.mdi-flask-plus-outline:before{content:"󱉃"}.mdi-flask-remove:before{content:"󱉄"}.mdi-flask-remove-outline:before{content:"󱉅"}.mdi-flask-round-bottom:before{content:"󱉋"}.mdi-flask-round-bottom-empty:before{content:"󱉌"}.mdi-flask-round-bottom-empty-outline:before{content:"󱉍"}.mdi-flask-round-bottom-outline:before{content:"󱉎"}.mdi-fleur-de-lis:before{content:"󱌃"}.mdi-flip-horizontal:before{content:"󱃧"}.mdi-flip-to-back:before{content:"󰉇"}.mdi-flip-to-front:before{content:"󰉈"}.mdi-flip-vertical:before{content:"󱃨"}.mdi-floor-lamp:before{content:"󰣝"}.mdi-floor-lamp-dual:before{content:"󱁀"}.mdi-floor-lamp-dual-outline:before{content:"󱟎"}.mdi-floor-lamp-outline:before{content:"󱟈"}.mdi-floor-lamp-torchiere:before{content:"󱝇"}.mdi-floor-lamp-torchiere-outline:before{content:"󱟖"}.mdi-floor-lamp-torchiere-variant:before{content:"󱁁"}.mdi-floor-lamp-torchiere-variant-outline:before{content:"󱟏"}.mdi-floor-plan:before{content:"󰠡"}.mdi-floppy:before{content:"󰉉"}.mdi-floppy-variant:before{content:"󰧯"}.mdi-flower:before{content:"󰉊"}.mdi-flower-outline:before{content:"󰧰"}.mdi-flower-pollen:before{content:"󱢅"}.mdi-flower-pollen-outline:before{content:"󱢆"}.mdi-flower-poppy:before{content:"󰴈"}.mdi-flower-tulip:before{content:"󰧱"}.mdi-flower-tulip-outline:before{content:"󰧲"}.mdi-focus-auto:before{content:"󰽎"}.mdi-focus-field:before{content:"󰽏"}.mdi-focus-field-horizontal:before{content:"󰽐"}.mdi-focus-field-vertical:before{content:"󰽑"}.mdi-folder:before{content:"󰉋"}.mdi-folder-account:before{content:"󰉌"}.mdi-folder-account-outline:before{content:"󰮜"}.mdi-folder-alert:before{content:"󰷌"}.mdi-folder-alert-outline:before{content:"󰷍"}.mdi-folder-arrow-down:before{content:"󱧨"}.mdi-folder-arrow-down-outline:before{content:"󱧩"}.mdi-folder-arrow-left:before{content:"󱧪"}.mdi-folder-arrow-left-outline:before{content:"󱧫"}.mdi-folder-arrow-left-right:before{content:"󱧬"}.mdi-folder-arrow-left-right-outline:before{content:"󱧭"}.mdi-folder-arrow-right:before{content:"󱧮"}.mdi-folder-arrow-right-outline:before{content:"󱧯"}.mdi-folder-arrow-up:before{content:"󱧰"}.mdi-folder-arrow-up-down:before{content:"󱧱"}.mdi-folder-arrow-up-down-outline:before{content:"󱧲"}.mdi-folder-arrow-up-outline:before{content:"󱧳"}.mdi-folder-cancel:before{content:"󱧴"}.mdi-folder-cancel-outline:before{content:"󱧵"}.mdi-folder-check:before{content:"󱥾"}.mdi-folder-check-outline:before{content:"󱥿"}.mdi-folder-clock:before{content:"󰪺"}.mdi-folder-clock-outline:before{content:"󰪻"}.mdi-folder-cog:before{content:"󱁿"}.mdi-folder-cog-outline:before{content:"󱂀"}.mdi-folder-download:before{content:"󰉍"}.mdi-folder-download-outline:before{content:"󱃩"}.mdi-folder-edit:before{content:"󰣞"}.mdi-folder-edit-outline:before{content:"󰷎"}.mdi-folder-eye:before{content:"󱞊"}.mdi-folder-eye-outline:before{content:"󱞋"}.mdi-folder-file:before{content:"󱧶"}.mdi-folder-file-outline:before{content:"󱧷"}.mdi-folder-google-drive:before{content:"󰉎"}.mdi-folder-heart:before{content:"󱃪"}.mdi-folder-heart-outline:before{content:"󱃫"}.mdi-folder-hidden:before{content:"󱞞"}.mdi-folder-home:before{content:"󱂵"}.mdi-folder-home-outline:before{content:"󱂶"}.mdi-folder-image:before{content:"󰉏"}.mdi-folder-information:before{content:"󱂷"}.mdi-folder-information-outline:before{content:"󱂸"}.mdi-folder-key:before{content:"󰢬"}.mdi-folder-key-network:before{content:"󰢭"}.mdi-folder-key-network-outline:before{content:"󰲀"}.mdi-folder-key-outline:before{content:"󱃬"}.mdi-folder-lock:before{content:"󰉐"}.mdi-folder-lock-open:before{content:"󰉑"}.mdi-folder-lock-open-outline:before{content:"󱪧"}.mdi-folder-lock-outline:before{content:"󱪨"}.mdi-folder-marker:before{content:"󱉭"}.mdi-folder-marker-outline:before{content:"󱉮"}.mdi-folder-minus:before{content:"󱭉"}.mdi-folder-minus-outline:before{content:"󱭊"}.mdi-folder-move:before{content:"󰉒"}.mdi-folder-move-outline:before{content:"󱉆"}.mdi-folder-multiple:before{content:"󰉓"}.mdi-folder-multiple-image:before{content:"󰉔"}.mdi-folder-multiple-outline:before{content:"󰉕"}.mdi-folder-multiple-plus:before{content:"󱑾"}.mdi-folder-multiple-plus-outline:before{content:"󱑿"}.mdi-folder-music:before{content:"󱍙"}.mdi-folder-music-outline:before{content:"󱍚"}.mdi-folder-network:before{content:"󰡰"}.mdi-folder-network-outline:before{content:"󰲁"}.mdi-folder-off:before{content:"󱧸"}.mdi-folder-off-outline:before{content:"󱧹"}.mdi-folder-open:before{content:"󰝰"}.mdi-folder-open-outline:before{content:"󰷏"}.mdi-folder-outline:before{content:"󰉖"}.mdi-folder-play:before{content:"󱧺"}.mdi-folder-play-outline:before{content:"󱧻"}.mdi-folder-plus:before{content:"󰉗"}.mdi-folder-plus-outline:before{content:"󰮝"}.mdi-folder-pound:before{content:"󰴉"}.mdi-folder-pound-outline:before{content:"󰴊"}.mdi-folder-question:before{content:"󱧊"}.mdi-folder-question-outline:before{content:"󱧋"}.mdi-folder-refresh:before{content:"󰝉"}.mdi-folder-refresh-outline:before{content:"󰕂"}.mdi-folder-remove:before{content:"󰉘"}.mdi-folder-remove-outline:before{content:"󰮞"}.mdi-folder-search:before{content:"󰥨"}.mdi-folder-search-outline:before{content:"󰥩"}.mdi-folder-settings:before{content:"󱁽"}.mdi-folder-settings-outline:before{content:"󱁾"}.mdi-folder-star:before{content:"󰚝"}.mdi-folder-star-multiple:before{content:"󱏓"}.mdi-folder-star-multiple-outline:before{content:"󱏔"}.mdi-folder-star-outline:before{content:"󰮟"}.mdi-folder-swap:before{content:"󰾶"}.mdi-folder-swap-outline:before{content:"󰾷"}.mdi-folder-sync:before{content:"󰴋"}.mdi-folder-sync-outline:before{content:"󰴌"}.mdi-folder-table:before{content:"󱋣"}.mdi-folder-table-outline:before{content:"󱋤"}.mdi-folder-text:before{content:"󰲂"}.mdi-folder-text-outline:before{content:"󰲃"}.mdi-folder-upload:before{content:"󰉙"}.mdi-folder-upload-outline:before{content:"󱃭"}.mdi-folder-wrench:before{content:"󱧼"}.mdi-folder-wrench-outline:before{content:"󱧽"}.mdi-folder-zip:before{content:"󰛫"}.mdi-folder-zip-outline:before{content:"󰞹"}.mdi-font-awesome:before{content:"󰀺"}.mdi-food:before{content:"󰉚"}.mdi-food-apple:before{content:"󰉛"}.mdi-food-apple-outline:before{content:"󰲄"}.mdi-food-croissant:before{content:"󰟈"}.mdi-food-drumstick:before{content:"󱐟"}.mdi-food-drumstick-off:before{content:"󱑨"}.mdi-food-drumstick-off-outline:before{content:"󱑩"}.mdi-food-drumstick-outline:before{content:"󱐠"}.mdi-food-fork-drink:before{content:"󰗲"}.mdi-food-halal:before{content:"󱕲"}.mdi-food-hot-dog:before{content:"󱡋"}.mdi-food-kosher:before{content:"󱕳"}.mdi-food-off:before{content:"󰗳"}.mdi-food-off-outline:before{content:"󱤕"}.mdi-food-outline:before{content:"󱤖"}.mdi-food-steak:before{content:"󱑪"}.mdi-food-steak-off:before{content:"󱑫"}.mdi-food-takeout-box:before{content:"󱠶"}.mdi-food-takeout-box-outline:before{content:"󱠷"}.mdi-food-turkey:before{content:"󱜜"}.mdi-food-variant:before{content:"󰉜"}.mdi-food-variant-off:before{content:"󱏥"}.mdi-foot-print:before{content:"󰽒"}.mdi-football:before{content:"󰉝"}.mdi-football-australian:before{content:"󰉞"}.mdi-football-helmet:before{content:"󰉟"}.mdi-forest:before{content:"󱢗"}.mdi-forest-outline:before{content:"󱱣"}.mdi-forklift:before{content:"󰟉"}.mdi-form-dropdown:before{content:"󱐀"}.mdi-form-select:before{content:"󱐁"}.mdi-form-textarea:before{content:"󱂕"}.mdi-form-textbox:before{content:"󰘎"}.mdi-form-textbox-lock:before{content:"󱍝"}.mdi-form-textbox-password:before{content:"󰟵"}.mdi-format-align-bottom:before{content:"󰝓"}.mdi-format-align-center:before{content:"󰉠"}.mdi-format-align-justify:before{content:"󰉡"}.mdi-format-align-left:before{content:"󰉢"}.mdi-format-align-middle:before{content:"󰝔"}.mdi-format-align-right:before{content:"󰉣"}.mdi-format-align-top:before{content:"󰝕"}.mdi-format-annotation-minus:before{content:"󰪼"}.mdi-format-annotation-plus:before{content:"󰙆"}.mdi-format-bold:before{content:"󰉤"}.mdi-format-clear:before{content:"󰉥"}.mdi-format-color-fill:before{content:"󰉦"}.mdi-format-color-highlight:before{content:"󰸱"}.mdi-format-color-marker-cancel:before{content:"󱌓"}.mdi-format-color-text:before{content:"󰚞"}.mdi-format-columns:before{content:"󰣟"}.mdi-format-float-center:before{content:"󰉧"}.mdi-format-float-left:before{content:"󰉨"}.mdi-format-float-none:before{content:"󰉩"}.mdi-format-float-right:before{content:"󰉪"}.mdi-format-font:before{content:"󰛖"}.mdi-format-font-size-decrease:before{content:"󰧳"}.mdi-format-font-size-increase:before{content:"󰧴"}.mdi-format-header-1:before{content:"󰉫"}.mdi-format-header-2:before{content:"󰉬"}.mdi-format-header-3:before{content:"󰉭"}.mdi-format-header-4:before{content:"󰉮"}.mdi-format-header-5:before{content:"󰉯"}.mdi-format-header-6:before{content:"󰉰"}.mdi-format-header-decrease:before{content:"󰉱"}.mdi-format-header-equal:before{content:"󰉲"}.mdi-format-header-increase:before{content:"󰉳"}.mdi-format-header-pound:before{content:"󰉴"}.mdi-format-horizontal-align-center:before{content:"󰘞"}.mdi-format-horizontal-align-left:before{content:"󰘟"}.mdi-format-horizontal-align-right:before{content:"󰘠"}.mdi-format-indent-decrease:before{content:"󰉵"}.mdi-format-indent-increase:before{content:"󰉶"}.mdi-format-italic:before{content:"󰉷"}.mdi-format-letter-case:before{content:"󰬴"}.mdi-format-letter-case-lower:before{content:"󰬵"}.mdi-format-letter-case-upper:before{content:"󰬶"}.mdi-format-letter-ends-with:before{content:"󰾸"}.mdi-format-letter-matches:before{content:"󰾹"}.mdi-format-letter-spacing:before{content:"󱥖"}.mdi-format-letter-spacing-variant:before{content:"󱫻"}.mdi-format-letter-starts-with:before{content:"󰾺"}.mdi-format-line-height:before{content:"󱫼"}.mdi-format-line-spacing:before{content:"󰉸"}.mdi-format-line-style:before{content:"󰗈"}.mdi-format-line-weight:before{content:"󰗉"}.mdi-format-list-bulleted:before{content:"󰉹"}.mdi-format-list-bulleted-square:before{content:"󰷐"}.mdi-format-list-bulleted-triangle:before{content:"󰺲"}.mdi-format-list-bulleted-type:before{content:"󰉺"}.mdi-format-list-checkbox:before{content:"󰥪"}.mdi-format-list-checks:before{content:"󰝖"}.mdi-format-list-group:before{content:"󱡠"}.mdi-format-list-group-plus:before{content:"󱭖"}.mdi-format-list-numbered:before{content:"󰉻"}.mdi-format-list-numbered-rtl:before{content:"󰴍"}.mdi-format-list-text:before{content:"󱉯"}.mdi-format-overline:before{content:"󰺳"}.mdi-format-page-break:before{content:"󰛗"}.mdi-format-page-split:before{content:"󱤗"}.mdi-format-paint:before{content:"󰉼"}.mdi-format-paragraph:before{content:"󰉽"}.mdi-format-paragraph-spacing:before{content:"󱫽"}.mdi-format-pilcrow:before{content:"󰛘"}.mdi-format-pilcrow-arrow-left:before{content:"󰊆"}.mdi-format-pilcrow-arrow-right:before{content:"󰊅"}.mdi-format-quote-close:before{content:"󰉾"}.mdi-format-quote-close-outline:before{content:"󱆨"}.mdi-format-quote-open:before{content:"󰝗"}.mdi-format-quote-open-outline:before{content:"󱆧"}.mdi-format-rotate-90:before{content:"󰚪"}.mdi-format-section:before{content:"󰚟"}.mdi-format-size:before{content:"󰉿"}.mdi-format-strikethrough:before{content:"󰊀"}.mdi-format-strikethrough-variant:before{content:"󰊁"}.mdi-format-subscript:before{content:"󰊂"}.mdi-format-superscript:before{content:"󰊃"}.mdi-format-text:before{content:"󰊄"}.mdi-format-text-rotation-angle-down:before{content:"󰾻"}.mdi-format-text-rotation-angle-up:before{content:"󰾼"}.mdi-format-text-rotation-down:before{content:"󰵳"}.mdi-format-text-rotation-down-vertical:before{content:"󰾽"}.mdi-format-text-rotation-none:before{content:"󰵴"}.mdi-format-text-rotation-up:before{content:"󰾾"}.mdi-format-text-rotation-vertical:before{content:"󰾿"}.mdi-format-text-variant:before{content:"󰸲"}.mdi-format-text-variant-outline:before{content:"󱔏"}.mdi-format-text-wrapping-clip:before{content:"󰴎"}.mdi-format-text-wrapping-overflow:before{content:"󰴏"}.mdi-format-text-wrapping-wrap:before{content:"󰴐"}.mdi-format-textbox:before{content:"󰴑"}.mdi-format-title:before{content:"󰗴"}.mdi-format-underline:before{content:"󰊇"}.mdi-format-underline-wavy:before{content:"󱣩"}.mdi-format-vertical-align-bottom:before{content:"󰘡"}.mdi-format-vertical-align-center:before{content:"󰘢"}.mdi-format-vertical-align-top:before{content:"󰘣"}.mdi-format-wrap-inline:before{content:"󰊈"}.mdi-format-wrap-square:before{content:"󰊉"}.mdi-format-wrap-tight:before{content:"󰊊"}.mdi-format-wrap-top-bottom:before{content:"󰊋"}.mdi-forum:before{content:"󰊌"}.mdi-forum-minus:before{content:"󱪩"}.mdi-forum-minus-outline:before{content:"󱪪"}.mdi-forum-outline:before{content:"󰠢"}.mdi-forum-plus:before{content:"󱪫"}.mdi-forum-plus-outline:before{content:"󱪬"}.mdi-forum-remove:before{content:"󱪭"}.mdi-forum-remove-outline:before{content:"󱪮"}.mdi-forward:before{content:"󰊍"}.mdi-forwardburger:before{content:"󰵵"}.mdi-fountain:before{content:"󰥫"}.mdi-fountain-pen:before{content:"󰴒"}.mdi-fountain-pen-tip:before{content:"󰴓"}.mdi-fraction-one-half:before{content:"󱦒"}.mdi-freebsd:before{content:"󰣠"}.mdi-french-fries:before{content:"󱥗"}.mdi-frequently-asked-questions:before{content:"󰺴"}.mdi-fridge:before{content:"󰊐"}.mdi-fridge-alert:before{content:"󱆱"}.mdi-fridge-alert-outline:before{content:"󱆲"}.mdi-fridge-bottom:before{content:"󰊒"}.mdi-fridge-industrial:before{content:"󱗮"}.mdi-fridge-industrial-alert:before{content:"󱗯"}.mdi-fridge-industrial-alert-outline:before{content:"󱗰"}.mdi-fridge-industrial-off:before{content:"󱗱"}.mdi-fridge-industrial-off-outline:before{content:"󱗲"}.mdi-fridge-industrial-outline:before{content:"󱗳"}.mdi-fridge-off:before{content:"󱆯"}.mdi-fridge-off-outline:before{content:"󱆰"}.mdi-fridge-outline:before{content:"󰊏"}.mdi-fridge-top:before{content:"󰊑"}.mdi-fridge-variant:before{content:"󱗴"}.mdi-fridge-variant-alert:before{content:"󱗵"}.mdi-fridge-variant-alert-outline:before{content:"󱗶"}.mdi-fridge-variant-off:before{content:"󱗷"}.mdi-fridge-variant-off-outline:before{content:"󱗸"}.mdi-fridge-variant-outline:before{content:"󱗹"}.mdi-fruit-cherries:before{content:"󱁂"}.mdi-fruit-cherries-off:before{content:"󱏸"}.mdi-fruit-citrus:before{content:"󱁃"}.mdi-fruit-citrus-off:before{content:"󱏹"}.mdi-fruit-grapes:before{content:"󱁄"}.mdi-fruit-grapes-outline:before{content:"󱁅"}.mdi-fruit-pear:before{content:"󱨎"}.mdi-fruit-pineapple:before{content:"󱁆"}.mdi-fruit-watermelon:before{content:"󱁇"}.mdi-fuel:before{content:"󰟊"}.mdi-fuel-cell:before{content:"󱢵"}.mdi-fullscreen:before{content:"󰊓"}.mdi-fullscreen-exit:before{content:"󰊔"}.mdi-function:before{content:"󰊕"}.mdi-function-variant:before{content:"󰡱"}.mdi-furigana-horizontal:before{content:"󱂁"}.mdi-furigana-vertical:before{content:"󱂂"}.mdi-fuse:before{content:"󰲅"}.mdi-fuse-alert:before{content:"󱐭"}.mdi-fuse-blade:before{content:"󰲆"}.mdi-fuse-off:before{content:"󱐬"}.mdi-gamepad:before{content:"󰊖"}.mdi-gamepad-circle:before{content:"󰸳"}.mdi-gamepad-circle-down:before{content:"󰸴"}.mdi-gamepad-circle-left:before{content:"󰸵"}.mdi-gamepad-circle-outline:before{content:"󰸶"}.mdi-gamepad-circle-right:before{content:"󰸷"}.mdi-gamepad-circle-up:before{content:"󰸸"}.mdi-gamepad-down:before{content:"󰸹"}.mdi-gamepad-left:before{content:"󰸺"}.mdi-gamepad-outline:before{content:"󱤙"}.mdi-gamepad-right:before{content:"󰸻"}.mdi-gamepad-round:before{content:"󰸼"}.mdi-gamepad-round-down:before{content:"󰸽"}.mdi-gamepad-round-left:before{content:"󰸾"}.mdi-gamepad-round-outline:before{content:"󰸿"}.mdi-gamepad-round-right:before{content:"󰹀"}.mdi-gamepad-round-up:before{content:"󰹁"}.mdi-gamepad-square:before{content:"󰺵"}.mdi-gamepad-square-outline:before{content:"󰺶"}.mdi-gamepad-up:before{content:"󰹂"}.mdi-gamepad-variant:before{content:"󰊗"}.mdi-gamepad-variant-outline:before{content:"󰺷"}.mdi-gamma:before{content:"󱃮"}.mdi-gantry-crane:before{content:"󰷑"}.mdi-garage:before{content:"󰛙"}.mdi-garage-alert:before{content:"󰡲"}.mdi-garage-alert-variant:before{content:"󱋕"}.mdi-garage-lock:before{content:"󱟻"}.mdi-garage-open:before{content:"󰛚"}.mdi-garage-open-variant:before{content:"󱋔"}.mdi-garage-variant:before{content:"󱋓"}.mdi-garage-variant-lock:before{content:"󱟼"}.mdi-gas-burner:before{content:"󱨛"}.mdi-gas-cylinder:before{content:"󰙇"}.mdi-gas-station:before{content:"󰊘"}.mdi-gas-station-off:before{content:"󱐉"}.mdi-gas-station-off-outline:before{content:"󱐊"}.mdi-gas-station-outline:before{content:"󰺸"}.mdi-gate:before{content:"󰊙"}.mdi-gate-alert:before{content:"󱟸"}.mdi-gate-and:before{content:"󰣡"}.mdi-gate-arrow-left:before{content:"󱟷"}.mdi-gate-arrow-right:before{content:"󱅩"}.mdi-gate-buffer:before{content:"󱫾"}.mdi-gate-nand:before{content:"󰣢"}.mdi-gate-nor:before{content:"󰣣"}.mdi-gate-not:before{content:"󰣤"}.mdi-gate-open:before{content:"󱅪"}.mdi-gate-or:before{content:"󰣥"}.mdi-gate-xnor:before{content:"󰣦"}.mdi-gate-xor:before{content:"󰣧"}.mdi-gatsby:before{content:"󰹃"}.mdi-gauge:before{content:"󰊚"}.mdi-gauge-empty:before{content:"󰡳"}.mdi-gauge-full:before{content:"󰡴"}.mdi-gauge-low:before{content:"󰡵"}.mdi-gavel:before{content:"󰊛"}.mdi-gender-female:before{content:"󰊜"}.mdi-gender-male:before{content:"󰊝"}.mdi-gender-male-female:before{content:"󰊞"}.mdi-gender-male-female-variant:before{content:"󱄿"}.mdi-gender-non-binary:before{content:"󱅀"}.mdi-gender-transgender:before{content:"󰊟"}.mdi-gentoo:before{content:"󰣨"}.mdi-gesture:before{content:"󰟋"}.mdi-gesture-double-tap:before{content:"󰜼"}.mdi-gesture-pinch:before{content:"󰪽"}.mdi-gesture-spread:before{content:"󰪾"}.mdi-gesture-swipe:before{content:"󰵶"}.mdi-gesture-swipe-down:before{content:"󰜽"}.mdi-gesture-swipe-horizontal:before{content:"󰪿"}.mdi-gesture-swipe-left:before{content:"󰜾"}.mdi-gesture-swipe-right:before{content:"󰜿"}.mdi-gesture-swipe-up:before{content:"󰝀"}.mdi-gesture-swipe-vertical:before{content:"󰫀"}.mdi-gesture-tap:before{content:"󰝁"}.mdi-gesture-tap-box:before{content:"󱊩"}.mdi-gesture-tap-button:before{content:"󱊨"}.mdi-gesture-tap-hold:before{content:"󰵷"}.mdi-gesture-two-double-tap:before{content:"󰝂"}.mdi-gesture-two-tap:before{content:"󰝃"}.mdi-ghost:before{content:"󰊠"}.mdi-ghost-off:before{content:"󰧵"}.mdi-ghost-off-outline:before{content:"󱙜"}.mdi-ghost-outline:before{content:"󱙝"}.mdi-gift:before{content:"󰹄"}.mdi-gift-off:before{content:"󱛯"}.mdi-gift-off-outline:before{content:"󱛰"}.mdi-gift-open:before{content:"󱛱"}.mdi-gift-open-outline:before{content:"󱛲"}.mdi-gift-outline:before{content:"󰊡"}.mdi-git:before{content:"󰊢"}.mdi-github:before{content:"󰊤"}.mdi-gitlab:before{content:"󰮠"}.mdi-glass-cocktail:before{content:"󰍖"}.mdi-glass-cocktail-off:before{content:"󱗦"}.mdi-glass-flute:before{content:"󰊥"}.mdi-glass-fragile:before{content:"󱡳"}.mdi-glass-mug:before{content:"󰊦"}.mdi-glass-mug-off:before{content:"󱗧"}.mdi-glass-mug-variant:before{content:"󱄖"}.mdi-glass-mug-variant-off:before{content:"󱗨"}.mdi-glass-pint-outline:before{content:"󱌍"}.mdi-glass-stange:before{content:"󰊧"}.mdi-glass-tulip:before{content:"󰊨"}.mdi-glass-wine:before{content:"󰡶"}.mdi-glasses:before{content:"󰊪"}.mdi-globe-light:before{content:"󰙯"}.mdi-globe-light-outline:before{content:"󱋗"}.mdi-globe-model:before{content:"󰣩"}.mdi-gmail:before{content:"󰊫"}.mdi-gnome:before{content:"󰊬"}.mdi-go-kart:before{content:"󰵹"}.mdi-go-kart-track:before{content:"󰵺"}.mdi-gog:before{content:"󰮡"}.mdi-gold:before{content:"󱉏"}.mdi-golf:before{content:"󰠣"}.mdi-golf-cart:before{content:"󱆤"}.mdi-golf-tee:before{content:"󱂃"}.mdi-gondola:before{content:"󰚆"}.mdi-goodreads:before{content:"󰵻"}.mdi-google:before{content:"󰊭"}.mdi-google-ads:before{content:"󰲇"}.mdi-google-analytics:before{content:"󰟌"}.mdi-google-assistant:before{content:"󰟍"}.mdi-google-cardboard:before{content:"󰊮"}.mdi-google-chrome:before{content:"󰊯"}.mdi-google-circles:before{content:"󰊰"}.mdi-google-circles-communities:before{content:"󰊱"}.mdi-google-circles-extended:before{content:"󰊲"}.mdi-google-circles-group:before{content:"󰊳"}.mdi-google-classroom:before{content:"󰋀"}.mdi-google-cloud:before{content:"󱇶"}.mdi-google-downasaur:before{content:"󱍢"}.mdi-google-drive:before{content:"󰊶"}.mdi-google-earth:before{content:"󰊷"}.mdi-google-fit:before{content:"󰥬"}.mdi-google-glass:before{content:"󰊸"}.mdi-google-hangouts:before{content:"󰋉"}.mdi-google-keep:before{content:"󰛜"}.mdi-google-lens:before{content:"󰧶"}.mdi-google-maps:before{content:"󰗵"}.mdi-google-my-business:before{content:"󱁈"}.mdi-google-nearby:before{content:"󰊹"}.mdi-google-play:before{content:"󰊼"}.mdi-google-plus:before{content:"󰊽"}.mdi-google-podcast:before{content:"󰺹"}.mdi-google-spreadsheet:before{content:"󰧷"}.mdi-google-street-view:before{content:"󰲈"}.mdi-google-translate:before{content:"󰊿"}.mdi-gradient-horizontal:before{content:"󱝊"}.mdi-gradient-vertical:before{content:"󰚠"}.mdi-grain:before{content:"󰵼"}.mdi-graph:before{content:"󱁉"}.mdi-graph-outline:before{content:"󱁊"}.mdi-graphql:before{content:"󰡷"}.mdi-grass:before{content:"󱔐"}.mdi-grave-stone:before{content:"󰮢"}.mdi-grease-pencil:before{content:"󰙈"}.mdi-greater-than:before{content:"󰥭"}.mdi-greater-than-or-equal:before{content:"󰥮"}.mdi-greenhouse:before{content:"󰀭"}.mdi-grid:before{content:"󰋁"}.mdi-grid-large:before{content:"󰝘"}.mdi-grid-off:before{content:"󰋂"}.mdi-grill:before{content:"󰹅"}.mdi-grill-outline:before{content:"󱆊"}.mdi-group:before{content:"󰋃"}.mdi-guitar-acoustic:before{content:"󰝱"}.mdi-guitar-electric:before{content:"󰋄"}.mdi-guitar-pick:before{content:"󰋅"}.mdi-guitar-pick-outline:before{content:"󰋆"}.mdi-guy-fawkes-mask:before{content:"󰠥"}.mdi-gymnastics:before{content:"󱩁"}.mdi-hail:before{content:"󰫁"}.mdi-hair-dryer:before{content:"󱃯"}.mdi-hair-dryer-outline:before{content:"󱃰"}.mdi-halloween:before{content:"󰮣"}.mdi-hamburger:before{content:"󰚅"}.mdi-hamburger-check:before{content:"󱝶"}.mdi-hamburger-minus:before{content:"󱝷"}.mdi-hamburger-off:before{content:"󱝸"}.mdi-hamburger-plus:before{content:"󱝹"}.mdi-hamburger-remove:before{content:"󱝺"}.mdi-hammer:before{content:"󰣪"}.mdi-hammer-screwdriver:before{content:"󱌢"}.mdi-hammer-sickle:before{content:"󱢇"}.mdi-hammer-wrench:before{content:"󱌣"}.mdi-hand-back-left:before{content:"󰹆"}.mdi-hand-back-left-off:before{content:"󱠰"}.mdi-hand-back-left-off-outline:before{content:"󱠲"}.mdi-hand-back-left-outline:before{content:"󱠬"}.mdi-hand-back-right:before{content:"󰹇"}.mdi-hand-back-right-off:before{content:"󱠱"}.mdi-hand-back-right-off-outline:before{content:"󱠳"}.mdi-hand-back-right-outline:before{content:"󱠭"}.mdi-hand-clap:before{content:"󱥋"}.mdi-hand-clap-off:before{content:"󱩂"}.mdi-hand-coin:before{content:"󱢏"}.mdi-hand-coin-outline:before{content:"󱢐"}.mdi-hand-cycle:before{content:"󱮜"}.mdi-hand-extended:before{content:"󱢶"}.mdi-hand-extended-outline:before{content:"󱢷"}.mdi-hand-front-left:before{content:"󱠫"}.mdi-hand-front-left-outline:before{content:"󱠮"}.mdi-hand-front-right:before{content:"󰩏"}.mdi-hand-front-right-outline:before{content:"󱠯"}.mdi-hand-heart:before{content:"󱃱"}.mdi-hand-heart-outline:before{content:"󱕾"}.mdi-hand-okay:before{content:"󰩐"}.mdi-hand-peace:before{content:"󰩑"}.mdi-hand-peace-variant:before{content:"󰩒"}.mdi-hand-pointing-down:before{content:"󰩓"}.mdi-hand-pointing-left:before{content:"󰩔"}.mdi-hand-pointing-right:before{content:"󰋇"}.mdi-hand-pointing-up:before{content:"󰩕"}.mdi-hand-saw:before{content:"󰹈"}.mdi-hand-wash:before{content:"󱕿"}.mdi-hand-wash-outline:before{content:"󱖀"}.mdi-hand-water:before{content:"󱎟"}.mdi-hand-wave:before{content:"󱠡"}.mdi-hand-wave-outline:before{content:"󱠢"}.mdi-handball:before{content:"󰽓"}.mdi-handcuffs:before{content:"󱄾"}.mdi-hands-pray:before{content:"󰕹"}.mdi-handshake:before{content:"󱈘"}.mdi-handshake-outline:before{content:"󱖡"}.mdi-hanger:before{content:"󰋈"}.mdi-hard-hat:before{content:"󰥯"}.mdi-harddisk:before{content:"󰋊"}.mdi-harddisk-plus:before{content:"󱁋"}.mdi-harddisk-remove:before{content:"󱁌"}.mdi-hat-fedora:before{content:"󰮤"}.mdi-hazard-lights:before{content:"󰲉"}.mdi-hdmi-port:before{content:"󱮸"}.mdi-hdr:before{content:"󰵽"}.mdi-hdr-off:before{content:"󰵾"}.mdi-head:before{content:"󱍞"}.mdi-head-alert:before{content:"󱌸"}.mdi-head-alert-outline:before{content:"󱌹"}.mdi-head-check:before{content:"󱌺"}.mdi-head-check-outline:before{content:"󱌻"}.mdi-head-cog:before{content:"󱌼"}.mdi-head-cog-outline:before{content:"󱌽"}.mdi-head-dots-horizontal:before{content:"󱌾"}.mdi-head-dots-horizontal-outline:before{content:"󱌿"}.mdi-head-flash:before{content:"󱍀"}.mdi-head-flash-outline:before{content:"󱍁"}.mdi-head-heart:before{content:"󱍂"}.mdi-head-heart-outline:before{content:"󱍃"}.mdi-head-lightbulb:before{content:"󱍄"}.mdi-head-lightbulb-outline:before{content:"󱍅"}.mdi-head-minus:before{content:"󱍆"}.mdi-head-minus-outline:before{content:"󱍇"}.mdi-head-outline:before{content:"󱍟"}.mdi-head-plus:before{content:"󱍈"}.mdi-head-plus-outline:before{content:"󱍉"}.mdi-head-question:before{content:"󱍊"}.mdi-head-question-outline:before{content:"󱍋"}.mdi-head-remove:before{content:"󱍌"}.mdi-head-remove-outline:before{content:"󱍍"}.mdi-head-snowflake:before{content:"󱍎"}.mdi-head-snowflake-outline:before{content:"󱍏"}.mdi-head-sync:before{content:"󱍐"}.mdi-head-sync-outline:before{content:"󱍑"}.mdi-headphones:before{content:"󰋋"}.mdi-headphones-bluetooth:before{content:"󰥰"}.mdi-headphones-box:before{content:"󰋌"}.mdi-headphones-off:before{content:"󰟎"}.mdi-headphones-settings:before{content:"󰋍"}.mdi-headset:before{content:"󰋎"}.mdi-headset-dock:before{content:"󰋏"}.mdi-headset-off:before{content:"󰋐"}.mdi-heart:before{content:"󰋑"}.mdi-heart-box:before{content:"󰋒"}.mdi-heart-box-outline:before{content:"󰋓"}.mdi-heart-broken:before{content:"󰋔"}.mdi-heart-broken-outline:before{content:"󰴔"}.mdi-heart-circle:before{content:"󰥱"}.mdi-heart-circle-outline:before{content:"󰥲"}.mdi-heart-cog:before{content:"󱙣"}.mdi-heart-cog-outline:before{content:"󱙤"}.mdi-heart-flash:before{content:"󰻹"}.mdi-heart-half:before{content:"󰛟"}.mdi-heart-half-full:before{content:"󰛞"}.mdi-heart-half-outline:before{content:"󰛠"}.mdi-heart-minus:before{content:"󱐯"}.mdi-heart-minus-outline:before{content:"󱐲"}.mdi-heart-multiple:before{content:"󰩖"}.mdi-heart-multiple-outline:before{content:"󰩗"}.mdi-heart-off:before{content:"󰝙"}.mdi-heart-off-outline:before{content:"󱐴"}.mdi-heart-outline:before{content:"󰋕"}.mdi-heart-plus:before{content:"󱐮"}.mdi-heart-plus-outline:before{content:"󱐱"}.mdi-heart-pulse:before{content:"󰗶"}.mdi-heart-remove:before{content:"󱐰"}.mdi-heart-remove-outline:before{content:"󱐳"}.mdi-heart-settings:before{content:"󱙥"}.mdi-heart-settings-outline:before{content:"󱙦"}.mdi-heat-pump:before{content:"󱩃"}.mdi-heat-pump-outline:before{content:"󱩄"}.mdi-heat-wave:before{content:"󱩅"}.mdi-heating-coil:before{content:"󱪯"}.mdi-helicopter:before{content:"󰫂"}.mdi-help:before{content:"󰋖"}.mdi-help-box:before{content:"󰞋"}.mdi-help-box-multiple:before{content:"󱰊"}.mdi-help-box-multiple-outline:before{content:"󱰋"}.mdi-help-box-outline:before{content:"󱰌"}.mdi-help-circle:before{content:"󰋗"}.mdi-help-circle-outline:before{content:"󰘥"}.mdi-help-network:before{content:"󰛵"}.mdi-help-network-outline:before{content:"󰲊"}.mdi-help-rhombus:before{content:"󰮥"}.mdi-help-rhombus-outline:before{content:"󰮦"}.mdi-hexadecimal:before{content:"󱊧"}.mdi-hexagon:before{content:"󰋘"}.mdi-hexagon-multiple:before{content:"󰛡"}.mdi-hexagon-multiple-outline:before{content:"󱃲"}.mdi-hexagon-outline:before{content:"󰋙"}.mdi-hexagon-slice-1:before{content:"󰫃"}.mdi-hexagon-slice-2:before{content:"󰫄"}.mdi-hexagon-slice-3:before{content:"󰫅"}.mdi-hexagon-slice-4:before{content:"󰫆"}.mdi-hexagon-slice-5:before{content:"󰫇"}.mdi-hexagon-slice-6:before{content:"󰫈"}.mdi-hexagram:before{content:"󰫉"}.mdi-hexagram-outline:before{content:"󰫊"}.mdi-high-definition:before{content:"󰟏"}.mdi-high-definition-box:before{content:"󰡸"}.mdi-highway:before{content:"󰗷"}.mdi-hiking:before{content:"󰵿"}.mdi-history:before{content:"󰋚"}.mdi-hockey-puck:before{content:"󰡹"}.mdi-hockey-sticks:before{content:"󰡺"}.mdi-hololens:before{content:"󰋛"}.mdi-home:before{content:"󰋜"}.mdi-home-account:before{content:"󰠦"}.mdi-home-alert:before{content:"󰡻"}.mdi-home-alert-outline:before{content:"󱗐"}.mdi-home-analytics:before{content:"󰺺"}.mdi-home-assistant:before{content:"󰟐"}.mdi-home-automation:before{content:"󰟑"}.mdi-home-battery:before{content:"󱤁"}.mdi-home-battery-outline:before{content:"󱤂"}.mdi-home-circle:before{content:"󰟒"}.mdi-home-circle-outline:before{content:"󱁍"}.mdi-home-city:before{content:"󰴕"}.mdi-home-city-outline:before{content:"󰴖"}.mdi-home-clock:before{content:"󱨒"}.mdi-home-clock-outline:before{content:"󱨓"}.mdi-home-edit:before{content:"󱅙"}.mdi-home-edit-outline:before{content:"󱅚"}.mdi-home-export-outline:before{content:"󰾛"}.mdi-home-flood:before{content:"󰻺"}.mdi-home-floor-0:before{content:"󰷒"}.mdi-home-floor-1:before{content:"󰶀"}.mdi-home-floor-2:before{content:"󰶁"}.mdi-home-floor-3:before{content:"󰶂"}.mdi-home-floor-a:before{content:"󰶃"}.mdi-home-floor-b:before{content:"󰶄"}.mdi-home-floor-g:before{content:"󰶅"}.mdi-home-floor-l:before{content:"󰶆"}.mdi-home-floor-negative-1:before{content:"󰷓"}.mdi-home-group:before{content:"󰷔"}.mdi-home-group-minus:before{content:"󱧁"}.mdi-home-group-plus:before{content:"󱧀"}.mdi-home-group-remove:before{content:"󱧂"}.mdi-home-heart:before{content:"󰠧"}.mdi-home-import-outline:before{content:"󰾜"}.mdi-home-lightbulb:before{content:"󱉑"}.mdi-home-lightbulb-outline:before{content:"󱉒"}.mdi-home-lightning-bolt:before{content:"󱤃"}.mdi-home-lightning-bolt-outline:before{content:"󱤄"}.mdi-home-lock:before{content:"󰣫"}.mdi-home-lock-open:before{content:"󰣬"}.mdi-home-map-marker:before{content:"󰗸"}.mdi-home-minus:before{content:"󰥴"}.mdi-home-minus-outline:before{content:"󱏕"}.mdi-home-modern:before{content:"󰋝"}.mdi-home-off:before{content:"󱩆"}.mdi-home-off-outline:before{content:"󱩇"}.mdi-home-outline:before{content:"󰚡"}.mdi-home-percent:before{content:"󱱼"}.mdi-home-percent-outline:before{content:"󱱽"}.mdi-home-plus:before{content:"󰥵"}.mdi-home-plus-outline:before{content:"󱏖"}.mdi-home-remove:before{content:"󱉇"}.mdi-home-remove-outline:before{content:"󱏗"}.mdi-home-roof:before{content:"󱄫"}.mdi-home-search:before{content:"󱎰"}.mdi-home-search-outline:before{content:"󱎱"}.mdi-home-silo:before{content:"󱮠"}.mdi-home-silo-outline:before{content:"󱮡"}.mdi-home-sound-in:before{content:"󱰯"}.mdi-home-sound-in-outline:before{content:"󱰰"}.mdi-home-sound-out:before{content:"󱰱"}.mdi-home-sound-out-outline:before{content:"󱰲"}.mdi-home-switch:before{content:"󱞔"}.mdi-home-switch-outline:before{content:"󱞕"}.mdi-home-thermometer:before{content:"󰽔"}.mdi-home-thermometer-outline:before{content:"󰽕"}.mdi-home-variant:before{content:"󰋞"}.mdi-home-variant-outline:before{content:"󰮧"}.mdi-hook:before{content:"󰛢"}.mdi-hook-off:before{content:"󰛣"}.mdi-hoop-house:before{content:"󰹖"}.mdi-hops:before{content:"󰋟"}.mdi-horizontal-rotate-clockwise:before{content:"󱃳"}.mdi-horizontal-rotate-counterclockwise:before{content:"󱃴"}.mdi-horse:before{content:"󱖿"}.mdi-horse-human:before{content:"󱗀"}.mdi-horse-variant:before{content:"󱗁"}.mdi-horse-variant-fast:before{content:"󱡮"}.mdi-horseshoe:before{content:"󰩘"}.mdi-hospital:before{content:"󰿶"}.mdi-hospital-box:before{content:"󰋠"}.mdi-hospital-box-outline:before{content:"󰿷"}.mdi-hospital-building:before{content:"󰋡"}.mdi-hospital-marker:before{content:"󰋢"}.mdi-hot-tub:before{content:"󰠨"}.mdi-hours-24:before{content:"󱑸"}.mdi-hubspot:before{content:"󰴗"}.mdi-hulu:before{content:"󰠩"}.mdi-human:before{content:"󰋦"}.mdi-human-baby-changing-table:before{content:"󱎋"}.mdi-human-cane:before{content:"󱖁"}.mdi-human-capacity-decrease:before{content:"󱖛"}.mdi-human-capacity-increase:before{content:"󱖜"}.mdi-human-child:before{content:"󰋧"}.mdi-human-dolly:before{content:"󱦀"}.mdi-human-edit:before{content:"󱓨"}.mdi-human-female:before{content:"󰙉"}.mdi-human-female-boy:before{content:"󰩙"}.mdi-human-female-dance:before{content:"󱗉"}.mdi-human-female-female:before{content:"󰩚"}.mdi-human-female-girl:before{content:"󰩛"}.mdi-human-greeting:before{content:"󱟄"}.mdi-human-greeting-proximity:before{content:"󱖝"}.mdi-human-greeting-variant:before{content:"󰙊"}.mdi-human-handsdown:before{content:"󰙋"}.mdi-human-handsup:before{content:"󰙌"}.mdi-human-male:before{content:"󰙍"}.mdi-human-male-board:before{content:"󰢐"}.mdi-human-male-board-poll:before{content:"󰡆"}.mdi-human-male-boy:before{content:"󰩜"}.mdi-human-male-child:before{content:"󱎌"}.mdi-human-male-female:before{content:"󰋨"}.mdi-human-male-female-child:before{content:"󱠣"}.mdi-human-male-girl:before{content:"󰩝"}.mdi-human-male-height:before{content:"󰻻"}.mdi-human-male-height-variant:before{content:"󰻼"}.mdi-human-male-male:before{content:"󰩞"}.mdi-human-non-binary:before{content:"󱡈"}.mdi-human-pregnant:before{content:"󰗏"}.mdi-human-queue:before{content:"󱕱"}.mdi-human-scooter:before{content:"󱇩"}.mdi-human-walker:before{content:"󱭱"}.mdi-human-wheelchair:before{content:"󱎍"}.mdi-human-white-cane:before{content:"󱦁"}.mdi-humble-bundle:before{content:"󰝄"}.mdi-hvac:before{content:"󱍒"}.mdi-hvac-off:before{content:"󱖞"}.mdi-hydraulic-oil-level:before{content:"󱌤"}.mdi-hydraulic-oil-temperature:before{content:"󱌥"}.mdi-hydro-power:before{content:"󱋥"}.mdi-hydrogen-station:before{content:"󱢔"}.mdi-ice-cream:before{content:"󰠪"}.mdi-ice-cream-off:before{content:"󰹒"}.mdi-ice-pop:before{content:"󰻽"}.mdi-id-card:before{content:"󰿀"}.mdi-identifier:before{content:"󰻾"}.mdi-ideogram-cjk:before{content:"󱌱"}.mdi-ideogram-cjk-variant:before{content:"󱌲"}.mdi-image:before{content:"󰋩"}.mdi-image-album:before{content:"󰋪"}.mdi-image-area:before{content:"󰋫"}.mdi-image-area-close:before{content:"󰋬"}.mdi-image-auto-adjust:before{content:"󰿁"}.mdi-image-broken:before{content:"󰋭"}.mdi-image-broken-variant:before{content:"󰋮"}.mdi-image-check:before{content:"󱬥"}.mdi-image-check-outline:before{content:"󱬦"}.mdi-image-edit:before{content:"󱇣"}.mdi-image-edit-outline:before{content:"󱇤"}.mdi-image-filter-black-white:before{content:"󰋰"}.mdi-image-filter-center-focus:before{content:"󰋱"}.mdi-image-filter-center-focus-strong:before{content:"󰻿"}.mdi-image-filter-center-focus-strong-outline:before{content:"󰼀"}.mdi-image-filter-center-focus-weak:before{content:"󰋲"}.mdi-image-filter-drama:before{content:"󰋳"}.mdi-image-filter-drama-outline:before{content:"󱯿"}.mdi-image-filter-frames:before{content:"󰋴"}.mdi-image-filter-hdr:before{content:"󰋵"}.mdi-image-filter-hdr-outline:before{content:"󱱤"}.mdi-image-filter-none:before{content:"󰋶"}.mdi-image-filter-tilt-shift:before{content:"󰋷"}.mdi-image-filter-vintage:before{content:"󰋸"}.mdi-image-frame:before{content:"󰹉"}.mdi-image-lock:before{content:"󱪰"}.mdi-image-lock-outline:before{content:"󱪱"}.mdi-image-marker:before{content:"󱝻"}.mdi-image-marker-outline:before{content:"󱝼"}.mdi-image-minus:before{content:"󱐙"}.mdi-image-minus-outline:before{content:"󱭇"}.mdi-image-move:before{content:"󰧸"}.mdi-image-multiple:before{content:"󰋹"}.mdi-image-multiple-outline:before{content:"󰋯"}.mdi-image-off:before{content:"󰠫"}.mdi-image-off-outline:before{content:"󱇑"}.mdi-image-outline:before{content:"󰥶"}.mdi-image-plus:before{content:"󰡼"}.mdi-image-plus-outline:before{content:"󱭆"}.mdi-image-refresh:before{content:"󱧾"}.mdi-image-refresh-outline:before{content:"󱧿"}.mdi-image-remove:before{content:"󱐘"}.mdi-image-remove-outline:before{content:"󱭈"}.mdi-image-search:before{content:"󰥷"}.mdi-image-search-outline:before{content:"󰥸"}.mdi-image-size-select-actual:before{content:"󰲍"}.mdi-image-size-select-large:before{content:"󰲎"}.mdi-image-size-select-small:before{content:"󰲏"}.mdi-image-sync:before{content:"󱨀"}.mdi-image-sync-outline:before{content:"󱨁"}.mdi-image-text:before{content:"󱘍"}.mdi-import:before{content:"󰋺"}.mdi-inbox:before{content:"󰚇"}.mdi-inbox-arrow-down:before{content:"󰋻"}.mdi-inbox-arrow-down-outline:before{content:"󱉰"}.mdi-inbox-arrow-up:before{content:"󰏑"}.mdi-inbox-arrow-up-outline:before{content:"󱉱"}.mdi-inbox-full:before{content:"󱉲"}.mdi-inbox-full-outline:before{content:"󱉳"}.mdi-inbox-multiple:before{content:"󰢰"}.mdi-inbox-multiple-outline:before{content:"󰮨"}.mdi-inbox-outline:before{content:"󱉴"}.mdi-inbox-remove:before{content:"󱖟"}.mdi-inbox-remove-outline:before{content:"󱖠"}.mdi-incognito:before{content:"󰗹"}.mdi-incognito-circle:before{content:"󱐡"}.mdi-incognito-circle-off:before{content:"󱐢"}.mdi-incognito-off:before{content:"󰁵"}.mdi-induction:before{content:"󱡌"}.mdi-infinity:before{content:"󰛤"}.mdi-information:before{content:"󰋼"}.mdi-information-box:before{content:"󱱥"}.mdi-information-box-outline:before{content:"󱱦"}.mdi-information-off:before{content:"󱞌"}.mdi-information-off-outline:before{content:"󱞍"}.mdi-information-outline:before{content:"󰋽"}.mdi-information-slab-box:before{content:"󱱧"}.mdi-information-slab-box-outline:before{content:"󱱨"}.mdi-information-slab-circle:before{content:"󱱩"}.mdi-information-slab-circle-outline:before{content:"󱱪"}.mdi-information-slab-symbol:before{content:"󱱫"}.mdi-information-symbol:before{content:"󱱬"}.mdi-information-variant:before{content:"󰙎"}.mdi-information-variant-box:before{content:"󱱭"}.mdi-information-variant-box-outline:before{content:"󱱮"}.mdi-information-variant-circle:before{content:"󱱯"}.mdi-information-variant-circle-outline:before{content:"󱱰"}.mdi-instagram:before{content:"󰋾"}.mdi-instrument-triangle:before{content:"󱁎"}.mdi-integrated-circuit-chip:before{content:"󱤓"}.mdi-invert-colors:before{content:"󰌁"}.mdi-invert-colors-off:before{content:"󰹊"}.mdi-iobroker:before{content:"󱋨"}.mdi-ip:before{content:"󰩟"}.mdi-ip-network:before{content:"󰩠"}.mdi-ip-network-outline:before{content:"󰲐"}.mdi-ip-outline:before{content:"󱦂"}.mdi-ipod:before{content:"󰲑"}.mdi-iron:before{content:"󱠤"}.mdi-iron-board:before{content:"󱠸"}.mdi-iron-outline:before{content:"󱠥"}.mdi-island:before{content:"󱁏"}.mdi-iv-bag:before{content:"󱂹"}.mdi-jabber:before{content:"󰷕"}.mdi-jeepney:before{content:"󰌂"}.mdi-jellyfish:before{content:"󰼁"}.mdi-jellyfish-outline:before{content:"󰼂"}.mdi-jira:before{content:"󰌃"}.mdi-jquery:before{content:"󰡽"}.mdi-jsfiddle:before{content:"󰌄"}.mdi-jump-rope:before{content:"󱋿"}.mdi-kabaddi:before{content:"󰶇"}.mdi-kangaroo:before{content:"󱕘"}.mdi-karate:before{content:"󰠬"}.mdi-kayaking:before{content:"󰢯"}.mdi-keg:before{content:"󰌅"}.mdi-kettle:before{content:"󰗺"}.mdi-kettle-alert:before{content:"󱌗"}.mdi-kettle-alert-outline:before{content:"󱌘"}.mdi-kettle-off:before{content:"󱌛"}.mdi-kettle-off-outline:before{content:"󱌜"}.mdi-kettle-outline:before{content:"󰽖"}.mdi-kettle-pour-over:before{content:"󱜼"}.mdi-kettle-steam:before{content:"󱌙"}.mdi-kettle-steam-outline:before{content:"󱌚"}.mdi-kettlebell:before{content:"󱌀"}.mdi-key:before{content:"󰌆"}.mdi-key-alert:before{content:"󱦃"}.mdi-key-alert-outline:before{content:"󱦄"}.mdi-key-arrow-right:before{content:"󱌒"}.mdi-key-chain:before{content:"󱕴"}.mdi-key-chain-variant:before{content:"󱕵"}.mdi-key-change:before{content:"󰌇"}.mdi-key-link:before{content:"󱆟"}.mdi-key-minus:before{content:"󰌈"}.mdi-key-outline:before{content:"󰷖"}.mdi-key-plus:before{content:"󰌉"}.mdi-key-remove:before{content:"󰌊"}.mdi-key-star:before{content:"󱆞"}.mdi-key-variant:before{content:"󰌋"}.mdi-key-wireless:before{content:"󰿂"}.mdi-keyboard:before{content:"󰌌"}.mdi-keyboard-backspace:before{content:"󰌍"}.mdi-keyboard-caps:before{content:"󰌎"}.mdi-keyboard-close:before{content:"󰌏"}.mdi-keyboard-close-outline:before{content:"󱰀"}.mdi-keyboard-esc:before{content:"󱊷"}.mdi-keyboard-f1:before{content:"󱊫"}.mdi-keyboard-f10:before{content:"󱊴"}.mdi-keyboard-f11:before{content:"󱊵"}.mdi-keyboard-f12:before{content:"󱊶"}.mdi-keyboard-f2:before{content:"󱊬"}.mdi-keyboard-f3:before{content:"󱊭"}.mdi-keyboard-f4:before{content:"󱊮"}.mdi-keyboard-f5:before{content:"󱊯"}.mdi-keyboard-f6:before{content:"󱊰"}.mdi-keyboard-f7:before{content:"󱊱"}.mdi-keyboard-f8:before{content:"󱊲"}.mdi-keyboard-f9:before{content:"󱊳"}.mdi-keyboard-off:before{content:"󰌐"}.mdi-keyboard-off-outline:before{content:"󰹋"}.mdi-keyboard-outline:before{content:"󰥻"}.mdi-keyboard-return:before{content:"󰌑"}.mdi-keyboard-settings:before{content:"󰧹"}.mdi-keyboard-settings-outline:before{content:"󰧺"}.mdi-keyboard-space:before{content:"󱁐"}.mdi-keyboard-tab:before{content:"󰌒"}.mdi-keyboard-tab-reverse:before{content:"󰌥"}.mdi-keyboard-variant:before{content:"󰌓"}.mdi-khanda:before{content:"󱃽"}.mdi-kickstarter:before{content:"󰝅"}.mdi-kite:before{content:"󱦅"}.mdi-kite-outline:before{content:"󱦆"}.mdi-kitesurfing:before{content:"󱝄"}.mdi-klingon:before{content:"󱍛"}.mdi-knife:before{content:"󰧻"}.mdi-knife-military:before{content:"󰧼"}.mdi-knob:before{content:"󱮖"}.mdi-koala:before{content:"󱜿"}.mdi-kodi:before{content:"󰌔"}.mdi-kubernetes:before{content:"󱃾"}.mdi-label:before{content:"󰌕"}.mdi-label-multiple:before{content:"󱍵"}.mdi-label-multiple-outline:before{content:"󱍶"}.mdi-label-off:before{content:"󰫋"}.mdi-label-off-outline:before{content:"󰫌"}.mdi-label-outline:before{content:"󰌖"}.mdi-label-percent:before{content:"󱋪"}.mdi-label-percent-outline:before{content:"󱋫"}.mdi-label-variant:before{content:"󰫍"}.mdi-label-variant-outline:before{content:"󰫎"}.mdi-ladder:before{content:"󱖢"}.mdi-ladybug:before{content:"󰠭"}.mdi-lambda:before{content:"󰘧"}.mdi-lamp:before{content:"󰚵"}.mdi-lamp-outline:before{content:"󱟐"}.mdi-lamps:before{content:"󱕶"}.mdi-lamps-outline:before{content:"󱟑"}.mdi-lan:before{content:"󰌗"}.mdi-lan-check:before{content:"󱊪"}.mdi-lan-connect:before{content:"󰌘"}.mdi-lan-disconnect:before{content:"󰌙"}.mdi-lan-pending:before{content:"󰌚"}.mdi-land-fields:before{content:"󱪲"}.mdi-land-plots:before{content:"󱪳"}.mdi-land-plots-circle:before{content:"󱪴"}.mdi-land-plots-circle-variant:before{content:"󱪵"}.mdi-land-plots-marker:before{content:"󱱝"}.mdi-land-rows-horizontal:before{content:"󱪶"}.mdi-land-rows-vertical:before{content:"󱪷"}.mdi-landslide:before{content:"󱩈"}.mdi-landslide-outline:before{content:"󱩉"}.mdi-language-c:before{content:"󰙱"}.mdi-language-cpp:before{content:"󰙲"}.mdi-language-csharp:before{content:"󰌛"}.mdi-language-css3:before{content:"󰌜"}.mdi-language-fortran:before{content:"󱈚"}.mdi-language-go:before{content:"󰟓"}.mdi-language-haskell:before{content:"󰲒"}.mdi-language-html5:before{content:"󰌝"}.mdi-language-java:before{content:"󰬷"}.mdi-language-javascript:before{content:"󰌞"}.mdi-language-kotlin:before{content:"󱈙"}.mdi-language-lua:before{content:"󰢱"}.mdi-language-markdown:before{content:"󰍔"}.mdi-language-markdown-outline:before{content:"󰽛"}.mdi-language-php:before{content:"󰌟"}.mdi-language-python:before{content:"󰌠"}.mdi-language-r:before{content:"󰟔"}.mdi-language-ruby:before{content:"󰴭"}.mdi-language-ruby-on-rails:before{content:"󰫏"}.mdi-language-rust:before{content:"󱘗"}.mdi-language-swift:before{content:"󰛥"}.mdi-language-typescript:before{content:"󰛦"}.mdi-language-xaml:before{content:"󰙳"}.mdi-laptop:before{content:"󰌢"}.mdi-laptop-account:before{content:"󱩊"}.mdi-laptop-off:before{content:"󰛧"}.mdi-laravel:before{content:"󰫐"}.mdi-laser-pointer:before{content:"󱒄"}.mdi-lasso:before{content:"󰼃"}.mdi-lastpass:before{content:"󰑆"}.mdi-latitude:before{content:"󰽗"}.mdi-launch:before{content:"󰌧"}.mdi-lava-lamp:before{content:"󰟕"}.mdi-layers:before{content:"󰌨"}.mdi-layers-edit:before{content:"󱢒"}.mdi-layers-minus:before{content:"󰹌"}.mdi-layers-off:before{content:"󰌩"}.mdi-layers-off-outline:before{content:"󰧽"}.mdi-layers-outline:before{content:"󰧾"}.mdi-layers-plus:before{content:"󰹍"}.mdi-layers-remove:before{content:"󰹎"}.mdi-layers-search:before{content:"󱈆"}.mdi-layers-search-outline:before{content:"󱈇"}.mdi-layers-triple:before{content:"󰽘"}.mdi-layers-triple-outline:before{content:"󰽙"}.mdi-lead-pencil:before{content:"󰙏"}.mdi-leaf:before{content:"󰌪"}.mdi-leaf-circle:before{content:"󱤅"}.mdi-leaf-circle-outline:before{content:"󱤆"}.mdi-leaf-maple:before{content:"󰲓"}.mdi-leaf-maple-off:before{content:"󱋚"}.mdi-leaf-off:before{content:"󱋙"}.mdi-leak:before{content:"󰷗"}.mdi-leak-off:before{content:"󰷘"}.mdi-lectern:before{content:"󱫰"}.mdi-led-off:before{content:"󰌫"}.mdi-led-on:before{content:"󰌬"}.mdi-led-outline:before{content:"󰌭"}.mdi-led-strip:before{content:"󰟖"}.mdi-led-strip-variant:before{content:"󱁑"}.mdi-led-strip-variant-off:before{content:"󱩋"}.mdi-led-variant-off:before{content:"󰌮"}.mdi-led-variant-on:before{content:"󰌯"}.mdi-led-variant-outline:before{content:"󰌰"}.mdi-leek:before{content:"󱅽"}.mdi-less-than:before{content:"󰥼"}.mdi-less-than-or-equal:before{content:"󰥽"}.mdi-library:before{content:"󰌱"}.mdi-library-outline:before{content:"󱨢"}.mdi-library-shelves:before{content:"󰮩"}.mdi-license:before{content:"󰿃"}.mdi-lifebuoy:before{content:"󰡾"}.mdi-light-flood-down:before{content:"󱦇"}.mdi-light-flood-up:before{content:"󱦈"}.mdi-light-recessed:before{content:"󱞛"}.mdi-light-switch:before{content:"󰥾"}.mdi-light-switch-off:before{content:"󱨤"}.mdi-lightbulb:before{content:"󰌵"}.mdi-lightbulb-alert:before{content:"󱧡"}.mdi-lightbulb-alert-outline:before{content:"󱧢"}.mdi-lightbulb-auto:before{content:"󱠀"}.mdi-lightbulb-auto-outline:before{content:"󱠁"}.mdi-lightbulb-cfl:before{content:"󱈈"}.mdi-lightbulb-cfl-off:before{content:"󱈉"}.mdi-lightbulb-cfl-spiral:before{content:"󱉵"}.mdi-lightbulb-cfl-spiral-off:before{content:"󱋃"}.mdi-lightbulb-fluorescent-tube:before{content:"󱠄"}.mdi-lightbulb-fluorescent-tube-outline:before{content:"󱠅"}.mdi-lightbulb-group:before{content:"󱉓"}.mdi-lightbulb-group-off:before{content:"󱋍"}.mdi-lightbulb-group-off-outline:before{content:"󱋎"}.mdi-lightbulb-group-outline:before{content:"󱉔"}.mdi-lightbulb-multiple:before{content:"󱉕"}.mdi-lightbulb-multiple-off:before{content:"󱋏"}.mdi-lightbulb-multiple-off-outline:before{content:"󱋐"}.mdi-lightbulb-multiple-outline:before{content:"󱉖"}.mdi-lightbulb-night:before{content:"󱩌"}.mdi-lightbulb-night-outline:before{content:"󱩍"}.mdi-lightbulb-off:before{content:"󰹏"}.mdi-lightbulb-off-outline:before{content:"󰹐"}.mdi-lightbulb-on:before{content:"󰛨"}.mdi-lightbulb-on-10:before{content:"󱩎"}.mdi-lightbulb-on-20:before{content:"󱩏"}.mdi-lightbulb-on-30:before{content:"󱩐"}.mdi-lightbulb-on-40:before{content:"󱩑"}.mdi-lightbulb-on-50:before{content:"󱩒"}.mdi-lightbulb-on-60:before{content:"󱩓"}.mdi-lightbulb-on-70:before{content:"󱩔"}.mdi-lightbulb-on-80:before{content:"󱩕"}.mdi-lightbulb-on-90:before{content:"󱩖"}.mdi-lightbulb-on-outline:before{content:"󰛩"}.mdi-lightbulb-outline:before{content:"󰌶"}.mdi-lightbulb-question:before{content:"󱧣"}.mdi-lightbulb-question-outline:before{content:"󱧤"}.mdi-lightbulb-spot:before{content:"󱟴"}.mdi-lightbulb-spot-off:before{content:"󱟵"}.mdi-lightbulb-variant:before{content:"󱠂"}.mdi-lightbulb-variant-outline:before{content:"󱠃"}.mdi-lighthouse:before{content:"󰧿"}.mdi-lighthouse-on:before{content:"󰨀"}.mdi-lightning-bolt:before{content:"󱐋"}.mdi-lightning-bolt-circle:before{content:"󰠠"}.mdi-lightning-bolt-outline:before{content:"󱐌"}.mdi-line-scan:before{content:"󰘤"}.mdi-lingerie:before{content:"󱑶"}.mdi-link:before{content:"󰌷"}.mdi-link-box:before{content:"󰴚"}.mdi-link-box-outline:before{content:"󰴛"}.mdi-link-box-variant:before{content:"󰴜"}.mdi-link-box-variant-outline:before{content:"󰴝"}.mdi-link-lock:before{content:"󱂺"}.mdi-link-off:before{content:"󰌸"}.mdi-link-plus:before{content:"󰲔"}.mdi-link-variant:before{content:"󰌹"}.mdi-link-variant-minus:before{content:"󱃿"}.mdi-link-variant-off:before{content:"󰌺"}.mdi-link-variant-plus:before{content:"󱄀"}.mdi-link-variant-remove:before{content:"󱄁"}.mdi-linkedin:before{content:"󰌻"}.mdi-linux:before{content:"󰌽"}.mdi-linux-mint:before{content:"󰣭"}.mdi-lipstick:before{content:"󱎵"}.mdi-liquid-spot:before{content:"󱠦"}.mdi-liquor:before{content:"󱤞"}.mdi-list-box:before{content:"󱭻"}.mdi-list-box-outline:before{content:"󱭼"}.mdi-list-status:before{content:"󱖫"}.mdi-litecoin:before{content:"󰩡"}.mdi-loading:before{content:"󰝲"}.mdi-location-enter:before{content:"󰿄"}.mdi-location-exit:before{content:"󰿅"}.mdi-lock:before{content:"󰌾"}.mdi-lock-alert:before{content:"󰣮"}.mdi-lock-alert-outline:before{content:"󱗑"}.mdi-lock-check:before{content:"󱎚"}.mdi-lock-check-outline:before{content:"󱚨"}.mdi-lock-clock:before{content:"󰥿"}.mdi-lock-minus:before{content:"󱚩"}.mdi-lock-minus-outline:before{content:"󱚪"}.mdi-lock-off:before{content:"󱙱"}.mdi-lock-off-outline:before{content:"󱙲"}.mdi-lock-open:before{content:"󰌿"}.mdi-lock-open-alert:before{content:"󱎛"}.mdi-lock-open-alert-outline:before{content:"󱗒"}.mdi-lock-open-check:before{content:"󱎜"}.mdi-lock-open-check-outline:before{content:"󱚫"}.mdi-lock-open-minus:before{content:"󱚬"}.mdi-lock-open-minus-outline:before{content:"󱚭"}.mdi-lock-open-outline:before{content:"󰍀"}.mdi-lock-open-plus:before{content:"󱚮"}.mdi-lock-open-plus-outline:before{content:"󱚯"}.mdi-lock-open-remove:before{content:"󱚰"}.mdi-lock-open-remove-outline:before{content:"󱚱"}.mdi-lock-open-variant:before{content:"󰿆"}.mdi-lock-open-variant-outline:before{content:"󰿇"}.mdi-lock-outline:before{content:"󰍁"}.mdi-lock-pattern:before{content:"󰛪"}.mdi-lock-percent:before{content:"󱰒"}.mdi-lock-percent-open:before{content:"󱰓"}.mdi-lock-percent-open-outline:before{content:"󱰔"}.mdi-lock-percent-open-variant:before{content:"󱰕"}.mdi-lock-percent-open-variant-outline:before{content:"󱰖"}.mdi-lock-percent-outline:before{content:"󱰗"}.mdi-lock-plus:before{content:"󰗻"}.mdi-lock-plus-outline:before{content:"󱚲"}.mdi-lock-question:before{content:"󰣯"}.mdi-lock-remove:before{content:"󱚳"}.mdi-lock-remove-outline:before{content:"󱚴"}.mdi-lock-reset:before{content:"󰝳"}.mdi-lock-smart:before{content:"󰢲"}.mdi-locker:before{content:"󰟗"}.mdi-locker-multiple:before{content:"󰟘"}.mdi-login:before{content:"󰍂"}.mdi-login-variant:before{content:"󰗼"}.mdi-logout:before{content:"󰍃"}.mdi-logout-variant:before{content:"󰗽"}.mdi-longitude:before{content:"󰽚"}.mdi-looks:before{content:"󰍄"}.mdi-lotion:before{content:"󱖂"}.mdi-lotion-outline:before{content:"󱖃"}.mdi-lotion-plus:before{content:"󱖄"}.mdi-lotion-plus-outline:before{content:"󱖅"}.mdi-loupe:before{content:"󰍅"}.mdi-lumx:before{content:"󰍆"}.mdi-lungs:before{content:"󱂄"}.mdi-mace:before{content:"󱡃"}.mdi-magazine-pistol:before{content:"󰌤"}.mdi-magazine-rifle:before{content:"󰌣"}.mdi-magic-staff:before{content:"󱡄"}.mdi-magnet:before{content:"󰍇"}.mdi-magnet-on:before{content:"󰍈"}.mdi-magnify:before{content:"󰍉"}.mdi-magnify-close:before{content:"󰦀"}.mdi-magnify-expand:before{content:"󱡴"}.mdi-magnify-minus:before{content:"󰍊"}.mdi-magnify-minus-cursor:before{content:"󰩢"}.mdi-magnify-minus-outline:before{content:"󰛬"}.mdi-magnify-plus:before{content:"󰍋"}.mdi-magnify-plus-cursor:before{content:"󰩣"}.mdi-magnify-plus-outline:before{content:"󰛭"}.mdi-magnify-remove-cursor:before{content:"󱈌"}.mdi-magnify-remove-outline:before{content:"󱈍"}.mdi-magnify-scan:before{content:"󱉶"}.mdi-mail:before{content:"󰺻"}.mdi-mailbox:before{content:"󰛮"}.mdi-mailbox-open:before{content:"󰶈"}.mdi-mailbox-open-outline:before{content:"󰶉"}.mdi-mailbox-open-up:before{content:"󰶊"}.mdi-mailbox-open-up-outline:before{content:"󰶋"}.mdi-mailbox-outline:before{content:"󰶌"}.mdi-mailbox-up:before{content:"󰶍"}.mdi-mailbox-up-outline:before{content:"󰶎"}.mdi-manjaro:before{content:"󱘊"}.mdi-map:before{content:"󰍍"}.mdi-map-check:before{content:"󰺼"}.mdi-map-check-outline:before{content:"󰺽"}.mdi-map-clock:before{content:"󰴞"}.mdi-map-clock-outline:before{content:"󰴟"}.mdi-map-legend:before{content:"󰨁"}.mdi-map-marker:before{content:"󰍎"}.mdi-map-marker-account:before{content:"󱣣"}.mdi-map-marker-account-outline:before{content:"󱣤"}.mdi-map-marker-alert:before{content:"󰼅"}.mdi-map-marker-alert-outline:before{content:"󰼆"}.mdi-map-marker-check:before{content:"󰲕"}.mdi-map-marker-check-outline:before{content:"󱋻"}.mdi-map-marker-circle:before{content:"󰍏"}.mdi-map-marker-distance:before{content:"󰣰"}.mdi-map-marker-down:before{content:"󱄂"}.mdi-map-marker-left:before{content:"󱋛"}.mdi-map-marker-left-outline:before{content:"󱋝"}.mdi-map-marker-minus:before{content:"󰙐"}.mdi-map-marker-minus-outline:before{content:"󱋹"}.mdi-map-marker-multiple:before{content:"󰍐"}.mdi-map-marker-multiple-outline:before{content:"󱉷"}.mdi-map-marker-off:before{content:"󰍑"}.mdi-map-marker-off-outline:before{content:"󱋽"}.mdi-map-marker-outline:before{content:"󰟙"}.mdi-map-marker-path:before{content:"󰴠"}.mdi-map-marker-plus:before{content:"󰙑"}.mdi-map-marker-plus-outline:before{content:"󱋸"}.mdi-map-marker-question:before{content:"󰼇"}.mdi-map-marker-question-outline:before{content:"󰼈"}.mdi-map-marker-radius:before{content:"󰍒"}.mdi-map-marker-radius-outline:before{content:"󱋼"}.mdi-map-marker-remove:before{content:"󰼉"}.mdi-map-marker-remove-outline:before{content:"󱋺"}.mdi-map-marker-remove-variant:before{content:"󰼊"}.mdi-map-marker-right:before{content:"󱋜"}.mdi-map-marker-right-outline:before{content:"󱋞"}.mdi-map-marker-star:before{content:"󱘈"}.mdi-map-marker-star-outline:before{content:"󱘉"}.mdi-map-marker-up:before{content:"󱄃"}.mdi-map-minus:before{content:"󰦁"}.mdi-map-outline:before{content:"󰦂"}.mdi-map-plus:before{content:"󰦃"}.mdi-map-search:before{content:"󰦄"}.mdi-map-search-outline:before{content:"󰦅"}.mdi-mapbox:before{content:"󰮪"}.mdi-margin:before{content:"󰍓"}.mdi-marker:before{content:"󰙒"}.mdi-marker-cancel:before{content:"󰷙"}.mdi-marker-check:before{content:"󰍕"}.mdi-mastodon:before{content:"󰫑"}.mdi-material-design:before{content:"󰦆"}.mdi-material-ui:before{content:"󰍗"}.mdi-math-compass:before{content:"󰍘"}.mdi-math-cos:before{content:"󰲖"}.mdi-math-integral:before{content:"󰿈"}.mdi-math-integral-box:before{content:"󰿉"}.mdi-math-log:before{content:"󱂅"}.mdi-math-norm:before{content:"󰿊"}.mdi-math-norm-box:before{content:"󰿋"}.mdi-math-sin:before{content:"󰲗"}.mdi-math-tan:before{content:"󰲘"}.mdi-matrix:before{content:"󰘨"}.mdi-medal:before{content:"󰦇"}.mdi-medal-outline:before{content:"󱌦"}.mdi-medical-bag:before{content:"󰛯"}.mdi-medical-cotton-swab:before{content:"󱪸"}.mdi-medication:before{content:"󱬔"}.mdi-medication-outline:before{content:"󱬕"}.mdi-meditation:before{content:"󱅻"}.mdi-memory:before{content:"󰍛"}.mdi-menorah:before{content:"󱟔"}.mdi-menorah-fire:before{content:"󱟕"}.mdi-menu:before{content:"󰍜"}.mdi-menu-down:before{content:"󰍝"}.mdi-menu-down-outline:before{content:"󰚶"}.mdi-menu-left:before{content:"󰍞"}.mdi-menu-left-outline:before{content:"󰨂"}.mdi-menu-open:before{content:"󰮫"}.mdi-menu-right:before{content:"󰍟"}.mdi-menu-right-outline:before{content:"󰨃"}.mdi-menu-swap:before{content:"󰩤"}.mdi-menu-swap-outline:before{content:"󰩥"}.mdi-menu-up:before{content:"󰍠"}.mdi-menu-up-outline:before{content:"󰚷"}.mdi-merge:before{content:"󰽜"}.mdi-message:before{content:"󰍡"}.mdi-message-alert:before{content:"󰍢"}.mdi-message-alert-outline:before{content:"󰨄"}.mdi-message-arrow-left:before{content:"󱋲"}.mdi-message-arrow-left-outline:before{content:"󱋳"}.mdi-message-arrow-right:before{content:"󱋴"}.mdi-message-arrow-right-outline:before{content:"󱋵"}.mdi-message-badge:before{content:"󱥁"}.mdi-message-badge-outline:before{content:"󱥂"}.mdi-message-bookmark:before{content:"󱖬"}.mdi-message-bookmark-outline:before{content:"󱖭"}.mdi-message-bulleted:before{content:"󰚢"}.mdi-message-bulleted-off:before{content:"󰚣"}.mdi-message-check:before{content:"󱮊"}.mdi-message-check-outline:before{content:"󱮋"}.mdi-message-cog:before{content:"󰛱"}.mdi-message-cog-outline:before{content:"󱅲"}.mdi-message-draw:before{content:"󰍣"}.mdi-message-fast:before{content:"󱧌"}.mdi-message-fast-outline:before{content:"󱧍"}.mdi-message-flash:before{content:"󱖩"}.mdi-message-flash-outline:before{content:"󱖪"}.mdi-message-image:before{content:"󰍤"}.mdi-message-image-outline:before{content:"󱅬"}.mdi-message-lock:before{content:"󰿌"}.mdi-message-lock-outline:before{content:"󱅭"}.mdi-message-minus:before{content:"󱅮"}.mdi-message-minus-outline:before{content:"󱅯"}.mdi-message-off:before{content:"󱙍"}.mdi-message-off-outline:before{content:"󱙎"}.mdi-message-outline:before{content:"󰍥"}.mdi-message-plus:before{content:"󰙓"}.mdi-message-plus-outline:before{content:"󱂻"}.mdi-message-processing:before{content:"󰍦"}.mdi-message-processing-outline:before{content:"󱅰"}.mdi-message-question:before{content:"󱜺"}.mdi-message-question-outline:before{content:"󱜻"}.mdi-message-reply:before{content:"󰍧"}.mdi-message-reply-outline:before{content:"󱜽"}.mdi-message-reply-text:before{content:"󰍨"}.mdi-message-reply-text-outline:before{content:"󱜾"}.mdi-message-settings:before{content:"󰛰"}.mdi-message-settings-outline:before{content:"󱅱"}.mdi-message-star:before{content:"󰚚"}.mdi-message-star-outline:before{content:"󱉐"}.mdi-message-text:before{content:"󰍩"}.mdi-message-text-clock:before{content:"󱅳"}.mdi-message-text-clock-outline:before{content:"󱅴"}.mdi-message-text-fast:before{content:"󱧎"}.mdi-message-text-fast-outline:before{content:"󱧏"}.mdi-message-text-lock:before{content:"󰿍"}.mdi-message-text-lock-outline:before{content:"󱅵"}.mdi-message-text-outline:before{content:"󰍪"}.mdi-message-video:before{content:"󰍫"}.mdi-meteor:before{content:"󰘩"}.mdi-meter-electric:before{content:"󱩗"}.mdi-meter-electric-outline:before{content:"󱩘"}.mdi-meter-gas:before{content:"󱩙"}.mdi-meter-gas-outline:before{content:"󱩚"}.mdi-metronome:before{content:"󰟚"}.mdi-metronome-tick:before{content:"󰟛"}.mdi-micro-sd:before{content:"󰟜"}.mdi-microphone:before{content:"󰍬"}.mdi-microphone-message:before{content:"󰔊"}.mdi-microphone-message-off:before{content:"󰔋"}.mdi-microphone-minus:before{content:"󰢳"}.mdi-microphone-off:before{content:"󰍭"}.mdi-microphone-outline:before{content:"󰍮"}.mdi-microphone-plus:before{content:"󰢴"}.mdi-microphone-question:before{content:"󱦉"}.mdi-microphone-question-outline:before{content:"󱦊"}.mdi-microphone-settings:before{content:"󰍯"}.mdi-microphone-variant:before{content:"󰍰"}.mdi-microphone-variant-off:before{content:"󰍱"}.mdi-microscope:before{content:"󰙔"}.mdi-microsoft:before{content:"󰍲"}.mdi-microsoft-access:before{content:"󱎎"}.mdi-microsoft-azure:before{content:"󰠅"}.mdi-microsoft-azure-devops:before{content:"󰿕"}.mdi-microsoft-bing:before{content:"󰂤"}.mdi-microsoft-dynamics-365:before{content:"󰦈"}.mdi-microsoft-edge:before{content:"󰇩"}.mdi-microsoft-excel:before{content:"󱎏"}.mdi-microsoft-internet-explorer:before{content:"󰌀"}.mdi-microsoft-office:before{content:"󰏆"}.mdi-microsoft-onedrive:before{content:"󰏊"}.mdi-microsoft-onenote:before{content:"󰝇"}.mdi-microsoft-outlook:before{content:"󰴢"}.mdi-microsoft-powerpoint:before{content:"󱎐"}.mdi-microsoft-sharepoint:before{content:"󱎑"}.mdi-microsoft-teams:before{content:"󰊻"}.mdi-microsoft-visual-studio:before{content:"󰘐"}.mdi-microsoft-visual-studio-code:before{content:"󰨞"}.mdi-microsoft-windows:before{content:"󰖳"}.mdi-microsoft-windows-classic:before{content:"󰨡"}.mdi-microsoft-word:before{content:"󱎒"}.mdi-microsoft-xbox:before{content:"󰖹"}.mdi-microsoft-xbox-controller:before{content:"󰖺"}.mdi-microsoft-xbox-controller-battery-alert:before{content:"󰝋"}.mdi-microsoft-xbox-controller-battery-charging:before{content:"󰨢"}.mdi-microsoft-xbox-controller-battery-empty:before{content:"󰝌"}.mdi-microsoft-xbox-controller-battery-full:before{content:"󰝍"}.mdi-microsoft-xbox-controller-battery-low:before{content:"󰝎"}.mdi-microsoft-xbox-controller-battery-medium:before{content:"󰝏"}.mdi-microsoft-xbox-controller-battery-unknown:before{content:"󰝐"}.mdi-microsoft-xbox-controller-menu:before{content:"󰹯"}.mdi-microsoft-xbox-controller-off:before{content:"󰖻"}.mdi-microsoft-xbox-controller-view:before{content:"󰹰"}.mdi-microwave:before{content:"󰲙"}.mdi-microwave-off:before{content:"󱐣"}.mdi-middleware:before{content:"󰽝"}.mdi-middleware-outline:before{content:"󰽞"}.mdi-midi:before{content:"󰣱"}.mdi-midi-port:before{content:"󰣲"}.mdi-mine:before{content:"󰷚"}.mdi-minecraft:before{content:"󰍳"}.mdi-mini-sd:before{content:"󰨅"}.mdi-minidisc:before{content:"󰨆"}.mdi-minus:before{content:"󰍴"}.mdi-minus-box:before{content:"󰍵"}.mdi-minus-box-multiple:before{content:"󱅁"}.mdi-minus-box-multiple-outline:before{content:"󱅂"}.mdi-minus-box-outline:before{content:"󰛲"}.mdi-minus-circle:before{content:"󰍶"}.mdi-minus-circle-multiple:before{content:"󰍚"}.mdi-minus-circle-multiple-outline:before{content:"󰫓"}.mdi-minus-circle-off:before{content:"󱑙"}.mdi-minus-circle-off-outline:before{content:"󱑚"}.mdi-minus-circle-outline:before{content:"󰍷"}.mdi-minus-network:before{content:"󰍸"}.mdi-minus-network-outline:before{content:"󰲚"}.mdi-minus-thick:before{content:"󱘹"}.mdi-mirror:before{content:"󱇽"}.mdi-mirror-rectangle:before{content:"󱞟"}.mdi-mirror-variant:before{content:"󱞠"}.mdi-mixed-martial-arts:before{content:"󰶏"}.mdi-mixed-reality:before{content:"󰡿"}.mdi-molecule:before{content:"󰮬"}.mdi-molecule-co:before{content:"󱋾"}.mdi-molecule-co2:before{content:"󰟤"}.mdi-monitor:before{content:"󰍹"}.mdi-monitor-account:before{content:"󱩛"}.mdi-monitor-arrow-down:before{content:"󱧐"}.mdi-monitor-arrow-down-variant:before{content:"󱧑"}.mdi-monitor-cellphone:before{content:"󰦉"}.mdi-monitor-cellphone-star:before{content:"󰦊"}.mdi-monitor-dashboard:before{content:"󰨇"}.mdi-monitor-edit:before{content:"󱋆"}.mdi-monitor-eye:before{content:"󱎴"}.mdi-monitor-lock:before{content:"󰷛"}.mdi-monitor-multiple:before{content:"󰍺"}.mdi-monitor-off:before{content:"󰶐"}.mdi-monitor-screenshot:before{content:"󰹑"}.mdi-monitor-share:before{content:"󱒃"}.mdi-monitor-shimmer:before{content:"󱄄"}.mdi-monitor-small:before{content:"󱡶"}.mdi-monitor-speaker:before{content:"󰽟"}.mdi-monitor-speaker-off:before{content:"󰽠"}.mdi-monitor-star:before{content:"󰷜"}.mdi-monitor-vertical:before{content:"󱰳"}.mdi-moon-first-quarter:before{content:"󰽡"}.mdi-moon-full:before{content:"󰽢"}.mdi-moon-last-quarter:before{content:"󰽣"}.mdi-moon-new:before{content:"󰽤"}.mdi-moon-waning-crescent:before{content:"󰽥"}.mdi-moon-waning-gibbous:before{content:"󰽦"}.mdi-moon-waxing-crescent:before{content:"󰽧"}.mdi-moon-waxing-gibbous:before{content:"󰽨"}.mdi-moped:before{content:"󱂆"}.mdi-moped-electric:before{content:"󱖷"}.mdi-moped-electric-outline:before{content:"󱖸"}.mdi-moped-outline:before{content:"󱖹"}.mdi-more:before{content:"󰍻"}.mdi-mortar-pestle:before{content:"󱝈"}.mdi-mortar-pestle-plus:before{content:"󰏱"}.mdi-mosque:before{content:"󰵅"}.mdi-mosque-outline:before{content:"󱠧"}.mdi-mother-heart:before{content:"󱌔"}.mdi-mother-nurse:before{content:"󰴡"}.mdi-motion:before{content:"󱖲"}.mdi-motion-outline:before{content:"󱖳"}.mdi-motion-pause:before{content:"󱖐"}.mdi-motion-pause-outline:before{content:"󱖒"}.mdi-motion-play:before{content:"󱖏"}.mdi-motion-play-outline:before{content:"󱖑"}.mdi-motion-sensor:before{content:"󰶑"}.mdi-motion-sensor-off:before{content:"󱐵"}.mdi-motorbike:before{content:"󰍼"}.mdi-motorbike-electric:before{content:"󱖺"}.mdi-motorbike-off:before{content:"󱬖"}.mdi-mouse:before{content:"󰍽"}.mdi-mouse-bluetooth:before{content:"󰦋"}.mdi-mouse-move-down:before{content:"󱕐"}.mdi-mouse-move-up:before{content:"󱕑"}.mdi-mouse-move-vertical:before{content:"󱕒"}.mdi-mouse-off:before{content:"󰍾"}.mdi-mouse-variant:before{content:"󰍿"}.mdi-mouse-variant-off:before{content:"󰎀"}.mdi-move-resize:before{content:"󰙕"}.mdi-move-resize-variant:before{content:"󰙖"}.mdi-movie:before{content:"󰎁"}.mdi-movie-check:before{content:"󱛳"}.mdi-movie-check-outline:before{content:"󱛴"}.mdi-movie-cog:before{content:"󱛵"}.mdi-movie-cog-outline:before{content:"󱛶"}.mdi-movie-edit:before{content:"󱄢"}.mdi-movie-edit-outline:before{content:"󱄣"}.mdi-movie-filter:before{content:"󱄤"}.mdi-movie-filter-outline:before{content:"󱄥"}.mdi-movie-minus:before{content:"󱛷"}.mdi-movie-minus-outline:before{content:"󱛸"}.mdi-movie-off:before{content:"󱛹"}.mdi-movie-off-outline:before{content:"󱛺"}.mdi-movie-open:before{content:"󰿎"}.mdi-movie-open-check:before{content:"󱛻"}.mdi-movie-open-check-outline:before{content:"󱛼"}.mdi-movie-open-cog:before{content:"󱛽"}.mdi-movie-open-cog-outline:before{content:"󱛾"}.mdi-movie-open-edit:before{content:"󱛿"}.mdi-movie-open-edit-outline:before{content:"󱜀"}.mdi-movie-open-minus:before{content:"󱜁"}.mdi-movie-open-minus-outline:before{content:"󱜂"}.mdi-movie-open-off:before{content:"󱜃"}.mdi-movie-open-off-outline:before{content:"󱜄"}.mdi-movie-open-outline:before{content:"󰿏"}.mdi-movie-open-play:before{content:"󱜅"}.mdi-movie-open-play-outline:before{content:"󱜆"}.mdi-movie-open-plus:before{content:"󱜇"}.mdi-movie-open-plus-outline:before{content:"󱜈"}.mdi-movie-open-remove:before{content:"󱜉"}.mdi-movie-open-remove-outline:before{content:"󱜊"}.mdi-movie-open-settings:before{content:"󱜋"}.mdi-movie-open-settings-outline:before{content:"󱜌"}.mdi-movie-open-star:before{content:"󱜍"}.mdi-movie-open-star-outline:before{content:"󱜎"}.mdi-movie-outline:before{content:"󰷝"}.mdi-movie-play:before{content:"󱜏"}.mdi-movie-play-outline:before{content:"󱜐"}.mdi-movie-plus:before{content:"󱜑"}.mdi-movie-plus-outline:before{content:"󱜒"}.mdi-movie-remove:before{content:"󱜓"}.mdi-movie-remove-outline:before{content:"󱜔"}.mdi-movie-roll:before{content:"󰟞"}.mdi-movie-search:before{content:"󱇒"}.mdi-movie-search-outline:before{content:"󱇓"}.mdi-movie-settings:before{content:"󱜕"}.mdi-movie-settings-outline:before{content:"󱜖"}.mdi-movie-star:before{content:"󱜗"}.mdi-movie-star-outline:before{content:"󱜘"}.mdi-mower:before{content:"󱙯"}.mdi-mower-bag:before{content:"󱙰"}.mdi-mower-bag-on:before{content:"󱭠"}.mdi-mower-on:before{content:"󱭟"}.mdi-muffin:before{content:"󰦌"}.mdi-multicast:before{content:"󱢓"}.mdi-multimedia:before{content:"󱮗"}.mdi-multiplication:before{content:"󰎂"}.mdi-multiplication-box:before{content:"󰎃"}.mdi-mushroom:before{content:"󰟟"}.mdi-mushroom-off:before{content:"󱏺"}.mdi-mushroom-off-outline:before{content:"󱏻"}.mdi-mushroom-outline:before{content:"󰟠"}.mdi-music:before{content:"󰝚"}.mdi-music-accidental-double-flat:before{content:"󰽩"}.mdi-music-accidental-double-sharp:before{content:"󰽪"}.mdi-music-accidental-flat:before{content:"󰽫"}.mdi-music-accidental-natural:before{content:"󰽬"}.mdi-music-accidental-sharp:before{content:"󰽭"}.mdi-music-box:before{content:"󰎄"}.mdi-music-box-multiple:before{content:"󰌳"}.mdi-music-box-multiple-outline:before{content:"󰼄"}.mdi-music-box-outline:before{content:"󰎅"}.mdi-music-circle:before{content:"󰎆"}.mdi-music-circle-outline:before{content:"󰫔"}.mdi-music-clef-alto:before{content:"󰽮"}.mdi-music-clef-bass:before{content:"󰽯"}.mdi-music-clef-treble:before{content:"󰽰"}.mdi-music-note:before{content:"󰎇"}.mdi-music-note-bluetooth:before{content:"󰗾"}.mdi-music-note-bluetooth-off:before{content:"󰗿"}.mdi-music-note-eighth:before{content:"󰎈"}.mdi-music-note-eighth-dotted:before{content:"󰽱"}.mdi-music-note-half:before{content:"󰎉"}.mdi-music-note-half-dotted:before{content:"󰽲"}.mdi-music-note-minus:before{content:"󱮉"}.mdi-music-note-off:before{content:"󰎊"}.mdi-music-note-off-outline:before{content:"󰽳"}.mdi-music-note-outline:before{content:"󰽴"}.mdi-music-note-plus:before{content:"󰷞"}.mdi-music-note-quarter:before{content:"󰎋"}.mdi-music-note-quarter-dotted:before{content:"󰽵"}.mdi-music-note-sixteenth:before{content:"󰎌"}.mdi-music-note-sixteenth-dotted:before{content:"󰽶"}.mdi-music-note-whole:before{content:"󰎍"}.mdi-music-note-whole-dotted:before{content:"󰽷"}.mdi-music-off:before{content:"󰝛"}.mdi-music-rest-eighth:before{content:"󰽸"}.mdi-music-rest-half:before{content:"󰽹"}.mdi-music-rest-quarter:before{content:"󰽺"}.mdi-music-rest-sixteenth:before{content:"󰽻"}.mdi-music-rest-whole:before{content:"󰽼"}.mdi-mustache:before{content:"󱗞"}.mdi-nail:before{content:"󰷟"}.mdi-nas:before{content:"󰣳"}.mdi-nativescript:before{content:"󰢀"}.mdi-nature:before{content:"󰎎"}.mdi-nature-outline:before{content:"󱱱"}.mdi-nature-people:before{content:"󰎏"}.mdi-nature-people-outline:before{content:"󱱲"}.mdi-navigation:before{content:"󰎐"}.mdi-navigation-outline:before{content:"󱘇"}.mdi-navigation-variant:before{content:"󱣰"}.mdi-navigation-variant-outline:before{content:"󱣱"}.mdi-near-me:before{content:"󰗍"}.mdi-necklace:before{content:"󰼋"}.mdi-needle:before{content:"󰎑"}.mdi-needle-off:before{content:"󱧒"}.mdi-netflix:before{content:"󰝆"}.mdi-network:before{content:"󰛳"}.mdi-network-off:before{content:"󰲛"}.mdi-network-off-outline:before{content:"󰲜"}.mdi-network-outline:before{content:"󰲝"}.mdi-network-pos:before{content:"󱫋"}.mdi-network-strength-1:before{content:"󰣴"}.mdi-network-strength-1-alert:before{content:"󰣵"}.mdi-network-strength-2:before{content:"󰣶"}.mdi-network-strength-2-alert:before{content:"󰣷"}.mdi-network-strength-3:before{content:"󰣸"}.mdi-network-strength-3-alert:before{content:"󰣹"}.mdi-network-strength-4:before{content:"󰣺"}.mdi-network-strength-4-alert:before{content:"󰣻"}.mdi-network-strength-4-cog:before{content:"󱤚"}.mdi-network-strength-off:before{content:"󰣼"}.mdi-network-strength-off-outline:before{content:"󰣽"}.mdi-network-strength-outline:before{content:"󰣾"}.mdi-new-box:before{content:"󰎔"}.mdi-newspaper:before{content:"󰎕"}.mdi-newspaper-check:before{content:"󱥃"}.mdi-newspaper-minus:before{content:"󰼌"}.mdi-newspaper-plus:before{content:"󰼍"}.mdi-newspaper-remove:before{content:"󱥄"}.mdi-newspaper-variant:before{content:"󱀁"}.mdi-newspaper-variant-multiple:before{content:"󱀂"}.mdi-newspaper-variant-multiple-outline:before{content:"󱀃"}.mdi-newspaper-variant-outline:before{content:"󱀄"}.mdi-nfc:before{content:"󰎖"}.mdi-nfc-search-variant:before{content:"󰹓"}.mdi-nfc-tap:before{content:"󰎗"}.mdi-nfc-variant:before{content:"󰎘"}.mdi-nfc-variant-off:before{content:"󰹔"}.mdi-ninja:before{content:"󰝴"}.mdi-nintendo-game-boy:before{content:"󱎓"}.mdi-nintendo-switch:before{content:"󰟡"}.mdi-nintendo-wii:before{content:"󰖫"}.mdi-nintendo-wiiu:before{content:"󰜭"}.mdi-nix:before{content:"󱄅"}.mdi-nodejs:before{content:"󰎙"}.mdi-noodles:before{content:"󱅾"}.mdi-not-equal:before{content:"󰦍"}.mdi-not-equal-variant:before{content:"󰦎"}.mdi-note:before{content:"󰎚"}.mdi-note-alert:before{content:"󱝽"}.mdi-note-alert-outline:before{content:"󱝾"}.mdi-note-check:before{content:"󱝿"}.mdi-note-check-outline:before{content:"󱞀"}.mdi-note-edit:before{content:"󱞁"}.mdi-note-edit-outline:before{content:"󱞂"}.mdi-note-minus:before{content:"󱙏"}.mdi-note-minus-outline:before{content:"󱙐"}.mdi-note-multiple:before{content:"󰚸"}.mdi-note-multiple-outline:before{content:"󰚹"}.mdi-note-off:before{content:"󱞃"}.mdi-note-off-outline:before{content:"󱞄"}.mdi-note-outline:before{content:"󰎛"}.mdi-note-plus:before{content:"󰎜"}.mdi-note-plus-outline:before{content:"󰎝"}.mdi-note-remove:before{content:"󱙑"}.mdi-note-remove-outline:before{content:"󱙒"}.mdi-note-search:before{content:"󱙓"}.mdi-note-search-outline:before{content:"󱙔"}.mdi-note-text:before{content:"󰎞"}.mdi-note-text-outline:before{content:"󱇗"}.mdi-notebook:before{content:"󰠮"}.mdi-notebook-check:before{content:"󱓵"}.mdi-notebook-check-outline:before{content:"󱓶"}.mdi-notebook-edit:before{content:"󱓧"}.mdi-notebook-edit-outline:before{content:"󱓩"}.mdi-notebook-heart:before{content:"󱨋"}.mdi-notebook-heart-outline:before{content:"󱨌"}.mdi-notebook-minus:before{content:"󱘐"}.mdi-notebook-minus-outline:before{content:"󱘑"}.mdi-notebook-multiple:before{content:"󰹕"}.mdi-notebook-outline:before{content:"󰺿"}.mdi-notebook-plus:before{content:"󱘒"}.mdi-notebook-plus-outline:before{content:"󱘓"}.mdi-notebook-remove:before{content:"󱘔"}.mdi-notebook-remove-outline:before{content:"󱘕"}.mdi-notification-clear-all:before{content:"󰎟"}.mdi-npm:before{content:"󰛷"}.mdi-nuke:before{content:"󰚤"}.mdi-null:before{content:"󰟢"}.mdi-numeric:before{content:"󰎠"}.mdi-numeric-0:before{content:"󰬹"}.mdi-numeric-0-box:before{content:"󰎡"}.mdi-numeric-0-box-multiple:before{content:"󰼎"}.mdi-numeric-0-box-multiple-outline:before{content:"󰎢"}.mdi-numeric-0-box-outline:before{content:"󰎣"}.mdi-numeric-0-circle:before{content:"󰲞"}.mdi-numeric-0-circle-outline:before{content:"󰲟"}.mdi-numeric-1:before{content:"󰬺"}.mdi-numeric-1-box:before{content:"󰎤"}.mdi-numeric-1-box-multiple:before{content:"󰼏"}.mdi-numeric-1-box-multiple-outline:before{content:"󰎥"}.mdi-numeric-1-box-outline:before{content:"󰎦"}.mdi-numeric-1-circle:before{content:"󰲠"}.mdi-numeric-1-circle-outline:before{content:"󰲡"}.mdi-numeric-10:before{content:"󰿩"}.mdi-numeric-10-box:before{content:"󰽽"}.mdi-numeric-10-box-multiple:before{content:"󰿪"}.mdi-numeric-10-box-multiple-outline:before{content:"󰿫"}.mdi-numeric-10-box-outline:before{content:"󰽾"}.mdi-numeric-10-circle:before{content:"󰿬"}.mdi-numeric-10-circle-outline:before{content:"󰿭"}.mdi-numeric-2:before{content:"󰬻"}.mdi-numeric-2-box:before{content:"󰎧"}.mdi-numeric-2-box-multiple:before{content:"󰼐"}.mdi-numeric-2-box-multiple-outline:before{content:"󰎨"}.mdi-numeric-2-box-outline:before{content:"󰎩"}.mdi-numeric-2-circle:before{content:"󰲢"}.mdi-numeric-2-circle-outline:before{content:"󰲣"}.mdi-numeric-3:before{content:"󰬼"}.mdi-numeric-3-box:before{content:"󰎪"}.mdi-numeric-3-box-multiple:before{content:"󰼑"}.mdi-numeric-3-box-multiple-outline:before{content:"󰎫"}.mdi-numeric-3-box-outline:before{content:"󰎬"}.mdi-numeric-3-circle:before{content:"󰲤"}.mdi-numeric-3-circle-outline:before{content:"󰲥"}.mdi-numeric-4:before{content:"󰬽"}.mdi-numeric-4-box:before{content:"󰎭"}.mdi-numeric-4-box-multiple:before{content:"󰼒"}.mdi-numeric-4-box-multiple-outline:before{content:"󰎲"}.mdi-numeric-4-box-outline:before{content:"󰎮"}.mdi-numeric-4-circle:before{content:"󰲦"}.mdi-numeric-4-circle-outline:before{content:"󰲧"}.mdi-numeric-5:before{content:"󰬾"}.mdi-numeric-5-box:before{content:"󰎱"}.mdi-numeric-5-box-multiple:before{content:"󰼓"}.mdi-numeric-5-box-multiple-outline:before{content:"󰎯"}.mdi-numeric-5-box-outline:before{content:"󰎰"}.mdi-numeric-5-circle:before{content:"󰲨"}.mdi-numeric-5-circle-outline:before{content:"󰲩"}.mdi-numeric-6:before{content:"󰬿"}.mdi-numeric-6-box:before{content:"󰎳"}.mdi-numeric-6-box-multiple:before{content:"󰼔"}.mdi-numeric-6-box-multiple-outline:before{content:"󰎴"}.mdi-numeric-6-box-outline:before{content:"󰎵"}.mdi-numeric-6-circle:before{content:"󰲪"}.mdi-numeric-6-circle-outline:before{content:"󰲫"}.mdi-numeric-7:before{content:"󰭀"}.mdi-numeric-7-box:before{content:"󰎶"}.mdi-numeric-7-box-multiple:before{content:"󰼕"}.mdi-numeric-7-box-multiple-outline:before{content:"󰎷"}.mdi-numeric-7-box-outline:before{content:"󰎸"}.mdi-numeric-7-circle:before{content:"󰲬"}.mdi-numeric-7-circle-outline:before{content:"󰲭"}.mdi-numeric-8:before{content:"󰭁"}.mdi-numeric-8-box:before{content:"󰎹"}.mdi-numeric-8-box-multiple:before{content:"󰼖"}.mdi-numeric-8-box-multiple-outline:before{content:"󰎺"}.mdi-numeric-8-box-outline:before{content:"󰎻"}.mdi-numeric-8-circle:before{content:"󰲮"}.mdi-numeric-8-circle-outline:before{content:"󰲯"}.mdi-numeric-9:before{content:"󰭂"}.mdi-numeric-9-box:before{content:"󰎼"}.mdi-numeric-9-box-multiple:before{content:"󰼗"}.mdi-numeric-9-box-multiple-outline:before{content:"󰎽"}.mdi-numeric-9-box-outline:before{content:"󰎾"}.mdi-numeric-9-circle:before{content:"󰲰"}.mdi-numeric-9-circle-outline:before{content:"󰲱"}.mdi-numeric-9-plus:before{content:"󰿮"}.mdi-numeric-9-plus-box:before{content:"󰎿"}.mdi-numeric-9-plus-box-multiple:before{content:"󰼘"}.mdi-numeric-9-plus-box-multiple-outline:before{content:"󰏀"}.mdi-numeric-9-plus-box-outline:before{content:"󰏁"}.mdi-numeric-9-plus-circle:before{content:"󰲲"}.mdi-numeric-9-plus-circle-outline:before{content:"󰲳"}.mdi-numeric-negative-1:before{content:"󱁒"}.mdi-numeric-off:before{content:"󱧓"}.mdi-numeric-positive-1:before{content:"󱗋"}.mdi-nut:before{content:"󰛸"}.mdi-nutrition:before{content:"󰏂"}.mdi-nuxt:before{content:"󱄆"}.mdi-oar:before{content:"󰙼"}.mdi-ocarina:before{content:"󰷠"}.mdi-oci:before{content:"󱋩"}.mdi-ocr:before{content:"󱄺"}.mdi-octagon:before{content:"󰏃"}.mdi-octagon-outline:before{content:"󰏄"}.mdi-octagram:before{content:"󰛹"}.mdi-octagram-edit:before{content:"󱰴"}.mdi-octagram-edit-outline:before{content:"󱰵"}.mdi-octagram-minus:before{content:"󱰶"}.mdi-octagram-minus-outline:before{content:"󱰷"}.mdi-octagram-outline:before{content:"󰝵"}.mdi-octagram-plus:before{content:"󱰸"}.mdi-octagram-plus-outline:before{content:"󱰹"}.mdi-octahedron:before{content:"󱥐"}.mdi-octahedron-off:before{content:"󱥑"}.mdi-odnoklassniki:before{content:"󰏅"}.mdi-offer:before{content:"󱈛"}.mdi-office-building:before{content:"󰦑"}.mdi-office-building-cog:before{content:"󱥉"}.mdi-office-building-cog-outline:before{content:"󱥊"}.mdi-office-building-marker:before{content:"󱔠"}.mdi-office-building-marker-outline:before{content:"󱔡"}.mdi-office-building-minus:before{content:"󱮪"}.mdi-office-building-minus-outline:before{content:"󱮫"}.mdi-office-building-outline:before{content:"󱔟"}.mdi-office-building-plus:before{content:"󱮨"}.mdi-office-building-plus-outline:before{content:"󱮩"}.mdi-office-building-remove:before{content:"󱮬"}.mdi-office-building-remove-outline:before{content:"󱮭"}.mdi-oil:before{content:"󰏇"}.mdi-oil-lamp:before{content:"󰼙"}.mdi-oil-level:before{content:"󱁓"}.mdi-oil-temperature:before{content:"󰿸"}.mdi-om:before{content:"󰥳"}.mdi-omega:before{content:"󰏉"}.mdi-one-up:before{content:"󰮭"}.mdi-onepassword:before{content:"󰢁"}.mdi-opacity:before{content:"󰗌"}.mdi-open-in-app:before{content:"󰏋"}.mdi-open-in-new:before{content:"󰏌"}.mdi-open-source-initiative:before{content:"󰮮"}.mdi-openid:before{content:"󰏍"}.mdi-opera:before{content:"󰏎"}.mdi-orbit:before{content:"󰀘"}.mdi-orbit-variant:before{content:"󱗛"}.mdi-order-alphabetical-ascending:before{content:"󰈍"}.mdi-order-alphabetical-descending:before{content:"󰴇"}.mdi-order-bool-ascending:before{content:"󰊾"}.mdi-order-bool-ascending-variant:before{content:"󰦏"}.mdi-order-bool-descending:before{content:"󱎄"}.mdi-order-bool-descending-variant:before{content:"󰦐"}.mdi-order-numeric-ascending:before{content:"󰕅"}.mdi-order-numeric-descending:before{content:"󰕆"}.mdi-origin:before{content:"󰭃"}.mdi-ornament:before{content:"󰏏"}.mdi-ornament-variant:before{content:"󰏐"}.mdi-outdoor-lamp:before{content:"󱁔"}.mdi-overscan:before{content:"󱀅"}.mdi-owl:before{content:"󰏒"}.mdi-pac-man:before{content:"󰮯"}.mdi-package:before{content:"󰏓"}.mdi-package-check:before{content:"󱭑"}.mdi-package-down:before{content:"󰏔"}.mdi-package-up:before{content:"󰏕"}.mdi-package-variant:before{content:"󰏖"}.mdi-package-variant-closed:before{content:"󰏗"}.mdi-package-variant-closed-check:before{content:"󱭒"}.mdi-package-variant-closed-minus:before{content:"󱧔"}.mdi-package-variant-closed-plus:before{content:"󱧕"}.mdi-package-variant-closed-remove:before{content:"󱧖"}.mdi-package-variant-minus:before{content:"󱧗"}.mdi-package-variant-plus:before{content:"󱧘"}.mdi-package-variant-remove:before{content:"󱧙"}.mdi-page-first:before{content:"󰘀"}.mdi-page-last:before{content:"󰘁"}.mdi-page-layout-body:before{content:"󰛺"}.mdi-page-layout-footer:before{content:"󰛻"}.mdi-page-layout-header:before{content:"󰛼"}.mdi-page-layout-header-footer:before{content:"󰽿"}.mdi-page-layout-sidebar-left:before{content:"󰛽"}.mdi-page-layout-sidebar-right:before{content:"󰛾"}.mdi-page-next:before{content:"󰮰"}.mdi-page-next-outline:before{content:"󰮱"}.mdi-page-previous:before{content:"󰮲"}.mdi-page-previous-outline:before{content:"󰮳"}.mdi-pail:before{content:"󱐗"}.mdi-pail-minus:before{content:"󱐷"}.mdi-pail-minus-outline:before{content:"󱐼"}.mdi-pail-off:before{content:"󱐹"}.mdi-pail-off-outline:before{content:"󱐾"}.mdi-pail-outline:before{content:"󱐺"}.mdi-pail-plus:before{content:"󱐶"}.mdi-pail-plus-outline:before{content:"󱐻"}.mdi-pail-remove:before{content:"󱐸"}.mdi-pail-remove-outline:before{content:"󱐽"}.mdi-palette:before{content:"󰏘"}.mdi-palette-advanced:before{content:"󰏙"}.mdi-palette-outline:before{content:"󰸌"}.mdi-palette-swatch:before{content:"󰢵"}.mdi-palette-swatch-outline:before{content:"󱍜"}.mdi-palette-swatch-variant:before{content:"󱥚"}.mdi-palm-tree:before{content:"󱁕"}.mdi-pan:before{content:"󰮴"}.mdi-pan-bottom-left:before{content:"󰮵"}.mdi-pan-bottom-right:before{content:"󰮶"}.mdi-pan-down:before{content:"󰮷"}.mdi-pan-horizontal:before{content:"󰮸"}.mdi-pan-left:before{content:"󰮹"}.mdi-pan-right:before{content:"󰮺"}.mdi-pan-top-left:before{content:"󰮻"}.mdi-pan-top-right:before{content:"󰮼"}.mdi-pan-up:before{content:"󰮽"}.mdi-pan-vertical:before{content:"󰮾"}.mdi-panda:before{content:"󰏚"}.mdi-pandora:before{content:"󰏛"}.mdi-panorama:before{content:"󰏜"}.mdi-panorama-fisheye:before{content:"󰏝"}.mdi-panorama-horizontal:before{content:"󱤨"}.mdi-panorama-horizontal-outline:before{content:"󰏞"}.mdi-panorama-outline:before{content:"󱦌"}.mdi-panorama-sphere:before{content:"󱦍"}.mdi-panorama-sphere-outline:before{content:"󱦎"}.mdi-panorama-variant:before{content:"󱦏"}.mdi-panorama-variant-outline:before{content:"󱦐"}.mdi-panorama-vertical:before{content:"󱤩"}.mdi-panorama-vertical-outline:before{content:"󰏟"}.mdi-panorama-wide-angle:before{content:"󱥟"}.mdi-panorama-wide-angle-outline:before{content:"󰏠"}.mdi-paper-cut-vertical:before{content:"󰏡"}.mdi-paper-roll:before{content:"󱅗"}.mdi-paper-roll-outline:before{content:"󱅘"}.mdi-paperclip:before{content:"󰏢"}.mdi-paperclip-check:before{content:"󱫆"}.mdi-paperclip-lock:before{content:"󱧚"}.mdi-paperclip-minus:before{content:"󱫇"}.mdi-paperclip-off:before{content:"󱫈"}.mdi-paperclip-plus:before{content:"󱫉"}.mdi-paperclip-remove:before{content:"󱫊"}.mdi-parachute:before{content:"󰲴"}.mdi-parachute-outline:before{content:"󰲵"}.mdi-paragliding:before{content:"󱝅"}.mdi-parking:before{content:"󰏣"}.mdi-party-popper:before{content:"󱁖"}.mdi-passport:before{content:"󰟣"}.mdi-passport-biometric:before{content:"󰷡"}.mdi-pasta:before{content:"󱅠"}.mdi-patio-heater:before{content:"󰾀"}.mdi-patreon:before{content:"󰢂"}.mdi-pause:before{content:"󰏤"}.mdi-pause-box:before{content:"󰂼"}.mdi-pause-box-outline:before{content:"󱭺"}.mdi-pause-circle:before{content:"󰏥"}.mdi-pause-circle-outline:before{content:"󰏦"}.mdi-pause-octagon:before{content:"󰏧"}.mdi-pause-octagon-outline:before{content:"󰏨"}.mdi-paw:before{content:"󰏩"}.mdi-paw-off:before{content:"󰙗"}.mdi-paw-off-outline:before{content:"󱙶"}.mdi-paw-outline:before{content:"󱙵"}.mdi-peace:before{content:"󰢄"}.mdi-peanut:before{content:"󰿼"}.mdi-peanut-off:before{content:"󰿽"}.mdi-peanut-off-outline:before{content:"󰿿"}.mdi-peanut-outline:before{content:"󰿾"}.mdi-pen:before{content:"󰏪"}.mdi-pen-lock:before{content:"󰷢"}.mdi-pen-minus:before{content:"󰷣"}.mdi-pen-off:before{content:"󰷤"}.mdi-pen-plus:before{content:"󰷥"}.mdi-pen-remove:before{content:"󰷦"}.mdi-pencil:before{content:"󰏫"}.mdi-pencil-box:before{content:"󰏬"}.mdi-pencil-box-multiple:before{content:"󱅄"}.mdi-pencil-box-multiple-outline:before{content:"󱅅"}.mdi-pencil-box-outline:before{content:"󰏭"}.mdi-pencil-circle:before{content:"󰛿"}.mdi-pencil-circle-outline:before{content:"󰝶"}.mdi-pencil-lock:before{content:"󰏮"}.mdi-pencil-lock-outline:before{content:"󰷧"}.mdi-pencil-minus:before{content:"󰷨"}.mdi-pencil-minus-outline:before{content:"󰷩"}.mdi-pencil-off:before{content:"󰏯"}.mdi-pencil-off-outline:before{content:"󰷪"}.mdi-pencil-outline:before{content:"󰲶"}.mdi-pencil-plus:before{content:"󰷫"}.mdi-pencil-plus-outline:before{content:"󰷬"}.mdi-pencil-remove:before{content:"󰷭"}.mdi-pencil-remove-outline:before{content:"󰷮"}.mdi-pencil-ruler:before{content:"󱍓"}.mdi-pencil-ruler-outline:before{content:"󱰑"}.mdi-penguin:before{content:"󰻀"}.mdi-pentagon:before{content:"󰜁"}.mdi-pentagon-outline:before{content:"󰜀"}.mdi-pentagram:before{content:"󱙧"}.mdi-percent:before{content:"󰏰"}.mdi-percent-box:before{content:"󱨂"}.mdi-percent-box-outline:before{content:"󱨃"}.mdi-percent-circle:before{content:"󱨄"}.mdi-percent-circle-outline:before{content:"󱨅"}.mdi-percent-outline:before{content:"󱉸"}.mdi-periodic-table:before{content:"󰢶"}.mdi-perspective-less:before{content:"󰴣"}.mdi-perspective-more:before{content:"󰴤"}.mdi-ph:before{content:"󱟅"}.mdi-phone:before{content:"󰏲"}.mdi-phone-alert:before{content:"󰼚"}.mdi-phone-alert-outline:before{content:"󱆎"}.mdi-phone-bluetooth:before{content:"󰏳"}.mdi-phone-bluetooth-outline:before{content:"󱆏"}.mdi-phone-cancel:before{content:"󱂼"}.mdi-phone-cancel-outline:before{content:"󱆐"}.mdi-phone-check:before{content:"󱆩"}.mdi-phone-check-outline:before{content:"󱆪"}.mdi-phone-classic:before{content:"󰘂"}.mdi-phone-classic-off:before{content:"󱉹"}.mdi-phone-clock:before{content:"󱧛"}.mdi-phone-dial:before{content:"󱕙"}.mdi-phone-dial-outline:before{content:"󱕚"}.mdi-phone-forward:before{content:"󰏴"}.mdi-phone-forward-outline:before{content:"󱆑"}.mdi-phone-hangup:before{content:"󰏵"}.mdi-phone-hangup-outline:before{content:"󱆒"}.mdi-phone-in-talk:before{content:"󰏶"}.mdi-phone-in-talk-outline:before{content:"󱆂"}.mdi-phone-incoming:before{content:"󰏷"}.mdi-phone-incoming-outgoing:before{content:"󱬿"}.mdi-phone-incoming-outgoing-outline:before{content:"󱭀"}.mdi-phone-incoming-outline:before{content:"󱆓"}.mdi-phone-lock:before{content:"󰏸"}.mdi-phone-lock-outline:before{content:"󱆔"}.mdi-phone-log:before{content:"󰏹"}.mdi-phone-log-outline:before{content:"󱆕"}.mdi-phone-message:before{content:"󱆖"}.mdi-phone-message-outline:before{content:"󱆗"}.mdi-phone-minus:before{content:"󰙘"}.mdi-phone-minus-outline:before{content:"󱆘"}.mdi-phone-missed:before{content:"󰏺"}.mdi-phone-missed-outline:before{content:"󱆥"}.mdi-phone-off:before{content:"󰷯"}.mdi-phone-off-outline:before{content:"󱆦"}.mdi-phone-outgoing:before{content:"󰏻"}.mdi-phone-outgoing-outline:before{content:"󱆙"}.mdi-phone-outline:before{content:"󰷰"}.mdi-phone-paused:before{content:"󰏼"}.mdi-phone-paused-outline:before{content:"󱆚"}.mdi-phone-plus:before{content:"󰙙"}.mdi-phone-plus-outline:before{content:"󱆛"}.mdi-phone-refresh:before{content:"󱦓"}.mdi-phone-refresh-outline:before{content:"󱦔"}.mdi-phone-remove:before{content:"󱔯"}.mdi-phone-remove-outline:before{content:"󱔰"}.mdi-phone-return:before{content:"󰠯"}.mdi-phone-return-outline:before{content:"󱆜"}.mdi-phone-ring:before{content:"󱆫"}.mdi-phone-ring-outline:before{content:"󱆬"}.mdi-phone-rotate-landscape:before{content:"󰢅"}.mdi-phone-rotate-portrait:before{content:"󰢆"}.mdi-phone-settings:before{content:"󰏽"}.mdi-phone-settings-outline:before{content:"󱆝"}.mdi-phone-sync:before{content:"󱦕"}.mdi-phone-sync-outline:before{content:"󱦖"}.mdi-phone-voip:before{content:"󰏾"}.mdi-pi:before{content:"󰏿"}.mdi-pi-box:before{content:"󰐀"}.mdi-pi-hole:before{content:"󰷱"}.mdi-piano:before{content:"󰙽"}.mdi-piano-off:before{content:"󰚘"}.mdi-pickaxe:before{content:"󰢷"}.mdi-picture-in-picture-bottom-right:before{content:"󰹗"}.mdi-picture-in-picture-bottom-right-outline:before{content:"󰹘"}.mdi-picture-in-picture-top-right:before{content:"󰹙"}.mdi-picture-in-picture-top-right-outline:before{content:"󰹚"}.mdi-pier:before{content:"󰢇"}.mdi-pier-crane:before{content:"󰢈"}.mdi-pig:before{content:"󰐁"}.mdi-pig-variant:before{content:"󱀆"}.mdi-pig-variant-outline:before{content:"󱙸"}.mdi-piggy-bank:before{content:"󱀇"}.mdi-piggy-bank-outline:before{content:"󱙹"}.mdi-pill:before{content:"󰐂"}.mdi-pill-multiple:before{content:"󱭌"}.mdi-pill-off:before{content:"󱩜"}.mdi-pillar:before{content:"󰜂"}.mdi-pin:before{content:"󰐃"}.mdi-pin-off:before{content:"󰐄"}.mdi-pin-off-outline:before{content:"󰤰"}.mdi-pin-outline:before{content:"󰤱"}.mdi-pine-tree:before{content:"󰐅"}.mdi-pine-tree-box:before{content:"󰐆"}.mdi-pine-tree-fire:before{content:"󱐚"}.mdi-pine-tree-variant:before{content:"󱱳"}.mdi-pine-tree-variant-outline:before{content:"󱱴"}.mdi-pinterest:before{content:"󰐇"}.mdi-pinwheel:before{content:"󰫕"}.mdi-pinwheel-outline:before{content:"󰫖"}.mdi-pipe:before{content:"󰟥"}.mdi-pipe-disconnected:before{content:"󰟦"}.mdi-pipe-leak:before{content:"󰢉"}.mdi-pipe-valve:before{content:"󱡍"}.mdi-pipe-wrench:before{content:"󱍔"}.mdi-pirate:before{content:"󰨈"}.mdi-pistol:before{content:"󰜃"}.mdi-piston:before{content:"󰢊"}.mdi-pitchfork:before{content:"󱕓"}.mdi-pizza:before{content:"󰐉"}.mdi-plane-car:before{content:"󱫿"}.mdi-plane-train:before{content:"󱬀"}.mdi-play:before{content:"󰐊"}.mdi-play-box:before{content:"󱉺"}.mdi-play-box-edit-outline:before{content:"󱰺"}.mdi-play-box-lock:before{content:"󱨖"}.mdi-play-box-lock-open:before{content:"󱨗"}.mdi-play-box-lock-open-outline:before{content:"󱨘"}.mdi-play-box-lock-outline:before{content:"󱨙"}.mdi-play-box-multiple:before{content:"󰴙"}.mdi-play-box-multiple-outline:before{content:"󱏦"}.mdi-play-box-outline:before{content:"󰐋"}.mdi-play-circle:before{content:"󰐌"}.mdi-play-circle-outline:before{content:"󰐍"}.mdi-play-network:before{content:"󰢋"}.mdi-play-network-outline:before{content:"󰲷"}.mdi-play-outline:before{content:"󰼛"}.mdi-play-pause:before{content:"󰐎"}.mdi-play-protected-content:before{content:"󰐏"}.mdi-play-speed:before{content:"󰣿"}.mdi-playlist-check:before{content:"󰗇"}.mdi-playlist-edit:before{content:"󰤀"}.mdi-playlist-minus:before{content:"󰐐"}.mdi-playlist-music:before{content:"󰲸"}.mdi-playlist-music-outline:before{content:"󰲹"}.mdi-playlist-play:before{content:"󰐑"}.mdi-playlist-plus:before{content:"󰐒"}.mdi-playlist-remove:before{content:"󰐓"}.mdi-playlist-star:before{content:"󰷲"}.mdi-plex:before{content:"󰚺"}.mdi-pliers:before{content:"󱦤"}.mdi-plus:before{content:"󰐕"}.mdi-plus-box:before{content:"󰐖"}.mdi-plus-box-multiple:before{content:"󰌴"}.mdi-plus-box-multiple-outline:before{content:"󱅃"}.mdi-plus-box-outline:before{content:"󰜄"}.mdi-plus-circle:before{content:"󰐗"}.mdi-plus-circle-multiple:before{content:"󰍌"}.mdi-plus-circle-multiple-outline:before{content:"󰐘"}.mdi-plus-circle-outline:before{content:"󰐙"}.mdi-plus-lock:before{content:"󱩝"}.mdi-plus-lock-open:before{content:"󱩞"}.mdi-plus-minus:before{content:"󰦒"}.mdi-plus-minus-box:before{content:"󰦓"}.mdi-plus-minus-variant:before{content:"󱓉"}.mdi-plus-network:before{content:"󰐚"}.mdi-plus-network-outline:before{content:"󰲺"}.mdi-plus-outline:before{content:"󰜅"}.mdi-plus-thick:before{content:"󱇬"}.mdi-podcast:before{content:"󰦔"}.mdi-podium:before{content:"󰴥"}.mdi-podium-bronze:before{content:"󰴦"}.mdi-podium-gold:before{content:"󰴧"}.mdi-podium-silver:before{content:"󰴨"}.mdi-point-of-sale:before{content:"󰶒"}.mdi-pokeball:before{content:"󰐝"}.mdi-pokemon-go:before{content:"󰨉"}.mdi-poker-chip:before{content:"󰠰"}.mdi-polaroid:before{content:"󰐞"}.mdi-police-badge:before{content:"󱅧"}.mdi-police-badge-outline:before{content:"󱅨"}.mdi-police-station:before{content:"󱠹"}.mdi-poll:before{content:"󰐟"}.mdi-polo:before{content:"󱓃"}.mdi-polymer:before{content:"󰐡"}.mdi-pool:before{content:"󰘆"}.mdi-pool-thermometer:before{content:"󱩟"}.mdi-popcorn:before{content:"󰐢"}.mdi-post:before{content:"󱀈"}.mdi-post-lamp:before{content:"󱩠"}.mdi-post-outline:before{content:"󱀉"}.mdi-postage-stamp:before{content:"󰲻"}.mdi-pot:before{content:"󰋥"}.mdi-pot-mix:before{content:"󰙛"}.mdi-pot-mix-outline:before{content:"󰙷"}.mdi-pot-outline:before{content:"󰋿"}.mdi-pot-steam:before{content:"󰙚"}.mdi-pot-steam-outline:before{content:"󰌦"}.mdi-pound:before{content:"󰐣"}.mdi-pound-box:before{content:"󰐤"}.mdi-pound-box-outline:before{content:"󱅿"}.mdi-power:before{content:"󰐥"}.mdi-power-cycle:before{content:"󰤁"}.mdi-power-off:before{content:"󰤂"}.mdi-power-on:before{content:"󰤃"}.mdi-power-plug:before{content:"󰚥"}.mdi-power-plug-battery:before{content:"󱰻"}.mdi-power-plug-battery-outline:before{content:"󱰼"}.mdi-power-plug-off:before{content:"󰚦"}.mdi-power-plug-off-outline:before{content:"󱐤"}.mdi-power-plug-outline:before{content:"󱐥"}.mdi-power-settings:before{content:"󰐦"}.mdi-power-sleep:before{content:"󰤄"}.mdi-power-socket:before{content:"󰐧"}.mdi-power-socket-au:before{content:"󰤅"}.mdi-power-socket-ch:before{content:"󰾳"}.mdi-power-socket-de:before{content:"󱄇"}.mdi-power-socket-eu:before{content:"󰟧"}.mdi-power-socket-fr:before{content:"󱄈"}.mdi-power-socket-it:before{content:"󱓿"}.mdi-power-socket-jp:before{content:"󱄉"}.mdi-power-socket-uk:before{content:"󰟨"}.mdi-power-socket-us:before{content:"󰟩"}.mdi-power-standby:before{content:"󰤆"}.mdi-powershell:before{content:"󰨊"}.mdi-prescription:before{content:"󰜆"}.mdi-presentation:before{content:"󰐨"}.mdi-presentation-play:before{content:"󰐩"}.mdi-pretzel:before{content:"󱕢"}.mdi-printer:before{content:"󰐪"}.mdi-printer-3d:before{content:"󰐫"}.mdi-printer-3d-nozzle:before{content:"󰹛"}.mdi-printer-3d-nozzle-alert:before{content:"󱇀"}.mdi-printer-3d-nozzle-alert-outline:before{content:"󱇁"}.mdi-printer-3d-nozzle-heat:before{content:"󱢸"}.mdi-printer-3d-nozzle-heat-outline:before{content:"󱢹"}.mdi-printer-3d-nozzle-off:before{content:"󱬙"}.mdi-printer-3d-nozzle-off-outline:before{content:"󱬚"}.mdi-printer-3d-nozzle-outline:before{content:"󰹜"}.mdi-printer-3d-off:before{content:"󱬎"}.mdi-printer-alert:before{content:"󰐬"}.mdi-printer-check:before{content:"󱅆"}.mdi-printer-eye:before{content:"󱑘"}.mdi-printer-off:before{content:"󰹝"}.mdi-printer-off-outline:before{content:"󱞅"}.mdi-printer-outline:before{content:"󱞆"}.mdi-printer-pos:before{content:"󱁗"}.mdi-printer-pos-alert:before{content:"󱮼"}.mdi-printer-pos-alert-outline:before{content:"󱮽"}.mdi-printer-pos-cancel:before{content:"󱮾"}.mdi-printer-pos-cancel-outline:before{content:"󱮿"}.mdi-printer-pos-check:before{content:"󱯀"}.mdi-printer-pos-check-outline:before{content:"󱯁"}.mdi-printer-pos-cog:before{content:"󱯂"}.mdi-printer-pos-cog-outline:before{content:"󱯃"}.mdi-printer-pos-edit:before{content:"󱯄"}.mdi-printer-pos-edit-outline:before{content:"󱯅"}.mdi-printer-pos-minus:before{content:"󱯆"}.mdi-printer-pos-minus-outline:before{content:"󱯇"}.mdi-printer-pos-network:before{content:"󱯈"}.mdi-printer-pos-network-outline:before{content:"󱯉"}.mdi-printer-pos-off:before{content:"󱯊"}.mdi-printer-pos-off-outline:before{content:"󱯋"}.mdi-printer-pos-outline:before{content:"󱯌"}.mdi-printer-pos-pause:before{content:"󱯍"}.mdi-printer-pos-pause-outline:before{content:"󱯎"}.mdi-printer-pos-play:before{content:"󱯏"}.mdi-printer-pos-play-outline:before{content:"󱯐"}.mdi-printer-pos-plus:before{content:"󱯑"}.mdi-printer-pos-plus-outline:before{content:"󱯒"}.mdi-printer-pos-refresh:before{content:"󱯓"}.mdi-printer-pos-refresh-outline:before{content:"󱯔"}.mdi-printer-pos-remove:before{content:"󱯕"}.mdi-printer-pos-remove-outline:before{content:"󱯖"}.mdi-printer-pos-star:before{content:"󱯗"}.mdi-printer-pos-star-outline:before{content:"󱯘"}.mdi-printer-pos-stop:before{content:"󱯙"}.mdi-printer-pos-stop-outline:before{content:"󱯚"}.mdi-printer-pos-sync:before{content:"󱯛"}.mdi-printer-pos-sync-outline:before{content:"󱯜"}.mdi-printer-pos-wrench:before{content:"󱯝"}.mdi-printer-pos-wrench-outline:before{content:"󱯞"}.mdi-printer-search:before{content:"󱑗"}.mdi-printer-settings:before{content:"󰜇"}.mdi-printer-wireless:before{content:"󰨋"}.mdi-priority-high:before{content:"󰘃"}.mdi-priority-low:before{content:"󰘄"}.mdi-professional-hexagon:before{content:"󰐭"}.mdi-progress-alert:before{content:"󰲼"}.mdi-progress-check:before{content:"󰦕"}.mdi-progress-clock:before{content:"󰦖"}.mdi-progress-close:before{content:"󱄊"}.mdi-progress-download:before{content:"󰦗"}.mdi-progress-helper:before{content:"󱮢"}.mdi-progress-pencil:before{content:"󱞇"}.mdi-progress-question:before{content:"󱔢"}.mdi-progress-star:before{content:"󱞈"}.mdi-progress-star-four-points:before{content:"󱰽"}.mdi-progress-upload:before{content:"󰦘"}.mdi-progress-wrench:before{content:"󰲽"}.mdi-projector:before{content:"󰐮"}.mdi-projector-off:before{content:"󱨣"}.mdi-projector-screen:before{content:"󰐯"}.mdi-projector-screen-off:before{content:"󱠍"}.mdi-projector-screen-off-outline:before{content:"󱠎"}.mdi-projector-screen-outline:before{content:"󱜤"}.mdi-projector-screen-variant:before{content:"󱠏"}.mdi-projector-screen-variant-off:before{content:"󱠐"}.mdi-projector-screen-variant-off-outline:before{content:"󱠑"}.mdi-projector-screen-variant-outline:before{content:"󱠒"}.mdi-propane-tank:before{content:"󱍗"}.mdi-propane-tank-outline:before{content:"󱍘"}.mdi-protocol:before{content:"󰿘"}.mdi-publish:before{content:"󰚧"}.mdi-publish-off:before{content:"󱥅"}.mdi-pulse:before{content:"󰐰"}.mdi-pump:before{content:"󱐂"}.mdi-pump-off:before{content:"󱬢"}.mdi-pumpkin:before{content:"󰮿"}.mdi-purse:before{content:"󰼜"}.mdi-purse-outline:before{content:"󰼝"}.mdi-puzzle:before{content:"󰐱"}.mdi-puzzle-check:before{content:"󱐦"}.mdi-puzzle-check-outline:before{content:"󱐧"}.mdi-puzzle-edit:before{content:"󱓓"}.mdi-puzzle-edit-outline:before{content:"󱓙"}.mdi-puzzle-heart:before{content:"󱓔"}.mdi-puzzle-heart-outline:before{content:"󱓚"}.mdi-puzzle-minus:before{content:"󱓑"}.mdi-puzzle-minus-outline:before{content:"󱓗"}.mdi-puzzle-outline:before{content:"󰩦"}.mdi-puzzle-plus:before{content:"󱓐"}.mdi-puzzle-plus-outline:before{content:"󱓖"}.mdi-puzzle-remove:before{content:"󱓒"}.mdi-puzzle-remove-outline:before{content:"󱓘"}.mdi-puzzle-star:before{content:"󱓕"}.mdi-puzzle-star-outline:before{content:"󱓛"}.mdi-pyramid:before{content:"󱥒"}.mdi-pyramid-off:before{content:"󱥓"}.mdi-qi:before{content:"󰦙"}.mdi-qqchat:before{content:"󰘅"}.mdi-qrcode:before{content:"󰐲"}.mdi-qrcode-edit:before{content:"󰢸"}.mdi-qrcode-minus:before{content:"󱆌"}.mdi-qrcode-plus:before{content:"󱆋"}.mdi-qrcode-remove:before{content:"󱆍"}.mdi-qrcode-scan:before{content:"󰐳"}.mdi-quadcopter:before{content:"󰐴"}.mdi-quality-high:before{content:"󰐵"}.mdi-quality-low:before{content:"󰨌"}.mdi-quality-medium:before{content:"󰨍"}.mdi-quora:before{content:"󰴩"}.mdi-rabbit:before{content:"󰤇"}.mdi-rabbit-variant:before{content:"󱩡"}.mdi-rabbit-variant-outline:before{content:"󱩢"}.mdi-racing-helmet:before{content:"󰶓"}.mdi-racquetball:before{content:"󰶔"}.mdi-radar:before{content:"󰐷"}.mdi-radiator:before{content:"󰐸"}.mdi-radiator-disabled:before{content:"󰫗"}.mdi-radiator-off:before{content:"󰫘"}.mdi-radio:before{content:"󰐹"}.mdi-radio-am:before{content:"󰲾"}.mdi-radio-fm:before{content:"󰲿"}.mdi-radio-handheld:before{content:"󰐺"}.mdi-radio-off:before{content:"󱈜"}.mdi-radio-tower:before{content:"󰐻"}.mdi-radioactive:before{content:"󰐼"}.mdi-radioactive-circle:before{content:"󱡝"}.mdi-radioactive-circle-outline:before{content:"󱡞"}.mdi-radioactive-off:before{content:"󰻁"}.mdi-radiobox-blank:before{content:"󰐽"}.mdi-radiobox-indeterminate-variant:before{content:"󱱞"}.mdi-radiobox-marked:before{content:"󰐾"}.mdi-radiology-box:before{content:"󱓅"}.mdi-radiology-box-outline:before{content:"󱓆"}.mdi-radius:before{content:"󰳀"}.mdi-radius-outline:before{content:"󰳁"}.mdi-railroad-light:before{content:"󰼞"}.mdi-rake:before{content:"󱕄"}.mdi-raspberry-pi:before{content:"󰐿"}.mdi-raw:before{content:"󱨏"}.mdi-raw-off:before{content:"󱨐"}.mdi-ray-end:before{content:"󰑀"}.mdi-ray-end-arrow:before{content:"󰑁"}.mdi-ray-start:before{content:"󰑂"}.mdi-ray-start-arrow:before{content:"󰑃"}.mdi-ray-start-end:before{content:"󰑄"}.mdi-ray-start-vertex-end:before{content:"󱗘"}.mdi-ray-vertex:before{content:"󰑅"}.mdi-razor-double-edge:before{content:"󱦗"}.mdi-razor-single-edge:before{content:"󱦘"}.mdi-react:before{content:"󰜈"}.mdi-read:before{content:"󰑇"}.mdi-receipt:before{content:"󰠤"}.mdi-receipt-clock:before{content:"󱰾"}.mdi-receipt-clock-outline:before{content:"󱰿"}.mdi-receipt-outline:before{content:"󰓷"}.mdi-receipt-send:before{content:"󱱀"}.mdi-receipt-send-outline:before{content:"󱱁"}.mdi-receipt-text:before{content:"󰑉"}.mdi-receipt-text-arrow-left:before{content:"󱱂"}.mdi-receipt-text-arrow-left-outline:before{content:"󱱃"}.mdi-receipt-text-arrow-right:before{content:"󱱄"}.mdi-receipt-text-arrow-right-outline:before{content:"󱱅"}.mdi-receipt-text-check:before{content:"󱩣"}.mdi-receipt-text-check-outline:before{content:"󱩤"}.mdi-receipt-text-clock:before{content:"󱱆"}.mdi-receipt-text-clock-outline:before{content:"󱱇"}.mdi-receipt-text-edit:before{content:"󱱈"}.mdi-receipt-text-edit-outline:before{content:"󱱉"}.mdi-receipt-text-minus:before{content:"󱩥"}.mdi-receipt-text-minus-outline:before{content:"󱩦"}.mdi-receipt-text-outline:before{content:"󱧜"}.mdi-receipt-text-plus:before{content:"󱩧"}.mdi-receipt-text-plus-outline:before{content:"󱩨"}.mdi-receipt-text-remove:before{content:"󱩩"}.mdi-receipt-text-remove-outline:before{content:"󱩪"}.mdi-receipt-text-send:before{content:"󱱊"}.mdi-receipt-text-send-outline:before{content:"󱱋"}.mdi-record:before{content:"󰑊"}.mdi-record-circle:before{content:"󰻂"}.mdi-record-circle-outline:before{content:"󰻃"}.mdi-record-player:before{content:"󰦚"}.mdi-record-rec:before{content:"󰑋"}.mdi-rectangle:before{content:"󰹞"}.mdi-rectangle-outline:before{content:"󰹟"}.mdi-recycle:before{content:"󰑌"}.mdi-recycle-variant:before{content:"󱎝"}.mdi-reddit:before{content:"󰑍"}.mdi-redhat:before{content:"󱄛"}.mdi-redo:before{content:"󰑎"}.mdi-redo-variant:before{content:"󰑏"}.mdi-reflect-horizontal:before{content:"󰨎"}.mdi-reflect-vertical:before{content:"󰨏"}.mdi-refresh:before{content:"󰑐"}.mdi-refresh-auto:before{content:"󱣲"}.mdi-refresh-circle:before{content:"󱍷"}.mdi-regex:before{content:"󰑑"}.mdi-registered-trademark:before{content:"󰩧"}.mdi-reiterate:before{content:"󱖈"}.mdi-relation-many-to-many:before{content:"󱒖"}.mdi-relation-many-to-one:before{content:"󱒗"}.mdi-relation-many-to-one-or-many:before{content:"󱒘"}.mdi-relation-many-to-only-one:before{content:"󱒙"}.mdi-relation-many-to-zero-or-many:before{content:"󱒚"}.mdi-relation-many-to-zero-or-one:before{content:"󱒛"}.mdi-relation-one-or-many-to-many:before{content:"󱒜"}.mdi-relation-one-or-many-to-one:before{content:"󱒝"}.mdi-relation-one-or-many-to-one-or-many:before{content:"󱒞"}.mdi-relation-one-or-many-to-only-one:before{content:"󱒟"}.mdi-relation-one-or-many-to-zero-or-many:before{content:"󱒠"}.mdi-relation-one-or-many-to-zero-or-one:before{content:"󱒡"}.mdi-relation-one-to-many:before{content:"󱒢"}.mdi-relation-one-to-one:before{content:"󱒣"}.mdi-relation-one-to-one-or-many:before{content:"󱒤"}.mdi-relation-one-to-only-one:before{content:"󱒥"}.mdi-relation-one-to-zero-or-many:before{content:"󱒦"}.mdi-relation-one-to-zero-or-one:before{content:"󱒧"}.mdi-relation-only-one-to-many:before{content:"󱒨"}.mdi-relation-only-one-to-one:before{content:"󱒩"}.mdi-relation-only-one-to-one-or-many:before{content:"󱒪"}.mdi-relation-only-one-to-only-one:before{content:"󱒫"}.mdi-relation-only-one-to-zero-or-many:before{content:"󱒬"}.mdi-relation-only-one-to-zero-or-one:before{content:"󱒭"}.mdi-relation-zero-or-many-to-many:before{content:"󱒮"}.mdi-relation-zero-or-many-to-one:before{content:"󱒯"}.mdi-relation-zero-or-many-to-one-or-many:before{content:"󱒰"}.mdi-relation-zero-or-many-to-only-one:before{content:"󱒱"}.mdi-relation-zero-or-many-to-zero-or-many:before{content:"󱒲"}.mdi-relation-zero-or-many-to-zero-or-one:before{content:"󱒳"}.mdi-relation-zero-or-one-to-many:before{content:"󱒴"}.mdi-relation-zero-or-one-to-one:before{content:"󱒵"}.mdi-relation-zero-or-one-to-one-or-many:before{content:"󱒶"}.mdi-relation-zero-or-one-to-only-one:before{content:"󱒷"}.mdi-relation-zero-or-one-to-zero-or-many:before{content:"󱒸"}.mdi-relation-zero-or-one-to-zero-or-one:before{content:"󱒹"}.mdi-relative-scale:before{content:"󰑒"}.mdi-reload:before{content:"󰑓"}.mdi-reload-alert:before{content:"󱄋"}.mdi-reminder:before{content:"󰢌"}.mdi-remote:before{content:"󰑔"}.mdi-remote-desktop:before{content:"󰢹"}.mdi-remote-off:before{content:"󰻄"}.mdi-remote-tv:before{content:"󰻅"}.mdi-remote-tv-off:before{content:"󰻆"}.mdi-rename:before{content:"󱰘"}.mdi-rename-box:before{content:"󰑕"}.mdi-rename-box-outline:before{content:"󱰙"}.mdi-rename-outline:before{content:"󱰚"}.mdi-reorder-horizontal:before{content:"󰚈"}.mdi-reorder-vertical:before{content:"󰚉"}.mdi-repeat:before{content:"󰑖"}.mdi-repeat-off:before{content:"󰑗"}.mdi-repeat-once:before{content:"󰑘"}.mdi-repeat-variant:before{content:"󰕇"}.mdi-replay:before{content:"󰑙"}.mdi-reply:before{content:"󰑚"}.mdi-reply-all:before{content:"󰑛"}.mdi-reply-all-outline:before{content:"󰼟"}.mdi-reply-circle:before{content:"󱆮"}.mdi-reply-outline:before{content:"󰼠"}.mdi-reproduction:before{content:"󰑜"}.mdi-resistor:before{content:"󰭄"}.mdi-resistor-nodes:before{content:"󰭅"}.mdi-resize:before{content:"󰩨"}.mdi-resize-bottom-right:before{content:"󰑝"}.mdi-responsive:before{content:"󰑞"}.mdi-restart:before{content:"󰜉"}.mdi-restart-alert:before{content:"󱄌"}.mdi-restart-off:before{content:"󰶕"}.mdi-restore:before{content:"󰦛"}.mdi-restore-alert:before{content:"󱄍"}.mdi-rewind:before{content:"󰑟"}.mdi-rewind-10:before{content:"󰴪"}.mdi-rewind-15:before{content:"󱥆"}.mdi-rewind-30:before{content:"󰶖"}.mdi-rewind-45:before{content:"󱬓"}.mdi-rewind-5:before{content:"󱇹"}.mdi-rewind-60:before{content:"󱘌"}.mdi-rewind-outline:before{content:"󰜊"}.mdi-rhombus:before{content:"󰜋"}.mdi-rhombus-medium:before{content:"󰨐"}.mdi-rhombus-medium-outline:before{content:"󱓜"}.mdi-rhombus-outline:before{content:"󰜌"}.mdi-rhombus-split:before{content:"󰨑"}.mdi-rhombus-split-outline:before{content:"󱓝"}.mdi-ribbon:before{content:"󰑠"}.mdi-rice:before{content:"󰟪"}.mdi-rickshaw:before{content:"󱖻"}.mdi-rickshaw-electric:before{content:"󱖼"}.mdi-ring:before{content:"󰟫"}.mdi-rivet:before{content:"󰹠"}.mdi-road:before{content:"󰑡"}.mdi-road-variant:before{content:"󰑢"}.mdi-robber:before{content:"󱁘"}.mdi-robot:before{content:"󰚩"}.mdi-robot-angry:before{content:"󱚝"}.mdi-robot-angry-outline:before{content:"󱚞"}.mdi-robot-confused:before{content:"󱚟"}.mdi-robot-confused-outline:before{content:"󱚠"}.mdi-robot-dead:before{content:"󱚡"}.mdi-robot-dead-outline:before{content:"󱚢"}.mdi-robot-excited:before{content:"󱚣"}.mdi-robot-excited-outline:before{content:"󱚤"}.mdi-robot-happy:before{content:"󱜙"}.mdi-robot-happy-outline:before{content:"󱜚"}.mdi-robot-industrial:before{content:"󰭆"}.mdi-robot-industrial-outline:before{content:"󱨚"}.mdi-robot-love:before{content:"󱚥"}.mdi-robot-love-outline:before{content:"󱚦"}.mdi-robot-mower:before{content:"󱇷"}.mdi-robot-mower-outline:before{content:"󱇳"}.mdi-robot-off:before{content:"󱚧"}.mdi-robot-off-outline:before{content:"󱙻"}.mdi-robot-outline:before{content:"󱙺"}.mdi-robot-vacuum:before{content:"󰜍"}.mdi-robot-vacuum-alert:before{content:"󱭝"}.mdi-robot-vacuum-off:before{content:"󱰁"}.mdi-robot-vacuum-variant:before{content:"󰤈"}.mdi-robot-vacuum-variant-alert:before{content:"󱭞"}.mdi-robot-vacuum-variant-off:before{content:"󱰂"}.mdi-rocket:before{content:"󰑣"}.mdi-rocket-launch:before{content:"󱓞"}.mdi-rocket-launch-outline:before{content:"󱓟"}.mdi-rocket-outline:before{content:"󱎯"}.mdi-rodent:before{content:"󱌧"}.mdi-roller-shade:before{content:"󱩫"}.mdi-roller-shade-closed:before{content:"󱩬"}.mdi-roller-skate:before{content:"󰴫"}.mdi-roller-skate-off:before{content:"󰅅"}.mdi-rollerblade:before{content:"󰴬"}.mdi-rollerblade-off:before{content:"󰀮"}.mdi-rollupjs:before{content:"󰯀"}.mdi-rolodex:before{content:"󱪹"}.mdi-rolodex-outline:before{content:"󱪺"}.mdi-roman-numeral-1:before{content:"󱂈"}.mdi-roman-numeral-10:before{content:"󱂑"}.mdi-roman-numeral-2:before{content:"󱂉"}.mdi-roman-numeral-3:before{content:"󱂊"}.mdi-roman-numeral-4:before{content:"󱂋"}.mdi-roman-numeral-5:before{content:"󱂌"}.mdi-roman-numeral-6:before{content:"󱂍"}.mdi-roman-numeral-7:before{content:"󱂎"}.mdi-roman-numeral-8:before{content:"󱂏"}.mdi-roman-numeral-9:before{content:"󱂐"}.mdi-room-service:before{content:"󰢍"}.mdi-room-service-outline:before{content:"󰶗"}.mdi-rotate-360:before{content:"󱦙"}.mdi-rotate-3d:before{content:"󰻇"}.mdi-rotate-3d-variant:before{content:"󰑤"}.mdi-rotate-left:before{content:"󰑥"}.mdi-rotate-left-variant:before{content:"󰑦"}.mdi-rotate-orbit:before{content:"󰶘"}.mdi-rotate-right:before{content:"󰑧"}.mdi-rotate-right-variant:before{content:"󰑨"}.mdi-rounded-corner:before{content:"󰘇"}.mdi-router:before{content:"󱇢"}.mdi-router-network:before{content:"󱂇"}.mdi-router-wireless:before{content:"󰑩"}.mdi-router-wireless-off:before{content:"󱖣"}.mdi-router-wireless-settings:before{content:"󰩩"}.mdi-routes:before{content:"󰑪"}.mdi-routes-clock:before{content:"󱁙"}.mdi-rowing:before{content:"󰘈"}.mdi-rss:before{content:"󰑫"}.mdi-rss-box:before{content:"󰑬"}.mdi-rss-off:before{content:"󰼡"}.mdi-rug:before{content:"󱑵"}.mdi-rugby:before{content:"󰶙"}.mdi-ruler:before{content:"󰑭"}.mdi-ruler-square:before{content:"󰳂"}.mdi-ruler-square-compass:before{content:"󰺾"}.mdi-run:before{content:"󰜎"}.mdi-run-fast:before{content:"󰑮"}.mdi-rv-truck:before{content:"󱇔"}.mdi-sack:before{content:"󰴮"}.mdi-sack-outline:before{content:"󱱌"}.mdi-sack-percent:before{content:"󰴯"}.mdi-safe:before{content:"󰩪"}.mdi-safe-square:before{content:"󱉼"}.mdi-safe-square-outline:before{content:"󱉽"}.mdi-safety-goggles:before{content:"󰴰"}.mdi-sail-boat:before{content:"󰻈"}.mdi-sail-boat-sink:before{content:"󱫯"}.mdi-sale:before{content:"󰑯"}.mdi-sale-outline:before{content:"󱨆"}.mdi-salesforce:before{content:"󰢎"}.mdi-sass:before{content:"󰟬"}.mdi-satellite:before{content:"󰑰"}.mdi-satellite-uplink:before{content:"󰤉"}.mdi-satellite-variant:before{content:"󰑱"}.mdi-sausage:before{content:"󰢺"}.mdi-sausage-off:before{content:"󱞉"}.mdi-saw-blade:before{content:"󰹡"}.mdi-sawtooth-wave:before{content:"󱑺"}.mdi-saxophone:before{content:"󰘉"}.mdi-scale:before{content:"󰑲"}.mdi-scale-balance:before{content:"󰗑"}.mdi-scale-bathroom:before{content:"󰑳"}.mdi-scale-off:before{content:"󱁚"}.mdi-scale-unbalanced:before{content:"󱦸"}.mdi-scan-helper:before{content:"󱏘"}.mdi-scanner:before{content:"󰚫"}.mdi-scanner-off:before{content:"󰤊"}.mdi-scatter-plot:before{content:"󰻉"}.mdi-scatter-plot-outline:before{content:"󰻊"}.mdi-scent:before{content:"󱥘"}.mdi-scent-off:before{content:"󱥙"}.mdi-school:before{content:"󰑴"}.mdi-school-outline:before{content:"󱆀"}.mdi-scissors-cutting:before{content:"󰩫"}.mdi-scooter:before{content:"󱖽"}.mdi-scooter-electric:before{content:"󱖾"}.mdi-scoreboard:before{content:"󱉾"}.mdi-scoreboard-outline:before{content:"󱉿"}.mdi-screen-rotation:before{content:"󰑵"}.mdi-screen-rotation-lock:before{content:"󰑸"}.mdi-screw-flat-top:before{content:"󰷳"}.mdi-screw-lag:before{content:"󰷴"}.mdi-screw-machine-flat-top:before{content:"󰷵"}.mdi-screw-machine-round-top:before{content:"󰷶"}.mdi-screw-round-top:before{content:"󰷷"}.mdi-screwdriver:before{content:"󰑶"}.mdi-script:before{content:"󰯁"}.mdi-script-outline:before{content:"󰑷"}.mdi-script-text:before{content:"󰯂"}.mdi-script-text-key:before{content:"󱜥"}.mdi-script-text-key-outline:before{content:"󱜦"}.mdi-script-text-outline:before{content:"󰯃"}.mdi-script-text-play:before{content:"󱜧"}.mdi-script-text-play-outline:before{content:"󱜨"}.mdi-sd:before{content:"󰑹"}.mdi-seal:before{content:"󰑺"}.mdi-seal-variant:before{content:"󰿙"}.mdi-search-web:before{content:"󰜏"}.mdi-seat:before{content:"󰳃"}.mdi-seat-flat:before{content:"󰑻"}.mdi-seat-flat-angled:before{content:"󰑼"}.mdi-seat-individual-suite:before{content:"󰑽"}.mdi-seat-legroom-extra:before{content:"󰑾"}.mdi-seat-legroom-normal:before{content:"󰑿"}.mdi-seat-legroom-reduced:before{content:"󰒀"}.mdi-seat-outline:before{content:"󰳄"}.mdi-seat-passenger:before{content:"󱉉"}.mdi-seat-recline-extra:before{content:"󰒁"}.mdi-seat-recline-normal:before{content:"󰒂"}.mdi-seatbelt:before{content:"󰳅"}.mdi-security:before{content:"󰒃"}.mdi-security-network:before{content:"󰒄"}.mdi-seed:before{content:"󰹢"}.mdi-seed-off:before{content:"󱏽"}.mdi-seed-off-outline:before{content:"󱏾"}.mdi-seed-outline:before{content:"󰹣"}.mdi-seed-plus:before{content:"󱩭"}.mdi-seed-plus-outline:before{content:"󱩮"}.mdi-seesaw:before{content:"󱖤"}.mdi-segment:before{content:"󰻋"}.mdi-select:before{content:"󰒅"}.mdi-select-all:before{content:"󰒆"}.mdi-select-arrow-down:before{content:"󱭙"}.mdi-select-arrow-up:before{content:"󱭘"}.mdi-select-color:before{content:"󰴱"}.mdi-select-compare:before{content:"󰫙"}.mdi-select-drag:before{content:"󰩬"}.mdi-select-group:before{content:"󰾂"}.mdi-select-inverse:before{content:"󰒇"}.mdi-select-marker:before{content:"󱊀"}.mdi-select-multiple:before{content:"󱊁"}.mdi-select-multiple-marker:before{content:"󱊂"}.mdi-select-off:before{content:"󰒈"}.mdi-select-place:before{content:"󰿚"}.mdi-select-remove:before{content:"󱟁"}.mdi-select-search:before{content:"󱈄"}.mdi-selection:before{content:"󰒉"}.mdi-selection-drag:before{content:"󰩭"}.mdi-selection-ellipse:before{content:"󰴲"}.mdi-selection-ellipse-arrow-inside:before{content:"󰼢"}.mdi-selection-ellipse-remove:before{content:"󱟂"}.mdi-selection-marker:before{content:"󱊃"}.mdi-selection-multiple:before{content:"󱊅"}.mdi-selection-multiple-marker:before{content:"󱊄"}.mdi-selection-off:before{content:"󰝷"}.mdi-selection-remove:before{content:"󱟃"}.mdi-selection-search:before{content:"󱈅"}.mdi-semantic-web:before{content:"󱌖"}.mdi-send:before{content:"󰒊"}.mdi-send-check:before{content:"󱅡"}.mdi-send-check-outline:before{content:"󱅢"}.mdi-send-circle:before{content:"󰷸"}.mdi-send-circle-outline:before{content:"󰷹"}.mdi-send-clock:before{content:"󱅣"}.mdi-send-clock-outline:before{content:"󱅤"}.mdi-send-lock:before{content:"󰟭"}.mdi-send-lock-outline:before{content:"󱅦"}.mdi-send-outline:before{content:"󱅥"}.mdi-send-variant:before{content:"󱱍"}.mdi-send-variant-clock:before{content:"󱱾"}.mdi-send-variant-clock-outline:before{content:"󱱿"}.mdi-send-variant-outline:before{content:"󱱎"}.mdi-serial-port:before{content:"󰙜"}.mdi-server:before{content:"󰒋"}.mdi-server-minus:before{content:"󰒌"}.mdi-server-network:before{content:"󰒍"}.mdi-server-network-off:before{content:"󰒎"}.mdi-server-off:before{content:"󰒏"}.mdi-server-plus:before{content:"󰒐"}.mdi-server-remove:before{content:"󰒑"}.mdi-server-security:before{content:"󰒒"}.mdi-set-all:before{content:"󰝸"}.mdi-set-center:before{content:"󰝹"}.mdi-set-center-right:before{content:"󰝺"}.mdi-set-left:before{content:"󰝻"}.mdi-set-left-center:before{content:"󰝼"}.mdi-set-left-right:before{content:"󰝽"}.mdi-set-merge:before{content:"󱓠"}.mdi-set-none:before{content:"󰝾"}.mdi-set-right:before{content:"󰝿"}.mdi-set-split:before{content:"󱓡"}.mdi-set-square:before{content:"󱑝"}.mdi-set-top-box:before{content:"󰦟"}.mdi-settings-helper:before{content:"󰩮"}.mdi-shaker:before{content:"󱄎"}.mdi-shaker-outline:before{content:"󱄏"}.mdi-shape:before{content:"󰠱"}.mdi-shape-circle-plus:before{content:"󰙝"}.mdi-shape-outline:before{content:"󰠲"}.mdi-shape-oval-plus:before{content:"󱇺"}.mdi-shape-plus:before{content:"󰒕"}.mdi-shape-plus-outline:before{content:"󱱏"}.mdi-shape-polygon-plus:before{content:"󰙞"}.mdi-shape-rectangle-plus:before{content:"󰙟"}.mdi-shape-square-plus:before{content:"󰙠"}.mdi-shape-square-rounded-plus:before{content:"󱓺"}.mdi-share:before{content:"󰒖"}.mdi-share-all:before{content:"󱇴"}.mdi-share-all-outline:before{content:"󱇵"}.mdi-share-circle:before{content:"󱆭"}.mdi-share-off:before{content:"󰼣"}.mdi-share-off-outline:before{content:"󰼤"}.mdi-share-outline:before{content:"󰤲"}.mdi-share-variant:before{content:"󰒗"}.mdi-share-variant-outline:before{content:"󱔔"}.mdi-shark:before{content:"󱢺"}.mdi-shark-fin:before{content:"󱙳"}.mdi-shark-fin-outline:before{content:"󱙴"}.mdi-shark-off:before{content:"󱢻"}.mdi-sheep:before{content:"󰳆"}.mdi-shield:before{content:"󰒘"}.mdi-shield-account:before{content:"󰢏"}.mdi-shield-account-outline:before{content:"󰨒"}.mdi-shield-account-variant:before{content:"󱖧"}.mdi-shield-account-variant-outline:before{content:"󱖨"}.mdi-shield-airplane:before{content:"󰚻"}.mdi-shield-airplane-outline:before{content:"󰳇"}.mdi-shield-alert:before{content:"󰻌"}.mdi-shield-alert-outline:before{content:"󰻍"}.mdi-shield-bug:before{content:"󱏚"}.mdi-shield-bug-outline:before{content:"󱏛"}.mdi-shield-car:before{content:"󰾃"}.mdi-shield-check:before{content:"󰕥"}.mdi-shield-check-outline:before{content:"󰳈"}.mdi-shield-cross:before{content:"󰳉"}.mdi-shield-cross-outline:before{content:"󰳊"}.mdi-shield-crown:before{content:"󱢼"}.mdi-shield-crown-outline:before{content:"󱢽"}.mdi-shield-edit:before{content:"󱆠"}.mdi-shield-edit-outline:before{content:"󱆡"}.mdi-shield-half:before{content:"󱍠"}.mdi-shield-half-full:before{content:"󰞀"}.mdi-shield-home:before{content:"󰚊"}.mdi-shield-home-outline:before{content:"󰳋"}.mdi-shield-key:before{content:"󰯄"}.mdi-shield-key-outline:before{content:"󰯅"}.mdi-shield-link-variant:before{content:"󰴳"}.mdi-shield-link-variant-outline:before{content:"󰴴"}.mdi-shield-lock:before{content:"󰦝"}.mdi-shield-lock-open:before{content:"󱦚"}.mdi-shield-lock-open-outline:before{content:"󱦛"}.mdi-shield-lock-outline:before{content:"󰳌"}.mdi-shield-moon:before{content:"󱠨"}.mdi-shield-moon-outline:before{content:"󱠩"}.mdi-shield-off:before{content:"󰦞"}.mdi-shield-off-outline:before{content:"󰦜"}.mdi-shield-outline:before{content:"󰒙"}.mdi-shield-plus:before{content:"󰫚"}.mdi-shield-plus-outline:before{content:"󰫛"}.mdi-shield-refresh:before{content:"󰂪"}.mdi-shield-refresh-outline:before{content:"󰇠"}.mdi-shield-remove:before{content:"󰫜"}.mdi-shield-remove-outline:before{content:"󰫝"}.mdi-shield-search:before{content:"󰶚"}.mdi-shield-star:before{content:"󱄻"}.mdi-shield-star-outline:before{content:"󱄼"}.mdi-shield-sun:before{content:"󱁝"}.mdi-shield-sun-outline:before{content:"󱁞"}.mdi-shield-sword:before{content:"󱢾"}.mdi-shield-sword-outline:before{content:"󱢿"}.mdi-shield-sync:before{content:"󱆢"}.mdi-shield-sync-outline:before{content:"󱆣"}.mdi-shimmer:before{content:"󱕅"}.mdi-ship-wheel:before{content:"󰠳"}.mdi-shipping-pallet:before{content:"󱡎"}.mdi-shoe-ballet:before{content:"󱗊"}.mdi-shoe-cleat:before{content:"󱗇"}.mdi-shoe-formal:before{content:"󰭇"}.mdi-shoe-heel:before{content:"󰭈"}.mdi-shoe-print:before{content:"󰷺"}.mdi-shoe-sneaker:before{content:"󱗈"}.mdi-shopping:before{content:"󰒚"}.mdi-shopping-music:before{content:"󰒛"}.mdi-shopping-outline:before{content:"󱇕"}.mdi-shopping-search:before{content:"󰾄"}.mdi-shopping-search-outline:before{content:"󱩯"}.mdi-shore:before{content:"󱓹"}.mdi-shovel:before{content:"󰜐"}.mdi-shovel-off:before{content:"󰜑"}.mdi-shower:before{content:"󰦠"}.mdi-shower-head:before{content:"󰦡"}.mdi-shredder:before{content:"󰒜"}.mdi-shuffle:before{content:"󰒝"}.mdi-shuffle-disabled:before{content:"󰒞"}.mdi-shuffle-variant:before{content:"󰒟"}.mdi-shuriken:before{content:"󱍿"}.mdi-sickle:before{content:"󱣀"}.mdi-sigma:before{content:"󰒠"}.mdi-sigma-lower:before{content:"󰘫"}.mdi-sign-caution:before{content:"󰒡"}.mdi-sign-direction:before{content:"󰞁"}.mdi-sign-direction-minus:before{content:"󱀀"}.mdi-sign-direction-plus:before{content:"󰿜"}.mdi-sign-direction-remove:before{content:"󰿝"}.mdi-sign-language:before{content:"󱭍"}.mdi-sign-language-outline:before{content:"󱭎"}.mdi-sign-pole:before{content:"󱓸"}.mdi-sign-real-estate:before{content:"󱄘"}.mdi-sign-text:before{content:"󰞂"}.mdi-sign-yield:before{content:"󱮯"}.mdi-signal:before{content:"󰒢"}.mdi-signal-2g:before{content:"󰜒"}.mdi-signal-3g:before{content:"󰜓"}.mdi-signal-4g:before{content:"󰜔"}.mdi-signal-5g:before{content:"󰩯"}.mdi-signal-cellular-1:before{content:"󰢼"}.mdi-signal-cellular-2:before{content:"󰢽"}.mdi-signal-cellular-3:before{content:"󰢾"}.mdi-signal-cellular-outline:before{content:"󰢿"}.mdi-signal-distance-variant:before{content:"󰹤"}.mdi-signal-hspa:before{content:"󰜕"}.mdi-signal-hspa-plus:before{content:"󰜖"}.mdi-signal-off:before{content:"󰞃"}.mdi-signal-variant:before{content:"󰘊"}.mdi-signature:before{content:"󰷻"}.mdi-signature-freehand:before{content:"󰷼"}.mdi-signature-image:before{content:"󰷽"}.mdi-signature-text:before{content:"󰷾"}.mdi-silo:before{content:"󱮟"}.mdi-silo-outline:before{content:"󰭉"}.mdi-silverware:before{content:"󰒣"}.mdi-silverware-clean:before{content:"󰿞"}.mdi-silverware-fork:before{content:"󰒤"}.mdi-silverware-fork-knife:before{content:"󰩰"}.mdi-silverware-spoon:before{content:"󰒥"}.mdi-silverware-variant:before{content:"󰒦"}.mdi-sim:before{content:"󰒧"}.mdi-sim-alert:before{content:"󰒨"}.mdi-sim-alert-outline:before{content:"󱗓"}.mdi-sim-off:before{content:"󰒩"}.mdi-sim-off-outline:before{content:"󱗔"}.mdi-sim-outline:before{content:"󱗕"}.mdi-simple-icons:before{content:"󱌝"}.mdi-sina-weibo:before{content:"󰫟"}.mdi-sine-wave:before{content:"󰥛"}.mdi-sitemap:before{content:"󰒪"}.mdi-sitemap-outline:before{content:"󱦜"}.mdi-size-l:before{content:"󱎦"}.mdi-size-m:before{content:"󱎥"}.mdi-size-s:before{content:"󱎤"}.mdi-size-xl:before{content:"󱎧"}.mdi-size-xs:before{content:"󱎣"}.mdi-size-xxl:before{content:"󱎨"}.mdi-size-xxs:before{content:"󱎢"}.mdi-size-xxxl:before{content:"󱎩"}.mdi-skate:before{content:"󰴵"}.mdi-skate-off:before{content:"󰚙"}.mdi-skateboard:before{content:"󱓂"}.mdi-skateboarding:before{content:"󰔁"}.mdi-skew-less:before{content:"󰴶"}.mdi-skew-more:before{content:"󰴷"}.mdi-ski:before{content:"󱌄"}.mdi-ski-cross-country:before{content:"󱌅"}.mdi-ski-water:before{content:"󱌆"}.mdi-skip-backward:before{content:"󰒫"}.mdi-skip-backward-outline:before{content:"󰼥"}.mdi-skip-forward:before{content:"󰒬"}.mdi-skip-forward-outline:before{content:"󰼦"}.mdi-skip-next:before{content:"󰒭"}.mdi-skip-next-circle:before{content:"󰙡"}.mdi-skip-next-circle-outline:before{content:"󰙢"}.mdi-skip-next-outline:before{content:"󰼧"}.mdi-skip-previous:before{content:"󰒮"}.mdi-skip-previous-circle:before{content:"󰙣"}.mdi-skip-previous-circle-outline:before{content:"󰙤"}.mdi-skip-previous-outline:before{content:"󰼨"}.mdi-skull:before{content:"󰚌"}.mdi-skull-crossbones:before{content:"󰯆"}.mdi-skull-crossbones-outline:before{content:"󰯇"}.mdi-skull-outline:before{content:"󰯈"}.mdi-skull-scan:before{content:"󱓇"}.mdi-skull-scan-outline:before{content:"󱓈"}.mdi-skype:before{content:"󰒯"}.mdi-skype-business:before{content:"󰒰"}.mdi-slack:before{content:"󰒱"}.mdi-slash-forward:before{content:"󰿟"}.mdi-slash-forward-box:before{content:"󰿠"}.mdi-sledding:before{content:"󰐛"}.mdi-sleep:before{content:"󰒲"}.mdi-sleep-off:before{content:"󰒳"}.mdi-slide:before{content:"󱖥"}.mdi-slope-downhill:before{content:"󰷿"}.mdi-slope-uphill:before{content:"󰸀"}.mdi-slot-machine:before{content:"󱄔"}.mdi-slot-machine-outline:before{content:"󱄕"}.mdi-smart-card:before{content:"󱂽"}.mdi-smart-card-off:before{content:"󱣷"}.mdi-smart-card-off-outline:before{content:"󱣸"}.mdi-smart-card-outline:before{content:"󱂾"}.mdi-smart-card-reader:before{content:"󱂿"}.mdi-smart-card-reader-outline:before{content:"󱃀"}.mdi-smog:before{content:"󰩱"}.mdi-smoke:before{content:"󱞙"}.mdi-smoke-detector:before{content:"󰎒"}.mdi-smoke-detector-alert:before{content:"󱤮"}.mdi-smoke-detector-alert-outline:before{content:"󱤯"}.mdi-smoke-detector-off:before{content:"󱠉"}.mdi-smoke-detector-off-outline:before{content:"󱠊"}.mdi-smoke-detector-outline:before{content:"󱠈"}.mdi-smoke-detector-variant:before{content:"󱠋"}.mdi-smoke-detector-variant-alert:before{content:"󱤰"}.mdi-smoke-detector-variant-off:before{content:"󱠌"}.mdi-smoking:before{content:"󰒴"}.mdi-smoking-off:before{content:"󰒵"}.mdi-smoking-pipe:before{content:"󱐍"}.mdi-smoking-pipe-off:before{content:"󱐨"}.mdi-snail:before{content:"󱙷"}.mdi-snake:before{content:"󱔎"}.mdi-snapchat:before{content:"󰒶"}.mdi-snowboard:before{content:"󱌇"}.mdi-snowflake:before{content:"󰜗"}.mdi-snowflake-alert:before{content:"󰼩"}.mdi-snowflake-check:before{content:"󱩰"}.mdi-snowflake-melt:before{content:"󱋋"}.mdi-snowflake-off:before{content:"󱓣"}.mdi-snowflake-thermometer:before{content:"󱩱"}.mdi-snowflake-variant:before{content:"󰼪"}.mdi-snowman:before{content:"󰒷"}.mdi-snowmobile:before{content:"󰛝"}.mdi-snowshoeing:before{content:"󱩲"}.mdi-soccer:before{content:"󰒸"}.mdi-soccer-field:before{content:"󰠴"}.mdi-social-distance-2-meters:before{content:"󱕹"}.mdi-social-distance-6-feet:before{content:"󱕺"}.mdi-sofa:before{content:"󰒹"}.mdi-sofa-outline:before{content:"󱕭"}.mdi-sofa-single:before{content:"󱕮"}.mdi-sofa-single-outline:before{content:"󱕯"}.mdi-solar-panel:before{content:"󰶛"}.mdi-solar-panel-large:before{content:"󰶜"}.mdi-solar-power:before{content:"󰩲"}.mdi-solar-power-variant:before{content:"󱩳"}.mdi-solar-power-variant-outline:before{content:"󱩴"}.mdi-soldering-iron:before{content:"󱂒"}.mdi-solid:before{content:"󰚍"}.mdi-sony-playstation:before{content:"󰐔"}.mdi-sort:before{content:"󰒺"}.mdi-sort-alphabetical-ascending:before{content:"󰖽"}.mdi-sort-alphabetical-ascending-variant:before{content:"󱅈"}.mdi-sort-alphabetical-descending:before{content:"󰖿"}.mdi-sort-alphabetical-descending-variant:before{content:"󱅉"}.mdi-sort-alphabetical-variant:before{content:"󰒻"}.mdi-sort-ascending:before{content:"󰒼"}.mdi-sort-bool-ascending:before{content:"󱎅"}.mdi-sort-bool-ascending-variant:before{content:"󱎆"}.mdi-sort-bool-descending:before{content:"󱎇"}.mdi-sort-bool-descending-variant:before{content:"󱎈"}.mdi-sort-calendar-ascending:before{content:"󱕇"}.mdi-sort-calendar-descending:before{content:"󱕈"}.mdi-sort-clock-ascending:before{content:"󱕉"}.mdi-sort-clock-ascending-outline:before{content:"󱕊"}.mdi-sort-clock-descending:before{content:"󱕋"}.mdi-sort-clock-descending-outline:before{content:"󱕌"}.mdi-sort-descending:before{content:"󰒽"}.mdi-sort-numeric-ascending:before{content:"󱎉"}.mdi-sort-numeric-ascending-variant:before{content:"󰤍"}.mdi-sort-numeric-descending:before{content:"󱎊"}.mdi-sort-numeric-descending-variant:before{content:"󰫒"}.mdi-sort-numeric-variant:before{content:"󰒾"}.mdi-sort-reverse-variant:before{content:"󰌼"}.mdi-sort-variant:before{content:"󰒿"}.mdi-sort-variant-lock:before{content:"󰳍"}.mdi-sort-variant-lock-open:before{content:"󰳎"}.mdi-sort-variant-off:before{content:"󱪻"}.mdi-sort-variant-remove:before{content:"󱅇"}.mdi-soundbar:before{content:"󱟛"}.mdi-soundcloud:before{content:"󰓀"}.mdi-source-branch:before{content:"󰘬"}.mdi-source-branch-check:before{content:"󱓏"}.mdi-source-branch-minus:before{content:"󱓋"}.mdi-source-branch-plus:before{content:"󱓊"}.mdi-source-branch-refresh:before{content:"󱓍"}.mdi-source-branch-remove:before{content:"󱓌"}.mdi-source-branch-sync:before{content:"󱓎"}.mdi-source-commit:before{content:"󰜘"}.mdi-source-commit-end:before{content:"󰜙"}.mdi-source-commit-end-local:before{content:"󰜚"}.mdi-source-commit-local:before{content:"󰜛"}.mdi-source-commit-next-local:before{content:"󰜜"}.mdi-source-commit-start:before{content:"󰜝"}.mdi-source-commit-start-next-local:before{content:"󰜞"}.mdi-source-fork:before{content:"󰓁"}.mdi-source-merge:before{content:"󰘭"}.mdi-source-pull:before{content:"󰓂"}.mdi-source-repository:before{content:"󰳏"}.mdi-source-repository-multiple:before{content:"󰳐"}.mdi-soy-sauce:before{content:"󰟮"}.mdi-soy-sauce-off:before{content:"󱏼"}.mdi-spa:before{content:"󰳑"}.mdi-spa-outline:before{content:"󰳒"}.mdi-space-invaders:before{content:"󰯉"}.mdi-space-station:before{content:"󱎃"}.mdi-spade:before{content:"󰹥"}.mdi-speaker:before{content:"󰓃"}.mdi-speaker-bluetooth:before{content:"󰦢"}.mdi-speaker-message:before{content:"󱬑"}.mdi-speaker-multiple:before{content:"󰴸"}.mdi-speaker-off:before{content:"󰓄"}.mdi-speaker-pause:before{content:"󱭳"}.mdi-speaker-play:before{content:"󱭲"}.mdi-speaker-stop:before{content:"󱭴"}.mdi-speaker-wireless:before{content:"󰜟"}.mdi-spear:before{content:"󱡅"}.mdi-speedometer:before{content:"󰓅"}.mdi-speedometer-medium:before{content:"󰾅"}.mdi-speedometer-slow:before{content:"󰾆"}.mdi-spellcheck:before{content:"󰓆"}.mdi-sphere:before{content:"󱥔"}.mdi-sphere-off:before{content:"󱥕"}.mdi-spider:before{content:"󱇪"}.mdi-spider-outline:before{content:"󱱵"}.mdi-spider-thread:before{content:"󱇫"}.mdi-spider-web:before{content:"󰯊"}.mdi-spirit-level:before{content:"󱓱"}.mdi-spoon-sugar:before{content:"󱐩"}.mdi-spotify:before{content:"󰓇"}.mdi-spotlight:before{content:"󰓈"}.mdi-spotlight-beam:before{content:"󰓉"}.mdi-spray:before{content:"󰙥"}.mdi-spray-bottle:before{content:"󰫠"}.mdi-sprinkler:before{content:"󱁟"}.mdi-sprinkler-fire:before{content:"󱦝"}.mdi-sprinkler-variant:before{content:"󱁠"}.mdi-sprout:before{content:"󰹦"}.mdi-sprout-outline:before{content:"󰹧"}.mdi-square:before{content:"󰝤"}.mdi-square-circle:before{content:"󱔀"}.mdi-square-circle-outline:before{content:"󱱐"}.mdi-square-edit-outline:before{content:"󰤌"}.mdi-square-medium:before{content:"󰨓"}.mdi-square-medium-outline:before{content:"󰨔"}.mdi-square-off:before{content:"󱋮"}.mdi-square-off-outline:before{content:"󱋯"}.mdi-square-opacity:before{content:"󱡔"}.mdi-square-outline:before{content:"󰝣"}.mdi-square-root:before{content:"󰞄"}.mdi-square-root-box:before{content:"󰦣"}.mdi-square-rounded:before{content:"󱓻"}.mdi-square-rounded-badge:before{content:"󱨇"}.mdi-square-rounded-badge-outline:before{content:"󱨈"}.mdi-square-rounded-outline:before{content:"󱓼"}.mdi-square-small:before{content:"󰨕"}.mdi-square-wave:before{content:"󱑻"}.mdi-squeegee:before{content:"󰫡"}.mdi-ssh:before{content:"󰣀"}.mdi-stack-exchange:before{content:"󰘋"}.mdi-stack-overflow:before{content:"󰓌"}.mdi-stackpath:before{content:"󰍙"}.mdi-stadium:before{content:"󰿹"}.mdi-stadium-outline:before{content:"󱬃"}.mdi-stadium-variant:before{content:"󰜠"}.mdi-stairs:before{content:"󰓍"}.mdi-stairs-box:before{content:"󱎞"}.mdi-stairs-down:before{content:"󱊾"}.mdi-stairs-up:before{content:"󱊽"}.mdi-stamper:before{content:"󰴹"}.mdi-standard-definition:before{content:"󰟯"}.mdi-star:before{content:"󰓎"}.mdi-star-box:before{content:"󰩳"}.mdi-star-box-multiple:before{content:"󱊆"}.mdi-star-box-multiple-outline:before{content:"󱊇"}.mdi-star-box-outline:before{content:"󰩴"}.mdi-star-check:before{content:"󱕦"}.mdi-star-check-outline:before{content:"󱕪"}.mdi-star-circle:before{content:"󰓏"}.mdi-star-circle-outline:before{content:"󰦤"}.mdi-star-cog:before{content:"󱙨"}.mdi-star-cog-outline:before{content:"󱙩"}.mdi-star-crescent:before{content:"󰥹"}.mdi-star-david:before{content:"󰥺"}.mdi-star-face:before{content:"󰦥"}.mdi-star-four-points:before{content:"󰫢"}.mdi-star-four-points-box:before{content:"󱱑"}.mdi-star-four-points-box-outline:before{content:"󱱒"}.mdi-star-four-points-circle:before{content:"󱱓"}.mdi-star-four-points-circle-outline:before{content:"󱱔"}.mdi-star-four-points-outline:before{content:"󰫣"}.mdi-star-four-points-small:before{content:"󱱕"}.mdi-star-half:before{content:"󰉆"}.mdi-star-half-full:before{content:"󰓐"}.mdi-star-minus:before{content:"󱕤"}.mdi-star-minus-outline:before{content:"󱕨"}.mdi-star-off:before{content:"󰓑"}.mdi-star-off-outline:before{content:"󱕛"}.mdi-star-outline:before{content:"󰓒"}.mdi-star-plus:before{content:"󱕣"}.mdi-star-plus-outline:before{content:"󱕧"}.mdi-star-remove:before{content:"󱕥"}.mdi-star-remove-outline:before{content:"󱕩"}.mdi-star-settings:before{content:"󱙪"}.mdi-star-settings-outline:before{content:"󱙫"}.mdi-star-shooting:before{content:"󱝁"}.mdi-star-shooting-outline:before{content:"󱝂"}.mdi-star-three-points:before{content:"󰫤"}.mdi-star-three-points-outline:before{content:"󰫥"}.mdi-state-machine:before{content:"󱇯"}.mdi-steam:before{content:"󰓓"}.mdi-steering:before{content:"󰓔"}.mdi-steering-off:before{content:"󰤎"}.mdi-step-backward:before{content:"󰓕"}.mdi-step-backward-2:before{content:"󰓖"}.mdi-step-forward:before{content:"󰓗"}.mdi-step-forward-2:before{content:"󰓘"}.mdi-stethoscope:before{content:"󰓙"}.mdi-sticker:before{content:"󱍤"}.mdi-sticker-alert:before{content:"󱍥"}.mdi-sticker-alert-outline:before{content:"󱍦"}.mdi-sticker-check:before{content:"󱍧"}.mdi-sticker-check-outline:before{content:"󱍨"}.mdi-sticker-circle-outline:before{content:"󰗐"}.mdi-sticker-emoji:before{content:"󰞅"}.mdi-sticker-minus:before{content:"󱍩"}.mdi-sticker-minus-outline:before{content:"󱍪"}.mdi-sticker-outline:before{content:"󱍫"}.mdi-sticker-plus:before{content:"󱍬"}.mdi-sticker-plus-outline:before{content:"󱍭"}.mdi-sticker-remove:before{content:"󱍮"}.mdi-sticker-remove-outline:before{content:"󱍯"}.mdi-sticker-text:before{content:"󱞎"}.mdi-sticker-text-outline:before{content:"󱞏"}.mdi-stocking:before{content:"󰓚"}.mdi-stomach:before{content:"󱂓"}.mdi-stool:before{content:"󱥝"}.mdi-stool-outline:before{content:"󱥞"}.mdi-stop:before{content:"󰓛"}.mdi-stop-circle:before{content:"󰙦"}.mdi-stop-circle-outline:before{content:"󰙧"}.mdi-storage-tank:before{content:"󱩵"}.mdi-storage-tank-outline:before{content:"󱩶"}.mdi-store:before{content:"󰓜"}.mdi-store-24-hour:before{content:"󰓝"}.mdi-store-alert:before{content:"󱣁"}.mdi-store-alert-outline:before{content:"󱣂"}.mdi-store-check:before{content:"󱣃"}.mdi-store-check-outline:before{content:"󱣄"}.mdi-store-clock:before{content:"󱣅"}.mdi-store-clock-outline:before{content:"󱣆"}.mdi-store-cog:before{content:"󱣇"}.mdi-store-cog-outline:before{content:"󱣈"}.mdi-store-edit:before{content:"󱣉"}.mdi-store-edit-outline:before{content:"󱣊"}.mdi-store-marker:before{content:"󱣋"}.mdi-store-marker-outline:before{content:"󱣌"}.mdi-store-minus:before{content:"󱙞"}.mdi-store-minus-outline:before{content:"󱣍"}.mdi-store-off:before{content:"󱣎"}.mdi-store-off-outline:before{content:"󱣏"}.mdi-store-outline:before{content:"󱍡"}.mdi-store-plus:before{content:"󱙟"}.mdi-store-plus-outline:before{content:"󱣐"}.mdi-store-remove:before{content:"󱙠"}.mdi-store-remove-outline:before{content:"󱣑"}.mdi-store-search:before{content:"󱣒"}.mdi-store-search-outline:before{content:"󱣓"}.mdi-store-settings:before{content:"󱣔"}.mdi-store-settings-outline:before{content:"󱣕"}.mdi-storefront:before{content:"󰟇"}.mdi-storefront-check:before{content:"󱭽"}.mdi-storefront-check-outline:before{content:"󱭾"}.mdi-storefront-edit:before{content:"󱭿"}.mdi-storefront-edit-outline:before{content:"󱮀"}.mdi-storefront-minus:before{content:"󱮃"}.mdi-storefront-minus-outline:before{content:"󱮄"}.mdi-storefront-outline:before{content:"󱃁"}.mdi-storefront-plus:before{content:"󱮁"}.mdi-storefront-plus-outline:before{content:"󱮂"}.mdi-storefront-remove:before{content:"󱮅"}.mdi-storefront-remove-outline:before{content:"󱮆"}.mdi-stove:before{content:"󰓞"}.mdi-strategy:before{content:"󱇖"}.mdi-stretch-to-page:before{content:"󰼫"}.mdi-stretch-to-page-outline:before{content:"󰼬"}.mdi-string-lights:before{content:"󱊺"}.mdi-string-lights-off:before{content:"󱊻"}.mdi-subdirectory-arrow-left:before{content:"󰘌"}.mdi-subdirectory-arrow-right:before{content:"󰘍"}.mdi-submarine:before{content:"󱕬"}.mdi-subtitles:before{content:"󰨖"}.mdi-subtitles-outline:before{content:"󰨗"}.mdi-subway:before{content:"󰚬"}.mdi-subway-alert-variant:before{content:"󰶝"}.mdi-subway-variant:before{content:"󰓟"}.mdi-summit:before{content:"󰞆"}.mdi-sun-angle:before{content:"󱬧"}.mdi-sun-angle-outline:before{content:"󱬨"}.mdi-sun-clock:before{content:"󱩷"}.mdi-sun-clock-outline:before{content:"󱩸"}.mdi-sun-compass:before{content:"󱦥"}.mdi-sun-snowflake:before{content:"󱞖"}.mdi-sun-snowflake-variant:before{content:"󱩹"}.mdi-sun-thermometer:before{content:"󱣖"}.mdi-sun-thermometer-outline:before{content:"󱣗"}.mdi-sun-wireless:before{content:"󱟾"}.mdi-sun-wireless-outline:before{content:"󱟿"}.mdi-sunglasses:before{content:"󰓠"}.mdi-surfing:before{content:"󱝆"}.mdi-surround-sound:before{content:"󰗅"}.mdi-surround-sound-2-0:before{content:"󰟰"}.mdi-surround-sound-2-1:before{content:"󱜩"}.mdi-surround-sound-3-1:before{content:"󰟱"}.mdi-surround-sound-5-1:before{content:"󰟲"}.mdi-surround-sound-5-1-2:before{content:"󱜪"}.mdi-surround-sound-7-1:before{content:"󰟳"}.mdi-svg:before{content:"󰜡"}.mdi-swap-horizontal:before{content:"󰓡"}.mdi-swap-horizontal-bold:before{content:"󰯍"}.mdi-swap-horizontal-circle:before{content:"󰿡"}.mdi-swap-horizontal-circle-outline:before{content:"󰿢"}.mdi-swap-horizontal-variant:before{content:"󰣁"}.mdi-swap-vertical:before{content:"󰓢"}.mdi-swap-vertical-bold:before{content:"󰯎"}.mdi-swap-vertical-circle:before{content:"󰿣"}.mdi-swap-vertical-circle-outline:before{content:"󰿤"}.mdi-swap-vertical-variant:before{content:"󰣂"}.mdi-swim:before{content:"󰓣"}.mdi-switch:before{content:"󰓤"}.mdi-sword:before{content:"󰓥"}.mdi-sword-cross:before{content:"󰞇"}.mdi-syllabary-hangul:before{content:"󱌳"}.mdi-syllabary-hiragana:before{content:"󱌴"}.mdi-syllabary-katakana:before{content:"󱌵"}.mdi-syllabary-katakana-halfwidth:before{content:"󱌶"}.mdi-symbol:before{content:"󱔁"}.mdi-symfony:before{content:"󰫦"}.mdi-synagogue:before{content:"󱬄"}.mdi-synagogue-outline:before{content:"󱬅"}.mdi-sync:before{content:"󰓦"}.mdi-sync-alert:before{content:"󰓧"}.mdi-sync-circle:before{content:"󱍸"}.mdi-sync-off:before{content:"󰓨"}.mdi-tab:before{content:"󰓩"}.mdi-tab-minus:before{content:"󰭋"}.mdi-tab-plus:before{content:"󰝜"}.mdi-tab-remove:before{content:"󰭌"}.mdi-tab-search:before{content:"󱦞"}.mdi-tab-unselected:before{content:"󰓪"}.mdi-table:before{content:"󰓫"}.mdi-table-account:before{content:"󱎹"}.mdi-table-alert:before{content:"󱎺"}.mdi-table-arrow-down:before{content:"󱎻"}.mdi-table-arrow-left:before{content:"󱎼"}.mdi-table-arrow-right:before{content:"󱎽"}.mdi-table-arrow-up:before{content:"󱎾"}.mdi-table-border:before{content:"󰨘"}.mdi-table-cancel:before{content:"󱎿"}.mdi-table-chair:before{content:"󱁡"}.mdi-table-check:before{content:"󱏀"}.mdi-table-clock:before{content:"󱏁"}.mdi-table-cog:before{content:"󱏂"}.mdi-table-column:before{content:"󰠵"}.mdi-table-column-plus-after:before{content:"󰓬"}.mdi-table-column-plus-before:before{content:"󰓭"}.mdi-table-column-remove:before{content:"󰓮"}.mdi-table-column-width:before{content:"󰓯"}.mdi-table-edit:before{content:"󰓰"}.mdi-table-eye:before{content:"󱂔"}.mdi-table-eye-off:before{content:"󱏃"}.mdi-table-filter:before{content:"󱮌"}.mdi-table-furniture:before{content:"󰖼"}.mdi-table-headers-eye:before{content:"󱈝"}.mdi-table-headers-eye-off:before{content:"󱈞"}.mdi-table-heart:before{content:"󱏄"}.mdi-table-key:before{content:"󱏅"}.mdi-table-large:before{content:"󰓱"}.mdi-table-large-plus:before{content:"󰾇"}.mdi-table-large-remove:before{content:"󰾈"}.mdi-table-lock:before{content:"󱏆"}.mdi-table-merge-cells:before{content:"󰦦"}.mdi-table-minus:before{content:"󱏇"}.mdi-table-multiple:before{content:"󱏈"}.mdi-table-network:before{content:"󱏉"}.mdi-table-of-contents:before{content:"󰠶"}.mdi-table-off:before{content:"󱏊"}.mdi-table-picnic:before{content:"󱝃"}.mdi-table-pivot:before{content:"󱠼"}.mdi-table-plus:before{content:"󰩵"}.mdi-table-question:before{content:"󱬡"}.mdi-table-refresh:before{content:"󱎠"}.mdi-table-remove:before{content:"󰩶"}.mdi-table-row:before{content:"󰠷"}.mdi-table-row-height:before{content:"󰓲"}.mdi-table-row-plus-after:before{content:"󰓳"}.mdi-table-row-plus-before:before{content:"󰓴"}.mdi-table-row-remove:before{content:"󰓵"}.mdi-table-search:before{content:"󰤏"}.mdi-table-settings:before{content:"󰠸"}.mdi-table-split-cell:before{content:"󱐪"}.mdi-table-star:before{content:"󱏋"}.mdi-table-sync:before{content:"󱎡"}.mdi-table-tennis:before{content:"󰹨"}.mdi-tablet:before{content:"󰓶"}.mdi-tablet-cellphone:before{content:"󰦧"}.mdi-tablet-dashboard:before{content:"󰻎"}.mdi-taco:before{content:"󰝢"}.mdi-tag:before{content:"󰓹"}.mdi-tag-arrow-down:before{content:"󱜫"}.mdi-tag-arrow-down-outline:before{content:"󱜬"}.mdi-tag-arrow-left:before{content:"󱜭"}.mdi-tag-arrow-left-outline:before{content:"󱜮"}.mdi-tag-arrow-right:before{content:"󱜯"}.mdi-tag-arrow-right-outline:before{content:"󱜰"}.mdi-tag-arrow-up:before{content:"󱜱"}.mdi-tag-arrow-up-outline:before{content:"󱜲"}.mdi-tag-check:before{content:"󱩺"}.mdi-tag-check-outline:before{content:"󱩻"}.mdi-tag-faces:before{content:"󰓺"}.mdi-tag-heart:before{content:"󰚋"}.mdi-tag-heart-outline:before{content:"󰯏"}.mdi-tag-hidden:before{content:"󱱶"}.mdi-tag-minus:before{content:"󰤐"}.mdi-tag-minus-outline:before{content:"󱈟"}.mdi-tag-multiple:before{content:"󰓻"}.mdi-tag-multiple-outline:before{content:"󱋷"}.mdi-tag-off:before{content:"󱈠"}.mdi-tag-off-outline:before{content:"󱈡"}.mdi-tag-outline:before{content:"󰓼"}.mdi-tag-plus:before{content:"󰜢"}.mdi-tag-plus-outline:before{content:"󱈢"}.mdi-tag-remove:before{content:"󰜣"}.mdi-tag-remove-outline:before{content:"󱈣"}.mdi-tag-search:before{content:"󱤇"}.mdi-tag-search-outline:before{content:"󱤈"}.mdi-tag-text:before{content:"󱈤"}.mdi-tag-text-outline:before{content:"󰓽"}.mdi-tailwind:before{content:"󱏿"}.mdi-tally-mark-1:before{content:"󱪼"}.mdi-tally-mark-2:before{content:"󱪽"}.mdi-tally-mark-3:before{content:"󱪾"}.mdi-tally-mark-4:before{content:"󱪿"}.mdi-tally-mark-5:before{content:"󱫀"}.mdi-tangram:before{content:"󰓸"}.mdi-tank:before{content:"󰴺"}.mdi-tanker-truck:before{content:"󰿥"}.mdi-tape-drive:before{content:"󱛟"}.mdi-tape-measure:before{content:"󰭍"}.mdi-target:before{content:"󰓾"}.mdi-target-account:before{content:"󰯐"}.mdi-target-variant:before{content:"󰩷"}.mdi-taxi:before{content:"󰓿"}.mdi-tea:before{content:"󰶞"}.mdi-tea-outline:before{content:"󰶟"}.mdi-teamviewer:before{content:"󰔀"}.mdi-teddy-bear:before{content:"󱣻"}.mdi-telescope:before{content:"󰭎"}.mdi-television:before{content:"󰔂"}.mdi-television-ambient-light:before{content:"󱍖"}.mdi-television-box:before{content:"󰠹"}.mdi-television-classic:before{content:"󰟴"}.mdi-television-classic-off:before{content:"󰠺"}.mdi-television-guide:before{content:"󰔃"}.mdi-television-off:before{content:"󰠻"}.mdi-television-pause:before{content:"󰾉"}.mdi-television-play:before{content:"󰻏"}.mdi-television-shimmer:before{content:"󱄐"}.mdi-television-speaker:before{content:"󱬛"}.mdi-television-speaker-off:before{content:"󱬜"}.mdi-television-stop:before{content:"󰾊"}.mdi-temperature-celsius:before{content:"󰔄"}.mdi-temperature-fahrenheit:before{content:"󰔅"}.mdi-temperature-kelvin:before{content:"󰔆"}.mdi-temple-buddhist:before{content:"󱬆"}.mdi-temple-buddhist-outline:before{content:"󱬇"}.mdi-temple-hindu:before{content:"󱬈"}.mdi-temple-hindu-outline:before{content:"󱬉"}.mdi-tennis:before{content:"󰶠"}.mdi-tennis-ball:before{content:"󰔇"}.mdi-tennis-ball-outline:before{content:"󱱟"}.mdi-tent:before{content:"󰔈"}.mdi-terraform:before{content:"󱁢"}.mdi-terrain:before{content:"󰔉"}.mdi-test-tube:before{content:"󰙨"}.mdi-test-tube-empty:before{content:"󰤑"}.mdi-test-tube-off:before{content:"󰤒"}.mdi-text:before{content:"󰦨"}.mdi-text-account:before{content:"󱕰"}.mdi-text-box:before{content:"󰈚"}.mdi-text-box-check:before{content:"󰺦"}.mdi-text-box-check-outline:before{content:"󰺧"}.mdi-text-box-edit:before{content:"󱩼"}.mdi-text-box-edit-outline:before{content:"󱩽"}.mdi-text-box-minus:before{content:"󰺨"}.mdi-text-box-minus-outline:before{content:"󰺩"}.mdi-text-box-multiple:before{content:"󰪷"}.mdi-text-box-multiple-outline:before{content:"󰪸"}.mdi-text-box-outline:before{content:"󰧭"}.mdi-text-box-plus:before{content:"󰺪"}.mdi-text-box-plus-outline:before{content:"󰺫"}.mdi-text-box-remove:before{content:"󰺬"}.mdi-text-box-remove-outline:before{content:"󰺭"}.mdi-text-box-search:before{content:"󰺮"}.mdi-text-box-search-outline:before{content:"󰺯"}.mdi-text-long:before{content:"󰦪"}.mdi-text-recognition:before{content:"󱄽"}.mdi-text-search:before{content:"󱎸"}.mdi-text-search-variant:before{content:"󱩾"}.mdi-text-shadow:before{content:"󰙩"}.mdi-text-short:before{content:"󰦩"}.mdi-texture:before{content:"󰔌"}.mdi-texture-box:before{content:"󰿦"}.mdi-theater:before{content:"󰔍"}.mdi-theme-light-dark:before{content:"󰔎"}.mdi-thermometer:before{content:"󰔏"}.mdi-thermometer-alert:before{content:"󰸁"}.mdi-thermometer-auto:before{content:"󱬏"}.mdi-thermometer-bluetooth:before{content:"󱢕"}.mdi-thermometer-check:before{content:"󱩿"}.mdi-thermometer-chevron-down:before{content:"󰸂"}.mdi-thermometer-chevron-up:before{content:"󰸃"}.mdi-thermometer-high:before{content:"󱃂"}.mdi-thermometer-lines:before{content:"󰔐"}.mdi-thermometer-low:before{content:"󱃃"}.mdi-thermometer-minus:before{content:"󰸄"}.mdi-thermometer-off:before{content:"󱔱"}.mdi-thermometer-plus:before{content:"󰸅"}.mdi-thermometer-probe:before{content:"󱬫"}.mdi-thermometer-probe-off:before{content:"󱬬"}.mdi-thermometer-water:before{content:"󱪀"}.mdi-thermostat:before{content:"󰎓"}.mdi-thermostat-auto:before{content:"󱬗"}.mdi-thermostat-box:before{content:"󰢑"}.mdi-thermostat-box-auto:before{content:"󱬘"}.mdi-thermostat-cog:before{content:"󱲀"}.mdi-thought-bubble:before{content:"󰟶"}.mdi-thought-bubble-outline:before{content:"󰟷"}.mdi-thumb-down:before{content:"󰔑"}.mdi-thumb-down-outline:before{content:"󰔒"}.mdi-thumb-up:before{content:"󰔓"}.mdi-thumb-up-outline:before{content:"󰔔"}.mdi-thumbs-up-down:before{content:"󰔕"}.mdi-thumbs-up-down-outline:before{content:"󱤔"}.mdi-ticket:before{content:"󰔖"}.mdi-ticket-account:before{content:"󰔗"}.mdi-ticket-confirmation:before{content:"󰔘"}.mdi-ticket-confirmation-outline:before{content:"󱎪"}.mdi-ticket-outline:before{content:"󰤓"}.mdi-ticket-percent:before{content:"󰜤"}.mdi-ticket-percent-outline:before{content:"󱐫"}.mdi-tie:before{content:"󰔙"}.mdi-tilde:before{content:"󰜥"}.mdi-tilde-off:before{content:"󱣳"}.mdi-timelapse:before{content:"󰔚"}.mdi-timeline:before{content:"󰯑"}.mdi-timeline-alert:before{content:"󰾕"}.mdi-timeline-alert-outline:before{content:"󰾘"}.mdi-timeline-check:before{content:"󱔲"}.mdi-timeline-check-outline:before{content:"󱔳"}.mdi-timeline-clock:before{content:"󱇻"}.mdi-timeline-clock-outline:before{content:"󱇼"}.mdi-timeline-minus:before{content:"󱔴"}.mdi-timeline-minus-outline:before{content:"󱔵"}.mdi-timeline-outline:before{content:"󰯒"}.mdi-timeline-plus:before{content:"󰾖"}.mdi-timeline-plus-outline:before{content:"󰾗"}.mdi-timeline-question:before{content:"󰾙"}.mdi-timeline-question-outline:before{content:"󰾚"}.mdi-timeline-remove:before{content:"󱔶"}.mdi-timeline-remove-outline:before{content:"󱔷"}.mdi-timeline-text:before{content:"󰯓"}.mdi-timeline-text-outline:before{content:"󰯔"}.mdi-timer:before{content:"󱎫"}.mdi-timer-10:before{content:"󰔜"}.mdi-timer-3:before{content:"󰔝"}.mdi-timer-alert:before{content:"󱫌"}.mdi-timer-alert-outline:before{content:"󱫍"}.mdi-timer-cancel:before{content:"󱫎"}.mdi-timer-cancel-outline:before{content:"󱫏"}.mdi-timer-check:before{content:"󱫐"}.mdi-timer-check-outline:before{content:"󱫑"}.mdi-timer-cog:before{content:"󱤥"}.mdi-timer-cog-outline:before{content:"󱤦"}.mdi-timer-edit:before{content:"󱫒"}.mdi-timer-edit-outline:before{content:"󱫓"}.mdi-timer-lock:before{content:"󱫔"}.mdi-timer-lock-open:before{content:"󱫕"}.mdi-timer-lock-open-outline:before{content:"󱫖"}.mdi-timer-lock-outline:before{content:"󱫗"}.mdi-timer-marker:before{content:"󱫘"}.mdi-timer-marker-outline:before{content:"󱫙"}.mdi-timer-minus:before{content:"󱫚"}.mdi-timer-minus-outline:before{content:"󱫛"}.mdi-timer-music:before{content:"󱫜"}.mdi-timer-music-outline:before{content:"󱫝"}.mdi-timer-off:before{content:"󱎬"}.mdi-timer-off-outline:before{content:"󰔞"}.mdi-timer-outline:before{content:"󰔛"}.mdi-timer-pause:before{content:"󱫞"}.mdi-timer-pause-outline:before{content:"󱫟"}.mdi-timer-play:before{content:"󱫠"}.mdi-timer-play-outline:before{content:"󱫡"}.mdi-timer-plus:before{content:"󱫢"}.mdi-timer-plus-outline:before{content:"󱫣"}.mdi-timer-refresh:before{content:"󱫤"}.mdi-timer-refresh-outline:before{content:"󱫥"}.mdi-timer-remove:before{content:"󱫦"}.mdi-timer-remove-outline:before{content:"󱫧"}.mdi-timer-sand:before{content:"󰔟"}.mdi-timer-sand-complete:before{content:"󱦟"}.mdi-timer-sand-empty:before{content:"󰚭"}.mdi-timer-sand-full:before{content:"󰞌"}.mdi-timer-sand-paused:before{content:"󱦠"}.mdi-timer-settings:before{content:"󱤣"}.mdi-timer-settings-outline:before{content:"󱤤"}.mdi-timer-star:before{content:"󱫨"}.mdi-timer-star-outline:before{content:"󱫩"}.mdi-timer-stop:before{content:"󱫪"}.mdi-timer-stop-outline:before{content:"󱫫"}.mdi-timer-sync:before{content:"󱫬"}.mdi-timer-sync-outline:before{content:"󱫭"}.mdi-timetable:before{content:"󰔠"}.mdi-tire:before{content:"󱢖"}.mdi-toaster:before{content:"󱁣"}.mdi-toaster-off:before{content:"󱆷"}.mdi-toaster-oven:before{content:"󰳓"}.mdi-toggle-switch:before{content:"󰔡"}.mdi-toggle-switch-off:before{content:"󰔢"}.mdi-toggle-switch-off-outline:before{content:"󰨙"}.mdi-toggle-switch-outline:before{content:"󰨚"}.mdi-toggle-switch-variant:before{content:"󱨥"}.mdi-toggle-switch-variant-off:before{content:"󱨦"}.mdi-toilet:before{content:"󰦫"}.mdi-toolbox:before{content:"󰦬"}.mdi-toolbox-outline:before{content:"󰦭"}.mdi-tools:before{content:"󱁤"}.mdi-tooltip:before{content:"󰔣"}.mdi-tooltip-account:before{content:"󰀌"}.mdi-tooltip-cellphone:before{content:"󱠻"}.mdi-tooltip-check:before{content:"󱕜"}.mdi-tooltip-check-outline:before{content:"󱕝"}.mdi-tooltip-edit:before{content:"󰔤"}.mdi-tooltip-edit-outline:before{content:"󱋅"}.mdi-tooltip-image:before{content:"󰔥"}.mdi-tooltip-image-outline:before{content:"󰯕"}.mdi-tooltip-minus:before{content:"󱕞"}.mdi-tooltip-minus-outline:before{content:"󱕟"}.mdi-tooltip-outline:before{content:"󰔦"}.mdi-tooltip-plus:before{content:"󰯖"}.mdi-tooltip-plus-outline:before{content:"󰔧"}.mdi-tooltip-question:before{content:"󱮺"}.mdi-tooltip-question-outline:before{content:"󱮻"}.mdi-tooltip-remove:before{content:"󱕠"}.mdi-tooltip-remove-outline:before{content:"󱕡"}.mdi-tooltip-text:before{content:"󰔨"}.mdi-tooltip-text-outline:before{content:"󰯗"}.mdi-tooth:before{content:"󰣃"}.mdi-tooth-outline:before{content:"󰔩"}.mdi-toothbrush:before{content:"󱄩"}.mdi-toothbrush-electric:before{content:"󱄬"}.mdi-toothbrush-paste:before{content:"󱄪"}.mdi-torch:before{content:"󱘆"}.mdi-tortoise:before{content:"󰴻"}.mdi-toslink:before{content:"󱊸"}.mdi-touch-text-outline:before{content:"󱱠"}.mdi-tournament:before{content:"󰦮"}.mdi-tow-truck:before{content:"󰠼"}.mdi-tower-beach:before{content:"󰚁"}.mdi-tower-fire:before{content:"󰚂"}.mdi-town-hall:before{content:"󱡵"}.mdi-toy-brick:before{content:"󱊈"}.mdi-toy-brick-marker:before{content:"󱊉"}.mdi-toy-brick-marker-outline:before{content:"󱊊"}.mdi-toy-brick-minus:before{content:"󱊋"}.mdi-toy-brick-minus-outline:before{content:"󱊌"}.mdi-toy-brick-outline:before{content:"󱊍"}.mdi-toy-brick-plus:before{content:"󱊎"}.mdi-toy-brick-plus-outline:before{content:"󱊏"}.mdi-toy-brick-remove:before{content:"󱊐"}.mdi-toy-brick-remove-outline:before{content:"󱊑"}.mdi-toy-brick-search:before{content:"󱊒"}.mdi-toy-brick-search-outline:before{content:"󱊓"}.mdi-track-light:before{content:"󰤔"}.mdi-track-light-off:before{content:"󱬁"}.mdi-trackpad:before{content:"󰟸"}.mdi-trackpad-lock:before{content:"󰤳"}.mdi-tractor:before{content:"󰢒"}.mdi-tractor-variant:before{content:"󱓄"}.mdi-trademark:before{content:"󰩸"}.mdi-traffic-cone:before{content:"󱍼"}.mdi-traffic-light:before{content:"󰔫"}.mdi-traffic-light-outline:before{content:"󱠪"}.mdi-train:before{content:"󰔬"}.mdi-train-car:before{content:"󰯘"}.mdi-train-car-autorack:before{content:"󱬭"}.mdi-train-car-box:before{content:"󱬮"}.mdi-train-car-box-full:before{content:"󱬯"}.mdi-train-car-box-open:before{content:"󱬰"}.mdi-train-car-caboose:before{content:"󱬱"}.mdi-train-car-centerbeam:before{content:"󱬲"}.mdi-train-car-centerbeam-full:before{content:"󱬳"}.mdi-train-car-container:before{content:"󱬴"}.mdi-train-car-flatbed:before{content:"󱬵"}.mdi-train-car-flatbed-car:before{content:"󱬶"}.mdi-train-car-flatbed-tank:before{content:"󱬷"}.mdi-train-car-gondola:before{content:"󱬸"}.mdi-train-car-gondola-full:before{content:"󱬹"}.mdi-train-car-hopper:before{content:"󱬺"}.mdi-train-car-hopper-covered:before{content:"󱬻"}.mdi-train-car-hopper-full:before{content:"󱬼"}.mdi-train-car-intermodal:before{content:"󱬽"}.mdi-train-car-passenger:before{content:"󱜳"}.mdi-train-car-passenger-door:before{content:"󱜴"}.mdi-train-car-passenger-door-open:before{content:"󱜵"}.mdi-train-car-passenger-variant:before{content:"󱜶"}.mdi-train-car-tank:before{content:"󱬾"}.mdi-train-variant:before{content:"󰣄"}.mdi-tram:before{content:"󰔭"}.mdi-tram-side:before{content:"󰿧"}.mdi-transcribe:before{content:"󰔮"}.mdi-transcribe-close:before{content:"󰔯"}.mdi-transfer:before{content:"󱁥"}.mdi-transfer-down:before{content:"󰶡"}.mdi-transfer-left:before{content:"󰶢"}.mdi-transfer-right:before{content:"󰔰"}.mdi-transfer-up:before{content:"󰶣"}.mdi-transit-connection:before{content:"󰴼"}.mdi-transit-connection-horizontal:before{content:"󱕆"}.mdi-transit-connection-variant:before{content:"󰴽"}.mdi-transit-detour:before{content:"󰾋"}.mdi-transit-skip:before{content:"󱔕"}.mdi-transit-transfer:before{content:"󰚮"}.mdi-transition:before{content:"󰤕"}.mdi-transition-masked:before{content:"󰤖"}.mdi-translate:before{content:"󰗊"}.mdi-translate-off:before{content:"󰸆"}.mdi-translate-variant:before{content:"󱮙"}.mdi-transmission-tower:before{content:"󰴾"}.mdi-transmission-tower-export:before{content:"󱤬"}.mdi-transmission-tower-import:before{content:"󱤭"}.mdi-transmission-tower-off:before{content:"󱧝"}.mdi-trash-can:before{content:"󰩹"}.mdi-trash-can-outline:before{content:"󰩺"}.mdi-tray:before{content:"󱊔"}.mdi-tray-alert:before{content:"󱊕"}.mdi-tray-arrow-down:before{content:"󰄠"}.mdi-tray-arrow-up:before{content:"󰄝"}.mdi-tray-full:before{content:"󱊖"}.mdi-tray-minus:before{content:"󱊗"}.mdi-tray-plus:before{content:"󱊘"}.mdi-tray-remove:before{content:"󱊙"}.mdi-treasure-chest:before{content:"󰜦"}.mdi-treasure-chest-outline:before{content:"󱱷"}.mdi-tree:before{content:"󰔱"}.mdi-tree-outline:before{content:"󰹩"}.mdi-trello:before{content:"󰔲"}.mdi-trending-down:before{content:"󰔳"}.mdi-trending-neutral:before{content:"󰔴"}.mdi-trending-up:before{content:"󰔵"}.mdi-triangle:before{content:"󰔶"}.mdi-triangle-down:before{content:"󱱖"}.mdi-triangle-down-outline:before{content:"󱱗"}.mdi-triangle-outline:before{content:"󰔷"}.mdi-triangle-small-down:before{content:"󱨉"}.mdi-triangle-small-up:before{content:"󱨊"}.mdi-triangle-wave:before{content:"󱑼"}.mdi-triforce:before{content:"󰯙"}.mdi-trophy:before{content:"󰔸"}.mdi-trophy-award:before{content:"󰔹"}.mdi-trophy-broken:before{content:"󰶤"}.mdi-trophy-outline:before{content:"󰔺"}.mdi-trophy-variant:before{content:"󰔻"}.mdi-trophy-variant-outline:before{content:"󰔼"}.mdi-truck:before{content:"󰔽"}.mdi-truck-alert:before{content:"󱧞"}.mdi-truck-alert-outline:before{content:"󱧟"}.mdi-truck-cargo-container:before{content:"󱣘"}.mdi-truck-check:before{content:"󰳔"}.mdi-truck-check-outline:before{content:"󱊚"}.mdi-truck-delivery:before{content:"󰔾"}.mdi-truck-delivery-outline:before{content:"󱊛"}.mdi-truck-fast:before{content:"󰞈"}.mdi-truck-fast-outline:before{content:"󱊜"}.mdi-truck-flatbed:before{content:"󱢑"}.mdi-truck-minus:before{content:"󱦮"}.mdi-truck-minus-outline:before{content:"󱦽"}.mdi-truck-outline:before{content:"󱊝"}.mdi-truck-plus:before{content:"󱦭"}.mdi-truck-plus-outline:before{content:"󱦼"}.mdi-truck-remove:before{content:"󱦯"}.mdi-truck-remove-outline:before{content:"󱦾"}.mdi-truck-snowflake:before{content:"󱦦"}.mdi-truck-trailer:before{content:"󰜧"}.mdi-trumpet:before{content:"󱂖"}.mdi-tshirt-crew:before{content:"󰩻"}.mdi-tshirt-crew-outline:before{content:"󰔿"}.mdi-tshirt-v:before{content:"󰩼"}.mdi-tshirt-v-outline:before{content:"󰕀"}.mdi-tsunami:before{content:"󱪁"}.mdi-tumble-dryer:before{content:"󰤗"}.mdi-tumble-dryer-alert:before{content:"󱆺"}.mdi-tumble-dryer-off:before{content:"󱆻"}.mdi-tune:before{content:"󰘮"}.mdi-tune-variant:before{content:"󱕂"}.mdi-tune-vertical:before{content:"󰙪"}.mdi-tune-vertical-variant:before{content:"󱕃"}.mdi-tunnel:before{content:"󱠽"}.mdi-tunnel-outline:before{content:"󱠾"}.mdi-turbine:before{content:"󱪂"}.mdi-turkey:before{content:"󱜛"}.mdi-turnstile:before{content:"󰳕"}.mdi-turnstile-outline:before{content:"󰳖"}.mdi-turtle:before{content:"󰳗"}.mdi-twitch:before{content:"󰕃"}.mdi-twitter:before{content:"󰕄"}.mdi-two-factor-authentication:before{content:"󰦯"}.mdi-typewriter:before{content:"󰼭"}.mdi-ubisoft:before{content:"󰯚"}.mdi-ubuntu:before{content:"󰕈"}.mdi-ufo:before{content:"󱃄"}.mdi-ufo-outline:before{content:"󱃅"}.mdi-ultra-high-definition:before{content:"󰟹"}.mdi-umbraco:before{content:"󰕉"}.mdi-umbrella:before{content:"󰕊"}.mdi-umbrella-beach:before{content:"󱢊"}.mdi-umbrella-beach-outline:before{content:"󱢋"}.mdi-umbrella-closed:before{content:"󰦰"}.mdi-umbrella-closed-outline:before{content:"󱏢"}.mdi-umbrella-closed-variant:before{content:"󱏡"}.mdi-umbrella-outline:before{content:"󰕋"}.mdi-undo:before{content:"󰕌"}.mdi-undo-variant:before{content:"󰕍"}.mdi-unfold-less-horizontal:before{content:"󰕎"}.mdi-unfold-less-vertical:before{content:"󰝠"}.mdi-unfold-more-horizontal:before{content:"󰕏"}.mdi-unfold-more-vertical:before{content:"󰝡"}.mdi-ungroup:before{content:"󰕐"}.mdi-unicode:before{content:"󰻐"}.mdi-unicorn:before{content:"󱗂"}.mdi-unicorn-variant:before{content:"󱗃"}.mdi-unicycle:before{content:"󱗥"}.mdi-unity:before{content:"󰚯"}.mdi-unreal:before{content:"󰦱"}.mdi-update:before{content:"󰚰"}.mdi-upload:before{content:"󰕒"}.mdi-upload-lock:before{content:"󱍳"}.mdi-upload-lock-outline:before{content:"󱍴"}.mdi-upload-multiple:before{content:"󰠽"}.mdi-upload-network:before{content:"󰛶"}.mdi-upload-network-outline:before{content:"󰳘"}.mdi-upload-off:before{content:"󱃆"}.mdi-upload-off-outline:before{content:"󱃇"}.mdi-upload-outline:before{content:"󰸇"}.mdi-usb:before{content:"󰕓"}.mdi-usb-flash-drive:before{content:"󱊞"}.mdi-usb-flash-drive-outline:before{content:"󱊟"}.mdi-usb-port:before{content:"󱇰"}.mdi-vacuum:before{content:"󱦡"}.mdi-vacuum-outline:before{content:"󱦢"}.mdi-valve:before{content:"󱁦"}.mdi-valve-closed:before{content:"󱁧"}.mdi-valve-open:before{content:"󱁨"}.mdi-van-passenger:before{content:"󰟺"}.mdi-van-utility:before{content:"󰟻"}.mdi-vanish:before{content:"󰟼"}.mdi-vanish-quarter:before{content:"󱕔"}.mdi-vanity-light:before{content:"󱇡"}.mdi-variable:before{content:"󰫧"}.mdi-variable-box:before{content:"󱄑"}.mdi-vector-arrange-above:before{content:"󰕔"}.mdi-vector-arrange-below:before{content:"󰕕"}.mdi-vector-bezier:before{content:"󰫨"}.mdi-vector-circle:before{content:"󰕖"}.mdi-vector-circle-variant:before{content:"󰕗"}.mdi-vector-combine:before{content:"󰕘"}.mdi-vector-curve:before{content:"󰕙"}.mdi-vector-difference:before{content:"󰕚"}.mdi-vector-difference-ab:before{content:"󰕛"}.mdi-vector-difference-ba:before{content:"󰕜"}.mdi-vector-ellipse:before{content:"󰢓"}.mdi-vector-intersection:before{content:"󰕝"}.mdi-vector-line:before{content:"󰕞"}.mdi-vector-link:before{content:"󰿨"}.mdi-vector-point:before{content:"󰇄"}.mdi-vector-point-edit:before{content:"󰧨"}.mdi-vector-point-minus:before{content:"󱭸"}.mdi-vector-point-plus:before{content:"󱭹"}.mdi-vector-point-select:before{content:"󰕟"}.mdi-vector-polygon:before{content:"󰕠"}.mdi-vector-polygon-variant:before{content:"󱡖"}.mdi-vector-polyline:before{content:"󰕡"}.mdi-vector-polyline-edit:before{content:"󱈥"}.mdi-vector-polyline-minus:before{content:"󱈦"}.mdi-vector-polyline-plus:before{content:"󱈧"}.mdi-vector-polyline-remove:before{content:"󱈨"}.mdi-vector-radius:before{content:"󰝊"}.mdi-vector-rectangle:before{content:"󰗆"}.mdi-vector-selection:before{content:"󰕢"}.mdi-vector-square:before{content:"󰀁"}.mdi-vector-square-close:before{content:"󱡗"}.mdi-vector-square-edit:before{content:"󱣙"}.mdi-vector-square-minus:before{content:"󱣚"}.mdi-vector-square-open:before{content:"󱡘"}.mdi-vector-square-plus:before{content:"󱣛"}.mdi-vector-square-remove:before{content:"󱣜"}.mdi-vector-triangle:before{content:"󰕣"}.mdi-vector-union:before{content:"󰕤"}.mdi-vhs:before{content:"󰨛"}.mdi-vibrate:before{content:"󰕦"}.mdi-vibrate-off:before{content:"󰳙"}.mdi-video:before{content:"󰕧"}.mdi-video-2d:before{content:"󱨜"}.mdi-video-3d:before{content:"󰟽"}.mdi-video-3d-off:before{content:"󱏙"}.mdi-video-3d-variant:before{content:"󰻑"}.mdi-video-4k-box:before{content:"󰠾"}.mdi-video-account:before{content:"󰤙"}.mdi-video-box:before{content:"󰃽"}.mdi-video-box-off:before{content:"󰃾"}.mdi-video-check:before{content:"󱁩"}.mdi-video-check-outline:before{content:"󱁪"}.mdi-video-high-definition:before{content:"󱔮"}.mdi-video-image:before{content:"󰤚"}.mdi-video-input-antenna:before{content:"󰠿"}.mdi-video-input-component:before{content:"󰡀"}.mdi-video-input-hdmi:before{content:"󰡁"}.mdi-video-input-scart:before{content:"󰾌"}.mdi-video-input-svideo:before{content:"󰡂"}.mdi-video-marker:before{content:"󱦩"}.mdi-video-marker-outline:before{content:"󱦪"}.mdi-video-minus:before{content:"󰦲"}.mdi-video-minus-outline:before{content:"󰊺"}.mdi-video-off:before{content:"󰕨"}.mdi-video-off-outline:before{content:"󰯛"}.mdi-video-outline:before{content:"󰯜"}.mdi-video-plus:before{content:"󰦳"}.mdi-video-plus-outline:before{content:"󰇓"}.mdi-video-stabilization:before{content:"󰤛"}.mdi-video-switch:before{content:"󰕩"}.mdi-video-switch-outline:before{content:"󰞐"}.mdi-video-vintage:before{content:"󰨜"}.mdi-video-wireless:before{content:"󰻒"}.mdi-video-wireless-outline:before{content:"󰻓"}.mdi-view-agenda:before{content:"󰕪"}.mdi-view-agenda-outline:before{content:"󱇘"}.mdi-view-array:before{content:"󰕫"}.mdi-view-array-outline:before{content:"󱒅"}.mdi-view-carousel:before{content:"󰕬"}.mdi-view-carousel-outline:before{content:"󱒆"}.mdi-view-column:before{content:"󰕭"}.mdi-view-column-outline:before{content:"󱒇"}.mdi-view-comfy:before{content:"󰹪"}.mdi-view-comfy-outline:before{content:"󱒈"}.mdi-view-compact:before{content:"󰹫"}.mdi-view-compact-outline:before{content:"󰹬"}.mdi-view-dashboard:before{content:"󰕮"}.mdi-view-dashboard-edit:before{content:"󱥇"}.mdi-view-dashboard-edit-outline:before{content:"󱥈"}.mdi-view-dashboard-outline:before{content:"󰨝"}.mdi-view-dashboard-variant:before{content:"󰡃"}.mdi-view-dashboard-variant-outline:before{content:"󱒉"}.mdi-view-day:before{content:"󰕯"}.mdi-view-day-outline:before{content:"󱒊"}.mdi-view-gallery:before{content:"󱢈"}.mdi-view-gallery-outline:before{content:"󱢉"}.mdi-view-grid:before{content:"󰕰"}.mdi-view-grid-compact:before{content:"󱱡"}.mdi-view-grid-outline:before{content:"󱇙"}.mdi-view-grid-plus:before{content:"󰾍"}.mdi-view-grid-plus-outline:before{content:"󱇚"}.mdi-view-headline:before{content:"󰕱"}.mdi-view-list:before{content:"󰕲"}.mdi-view-list-outline:before{content:"󱒋"}.mdi-view-module:before{content:"󰕳"}.mdi-view-module-outline:before{content:"󱒌"}.mdi-view-parallel:before{content:"󰜨"}.mdi-view-parallel-outline:before{content:"󱒍"}.mdi-view-quilt:before{content:"󰕴"}.mdi-view-quilt-outline:before{content:"󱒎"}.mdi-view-sequential:before{content:"󰜩"}.mdi-view-sequential-outline:before{content:"󱒏"}.mdi-view-split-horizontal:before{content:"󰯋"}.mdi-view-split-vertical:before{content:"󰯌"}.mdi-view-stream:before{content:"󰕵"}.mdi-view-stream-outline:before{content:"󱒐"}.mdi-view-week:before{content:"󰕶"}.mdi-view-week-outline:before{content:"󱒑"}.mdi-vimeo:before{content:"󰕷"}.mdi-violin:before{content:"󰘏"}.mdi-virtual-reality:before{content:"󰢔"}.mdi-virus:before{content:"󱎶"}.mdi-virus-off:before{content:"󱣡"}.mdi-virus-off-outline:before{content:"󱣢"}.mdi-virus-outline:before{content:"󱎷"}.mdi-vlc:before{content:"󰕼"}.mdi-voicemail:before{content:"󰕽"}.mdi-volcano:before{content:"󱪃"}.mdi-volcano-outline:before{content:"󱪄"}.mdi-volleyball:before{content:"󰦴"}.mdi-volume-equal:before{content:"󱬐"}.mdi-volume-high:before{content:"󰕾"}.mdi-volume-low:before{content:"󰕿"}.mdi-volume-medium:before{content:"󰖀"}.mdi-volume-minus:before{content:"󰝞"}.mdi-volume-mute:before{content:"󰝟"}.mdi-volume-off:before{content:"󰖁"}.mdi-volume-plus:before{content:"󰝝"}.mdi-volume-source:before{content:"󱄠"}.mdi-volume-variant-off:before{content:"󰸈"}.mdi-volume-vibrate:before{content:"󱄡"}.mdi-vote:before{content:"󰨟"}.mdi-vote-outline:before{content:"󰨠"}.mdi-vpn:before{content:"󰖂"}.mdi-vuejs:before{content:"󰡄"}.mdi-vuetify:before{content:"󰹭"}.mdi-walk:before{content:"󰖃"}.mdi-wall:before{content:"󰟾"}.mdi-wall-fire:before{content:"󱨑"}.mdi-wall-sconce:before{content:"󰤜"}.mdi-wall-sconce-flat:before{content:"󰤝"}.mdi-wall-sconce-flat-outline:before{content:"󱟉"}.mdi-wall-sconce-flat-variant:before{content:"󰐜"}.mdi-wall-sconce-flat-variant-outline:before{content:"󱟊"}.mdi-wall-sconce-outline:before{content:"󱟋"}.mdi-wall-sconce-round:before{content:"󰝈"}.mdi-wall-sconce-round-outline:before{content:"󱟌"}.mdi-wall-sconce-round-variant:before{content:"󰤞"}.mdi-wall-sconce-round-variant-outline:before{content:"󱟍"}.mdi-wallet:before{content:"󰖄"}.mdi-wallet-bifold:before{content:"󱱘"}.mdi-wallet-bifold-outline:before{content:"󱱙"}.mdi-wallet-giftcard:before{content:"󰖅"}.mdi-wallet-membership:before{content:"󰖆"}.mdi-wallet-outline:before{content:"󰯝"}.mdi-wallet-plus:before{content:"󰾎"}.mdi-wallet-plus-outline:before{content:"󰾏"}.mdi-wallet-travel:before{content:"󰖇"}.mdi-wallpaper:before{content:"󰸉"}.mdi-wan:before{content:"󰖈"}.mdi-wardrobe:before{content:"󰾐"}.mdi-wardrobe-outline:before{content:"󰾑"}.mdi-warehouse:before{content:"󰾁"}.mdi-washing-machine:before{content:"󰜪"}.mdi-washing-machine-alert:before{content:"󱆼"}.mdi-washing-machine-off:before{content:"󱆽"}.mdi-watch:before{content:"󰖉"}.mdi-watch-export:before{content:"󰖊"}.mdi-watch-export-variant:before{content:"󰢕"}.mdi-watch-import:before{content:"󰖋"}.mdi-watch-import-variant:before{content:"󰢖"}.mdi-watch-variant:before{content:"󰢗"}.mdi-watch-vibrate:before{content:"󰚱"}.mdi-watch-vibrate-off:before{content:"󰳚"}.mdi-water:before{content:"󰖌"}.mdi-water-alert:before{content:"󱔂"}.mdi-water-alert-outline:before{content:"󱔃"}.mdi-water-boiler:before{content:"󰾒"}.mdi-water-boiler-alert:before{content:"󱆳"}.mdi-water-boiler-auto:before{content:"󱮘"}.mdi-water-boiler-off:before{content:"󱆴"}.mdi-water-check:before{content:"󱔄"}.mdi-water-check-outline:before{content:"󱔅"}.mdi-water-circle:before{content:"󱠆"}.mdi-water-minus:before{content:"󱔆"}.mdi-water-minus-outline:before{content:"󱔇"}.mdi-water-off:before{content:"󰖍"}.mdi-water-off-outline:before{content:"󱔈"}.mdi-water-opacity:before{content:"󱡕"}.mdi-water-outline:before{content:"󰸊"}.mdi-water-percent:before{content:"󰖎"}.mdi-water-percent-alert:before{content:"󱔉"}.mdi-water-plus:before{content:"󱔊"}.mdi-water-plus-outline:before{content:"󱔋"}.mdi-water-polo:before{content:"󱊠"}.mdi-water-pump:before{content:"󰖏"}.mdi-water-pump-off:before{content:"󰾓"}.mdi-water-remove:before{content:"󱔌"}.mdi-water-remove-outline:before{content:"󱔍"}.mdi-water-sync:before{content:"󱟆"}.mdi-water-thermometer:before{content:"󱪅"}.mdi-water-thermometer-outline:before{content:"󱪆"}.mdi-water-well:before{content:"󱁫"}.mdi-water-well-outline:before{content:"󱁬"}.mdi-waterfall:before{content:"󱡉"}.mdi-watering-can:before{content:"󱒁"}.mdi-watering-can-outline:before{content:"󱒂"}.mdi-watermark:before{content:"󰘒"}.mdi-wave:before{content:"󰼮"}.mdi-waveform:before{content:"󱑽"}.mdi-waves:before{content:"󰞍"}.mdi-waves-arrow-left:before{content:"󱡙"}.mdi-waves-arrow-right:before{content:"󱡚"}.mdi-waves-arrow-up:before{content:"󱡛"}.mdi-waze:before{content:"󰯞"}.mdi-weather-cloudy:before{content:"󰖐"}.mdi-weather-cloudy-alert:before{content:"󰼯"}.mdi-weather-cloudy-arrow-right:before{content:"󰹮"}.mdi-weather-cloudy-clock:before{content:"󱣶"}.mdi-weather-dust:before{content:"󱭚"}.mdi-weather-fog:before{content:"󰖑"}.mdi-weather-hail:before{content:"󰖒"}.mdi-weather-hazy:before{content:"󰼰"}.mdi-weather-hurricane:before{content:"󰢘"}.mdi-weather-hurricane-outline:before{content:"󱱸"}.mdi-weather-lightning:before{content:"󰖓"}.mdi-weather-lightning-rainy:before{content:"󰙾"}.mdi-weather-night:before{content:"󰖔"}.mdi-weather-night-partly-cloudy:before{content:"󰼱"}.mdi-weather-partly-cloudy:before{content:"󰖕"}.mdi-weather-partly-lightning:before{content:"󰼲"}.mdi-weather-partly-rainy:before{content:"󰼳"}.mdi-weather-partly-snowy:before{content:"󰼴"}.mdi-weather-partly-snowy-rainy:before{content:"󰼵"}.mdi-weather-pouring:before{content:"󰖖"}.mdi-weather-rainy:before{content:"󰖗"}.mdi-weather-snowy:before{content:"󰖘"}.mdi-weather-snowy-heavy:before{content:"󰼶"}.mdi-weather-snowy-rainy:before{content:"󰙿"}.mdi-weather-sunny:before{content:"󰖙"}.mdi-weather-sunny-alert:before{content:"󰼷"}.mdi-weather-sunny-off:before{content:"󱓤"}.mdi-weather-sunset:before{content:"󰖚"}.mdi-weather-sunset-down:before{content:"󰖛"}.mdi-weather-sunset-up:before{content:"󰖜"}.mdi-weather-tornado:before{content:"󰼸"}.mdi-weather-windy:before{content:"󰖝"}.mdi-weather-windy-variant:before{content:"󰖞"}.mdi-web:before{content:"󰖟"}.mdi-web-box:before{content:"󰾔"}.mdi-web-cancel:before{content:"󱞐"}.mdi-web-check:before{content:"󰞉"}.mdi-web-clock:before{content:"󱉊"}.mdi-web-minus:before{content:"󱂠"}.mdi-web-off:before{content:"󰪎"}.mdi-web-plus:before{content:"󰀳"}.mdi-web-refresh:before{content:"󱞑"}.mdi-web-remove:before{content:"󰕑"}.mdi-web-sync:before{content:"󱞒"}.mdi-webcam:before{content:"󰖠"}.mdi-webcam-off:before{content:"󱜷"}.mdi-webhook:before{content:"󰘯"}.mdi-webpack:before{content:"󰜫"}.mdi-webrtc:before{content:"󱉈"}.mdi-wechat:before{content:"󰘑"}.mdi-weight:before{content:"󰖡"}.mdi-weight-gram:before{content:"󰴿"}.mdi-weight-kilogram:before{content:"󰖢"}.mdi-weight-lifter:before{content:"󱅝"}.mdi-weight-pound:before{content:"󰦵"}.mdi-whatsapp:before{content:"󰖣"}.mdi-wheel-barrow:before{content:"󱓲"}.mdi-wheelchair:before{content:"󱪇"}.mdi-wheelchair-accessibility:before{content:"󰖤"}.mdi-whistle:before{content:"󰦶"}.mdi-whistle-outline:before{content:"󱊼"}.mdi-white-balance-auto:before{content:"󰖥"}.mdi-white-balance-incandescent:before{content:"󰖦"}.mdi-white-balance-iridescent:before{content:"󰖧"}.mdi-white-balance-sunny:before{content:"󰖨"}.mdi-widgets:before{content:"󰜬"}.mdi-widgets-outline:before{content:"󱍕"}.mdi-wifi:before{content:"󰖩"}.mdi-wifi-alert:before{content:"󱚵"}.mdi-wifi-arrow-down:before{content:"󱚶"}.mdi-wifi-arrow-left:before{content:"󱚷"}.mdi-wifi-arrow-left-right:before{content:"󱚸"}.mdi-wifi-arrow-right:before{content:"󱚹"}.mdi-wifi-arrow-up:before{content:"󱚺"}.mdi-wifi-arrow-up-down:before{content:"󱚻"}.mdi-wifi-cancel:before{content:"󱚼"}.mdi-wifi-check:before{content:"󱚽"}.mdi-wifi-cog:before{content:"󱚾"}.mdi-wifi-lock:before{content:"󱚿"}.mdi-wifi-lock-open:before{content:"󱛀"}.mdi-wifi-marker:before{content:"󱛁"}.mdi-wifi-minus:before{content:"󱛂"}.mdi-wifi-off:before{content:"󰖪"}.mdi-wifi-plus:before{content:"󱛃"}.mdi-wifi-refresh:before{content:"󱛄"}.mdi-wifi-remove:before{content:"󱛅"}.mdi-wifi-settings:before{content:"󱛆"}.mdi-wifi-star:before{content:"󰸋"}.mdi-wifi-strength-1:before{content:"󰤟"}.mdi-wifi-strength-1-alert:before{content:"󰤠"}.mdi-wifi-strength-1-lock:before{content:"󰤡"}.mdi-wifi-strength-1-lock-open:before{content:"󱛋"}.mdi-wifi-strength-2:before{content:"󰤢"}.mdi-wifi-strength-2-alert:before{content:"󰤣"}.mdi-wifi-strength-2-lock:before{content:"󰤤"}.mdi-wifi-strength-2-lock-open:before{content:"󱛌"}.mdi-wifi-strength-3:before{content:"󰤥"}.mdi-wifi-strength-3-alert:before{content:"󰤦"}.mdi-wifi-strength-3-lock:before{content:"󰤧"}.mdi-wifi-strength-3-lock-open:before{content:"󱛍"}.mdi-wifi-strength-4:before{content:"󰤨"}.mdi-wifi-strength-4-alert:before{content:"󰤩"}.mdi-wifi-strength-4-lock:before{content:"󰤪"}.mdi-wifi-strength-4-lock-open:before{content:"󱛎"}.mdi-wifi-strength-alert-outline:before{content:"󰤫"}.mdi-wifi-strength-lock-open-outline:before{content:"󱛏"}.mdi-wifi-strength-lock-outline:before{content:"󰤬"}.mdi-wifi-strength-off:before{content:"󰤭"}.mdi-wifi-strength-off-outline:before{content:"󰤮"}.mdi-wifi-strength-outline:before{content:"󰤯"}.mdi-wifi-sync:before{content:"󱛇"}.mdi-wikipedia:before{content:"󰖬"}.mdi-wind-power:before{content:"󱪈"}.mdi-wind-power-outline:before{content:"󱪉"}.mdi-wind-turbine:before{content:"󰶥"}.mdi-wind-turbine-alert:before{content:"󱦫"}.mdi-wind-turbine-check:before{content:"󱦬"}.mdi-window-close:before{content:"󰖭"}.mdi-window-closed:before{content:"󰖮"}.mdi-window-closed-variant:before{content:"󱇛"}.mdi-window-maximize:before{content:"󰖯"}.mdi-window-minimize:before{content:"󰖰"}.mdi-window-open:before{content:"󰖱"}.mdi-window-open-variant:before{content:"󱇜"}.mdi-window-restore:before{content:"󰖲"}.mdi-window-shutter:before{content:"󱄜"}.mdi-window-shutter-alert:before{content:"󱄝"}.mdi-window-shutter-auto:before{content:"󱮣"}.mdi-window-shutter-cog:before{content:"󱪊"}.mdi-window-shutter-open:before{content:"󱄞"}.mdi-window-shutter-settings:before{content:"󱪋"}.mdi-windsock:before{content:"󱗺"}.mdi-wiper:before{content:"󰫩"}.mdi-wiper-wash:before{content:"󰶦"}.mdi-wiper-wash-alert:before{content:"󱣟"}.mdi-wizard-hat:before{content:"󱑷"}.mdi-wordpress:before{content:"󰖴"}.mdi-wrap:before{content:"󰖶"}.mdi-wrap-disabled:before{content:"󰯟"}.mdi-wrench:before{content:"󰖷"}.mdi-wrench-check:before{content:"󱮏"}.mdi-wrench-check-outline:before{content:"󱮐"}.mdi-wrench-clock:before{content:"󱦣"}.mdi-wrench-clock-outline:before{content:"󱮓"}.mdi-wrench-cog:before{content:"󱮑"}.mdi-wrench-cog-outline:before{content:"󱮒"}.mdi-wrench-outline:before{content:"󰯠"}.mdi-xamarin:before{content:"󰡅"}.mdi-xml:before{content:"󰗀"}.mdi-xmpp:before{content:"󰟿"}.mdi-yahoo:before{content:"󰭏"}.mdi-yeast:before{content:"󰗁"}.mdi-yin-yang:before{content:"󰚀"}.mdi-yoga:before{content:"󱅼"}.mdi-youtube:before{content:"󰗃"}.mdi-youtube-gaming:before{content:"󰡈"}.mdi-youtube-studio:before{content:"󰡇"}.mdi-youtube-subscription:before{content:"󰵀"}.mdi-youtube-tv:before{content:"󰑈"}.mdi-yurt:before{content:"󱔖"}.mdi-z-wave:before{content:"󰫪"}.mdi-zend:before{content:"󰫫"}.mdi-zigbee:before{content:"󰵁"}.mdi-zip-box:before{content:"󰗄"}.mdi-zip-box-outline:before{content:"󰿺"}.mdi-zip-disk:before{content:"󰨣"}.mdi-zodiac-aquarius:before{content:"󰩽"}.mdi-zodiac-aries:before{content:"󰩾"}.mdi-zodiac-cancer:before{content:"󰩿"}.mdi-zodiac-capricorn:before{content:"󰪀"}.mdi-zodiac-gemini:before{content:"󰪁"}.mdi-zodiac-leo:before{content:"󰪂"}.mdi-zodiac-libra:before{content:"󰪃"}.mdi-zodiac-pisces:before{content:"󰪄"}.mdi-zodiac-sagittarius:before{content:"󰪅"}.mdi-zodiac-scorpio:before{content:"󰪆"}.mdi-zodiac-taurus:before{content:"󰪇"}.mdi-zodiac-virgo:before{content:"󰪈"}.mdi-blank:before{content:"";visibility:hidden}.mdi-18px.mdi-set,.mdi-18px.mdi:before{font-size:18px}.mdi-24px.mdi-set,.mdi-24px.mdi:before{font-size:24px}.mdi-36px.mdi-set,.mdi-36px.mdi:before{font-size:36px}.mdi-48px.mdi-set,.mdi-48px.mdi:before{font-size:48px}.mdi-dark:before{color:#0000008a}.mdi-dark.mdi-inactive:before{color:#00000042}.mdi-light:before{color:#fff}.mdi-light.mdi-inactive:before{color:#ffffff4d}.mdi-rotate-45:before{-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.mdi-rotate-90:before{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.mdi-rotate-135:before{-webkit-transform:rotate(135deg);-ms-transform:rotate(135deg);transform:rotate(135deg)}.mdi-rotate-180:before{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.mdi-rotate-225:before{-webkit-transform:rotate(225deg);-ms-transform:rotate(225deg);transform:rotate(225deg)}.mdi-rotate-270:before{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.mdi-rotate-315:before{-webkit-transform:rotate(315deg);-ms-transform:rotate(315deg);transform:rotate(315deg)}.mdi-flip-h:before{-webkit-transform:scaleX(-1);transform:scaleX(-1);filter:FlipH;-ms-filter:"FlipH"}.mdi-flip-v:before{-webkit-transform:scaleY(-1);transform:scaleY(-1);filter:FlipV;-ms-filter:"FlipV"}.mdi-spin:before{-webkit-animation:mdi-spin 2s infinite linear;animation:mdi-spin 2s infinite linear}@-webkit-keyframes mdi-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes mdi-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(/app/assets/fontawesome-webfont-G5YE5S7X.eot?v=4.7.0);src:url(/app/assets/fontawesome-webfont-G5YE5S7X.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/app/assets/fontawesome-webfont-B-jkhYfk.woff2?v=4.7.0) format("woff2"),url(/app/assets/fontawesome-webfont-CDK5bt4p.woff?v=4.7.0) format("woff"),url(/app/assets/fontawesome-webfont-CQDK8MU3.ttf?v=4.7.0) format("truetype"),url(/app/assets/fontawesome-webfont-D13rzr4g.svg?v=4.7.0#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa{display:inline-block;font: 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scaleY(-1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before{content:""}.fa-check-circle:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before{content:""}.fa-arrow-circle-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-hotel:before,.fa-bed:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-yc:before,.fa-y-combinator:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-tv:before,.fa-television:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:""}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-signing:before,.fa-sign-language:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-vcard:before,.fa-address-card:before{content:""}.fa-vcard-o:before,.fa-address-card-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.choices{position:relative;overflow:hidden;margin-bottom:24px;font-size:16px}.choices:focus{outline:0}.choices:last-child{margin-bottom:0}.choices.is-open{overflow:visible}.choices.is-disabled .choices__inner,.choices.is-disabled .choices__input{background-color:#eaeaea;cursor:not-allowed;-webkit-user-select:none;user-select:none}.choices.is-disabled .choices__item{cursor:not-allowed}.choices [hidden]{display:none!important}.choices[data-type*=select-one]{cursor:pointer}.choices[data-type*=select-one] .choices__inner{padding-bottom:7.5px}.choices[data-type*=select-one] .choices__input{display:block;width:100%;padding:10px;border-bottom:1px solid #ddd;background-color:#fff;margin:0}.choices[data-type*=select-one] .choices__button{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);padding:0;background-size:8px;position:absolute;top:50%;right:0;margin-top:-10px;margin-right:25px;height:20px;width:20px;border-radius:10em;opacity:.25}.choices[data-type*=select-one] .choices__button:focus,.choices[data-type*=select-one] .choices__button:hover{opacity:1}.choices[data-type*=select-one] .choices__button:focus{box-shadow:0 0 0 2px #00bcd4}.choices[data-type*=select-one] .choices__item[data-value=""] .choices__button{display:none}.choices[data-type*=select-one]:after{content:"";height:0;width:0;border-style:solid;border-color:#333 transparent transparent transparent;border-width:5px;position:absolute;right:11.5px;top:50%;margin-top:-2.5px;pointer-events:none}.choices[data-type*=select-one].is-open:after{border-color:transparent transparent #333 transparent;margin-top:-7.5px}.choices[data-type*=select-one][dir=rtl]:after{left:11.5px;right:auto}.choices[data-type*=select-one][dir=rtl] .choices__button{right:auto;left:0;margin-left:25px;margin-right:0}.choices[data-type*=select-multiple] .choices__inner,.choices[data-type*=text] .choices__inner{cursor:text}.choices[data-type*=select-multiple] .choices__button,.choices[data-type*=text] .choices__button{position:relative;display:inline-block;margin:0 -4px 0 8px;padding-left:16px;border-left:1px solid #008fa1;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);background-size:8px;width:8px;line-height:1;opacity:.75;border-radius:0}.choices[data-type*=select-multiple] .choices__button:focus,.choices[data-type*=select-multiple] .choices__button:hover,.choices[data-type*=text] .choices__button:focus,.choices[data-type*=text] .choices__button:hover{opacity:1}.choices__inner{display:inline-block;vertical-align:top;width:100%;background-color:#f9f9f9;padding:7.5px 7.5px 3.75px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;min-height:44px;overflow:hidden}.is-focused .choices__inner,.is-open .choices__inner{border-color:#b7b7b7}.is-open .choices__inner{border-radius:2.5px 2.5px 0 0}.is-flipped.is-open .choices__inner{border-radius:0 0 2.5px 2.5px}.choices__list{margin:0;padding-left:0;list-style:none}.choices__list--single{display:inline-block;padding:4px 16px 4px 4px;width:100%}[dir=rtl] .choices__list--single{padding-right:4px;padding-left:16px}.choices__list--single .choices__item{width:100%}.choices__list--multiple{display:inline}.choices__list--multiple .choices__item{display:inline-block;vertical-align:middle;border-radius:20px;padding:4px 10px;font-size:12px;font-weight:500;margin-right:3.75px;margin-bottom:3.75px;background-color:#00bcd4;border:1px solid #00a5bb;color:#fff;word-break:break-all;box-sizing:border-box}.choices__list--multiple .choices__item[data-deletable]{padding-right:5px}[dir=rtl] .choices__list--multiple .choices__item{margin-right:0;margin-left:3.75px}.choices__list--multiple .choices__item.is-highlighted{background-color:#00a5bb;border:1px solid #008fa1}.is-disabled .choices__list--multiple .choices__item{background-color:#aaa;border:1px solid #919191}.choices__list--dropdown,.choices__list[aria-expanded]{visibility:hidden;z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;border-bottom-left-radius:2.5px;border-bottom-right-radius:2.5px;overflow:hidden;word-break:break-all;will-change:visibility}.is-active.choices__list--dropdown,.is-active.choices__list[aria-expanded]{visibility:visible}.is-open .choices__list--dropdown,.is-open .choices__list[aria-expanded]{border-color:#b7b7b7}.is-flipped .choices__list--dropdown,.is-flipped .choices__list[aria-expanded]{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-radius:.25rem .25rem 0 0}.choices__list--dropdown .choices__list,.choices__list[aria-expanded] .choices__list{position:relative;max-height:300px;overflow:auto;-webkit-overflow-scrolling:touch;will-change:scroll-position}.choices__list--dropdown .choices__item,.choices__list[aria-expanded] .choices__item{position:relative;padding:10px;font-size:14px}[dir=rtl] .choices__list--dropdown .choices__item,[dir=rtl] .choices__list[aria-expanded] .choices__item{text-align:right}@media (min-width:640px){.choices__list--dropdown .choices__item--selectable,.choices__list[aria-expanded] .choices__item--selectable{padding-right:100px}.choices__list--dropdown .choices__item--selectable:after,.choices__list[aria-expanded] .choices__item--selectable:after{content:attr(data-select-text);font-size:12px;opacity:0;position:absolute;right:10px;top:50%;transform:translateY(-50%)}[dir=rtl] .choices__list--dropdown .choices__item--selectable,[dir=rtl] .choices__list[aria-expanded] .choices__item--selectable{text-align:right;padding-left:100px;padding-right:10px}[dir=rtl] .choices__list--dropdown .choices__item--selectable:after,[dir=rtl] .choices__list[aria-expanded] .choices__item--selectable:after{right:auto;left:10px}}.choices__list--dropdown .choices__item--selectable.is-highlighted,.choices__list[aria-expanded] .choices__item--selectable.is-highlighted{background-color:#f2f2f2}.choices__list--dropdown .choices__item--selectable.is-highlighted:after,.choices__list[aria-expanded] .choices__item--selectable.is-highlighted:after{opacity:.5}.choices__item{cursor:default}.choices__item--selectable{cursor:pointer}.choices__item--disabled{cursor:not-allowed;-webkit-user-select:none;user-select:none;opacity:.5}.choices__heading{font-weight:600;font-size:12px;padding:10px;border-bottom:1px solid #f7f7f7;color:gray}.choices__button{text-indent:-9999px;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:0;background-color:transparent;background-repeat:no-repeat;background-position:center;cursor:pointer}.choices__button:focus{outline:0}.choices__input{display:inline-block;vertical-align:baseline;background-color:#f9f9f9;font-size:14px;margin-bottom:5px;border:0;border-radius:0;max-width:100%;padding:4px 0 4px 2px}.choices__input:focus{outline:0}.choices__input::-webkit-search-cancel-button,.choices__input::-webkit-search-decoration,.choices__input::-webkit-search-results-button,.choices__input::-webkit-search-results-decoration{display:none}.choices__input::-ms-clear,.choices__input::-ms-reveal{display:none;width:0;height:0}[dir=rtl] .choices__input{padding-right:2px;padding-left:0}.choices__placeholder{opacity:.5}.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}dialog{position:absolute;left:0;right:0;width:-moz-fit-content;width:-webkit-fit-content;width:fit-content;height:-moz-fit-content;height:-webkit-fit-content;height:fit-content;margin:auto;border:solid;padding:1em;background:#fff;color:#000;display:block}dialog:not([open]){display:none}dialog+.backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0000001a}._dialog_overlay{position:fixed;top:0;right:0;bottom:0;left:0}dialog.fixed{position:fixed;top:50%;transform:translateY(-50%)}.gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.gu-hide{display:none!important}.gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.gu-transit{opacity:.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20)}.formio-loader{position:relative;min-height:60px}.loader-wrapper{z-index:1000;position:absolute;top:0;left:0;bottom:0;right:0;height:120px;background-color:#0000}.loader{position:absolute;left:50%;top:50%;margin-left:-30px;margin-top:-30px;z-index:10000;display:inline-block;border:6px solid #f3f3f3;border-top:6px solid #3498db;border-radius:50%;width:60px;height:60px;animation:spin 2s linear infinite}.formio-form{position:relative;min-height:80px}.formio-error-wrapper,.formio-warning-wrapper{padding:1em}.formio-error-wrapper{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.formio-error-wrapper .formio-errors .error{color:#c20000}.formio-error-wrapper .field-required:after{color:#c20000}.formio-warning-wrapper{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.formio-disabled-input .form-control.flatpickr-input{background-color:#eee}.builder-component.has-error .invalid-feedback,.formio-component-modal-wrapper.has-error .invalid-feedback,.formio-component-modal-wrapper.has-message .invalid-feedback,.formio-component.alert-danger .invalid-feedback,.formio-component.has-error .invalid-feedback,.formio-component.has-message .invalid-feedback{display:block;color:inherit;margin-top:4px}.formio-errors .error{color:#dc3545}.formio-errors .warning{color:#856404}.formio-errors .info{color:#004085}.formio-form-group{margin-bottom:1rem}.formio-wysiwyg-editor{min-height:200px;background-color:#fff}.has-feedback .form-control{padding-right:10px}.has-feedback .form-control[type=hidden]{padding-right:0}.has-error.bg-danger{padding:4px}.ql-source:after{content:"[source]";white-space:nowrap}.quill-source-code{width:100%;margin:0;background:#1d1d1d;box-sizing:border-box;color:#ccc;font-size:15px;outline:0;padding:20px;line-height:24px;font-family:Consolas,Menlo,Monaco,Courier New,monospace;position:absolute;top:0;bottom:0;border:none;display:none}.formio-component-tags tags{background-color:#fff}.field-required:after,.tab-error:after{content:" *";color:#eb0000}.field-required:after{position:relative;z-index:10}.glyphicon-spin{-webkit-animation:formio-spin 1s infinite linear;-moz-animation:formio-spin 1s infinite linear;-o-animation:formio-spin 1s infinite linear;animation:formio-spin 1s infinite linear}@-moz-keyframes formio-spin{0%{-moz-transform:rotate(0)}to{-moz-transform:rotate(360deg)}}@-webkit-keyframes formio-spin{0%{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes formio-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.button-icon-right{margin-left:5px}.formio-component-submit .submit-success:after{content:"✓";position:relative;right:-4px;top:1px;line-height:1}.formio-component-submit .submit-fail:after{content:"✗";position:relative;right:-4px;top:1px;line-height:1}.card-vertical{display:flex;flex-direction:row;margin-top:5px}.card-vertical .card-body,.tab,.tab-content{flex-grow:2}.nav-tabs-vertical{display:flex;flex-direction:column;border-right:1px solid #ddd;padding-left:5px;margin-right:10px;border-bottom:0}.card-vertical>.card-body,.card-vertical>.tab,.card-vertical>.tab-content{flex-basis:85%}.card-vertical ul>li>.nav-link-vertical{border-right-color:transparent;border-radius:4px 0 0 4px;margin-right:0}.card-vertical ul>li>.nav-link-vertical.active{border-bottom-color:#ddd;border-right-color:transparent}.card-vertical ul>li>.nav-link-vertical.active:hover{border-right-color:transparent}.nav-tabs-vertical>li{margin:0 -1px 0 0}.formio-component-submit .submit-fail[disabled]{opacity:1}.form-control.flatpickr-input{background-color:#fff}.input-group .flatpickr-wrapper{flex-grow:1}.flatpickr-calendar .flatpickr-current-month .flatpickr-monthDropdown-months:focus,.flatpickr-calendar .flatpickr-current-month input.cur-year:focus,.flatpickr-calendar .flatpickr-days:focus{outline:auto}td>.form-group,td>.formio-form-group{margin-bottom:0}.signature-pad-body{overflow:hidden;position:relative}.signature-pad-body .form-control-feedback{position:absolute;font-size:.8rem;top:1px;right:3px}.signature-pad-canvas{border-radius:4px;box-shadow:0 0 5px #00000005 inset;border:1px solid #f4f4f4}.btn.signature-pad-refresh{position:absolute;left:0;top:0;z-index:1000;padding:3px;line-height:0}[dir=rtl] .btn.signature-pad-refresh{left:unset;right:0}.formio-component-multiple .choices__input{width:100%}.formio-component-multiple .is-invalid{border-color:#f04124}.formio-component-multiple :not(.is-invalid){border-color:#ccc}.choices__list--dropdown .choices__item--selectable{padding-right:0}.signature-pad-refresh img{height:1.2em}.signature-pad-footer{text-align:center;color:#c3c3c3}.is-active.choices__list--dropdown{z-index:100}.choices__list--multiple .choices__item{border-radius:0;padding:2px 8px;line-height:1em;margin-bottom:6px}.choices__list--single{padding:0}.choices__item.choices__item--selectable{white-space:nowrap;overflow:hidden;padding-right:25px;text-overflow:ellipsis}.choices__input{padding:2px}.choices[dir=rtl]>*{text-align:right}.choices[dir=rtl] .choices__list--multiple .choices__item[data-deletable]{padding-left:5px;float:right}.choices[dir=rtl] .choices__list--multiple .choices__item[data-deletable] .choices__button{float:left;margin:0 8px 0 -4px;padding-left:unset;padding-right:16px;border-left:unset;border-right:1px solid #008fa1;overflow:hidden}@-moz-document url-prefix(){.choices__button{float:right}}.formio-component-file .fileSelector{position:relative;padding:15px;border:2px dashed #ddd;text-align:center}.formio-component-file .fileSelector .loader-wrapper{display:none;width:100%;height:100%;background-color:#0000001a}.formio-component-file .fileSelector .loader-wrapper .loader{height:45px;width:45px;margin-top:-23px;margin-left:-23px}.formio-component-file .fileSelector a{text-decoration:underline}.formio-component-file .fileSelector.fileDragOver{border-color:#127abe}.formio-component-file .fileSelector .fa,.formio-component-file .fileSelector .glyphicon{font-size:20px;margin-right:5px}[dir=rtl] .formio-component-file .fileSelector .fa,[dir=rtl] .formio-component-file .fileSelector .glyphicon{margin-right:unset;margin-left:5px}.formio-component-file .fileSelector .browse{cursor:pointer}@-webkit-keyframes formio-dialog-fadeout{0%{opacity:1}to{opacity:0}}@keyframes formio-dialog-fadeout{0%{opacity:1}to{opacity:0}}@-webkit-keyframes formio-dialog-fadein{0%{opacity:0}to{opacity:1}}@keyframes formio-dialog-fadein{0%{opacity:0}to{opacity:1}}.formio-dialog{box-sizing:border-box;font-size:.8em;color:#666}.formio-dialog.formio-modaledit-dialog{font-size:inherit}.formio-dialog *,.formio-dialog :after,.formio-dialog :before{box-sizing:inherit}.formio-dialog{position:fixed;overflow:auto;-webkit-overflow-scrolling:touch;z-index:10000;top:0;right:0;bottom:0;left:0;background:#0006;animation:formio-dialog-fadein .5s}.formio-dialog.formio-dialog-disabled-animation,.formio-dialog.formio-dialog-disabled-animation .formio-dialog-content,.formio-dialog.formio-dialog-disabled-animation .formio-dialog-overlay{-webkit-animation:none!important;animation:none!important}.formio-dialog-overlay{position:fixed;top:0;right:0;bottom:0;left:0;-webkit-backface-visibility:hidden;-webkit-animation:formio-dialog-fadein .5s;animation:formio-dialog-fadein .5s;margin-right:15px;background:0 0}.formio-dialog-no-overlay{pointer-events:none}.formio-dialog.formio-dialog-closing .formio-dialog-overlay{-webkit-backface-visibility:hidden;-webkit-animation:formio-dialog-fadeout .5s;animation:formio-dialog-fadeout .5s}.formio-dialog-content{background:#fff;-webkit-backface-visibility:hidden;-webkit-animation:formio-dialog-fadein .5s;animation:formio-dialog-fadein .5s;pointer-events:all;overflow:auto}.formio-component-modal-wrapper-select .formio-dialog-content{overflow:initial}.formio-dialog.formio-dialog-closing .formio-dialog-content{-webkit-backface-visibility:hidden;-webkit-animation:formio-dialog-fadeout .5s;animation:formio-dialog-fadeout .5s}.formio-dialog-close:before{font-family:Helvetica,Arial,sans-serif;content:"×";cursor:pointer}body.formio-dialog-open,html.formio-dialog-open{overflow:hidden}.formio-dialog .tab-content{padding-top:12px}.formio-dialog-close{z-index:1000}@-webkit-keyframes formio-dialog-flyin{0%{opacity:0;-webkit-transform:translateY(-40px);transform:translateY(-40px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes formio-dialog-flyin{0%{opacity:0;-webkit-transform:translateY(-40px);transform:translateY(-40px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes formio-dialog-flyout{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}to{opacity:0;-webkit-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes formio-dialog-flyout{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}to{opacity:0;-webkit-transform:translateY(-40px);transform:translateY(-40px)}}.formio-dialog.formio-dialog-theme-default{padding-bottom:160px;padding-top:160px}.formio-dialog.formio-dialog-theme-default .component-edit-container{padding:.5em}.formio-dialog.formio-dialog-theme-default.formio-dialog-closing .formio-dialog-content{-webkit-animation:formio-dialog-flyout .5s;animation:formio-dialog-flyout .5s}.formio-dialog.formio-dialog-theme-default .formio-dialog-content{-webkit-animation:formio-dialog-flyin .5s;animation:formio-dialog-flyin .5s;background:#f0f0f0;border-radius:5px;font-family:Helvetica,sans-serif;font-size:1.1em;line-height:1.5em;margin:0 auto;max-width:100%;padding:1em;position:relative;width:80%}.formio-dialog.formio-dialog-theme-default .formio-dialog-close{border:none;background:0 0;cursor:pointer;position:absolute;right:1px;top:1px;z-index:100}.formio-clickable{cursor:pointer}.component-settings .nav>li>a{padding:8px 10px}.formio-dialog.formio-dialog-theme-default .formio-dialog-close:before{display:block;padding:3px;background:0 0;color:#8a8a8a;content:"×";font-size:26px;font-weight:400;line-height:26px;text-align:center}.formio-dialog.formio-dialog-theme-default .formio-dialog-close:active:before,.formio-dialog.formio-dialog-theme-default .formio-dialog-close:hover:before{color:#777}.formio-dialog.formio-dialog-theme-default .formio-dialog-message{margin-bottom:.5em}.formio-dialog.formio-dialog-theme-default .formio-dialog-input{margin-bottom:1em}.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=email],.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=password],.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=text],.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=url],.formio-dialog.formio-dialog-theme-default .formio-dialog-input textarea{background:#fff;border:0;border-radius:3px;font-family:inherit;font-size:inherit;font-weight:inherit;margin:0 0 .25em;min-height:2.5em;padding:.25em .67em;width:100%}.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=email]:focus,.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=password]:focus,.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=text]:focus,.formio-dialog.formio-dialog-theme-default .formio-dialog-input input[type=url]:focus,.formio-dialog.formio-dialog-theme-default .formio-dialog-input textarea:focus{box-shadow:inset 0 0 0 2px #8dbdf1;outline:0}.formio-dialog-buttons{display:flex;justify-content:flex-end}.formio-dialog.formio-dialog-theme-default .formio-dialog-buttons{*zoom:1}.formio-dialog.formio-dialog-theme-default .formio-dialog-buttons:after{content:"";display:table;clear:both}.formio-dialog.formio-dialog-theme-default .formio-dialog-button{border:0;border-radius:3px;cursor:pointer;float:right;font-family:inherit;font-size:.8em;letter-spacing:.1em;line-height:1em;margin:0 0 0 .5em;padding:.75em 2em;text-transform:uppercase}.formio-dialog.formio-dialog-theme-default .formio-dialog-button:focus{-webkit-animation:formio-dialog-pulse 1.1s infinite;animation:formio-dialog-pulse 1.1s infinite;outline:0}@media (max-width:568px){.formio-dialog.formio-dialog-theme-default .formio-dialog-button:focus{-webkit-animation:none;animation:none}}.formio-dialog.formio-dialog-theme-default .formio-dialog-button.formio-dialog-button-primary{background:#3288e6;color:#fff}.formio-dialog.formio-dialog-theme-default .formio-dialog-button.formio-dialog-button-secondary{background:#e0e0e0;color:#777}.formio-dialog-content .panel{margin:0}.formio-dialog-content [ref=dialogHeader]{padding-right:15px}.formio-placeholder{position:absolute;color:#999}.formio-dialog .formio-dialog-close{cursor:pointer}.formio-iframe{border:none;width:100%;height:1000px}.inline-form-button{margin-right:10px}.tooltip{opacity:1}.tooltip[x-placement=right] .tooltip-arrow{border-right:5px solid #000}.tooltip[x-placement=right] .tooltip-inner{margin-left:8px}.control-label--bottom{margin-bottom:0;margin-top:5px}.formio-component-label-hidden{position:relative}.formio-hidden{margin:0}.formio-removed{display:none}.control-label--hidden{position:absolute;top:6px;right:5px}.formio-component-datetime .control-label--hidden.field-required{right:45px;z-index:3}.formio-component-selectboxes .control-label--hidden.field-required,.formio-component-survey .control-label--hidden.field-required{top:0}.formio-component-resource .control-label--hidden.field-required,.formio-component-select .control-label--hidden.field-required{right:40px;z-index:2}.formio-component-radio .control-label--hidden.field-required:after,.formio-component-selectboxes .control-label--hidden.field-required:after{display:none}.formio-component-radio.formio-component-label-hidden.required .form-check-label:before,.formio-component-selectboxes.formio-component-label-hidden.required .form-check-label:before{position:relative;content:"* ";color:#eb0000}.formio-component-radio.formio-component-label-hidden.required .label-position-right.form-check-label:before,.formio-component-selectboxes.formio-component-label-hidden.required .label-position-right.form-check-label:before{right:20px}.formio-component-datasource,.formio-component-hidden:not(.formio-component-checkbox){margin-bottom:0}.checkbox-inline label,.radio-inline label{font-weight:400;cursor:pointer}.editgrid-listgroup{margin-bottom:10px;overflow-wrap:break-word}.tree-listgroup{flex-direction:row}.formio-component-submit button[disabled]+.has-error{display:block}.formio-choices.form-group,.formio-choices.formio-form-group{margin-bottom:0}.formio-choices[data-type=select-multiple] .form-control{height:auto}.form-control.formio-multiple-mask-select{width:15%;z-index:4}.form-control.formio-multiple-mask-input{width:85%}.input-group.formio-multiple-mask-container{width:100%}.formio-component .table{margin-bottom:0;word-break:break-all}.formio-component-htmlelement{word-wrap:break-word}.formio-component-htmlelement ol,.formio-component-htmlelement ul{margin-left:10px}.editgrid-table-container{margin-bottom:10px;max-width:calc(100vw - 140px)}.editgrid-table-container .table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.editgrid-table-column{border:none}.editgrid-table-head{border:1px solid #ddd}.editgrid-table-body{border:1px solid #ddd;border-top:0}.formio-hide-label-panel-tooltip{margin-top:-10px;margin-left:-10px}.is-disabled .choices__list--multiple .choices__item{padding:5px 10px}.is-disabled .choices__list--multiple .choices__item .choices__button{display:none}.formio-collapse-icon{cursor:pointer;margin-right:4px}[dir=rtl] .formio-collapse-icon{margin-right:unset;margin-left:4px}.formio-component-dateTime .form-control[type=datetime-local]~.input-group-addon,.formio-component-datetime .form-control[type=datetime-local]~.input-group-addon{width:auto}.formio-component-datagrid .formio-datagrid-remove{position:absolute;top:0;right:0;visibility:hidden;opacity:0;transition:opacity .2s linear,visibility 0s .2s}.formio-component-datagrid{overflow-x:auto}.formio-component-datagrid .datagrid-table,.formio-component-datagrid .datagrid-table td,.formio-component-datagrid .datagrid-table th{border:3px solid #ddd!important;padding:10px}.formio-component-datagrid .datagrid-table>tbody>tr>td:last-child{position:relative}.formio-component-datagrid .datagrid-table>tbody>tr:hover>td:last-child .formio-datagrid-remove{visibility:visible;opacity:1;transition:visibility 0s,opacity .2s linear}.datagrid-table>tbody>tr>td{word-break:break-all}.formio-component-modaledit .formio-modaledit-view-container{position:relative;border:1px solid #ddd;min-height:34px;padding:6px 12px;cursor:text}td .formio-component-modaledit .formio-modaledit-view-container{padding:0;border-style:none}.formio-component-modaledit .formio-modaledit-edit{position:absolute;top:0;left:0;visibility:hidden;opacity:0;transition:opacity .2s linear,visibility 0s .2s}.formio-component-modaledit .formio-modaledit-view-container:hover .formio-modaledit-edit{visibility:visible;opacity:1;transition:visibility 0s,opacity .2s linear}.formio-modaledit-dialog .formio-modaledit-close{position:absolute;top:100%;right:0;border-radius:0}.reset-margins a,.reset-margins abbr,.reset-margins acronym,.reset-margins address,.reset-margins applet,.reset-margins article,.reset-margins aside,.reset-margins audio,.reset-margins b,.reset-margins big,.reset-margins blockquote,.reset-margins body,.reset-margins canvas,.reset-margins caption,.reset-margins center,.reset-margins cite,.reset-margins code,.reset-margins dd,.reset-margins del,.reset-margins details,.reset-margins dfn,.reset-margins div,.reset-margins dl,.reset-margins dt,.reset-margins em,.reset-margins embed,.reset-margins fieldset,.reset-margins figcaption,.reset-margins figure,.reset-margins footer,.reset-margins form,.reset-margins h1,.reset-margins h2,.reset-margins h3,.reset-margins h4,.reset-margins h5,.reset-margins h6,.reset-margins header,.reset-margins hgroup,.reset-margins html,.reset-margins i,.reset-margins iframe,.reset-margins img,.reset-margins ins,.reset-margins kbd,.reset-margins label,.reset-margins legend,.reset-margins li,.reset-margins mark,.reset-margins menu,.reset-margins nav,.reset-margins object,.reset-margins ol,.reset-margins output,.reset-margins p,.reset-margins pre,.reset-margins q,.reset-margins ruby,.reset-margins s,.reset-margins samp,.reset-margins section,.reset-margins small,.reset-margins span,.reset-margins strike,.reset-margins strong,.reset-margins sub,.reset-margins summary,.reset-margins sup,.reset-margins table,.reset-margins tbody,.reset-margins td,.reset-margins tfoot,.reset-margins th,.reset-margins thead,.reset-margins time,.reset-margins tr,.reset-margins tt,.reset-margins u,.reset-margins ul,.reset-margins var,.reset-margins video{margin:0}.ck-body .ck.ck-balloon-panel{z-index:101000}.formio-component-select select[disabled=disabled]{-webkit-appearance:none;-moz-appearance:none;text-indent:1px;text-overflow:""}.formio-component-select .choices.is-disabled[data-type*=select-one]:after,.formio-component-select div[disabled=disabled] button{display:none}.datagrid-group-label.collapsed>td{display:none}.datagrid-group-header.clickable{cursor:pointer}.datagrid-group-header.clickable .datagrid-group-label:before{display:inline-block;vertical-align:middle;content:"▾";margin:0 5px}.datagrid-group-header.clickable.collapsed .datagrid-group-label:before{content:"▸"}.formio-component.alert-danger .help-block,.formio-component.alert-warning .help-block{color:inherit}.tree__level_even{background-color:#f6f6f6}.tree__node-content{margin-bottom:10px;overflow-wrap:break-word}.tree__node-children{margin:0}.formio-select-autocomplete-input{opacity:0;position:relative;z-index:-1;display:block;height:0;border:none}.has-error>.help-block{margin-top:5px;margin-bottom:10px}.no-top-border-table>.table>tbody>tr:first-child>td{border-top:none}.table>tbody>tr>td.cell-align-left{text-align:left}.table>tbody>tr>td.cell-align-center{text-align:center}.table>tbody>tr>td.cell-align-center>div{margin-left:auto;margin-right:auto}.table>tbody>tr>td.cell-align-right{text-align:right}.table>tbody>tr>td.cell-align-right>div{margin-left:auto}.table-responsive[ref=component]{overflow-x:visible}.formio-component-textarea .alert .ck-editor__editable{color:inherit}.formio-component-textarea .ck.ck-editor__editable .image .ck-progress-bar{height:4px}.formio-component-textarea .ck.ck-editor ol,.formio-component-textarea .ck.ck-editor ul{margin-left:10px}div[data-oembed-url]{width:100%}.checkbox label.label-position-bottom,.checkbox label.label-position-left,.checkbox label.label-position-top,.radio label.label-position-bottom,.radio label.label-position-left,.radio label.label-position-top{padding-left:0}.checkbox label.label-position-bottom span,.checkbox label.label-position-top span,.radio label.label-position-bottom span,.radio label.label-position-top span{display:block}.checkbox label.label-position-bottom input[type=checkbox],.checkbox label.label-position-top input[type=checkbox],.radio label.label-position-bottom input[type=radio],.radio label.label-position-top input[type=radio]{position:relative;margin-left:0}.checkbox label.label-position-top input[type=checkbox],.radio label.label-position-top input[type=radio]{margin-top:4px}.checkbox label.label-position-bottom input[type=checkbox],.radio label.label-position-bottom input[type=radio]{margin-bottom:8px}.radio label.label-position-left input[type=radio]{margin-left:10px}.checkbox label.label-position-left input[type=checkbox]{margin-left:4px;position:relative}.open-modal-button{width:100%;text-align:left;white-space:normal;height:auto}.formio-component-modal-wrapper-signature .open-modal-button{text-align:center;height:100%;font-size:1.4em;padding:0;margin:0}.formio-component-content .image{display:table;clear:both;text-align:center;margin:1em auto}.formio-component-content .image>img{display:block;margin:0 auto;max-width:100%;min-width:50px}.formio-component-content .image>figcaption{display:table-caption;caption-side:bottom;word-break:break-word;color:#333;background-color:#f7f7f7;padding:.6em;font-size:.75em;outline-offset:-1px}.formio-component-content .image.image_resized{max-width:100%;display:block;box-sizing:border-box}.formio-component-content .image.image_resized img{width:100%}.formio-component-content .image.image_resized>figcaption{display:block}.formio-component-content .media{clear:both;margin:1em 0;display:block;min-width:15em}.formio-component-content .image-style-align-center:not(.image_resized),.formio-component-content .image-style-align-left:not(.image_resized),.formio-component-content .image-style-align-right:not(.image_resized),.formio-component-content .image-style-side:not(.image_resized){max-width:50%}.formio-component-content .image-style-side{float:right;margin-left:var(--ck-image-style-spacing)}.formio-component-content .image-style-align-left{float:left;margin-right:var(--ck-image-style-spacing)}.formio-component-content .image-style-align-center{margin-left:auto;margin-right:auto}.formio-component-content .image-style-align-right{float:right;margin-left:var(--ck-image-style-spacing)}.formio-component-content blockquote{overflow:hidden;padding-right:1.5em;padding-left:1.5em;margin-left:0;margin-right:0;font-style:italic;border-left:solid 5px hsl(0deg,0%,80%)}.formio-component-content[dir=rtl] blockquote{border-left:0;border-right:solid 5px hsl(0deg,0%,80%)}.formio-component-content .text-tiny{font-size:.7em}.formio-component-content .text-small{font-size:.85em}.formio-component-content .text-big{font-size:1.4em}.formio-component-content .text-huge{font-size:1.8em}.formio-component-content ol{padding-inline-start:40px}.formio-component-address.formio-component-label-hidden>label.field-required{z-index:1}.formio-component-address.formio-component-label-hidden>label.field-required~.address-autocomplete-container .address-autocomplete-remove-value-icon{right:20px}.address-autocomplete-container{position:relative}.address-autocomplete-container .address-autocomplete-remove-value-icon{cursor:pointer;position:absolute;margin-top:-9px;right:10px;top:50%}.address-autocomplete-container .address-autocomplete-remove-value-icon--hidden{display:none}.autocomplete{background:#fff;font:14px/22px -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;overflow:auto;box-sizing:border-box;border:1px solid rgba(50,50,50,.6);z-index:11000}.autocomplete>div{cursor:pointer;padding:6px 10px}.autocomplete>div.selected,.autocomplete>div:hover:not(.group){background:#1e90ff;color:#fff}.field-wrapper{display:flex}.field-wrapper--reverse{flex-direction:row-reverse}.field-wrapper .field-label--right{text-align:right}.formio-component-modal-wrapper{margin-bottom:10px}.formio-component-modal-wrapper .open-modal-button{height:auto}.formio-component-modal-wrapper .component-rendering-hidden{visibility:hidden}.formio-component-textarea div.formio-editor-read-only-content[ref=input]{white-space:pre-wrap}.formio-editor-read-only-content img{max-width:100%}.formio-editor-read-only-content li[data-list=bullet]{list-style-type:none}.formio-editor-read-only-content li[data-list=bullet] .ql-ui{padding-right:.5rem}.formio-editor-read-only-content li[data-list=bullet] .ql-ui:before{content:"•"}.formio-editor-read-only-content li[data-list=ordered]{list-style-type:none;counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;counter-increment:list-0}.formio-editor-read-only-content li[data-list=ordered] .ql-ui{padding-right:.5rem}.formio-editor-read-only-content li[data-list=ordered] .ql-ui:before{content:counter(list-0,decimal) ". "}.formio-editor-read-only-content figure.table table{border-collapse:collapse;border-spacing:0;width:100%;height:100%;border:1px double #b3b3b3;table-layout:fixed}.formio-editor-read-only-content figure.table table td,.formio-editor-read-only-content figure.table table th{min-width:2em;padding:.4em;border:1px solid #bfbfbf}.formio-component-password .pull-right:not(:last-child),.formio-component-textarea .pull-right:not(:last-child),.formio-component-textfield .pull-right:not(:last-child){padding-left:12px}.formio-form>div>nav>ul.pagination{flex-flow:wrap row;justify-content:flex-start}.formio-form>div>nav>ul.pagination .page-link{cursor:pointer;color:#1c74d9}.formio-form>div>nav>ul.pagination .page-item.active .page-link{color:#fff;background-color:#1c74d9;border-color:#1c74d9}.classic-pagination{border-bottom:solid 1px #e0e0e0;padding:0 15px 10px;line-height:1em}.classic-pagination-page{padding:0;position:relative}.classic-pagination-title{color:#595959;font-size:16px;margin-bottom:5px}.classic-pagination-dot{position:absolute;width:30px;height:30px;display:block;background:#fbe8aa;top:40px;left:50%;margin-top:-15px;margin-left:-15px;border-radius:50%}.classic-pagination-dot:after{content:" ";width:14px;height:14px;background:#fbbd19;border-radius:50px;position:absolute;top:8px;left:8px}.classic-pagination .progress,.classic-pagination-progress{position:relative;border-radius:0;height:8px;box-shadow:none;margin:20px 0;border:none;padding:0;background-color:#f6f6f6}.classic-pagination .progress-bar,.classic-pagination-progress-bar{width:0;height:10px;box-shadow:none;background:#fbe8aa}.classic-pagination-page.complete .classic-pagination-progress-bar,.classic-pagination-page.complete .progress-bar{width:100%}.classic-pagination-page.active .classic-pagination-progress-bar,.classic-pagination-page.active .progress-bar{width:50%}.classic-pagination-page.disabled .classic-pagination-dot{background-color:#f5f5f5}.classic-pagination-page.disabled .classic-pagination-dot:after{opacity:0}.classic-pagination-page:first-child .classic-pagination-progress,.classic-pagination-page:first-child .progress{left:50%;width:50%}.classic-pagination-page:first-child.active .classic-pagination-progress-bar,.classic-pagination-page:first-child.active .progress-bar{width:0%}.classic-pagination-page:last-child .classic-pagination-progress,.classic-pagination-page:last-child .progress{width:50%}.classic-pagination-page:last-child.active .classic-pagination-progress-bar,.classic-pagination-page:last-child.active .progress-bar{width:100%}.pac-container{z-index:11000}[ref=buttonMessageContainer].has-error{cursor:pointer}[ref=passwordStrengthIndicator]{display:inline}.formio-security-indicator{display:flex;height:5px}.formio-security-indicator [class^=security-]{width:100%;height:100%}.formio-security-indicator .security-low{background-color:#c51e00}.formio-security-indicator .security-medium{background-color:#ebb400}.formio-security-indicator .security-high{background-color:#bddf00}.formio-security-indicator .security-very-high{background-color:#009118}.formio-component-textarea .formio-editor-read-only-content .text-big{font-size:1.4em}.formio-component-textarea .formio-editor-read-only-content .text-huge{font-size:1.8em}.formio-component-textarea .formio-editor-read-only-content .text-small{font-size:.85em}.formio-component-textarea .formio-editor-read-only-content .text-tiny{font-size:.7em}.formio-component [ref=valueMaskInput]{display:none}.formio-wizard-nav-container{display:flex}.formio-wizard-nav-container li{margin-right:.5rem}@media not all and (min-width:30em){.formio-wizard-nav-container{flex-direction:column}.formio-wizard-nav-container li{margin-right:0}.formio-wizard-nav-container li .btn{width:100%;margin-bottom:.25rem}}.formio-tooltip__trigger{cursor:pointer}.formio-tooltip__body{background-color:#1b1b1b;border-radius:.25rem;bottom:0;color:#f0f0f0;display:none;font-size:1rem;padding:.5rem;position:absolute;left:0;transform:translate(-50%);width:auto;white-space:pre;z-index:1000}.formio-tooltip__body.formio-tooltip--is-set{display:block}.formio-tooltip__body--whitespace{white-space:normal;width:250px}.formio-tooltip__body--right{top:auto;transform:translate(0)}.formio-tooltip__body--left{top:auto;left:0;right:auto;transform:translate(0)}.formio-tooltip__body--bottom{bottom:auto;top:0}.formio-tooltip__wrapper{position:relative}.formio-tooltip__wrapper>span{font-weight:400}.ace_editor,.ace_editor div,.ace_editor span{font-family:Monaco,Menlo,Ubuntu Mono,Droid Sans Mono,Consolas,monospace!important}span[role=link]{text-decoration:underline;cursor:pointer}.hidden{display:none!important}.formbuilder{position:relative}.drag-container{padding:10px;border:dotted 2px #e8e8e8}.drag-container:hover{cursor:move;border:dotted 2px #ccc}.drag-container.formio-builder-form,.drag-container.formio-builder-form:hover,.panel-body>.drag-container.formio-builder-components,.panel-body>.drag-container.formio-builder-components:hover,.tab-pane>.drag-container.formio-builder-components,.tab-pane>.drag-container.formio-builder-components:hover{padding:0 0 1rem;border:none}.component-btn-group{display:flex;flex-direction:row-reverse;position:absolute;right:0;z-index:1000;margin-top:-2px}.builder-component{position:relative;min-height:15px;margin-bottom:15px}.builder-component .formio-component-htmlelement{border:dotted 2px #e8e8e8}.builder-component .formio-component-htmlelement [ref=html]:empty:before{content:"HTML Content";color:#aaa}.builder-component:not(:hover) .component-btn-group{display:none}.builder-group-button{background-color:transparent;white-space:normal;text-align:left}.form-builder-group-header{padding:0}.component-btn-group .component-settings-button{float:right;margin:4px 4px 0 0;z-index:1001;-webkit-box-shadow:0 0 10px 1px rgba(48,113,169,.6);-moz-box-shadow:0 0 10px 1px rgba(48,113,169,.6);box-shadow:0 0 10px 1px #3071a999}.formbuilder .formio-component-content,.formbuilder .formio-component-datasource,.formbuilder .formio-component-form,.formbuilder .formio-component-hidden{border:2px dashed #ddd}.formbuilder .formio-component-datasource,.formbuilder .formio-component-form,.formbuilder .formio-component-hidden{min-height:3em;text-align:center;color:#aaa;padding-top:.5em}.btn-group-xxs>.btn,.btn-xxs,.component-btn-group .component-settings-button{padding:2px;font-size:10px;line-height:1.2em;border-radius:0;width:18px;height:18px}.formcomponents .formcomponent{text-align:left;padding:5px 5px 5px 8px;margin-top:.2rem;font-size:.8em;line-height:1.2;border-radius:.3em}.form-builder-panel .panel-body{padding:5px}.formio-component-tabs .ui.tabular.menu .item{padding:.8em}.formio-pdf-builder{position:relative}.formio-drop-zone{display:none;position:absolute;z-index:10;background-color:#0d87e9;opacity:.1}.formio-drop-zone.enabled{display:inherit}.component-settings .formio-dialog-content{max-height:100%}.component-settings .formio-dialog-content .ck-editor__editable ol{padding-inline-start:40px}.component-btn-group .btn.component-settings-button-paste{display:none}.builder-paste-mode .component-settings-button-paste{display:inherit!important}.wizard-page-label{cursor:pointer;border-radius:0}.panel-body .drag-and-drop-alert{margin-bottom:0}.builder-sidebar_scroll{position:sticky;top:15px;max-height:100vh;overflow-y:auto}.builder-sidebar_search{margin-bottom:10px;-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}.formio-wizard-builder-component-title{color:#6c757d;text-align:center;padding:.5rem}.formio-wizard-position{position:relative}.gu-mirror{list-style-type:none}.formio-settings-help{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc;margin-top:10px}.help-block{margin:0}.builder-sidebar .btn{white-space:normal}.component-settings{padding-top:20px!important;padding-bottom:20px!important}.component-edit-container{height:auto;overflow:hidden}.component-edit-content{height:calc(100% - 4em)}.component-edit-tabs.col-sm-6{min-height:87vh;height:100%}.component-edit-tabs.col-sm-12,.component-edit-tabs.col-sm-12 .editForm{height:calc(100% - 4em);overflow-y:auto}.progress.pdf-progress{height:2rem}.progress.pdf-progress .progress-bar{font-size:1rem;line-height:2rem}.builder-sidebar.disabled .formcomponent{cursor:not-allowed;opacity:.65;box-shadow:none}.builder-component-selected{border:2px dashed #919191;outline:0!important}.vjs-tree-brackets{cursor:pointer}.vjs-tree-brackets:hover{color:#1890ff}.vjs-check-controller{position:absolute;left:0}.vjs-check-controller.is-checked .vjs-check-controller-inner{background-color:#1890ff;border-color:#0076e4}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-checkbox:after{transform:rotate(45deg) scaleY(1)}.vjs-check-controller.is-checked .vjs-check-controller-inner.is-radio:after{transform:translate(-50%,-50%) scale(1)}.vjs-check-controller .vjs-check-controller-inner{display:inline-block;position:relative;border:1px solid #bfcbd9;border-radius:2px;vertical-align:middle;box-sizing:border-box;width:16px;height:16px;background-color:#fff;z-index:1;cursor:pointer;transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.vjs-check-controller .vjs-check-controller-inner:after{box-sizing:content-box;content:"";border:2px solid #fff;border-left:0;border-top:0;height:8px;left:4px;position:absolute;top:1px;transform:rotate(45deg) scaleY(0);width:4px;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;transform-origin:center}.vjs-check-controller .vjs-check-controller-inner.is-radio{border-radius:100%}.vjs-check-controller .vjs-check-controller-inner.is-radio:after{border-radius:100%;height:4px;background-color:#fff;left:50%;top:50%}.vjs-check-controller .vjs-check-controller-original{opacity:0;outline:none;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.vjs-carets{position:absolute;right:0;cursor:pointer}.vjs-carets svg{transition:transform .3s}.vjs-carets:hover{color:#1890ff}.vjs-carets-close{transform:rotate(-90deg)}.vjs-tree-node{display:flex;position:relative;line-height:20px}.vjs-tree-node.has-carets{padding-left:15px}.vjs-tree-node.has-carets.has-selector,.vjs-tree-node.has-selector{padding-left:30px}.vjs-tree-node.is-highlight,.vjs-tree-node:hover{background-color:#e6f7ff}.vjs-tree-node .vjs-indent{display:flex;position:relative}.vjs-tree-node .vjs-indent-unit{width:1em}.vjs-tree-node .vjs-indent-unit.has-line{border-left:1px dashed #bfcbd9}.vjs-node-index{position:absolute;right:100%;margin-right:4px}.vjs-colon{white-space:pre}.vjs-comment{color:#bfcbd9}.vjs-value{word-break:break-word}.vjs-value-null,.vjs-value-undefined{color:#d55fde}.vjs-value-boolean,.vjs-value-number{color:#1d8ce0}.vjs-value-string{color:#13ce66}.vjs-tree{font-family:Monaco,Menlo,Consolas,Bitstream Vera Sans Mono,monospace;font-size:14px;text-align:left}.vjs-tree.is-virtual{overflow:auto}.vjs-tree.is-virtual .vjs-tree-node{white-space:nowrap}/*! + * Bootstrap v5.3.1 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root,[data-bs-theme=light]{--bs-blue: #0d6efd;--bs-indigo: #6610f2;--bs-purple: #6f42c1;--bs-pink: #d63384;--bs-red: #dc3545;--bs-orange: #fd7e14;--bs-yellow: #ffc107;--bs-green: #198754;--bs-teal: #20c997;--bs-cyan: #0dcaf0;--bs-black: #000;--bs-white: #fff;--bs-gray: #6c757d;--bs-gray-dark: #343a40;--bs-gray-100: #f8f9fa;--bs-gray-200: #e9ecef;--bs-gray-300: #dee2e6;--bs-gray-400: #ced4da;--bs-gray-500: #adb5bd;--bs-gray-600: #6c757d;--bs-gray-700: #495057;--bs-gray-800: #343a40;--bs-gray-900: #212529;--bs-primary: #0d6efd;--bs-secondary: #6c757d;--bs-success: #198754;--bs-info: #0dcaf0;--bs-warning: #ffc107;--bs-danger: #dc3545;--bs-light: #f8f9fa;--bs-dark: #212529;--bs-primary-rgb: 13, 110, 253;--bs-secondary-rgb: 108, 117, 125;--bs-success-rgb: 25, 135, 84;--bs-info-rgb: 13, 202, 240;--bs-warning-rgb: 255, 193, 7;--bs-danger-rgb: 220, 53, 69;--bs-light-rgb: 248, 249, 250;--bs-dark-rgb: 33, 37, 41;--bs-primary-text-emphasis: #052c65;--bs-secondary-text-emphasis: #2b2f32;--bs-success-text-emphasis: #0a3622;--bs-info-text-emphasis: #055160;--bs-warning-text-emphasis: #664d03;--bs-danger-text-emphasis: #58151c;--bs-light-text-emphasis: #495057;--bs-dark-text-emphasis: #495057;--bs-primary-bg-subtle: #cfe2ff;--bs-secondary-bg-subtle: #e2e3e5;--bs-success-bg-subtle: #d1e7dd;--bs-info-bg-subtle: #cff4fc;--bs-warning-bg-subtle: #fff3cd;--bs-danger-bg-subtle: #f8d7da;--bs-light-bg-subtle: #fcfcfd;--bs-dark-bg-subtle: #ced4da;--bs-primary-border-subtle: #9ec5fe;--bs-secondary-border-subtle: #c4c8cb;--bs-success-border-subtle: #a3cfbb;--bs-info-border-subtle: #9eeaf9;--bs-warning-border-subtle: #ffe69c;--bs-danger-border-subtle: #f1aeb5;--bs-light-border-subtle: #e9ecef;--bs-dark-border-subtle: #adb5bd;--bs-white-rgb: 255, 255, 255;--bs-black-rgb: 0, 0, 0;--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--bs-body-font-family: var(--bs-font-sans-serif);--bs-body-font-size: 1rem;--bs-body-font-weight: 400;--bs-body-line-height: 1.5;--bs-body-color: #212529;--bs-body-color-rgb: 33, 37, 41;--bs-body-bg: #fff;--bs-body-bg-rgb: 255, 255, 255;--bs-emphasis-color: #000;--bs-emphasis-color-rgb: 0, 0, 0;--bs-secondary-color: rgba(33, 37, 41, .75);--bs-secondary-color-rgb: 33, 37, 41;--bs-secondary-bg: #e9ecef;--bs-secondary-bg-rgb: 233, 236, 239;--bs-tertiary-color: rgba(33, 37, 41, .5);--bs-tertiary-color-rgb: 33, 37, 41;--bs-tertiary-bg: #f8f9fa;--bs-tertiary-bg-rgb: 248, 249, 250;--bs-heading-color: inherit;--bs-link-color: #0d6efd;--bs-link-color-rgb: 13, 110, 253;--bs-link-decoration: underline;--bs-link-hover-color: #0a58ca;--bs-link-hover-color-rgb: 10, 88, 202;--bs-code-color: #d63384;--bs-highlight-bg: #fff3cd;--bs-border-width: 1px;--bs-border-style: solid;--bs-border-color: #dee2e6;--bs-border-color-translucent: rgba(0, 0, 0, .175);--bs-border-radius: .375rem;--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: 0 .5rem 1rem rgba(0, 0, 0, .15);--bs-box-shadow-sm: 0 .125rem .25rem rgba(0, 0, 0, .075);--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, .175);--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, .075);--bs-focus-ring-width: .25rem;--bs-focus-ring-opacity: .25;--bs-focus-ring-color: rgba(13, 110, 253, .25);--bs-form-valid-color: #198754;--bs-form-valid-border-color: #198754;--bs-form-invalid-color: #dc3545;--bs-form-invalid-border-color: #dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color: #dee2e6;--bs-body-color-rgb: 222, 226, 230;--bs-body-bg: #212529;--bs-body-bg-rgb: 33, 37, 41;--bs-emphasis-color: #fff;--bs-emphasis-color-rgb: 255, 255, 255;--bs-secondary-color: rgba(222, 226, 230, .75);--bs-secondary-color-rgb: 222, 226, 230;--bs-secondary-bg: #343a40;--bs-secondary-bg-rgb: 52, 58, 64;--bs-tertiary-color: rgba(222, 226, 230, .5);--bs-tertiary-color-rgb: 222, 226, 230;--bs-tertiary-bg: #2b3035;--bs-tertiary-bg-rgb: 43, 48, 53;--bs-primary-text-emphasis: #6ea8fe;--bs-secondary-text-emphasis: #a7acb1;--bs-success-text-emphasis: #75b798;--bs-info-text-emphasis: #6edff6;--bs-warning-text-emphasis: #ffda6a;--bs-danger-text-emphasis: #ea868f;--bs-light-text-emphasis: #f8f9fa;--bs-dark-text-emphasis: #dee2e6;--bs-primary-bg-subtle: #031633;--bs-secondary-bg-subtle: #161719;--bs-success-bg-subtle: #051b11;--bs-info-bg-subtle: #032830;--bs-warning-bg-subtle: #332701;--bs-danger-bg-subtle: #2c0b0e;--bs-light-bg-subtle: #343a40;--bs-dark-bg-subtle: #1a1d20;--bs-primary-border-subtle: #084298;--bs-secondary-border-subtle: #41464b;--bs-success-border-subtle: #0f5132;--bs-info-border-subtle: #087990;--bs-warning-border-subtle: #997404;--bs-danger-border-subtle: #842029;--bs-light-border-subtle: #495057;--bs-dark-border-subtle: #343a40;--bs-heading-color: inherit;--bs-link-color: #6ea8fe;--bs-link-hover-color: #8bb9fe;--bs-link-color-rgb: 110, 168, 254;--bs-link-hover-color-rgb: 139, 185, 254;--bs-code-color: #e685b5;--bs-border-color: #495057;--bs-border-color-translucent: rgba(255, 255, 255, .15);--bs-form-valid-color: #75b798;--bs-form-valid-border-color: #75b798;--bs-form-invalid-color: #ea868f;--bs-form-invalid-border-color: #ea868f}*,*:before,*:after{box-sizing:border-box}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}hr{margin:1rem 0;color:inherit;border:0;border-top: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:500;line-height:1.2;color:var(--bs-heading-color)}h1,.h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width: 1200px){h1,.h1{font-size:2.5rem}}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;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}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}a,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity, 1));text-decoration:underline}a:hover,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover{--bs-link-color-rgb: var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:not([href]):not([class]),.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:not([href]):not([class]),.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link: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}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link>code,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link>code,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link>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}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled,.form-designer .formio-component-submit select.btn.btn-primary,.form-designer .formio-component-submit select.btn.btn-primary:hover{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}::-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}[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,.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:#6c757d}.blockquote-footer:before{content:"— "}.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;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;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)}.col{flex:1 0 0%}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.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%}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.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%}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.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%}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.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%}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.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%}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.3333333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.6666666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.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: transparent;--bs-table-striped-color: var(--bs-body-color);--bs-table-striped-bg: rgba(0, 0, 0, .05);--bs-table-active-color: var(--bs-body-color);--bs-table-active-bg: rgba(0, 0, 0, .1);--bs-table-hover-color: var(--bs-body-color);--bs-table-hover-bg: rgba(0, 0, 0, .075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.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}.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(odd)>*{--bs-table-color-type: var(--bs-table-striped-color);--bs-table-bg-type: var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--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: #cfe2ff;--bs-table-border-color: #bacbe6;--bs-table-striped-bg: #c5d7f2;--bs-table-striped-color: #000;--bs-table-active-bg: #bacbe6;--bs-table-active-color: #000;--bs-table-hover-bg: #bfd1ec;--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: #e2e3e5;--bs-table-border-color: #cbccce;--bs-table-striped-bg: #d7d8da;--bs-table-striped-color: #000;--bs-table-active-bg: #cbccce;--bs-table-active-color: #000;--bs-table-hover-bg: #d1d2d4;--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: #d1e7dd;--bs-table-border-color: #bcd0c7;--bs-table-striped-bg: #c7dbd2;--bs-table-striped-color: #000;--bs-table-active-bg: #bcd0c7;--bs-table-active-color: #000;--bs-table-hover-bg: #c1d6cc;--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: #cff4fc;--bs-table-border-color: #badce3;--bs-table-striped-bg: #c5e8ef;--bs-table-striped-color: #000;--bs-table-active-bg: #badce3;--bs-table-active-color: #000;--bs-table-hover-bg: #bfe2e9;--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: #fff3cd;--bs-table-border-color: #e6dbb9;--bs-table-striped-bg: #f2e7c3;--bs-table-striped-color: #000;--bs-table-active-bg: #e6dbb9;--bs-table-active-color: #000;--bs-table-hover-bg: #ece1be;--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: #f8d7da;--bs-table-border-color: #dfc2c4;--bs-table-striped-bg: #eccccf;--bs-table-striped-color: #000;--bs-table-active-bg: #dfc2c4;--bs-table-active-color: #000;--bs-table-hover-bg: #e5c7ca;--bs-table-hover-color: #000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color: #000;--bs-table-bg: #f8f9fa;--bs-table-border-color: #dfe0e1;--bs-table-striped-bg: #ecedee;--bs-table-striped-color: #000;--bs-table-active-bg: #dfe0e1;--bs-table-active-color: #000;--bs-table-hover-bg: #e5e6e7;--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: #212529;--bs-table-border-color: #373b3e;--bs-table-striped-bg: #2c3034;--bs-table-striped-color: #fff;--bs-table-active-bg: #373b3e;--bs-table-active-color: #fff;--bs-table-hover-bg: #323539;--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{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{margin-top:.25rem;font-size:.875em;color:var(--bs-secondary-color)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.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,.form-designer .formio-component-submit .form-control.btn.btn-primary{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 .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color: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='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;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 var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled,.form-designer .formio-component-submit .form-select.btn.btn-primary{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{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{--bs-form-check-bg: var(--bs-body-bg);width:1em;height:1em;margin-top:.25em;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;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 var(--bs-border-color);-webkit-print-color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-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]{--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{background-color:#0d6efd;border-color:#0d6efd;--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled,.form-designer .formio-component-submit .form-check-input.btn.btn-primary{pointer-events:none;filter:none;opacity:.5}.form-check-input[disabled]~.form-check-label,.form-check-input:disabled~.form-check-label,.form-designer .formio-component-submit .form-check-input.btn.btn-primary~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%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,.form-designer .formio-component-submit .btn-check.btn.btn-primary+.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;-webkit-appearance:none;-moz-appearance:none;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 #0d6efd40}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem #0d6efd40}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-range::-webkit-slider-thumb{transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.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;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-range::-moz-range-thumb{transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.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,.form-designer .formio-component-submit .form-range.btn.btn-primary{pointer-events:none}.form-range:disabled::-webkit-slider-thumb,.form-designer .formio-component-submit .form-range.btn.btn-primary::-webkit-slider-thumb{background-color:var(--bs-secondary-color)}.form-range:disabled::-moz-range-thumb,.form-designer .formio-component-submit .form-range.btn.btn-primary::-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 .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion: reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control::placeholder,.form-floating>.form-control-plaintext::placeholder{color: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(.85) translateY(-.5rem) translate(.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;top:1rem;right:.375rem;bottom:1rem;left:.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(.85) translateY(-.5rem) translate(.15rem)}.form-floating>.form-control-plaintext~label{border-width:var(--bs-border-width) 0}.form-floating>:disabled~label,.form-designer .formio-component-submit .form-floating>.btn.btn-primary~label,.form-floating>.form-control:disabled~label{color:#6c757d}.form-floating>:disabled~label:after,.form-designer .formio-component-submit .form-floating>.btn.btn-primary~label:after,.form-floating>.form-control:disabled~label:after{background-color:var(--bs-secondary-bg)}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-select,.input-group>.form-floating{position:relative;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;align-items:center;padding:.375rem .75rem;font-size:1rem;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 var(--bs-border-color);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='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.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),.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='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.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),.25)}.was-validated .form-control-color:valid,.form-control-color.is-valid{width:calc(3.75rem + 1.5em)}.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),.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='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.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),.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='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.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),.25)}.was-validated .form-control-color:invalid,.form-control-color.is-invalid{width:calc(3.75rem + 1.5em)}.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),.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: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--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, .15), 0 1px 1px rgba(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;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,:not(.btn-check)+.btn:active,.btn:first-child:active,.btn.active,.btn.show{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,:not(.btn-check)+.btn:active:focus-visible,.btn:first-child:active:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn:disabled,.form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .btn.btn-primary:hover,.btn.disabled,fieldset:disabled .btn,.form-designer .formio-component-submit fieldset.btn.btn-primary .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-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-secondary{--bs-btn-color: #fff;--bs-btn-bg: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #5c636a;--bs-btn-hover-border-color: #565e64;--bs-btn-focus-shadow-rgb: 130, 138, 145;--bs-btn-active-color: #fff;--bs-btn-active-bg: #565e64;--bs-btn-active-border-color: #51585e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #6c757d;--bs-btn-disabled-border-color: #6c757d}.btn-success{--bs-btn-color: #fff;--bs-btn-bg: #198754;--bs-btn-border-color: #198754;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #157347;--bs-btn-hover-border-color: #146c43;--bs-btn-focus-shadow-rgb: 60, 153, 110;--bs-btn-active-color: #fff;--bs-btn-active-bg: #146c43;--bs-btn-active-border-color: #13653f;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #198754;--bs-btn-disabled-border-color: #198754}.btn-info{--bs-btn-color: #000;--bs-btn-bg: #0dcaf0;--bs-btn-border-color: #0dcaf0;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #31d2f2;--bs-btn-hover-border-color: #25cff2;--bs-btn-focus-shadow-rgb: 11, 172, 204;--bs-btn-active-color: #000;--bs-btn-active-bg: #3dd5f3;--bs-btn-active-border-color: #25cff2;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #0dcaf0;--bs-btn-disabled-border-color: #0dcaf0}.btn-warning{--bs-btn-color: #000;--bs-btn-bg: #ffc107;--bs-btn-border-color: #ffc107;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #ffca2c;--bs-btn-hover-border-color: #ffc720;--bs-btn-focus-shadow-rgb: 217, 164, 6;--bs-btn-active-color: #000;--bs-btn-active-bg: #ffcd39;--bs-btn-active-border-color: #ffc720;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #ffc107;--bs-btn-disabled-border-color: #ffc107}.btn-danger{--bs-btn-color: #fff;--bs-btn-bg: #dc3545;--bs-btn-border-color: #dc3545;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #bb2d3b;--bs-btn-hover-border-color: #b02a37;--bs-btn-focus-shadow-rgb: 225, 83, 97;--bs-btn-active-color: #fff;--bs-btn-active-bg: #b02a37;--bs-btn-active-border-color: #a52834;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #dc3545;--bs-btn-disabled-border-color: #dc3545}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.btn-dark{--bs-btn-color: #fff;--bs-btn-bg: #212529;--bs-btn-border-color: #212529;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #424649;--bs-btn-hover-border-color: #373b3e;--bs-btn-focus-shadow-rgb: 66, 70, 73;--bs-btn-active-color: #fff;--bs-btn-active-bg: #4d5154;--bs-btn-active-border-color: #373b3e;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #212529;--bs-btn-disabled-border-color: #212529}.btn-outline-primary{--bs-btn-color: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0d6efd;--bs-btn-hover-border-color: #0d6efd;--bs-btn-focus-shadow-rgb: 13, 110, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0d6efd;--bs-btn-active-border-color: #0d6efd;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #0d6efd;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #0d6efd;--bs-gradient: none}.btn-outline-secondary{--bs-btn-color: #6c757d;--bs-btn-border-color: #6c757d;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #6c757d;--bs-btn-hover-border-color: #6c757d;--bs-btn-focus-shadow-rgb: 108, 117, 125;--bs-btn-active-color: #fff;--bs-btn-active-bg: #6c757d;--bs-btn-active-border-color: #6c757d;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #6c757d;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #6c757d;--bs-gradient: none}.btn-outline-success{--bs-btn-color: #198754;--bs-btn-border-color: #198754;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #198754;--bs-btn-hover-border-color: #198754;--bs-btn-focus-shadow-rgb: 25, 135, 84;--bs-btn-active-color: #fff;--bs-btn-active-bg: #198754;--bs-btn-active-border-color: #198754;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #198754;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #198754;--bs-gradient: none}.btn-outline-info{--bs-btn-color: #0dcaf0;--bs-btn-border-color: #0dcaf0;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #0dcaf0;--bs-btn-hover-border-color: #0dcaf0;--bs-btn-focus-shadow-rgb: 13, 202, 240;--bs-btn-active-color: #000;--bs-btn-active-bg: #0dcaf0;--bs-btn-active-border-color: #0dcaf0;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #0dcaf0;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #0dcaf0;--bs-gradient: none}.btn-outline-warning{--bs-btn-color: #ffc107;--bs-btn-border-color: #ffc107;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #ffc107;--bs-btn-hover-border-color: #ffc107;--bs-btn-focus-shadow-rgb: 255, 193, 7;--bs-btn-active-color: #000;--bs-btn-active-bg: #ffc107;--bs-btn-active-border-color: #ffc107;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #ffc107;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #ffc107;--bs-gradient: none}.btn-outline-danger{--bs-btn-color: #dc3545;--bs-btn-border-color: #dc3545;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #dc3545;--bs-btn-hover-border-color: #dc3545;--bs-btn-focus-shadow-rgb: 220, 53, 69;--bs-btn-active-color: #fff;--bs-btn-active-bg: #dc3545;--bs-btn-active-border-color: #dc3545;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #dc3545;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #dc3545;--bs-gradient: none}.btn-outline-light{--bs-btn-color: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #f8f9fa;--bs-btn-hover-border-color: #f8f9fa;--bs-btn-focus-shadow-rgb: 248, 249, 250;--bs-btn-active-color: #000;--bs-btn-active-bg: #f8f9fa;--bs-btn-active-border-color: #f8f9fa;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #f8f9fa;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #f8f9fa;--bs-gradient: none}.btn-outline-dark{--bs-btn-color: #212529;--bs-btn-border-color: #212529;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #212529;--bs-btn-hover-border-color: #212529;--bs-btn-focus-shadow-rgb: 33, 37, 41;--bs-btn-active-color: #fff;--bs-btn-active-bg: #212529;--bs-btn-active-border-color: #212529;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #212529;--bs-btn-disabled-bg: transparent;--bs-btn-disabled-border-color: #212529;--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: #6c757d;--bs-btn-disabled-border-color: transparent;--bs-btn-box-shadow: 0 0 0 #000;--bs-btn-focus-shadow-rgb: 49, 132, 253;text-decoration:underline}.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 .15s linear}@media (prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion: reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion: reduce){.collapsing.collapse-horizontal{transition:none}}.dropup,.dropend,.dropdown,.dropstart,.dropup-center,.dropdown-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle:after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid 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: 0 .5rem 1rem rgba(0, 0, 0, .15);--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: #0d6efd;--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: #6c757d;--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{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--bs-dropdown-item-border-radius, 0)}.dropdown-item:hover,.dropdown-item:focus{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled,.form-designer .formio-component-submit .dropdown-item.btn.btn-primary{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color: #dee2e6;--bs-dropdown-bg: #343a40;--bs-dropdown-border-color: 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, .15);--bs-dropdown-link-active-color: #fff;--bs-dropdown-link-active-bg: #0d6efd;--bs-dropdown-link-disabled-color: #adb5bd;--bs-dropdown-header-color: #adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto}.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;flex-wrap:wrap;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:.5625rem;padding-left:.5625rem}.dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after,.dropend .dropdown-toggle-split:after{margin-left:0}.dropstart .dropdown-toggle-split:before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;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;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;background:none;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion: reduce){.nav-link{transition:none}}.nav-link:hover,.nav-link:focus{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.nav-link.disabled,.nav-link:disabled,.form-designer .formio-component-submit .nav-link.btn.btn-primary{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{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 .nav-link:focus{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius: var(--bs-border-radius);--bs-nav-pills-link-active-color: #fff;--bs-nav-pills-link-active-bg: #0d6efd}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap: 1rem;--bs-nav-underline-border-width: .125rem;--bs-nav-underline-link-active-color: var(--bs-emphasis-color);gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid transparent}.nav-underline .nav-link:hover,.nav-underline .nav-link:focus{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill>.nav-link,.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-justified .nav-item{flex-basis:0;flex-grow:1;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x: 0;--bs-navbar-padding-y: .5rem;--bs-navbar-color: rgba(var(--bs-emphasis-color-rgb), .65);--bs-navbar-hover-color: rgba(var(--bs-emphasis-color-rgb), .8);--bs-navbar-disabled-color: rgba(var(--bs-emphasis-color-rgb), .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%2833, 37, 41, 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), .15);--bs-navbar-toggler-border-radius: var(--bs-border-radius);--bs-navbar-toggler-focus-width: .25rem;--bs-navbar-toggler-transition: box-shadow .15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;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;flex-wrap:inherit;align-items:center;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;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;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text .form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .navbar-text .nav-link,.navbar-text .form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .navbar-text .nav-link,.navbar-text .component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .navbar-text .nav-link,.navbar-text a:hover,.navbar-text a:focus{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color: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{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height, 75vh);overflow-y:auto}@media (min-width: 576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;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;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width: 768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;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;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width: 992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;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{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width: 1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;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;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width: 1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;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;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;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;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color: rgba(255, 255, 255, .55);--bs-navbar-hover-color: rgba(255, 255, 255, .75);--bs-navbar-disabled-color: rgba(255, 255, 255, .25);--bs-navbar-active-color: #fff;--bs-navbar-brand-color: #fff;--bs-navbar-brand-hover-color: #fff;--bs-navbar-toggler-border-color: rgba(255, 255, 255, .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.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y: 1rem;--bs-card-spacer-x: 1rem;--bs-card-title-spacer-y: .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: var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius: calc(var(--bs-border-radius) - (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), .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;flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;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{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{margin-bottom:var(--bs-card-group-margin)}@media (min-width: 576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer{border-bottom-left-radius:0}}.accordion{--bs-accordion-color: var(--bs-body-color);--bs-accordion-bg: var(--bs-body-bg);--bs-accordion-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, border-radius .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='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width: 1.25rem;--bs-accordion-btn-icon-transform: rotate(-180deg);--bs-accordion-btn-icon-transition: transform .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='%23052c65'%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: #86b7fe;--bs-accordion-btn-focus-box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25);--bs-accordion-body-padding-x: 1.25rem;--bs-accordion-body-padding-y: 1rem;--bs-accordion-active-color: var(--bs-primary-text-emphasis);--bs-accordion-active-bg: var(--bs-primary-bg-subtle)}.accordion-button{position:relative;display:flex;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;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='%236ea8fe'%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='%236ea8fe'%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;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, "/")}.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(13, 110, 253, .25);--bs-pagination-active-color: #fff;--bs-pagination-active-bg: #0d6efd;--bs-pagination-active-border-color: #0d6efd;--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;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;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion: reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.page-link.active,.active>.page-link{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.page-link.disabled,.disabled>.page-link{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(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-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: #0d6efd;--bs-progress-bar-transition: width .6s ease;display: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;flex-direction:column;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,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.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: #0d6efd;--bs-list-group-active-border-color: #0d6efd;display:flex;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;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,.form-designer .formio-component-submit .list-group-item.btn.btn-primary{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}.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}.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}.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}.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}.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}.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-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(13, 110, 253, .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;color:var(--bs-btn-close-color);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close:disabled,.form-designer .formio-component-submit .btn-close.btn.btn-primary,.btn-close.disabled{pointer-events:none;-webkit-user-select:none;user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white,[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), .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), .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){display:none}.toast-container{--bs-toast-zindex: 1090;position:absolute;z-index:var(--bs-toast-zindex);width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;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: 0 .125rem .25rem rgba(0, 0, 0, .075);--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: 1rem 1rem;--bs-modal-header-border-color: var(--bs-border-color);--bs-modal-header-border-width: var(--bs-border-width);--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: var(--bs-border-width);position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transition:transform .3s ease-out;transform:translateY(-50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex: 1050;--bs-backdrop-bg: #000;--bs-backdrop-opacity: .5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;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;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width: 576px){.modal{--bs-modal-margin: 1.75rem;--bs-modal-box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width: 300px}}@media (min-width: 992px){.modal-lg,.modal-xl{--bs-modal-width: 800px}}@media (min-width: 1200px){.modal-xl{--bs-modal-width: 1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-header,.modal-fullscreen .modal-footer{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width: 575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-header,.modal-fullscreen-sm-down .modal-footer{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width: 767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-header,.modal-fullscreen-md-down .modal-footer{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width: 991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-header,.modal-fullscreen-lg-down .modal-footer{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width: 1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-header,.modal-fullscreen-xl-down .modal-footer{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width: 1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-header,.modal-fullscreen-xxl-down .modal-footer{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex: 1080;--bs-tooltip-max-width: 200px;--bs-tooltip-padding-x: .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:var(--bs-font-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{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: 0 .5rem 1rem rgba(0, 0, 0, .15);--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:var(--bs-font-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}.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;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:translate(100%)}.carousel-item-prev:not(.carousel-item-end),.active.carousel-item-start{transform:translate(-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;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:none;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%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;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;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 .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)}}.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: 0 .125rem .25rem rgba(0, 0, 0, .075);--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;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:translate(-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:translate(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.showing,.offcanvas-sm.show:not(.hiding){transform:none}.offcanvas-sm.showing,.offcanvas-sm.hiding,.offcanvas-sm.show{visibility:visible}}@media (min-width: 576px){.offcanvas-sm{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;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;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:translate(-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:translate(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.showing,.offcanvas-md.show:not(.hiding){transform:none}.offcanvas-md.showing,.offcanvas-md.hiding,.offcanvas-md.show{visibility:visible}}@media (min-width: 768px){.offcanvas-md{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;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;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:translate(-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:translate(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.showing,.offcanvas-lg.show:not(.hiding){transform:none}.offcanvas-lg.showing,.offcanvas-lg.hiding,.offcanvas-lg.show{visibility:visible}}@media (min-width: 992px){.offcanvas-lg{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;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;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:translate(-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:translate(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.showing,.offcanvas-xl.show:not(.hiding){transform:none}.offcanvas-xl.showing,.offcanvas-xl.hiding,.offcanvas-xl.show{visibility:visible}}@media (min-width: 1200px){.offcanvas-xl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;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;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:translate(-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:translate(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.showing,.offcanvas-xxl.show:not(.hiding){transform:none}.offcanvas-xxl.showing,.offcanvas-xxl.hiding,.offcanvas-xxl.show{visibility:visible}}@media (min-width: 1400px){.offcanvas-xxl{--bs-offcanvas-height: auto;--bs-offcanvas-border-width: 0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;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;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:translate(-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:translate(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.showing,.offcanvas.show:not(.hiding){transform:none}.offcanvas.showing,.offcanvas.hiding,.offcanvas.show{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;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;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{-webkit-mask-image:linear-gradient(130deg,#000 55%,#000c,#000 95%);mask-image:linear-gradient(130deg,#000 55%,#000c,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{to{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix:after{display:block;clear:both;content:""}.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-primary{color:RGBA(var(--bs-primary-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity, 1))!important}.link-primary:hover,.link-primary:focus{color:RGBA(10,88,202,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity, 1))!important}.link-secondary{color:RGBA(var(--bs-secondary-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity, 1))!important}.link-secondary:hover,.link-secondary:focus{color:RGBA(86,94,100,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity, 1))!important}.link-success{color:RGBA(var(--bs-success-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity, 1))!important}.link-success:hover,.link-success:focus{color:RGBA(20,108,67,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity, 1))!important}.link-info{color:RGBA(var(--bs-info-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity, 1))!important}.link-info:hover,.link-info:focus{color:RGBA(61,213,243,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity, 1))!important}.link-warning{color:RGBA(var(--bs-warning-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity, 1))!important}.link-warning:hover,.link-warning:focus{color:RGBA(255,205,57,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity, 1))!important}.link-danger{color:RGBA(var(--bs-danger-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity, 1))!important}.link-danger:hover,.link-danger:focus{color:RGBA(176,42,55,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity, 1))!important}.link-light{color:RGBA(var(--bs-light-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity, 1))!important}.link-light:hover,.link-light:focus{color:RGBA(249,250,251,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity, 1))!important}.link-dark{color:RGBA(var(--bs-dark-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity, 1))!important}.link-dark:hover,.link-dark:focus{color:RGBA(26,30,33,var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity, 1))!important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity, 1))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity, 1))!important}.link-body-emphasis:hover,.link-body-emphasis:focus{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity, .75))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity, .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;text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity, .5));text-underline-offset:.25em;backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media (prefers-reduced-motion: reduce){.icon-link>.bi{transition:none}}.icon-link-hover:hover>.bi,.icon-link-hover:focus-visible>.bi{transform:var(--bs-icon-link-transform, translate3d(.25em, 0, 0))}.ratio{position:relative;width:100%}.ratio:before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio: 100%}.ratio-4x3{--bs-aspect-ratio: 75%}.ratio-16x9{--bs-aspect-ratio: 56.25%}.ratio-21x9{--bs-aspect-ratio: 42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:sticky;top:0;z-index:1020}.sticky-bottom{position:sticky;bottom:0;z-index:1020}@media (min-width: 576px){.sticky-sm-top{position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width: 768px){.sticky-md-top{position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width: 992px){.sticky-lg-top{position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width: 1200px){.sticky-xl-top{position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:sticky;bottom:0;z-index:1020}}@media (min-width: 1400px){.sticky-xxl-top{position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;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;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!important}.float-end{float:right!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-scroll{overflow:scroll!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!important}.shadow{box-shadow:0 .5rem 1rem #00000026!important}.shadow-sm{box-shadow:0 .125rem .25rem #00000013!important}.shadow-lg{box-shadow:0 1rem 3rem #0000002d!important}.shadow-none{box-shadow:none!important}.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))}.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:translate(-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-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}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!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}.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-between{align-content:space-between!important}.align-content-around{align-content:space-around!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-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}.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}.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}.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-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}.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-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-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-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-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.375rem + 1.5vw)!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-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity: 1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity: 1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity: 1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity: 1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity: 1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity: 1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity: 1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity: 1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity: 1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity: 1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)!important}.text-black-50{--bs-text-opacity: 1;color:#00000080!important}.text-white-50{--bs-text-opacity: 1;color:#ffffff80!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,.link-opacity-10-hover:hover{--bs-link-opacity: .1}.link-opacity-25,.link-opacity-25-hover:hover{--bs-link-opacity: .25}.link-opacity-50,.link-opacity-50-hover:hover{--bs-link-opacity: .5}.link-opacity-75,.link-opacity-75-hover:hover{--bs-link-opacity: .75}.link-opacity-100,.link-opacity-100-hover:hover{--bs-link-opacity: 1}.link-offset-1,.link-offset-1-hover:hover{text-underline-offset:.125em!important}.link-offset-2,.link-offset-2-hover:hover{text-underline-offset:.25em!important}.link-offset-3,.link-offset-3-hover:hover{text-underline-offset:.375em!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,.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity: 0}.link-underline-opacity-10,.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity: .1}.link-underline-opacity-25,.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity: .25}.link-underline-opacity-50,.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity: .5}.link-underline-opacity-75,.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity: .75}.link-underline-opacity-100,.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity: 1}.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:transparent!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{-webkit-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;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-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-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}}@media (min-width: 1200px){.fs-1{font-size:2.5rem!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}}body{display:flex;flex-direction:column}body>.v-content{flex:1 0 auto}.v-application{font-family:-apple-system,BlinkMacSystemFont,BCSans,Roboto,Verdana,Arial,sans-serif!important;line-height:1.4;font-size:.875rem}h1,.h1{font-size:1.9em}h2,.h2{font-size:1.7em}h3,.h3{font-size:1.3em}h4,.h4{font-size:1.05em}h1,.h1,h2,.h2,h3,.h3,h4,.h4,h5,.h5{color:#313132;line-height:1.2;font-weight:700}p{color:#313132;line-height:1.7}a,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link{color:#1a5a96}a:hover,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover{color:#3b99fc}hr{margin-bottom:1em}hr .orange{border-top:2px solid #fcba19}.component-fade-enter-active,.component-fade-leave-active{transition:opacity .3s ease}.component-fade-enter,.component-fade-leave-to{opacity:0}a,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.v-tab{text-decoration:none}a:hover,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover,.v-tab:hover{text-decoration:underline}a:hover button,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover button,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover button,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover button,a:hover .v-icon,.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover .v-icon,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover .v-icon,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link:hover .v-icon,.v-tab:hover button,.v-tab:hover .v-icon{text-decoration:none}.v-btn span>span,.form-designer .btn span>span,.form-wrapper .btn span>span,.component-preview .btn span>span{font-weight:700}.v-btn:hover,.form-designer .btn:hover,.form-wrapper .btn:hover,.component-preview .btn:hover{opacity:.8}.v-btn:hover span>span,.form-designer .btn:hover span>span,.form-wrapper .btn:hover span>span,.component-preview .btn:hover span>span{text-decoration:underline}.v-btn.v-btn--disabled,.form-designer .v-btn.btn.btn-primary:disabled,.form-designer .formio-component-submit .v-btn.btn.btn-primary,.form-designer .v-btn.btn.btn-primary[disabled=disabled],.form-wrapper .v-btn.btn.btn-primary:disabled,.form-wrapper .form-designer .formio-component-submit .v-btn.btn.btn-primary,.form-designer .formio-component-submit .form-wrapper .v-btn.btn.btn-primary,.form-wrapper .v-btn.btn.btn-primary[disabled=disabled],.component-preview .v-btn.btn.btn-primary:disabled,.component-preview .form-designer .formio-component-submit .v-btn.btn.btn-primary,.form-designer .formio-component-submit .component-preview .v-btn.btn.btn-primary,.component-preview .v-btn.btn.btn-primary[disabled=disabled],.form-designer .v-btn--disabled.btn,.form-designer .btn.btn-primary:disabled,.form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .form-designer .btn.btn-primary:hover,.form-designer .form-wrapper .btn.btn-primary:disabled,.form-designer .form-wrapper .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .form-wrapper .btn.btn-primary,.form-designer .form-wrapper .formio-component-submit .btn.btn-primary:hover,.form-designer .formio-component-submit .form-wrapper .btn.btn-primary:hover,.form-wrapper .form-designer .btn.btn-primary:disabled,.form-wrapper .form-designer .formio-component-submit .btn.btn-primary,.form-wrapper .form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .form-wrapper .btn.btn-primary[disabled=disabled],.form-wrapper .form-designer .btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .form-wrapper .btn.btn-primary:hover,.form-designer .component-preview .btn.btn-primary:disabled,.form-designer .component-preview .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .component-preview .btn.btn-primary,.form-designer .component-preview .formio-component-submit .btn.btn-primary:hover,.form-designer .formio-component-submit .component-preview .btn.btn-primary:hover,.component-preview .form-designer .btn.btn-primary:disabled,.component-preview .form-designer .formio-component-submit .btn.btn-primary,.component-preview .form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .component-preview .btn.btn-primary[disabled=disabled],.component-preview .form-designer .btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .component-preview .btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled] .form-designer .btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled] .form-designer .btn.btn-primary:hover,.form-wrapper .v-btn--disabled.btn,.form-wrapper .btn.btn-primary:disabled,.form-wrapper .btn.btn-primary[disabled=disabled],.form-wrapper .component-preview .btn.btn-primary:disabled,.form-wrapper .component-preview .form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .form-wrapper .component-preview .btn.btn-primary,.form-wrapper .component-preview .form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .formio-component-submit .form-wrapper .component-preview .btn.btn-primary:hover,.component-preview .form-wrapper .btn.btn-primary:disabled,.component-preview .form-wrapper .form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .component-preview .form-wrapper .btn.btn-primary,.component-preview .form-wrapper .form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .formio-component-submit .component-preview .form-wrapper .btn.btn-primary:hover,.form-wrapper .component-preview .btn.btn-primary[disabled=disabled],.component-preview .form-wrapper .btn.btn-primary[disabled=disabled],.form-wrapper .btn.btn-primary[disabled=disabled] .form-wrapper .btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled] .component-preview .btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled] .form-wrapper .btn.btn-primary:hover,.component-preview .v-btn--disabled.btn,.component-preview .btn.btn-primary:disabled,.component-preview .btn.btn-primary[disabled=disabled],.component-preview .btn.btn-primary[disabled=disabled] .component-preview .btn.btn-primary:hover{color:#777}.v-btn.v-btn--outlined,.form-designer .v-btn--outlined.btn,.form-wrapper .v-btn--outlined.btn,.component-preview .v-btn--outlined.btn{border:2px solid #fff}.v-btn.v-btn--outlined.v-btn--disabled,.form-designer .v-btn.v-btn--outlined.btn.btn-primary:disabled,.form-designer .v-btn.v-btn--outlined.btn.btn-primary[disabled=disabled],.form-wrapper .v-btn.v-btn--outlined.btn.btn-primary:disabled,.form-wrapper .v-btn.v-btn--outlined.btn.btn-primary[disabled=disabled],.component-preview .v-btn.v-btn--outlined.btn.btn-primary:disabled,.component-preview .v-btn.v-btn--outlined.btn.btn-primary[disabled=disabled],.form-designer .v-btn--outlined.v-btn--disabled.btn,.form-designer .v-btn--outlined.btn.btn-primary:disabled,.form-designer .formio-component-submit .v-btn--outlined.btn.btn-primary,.form-designer .v-btn--outlined.btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .form-designer .v-btn--outlined.btn.btn-primary:hover,.form-designer .form-wrapper .v-btn--outlined.btn.btn-primary:disabled,.form-designer .form-wrapper .formio-component-submit .v-btn--outlined.btn.btn-primary,.form-designer .formio-component-submit .form-wrapper .v-btn--outlined.btn.btn-primary,.form-wrapper .form-designer .v-btn--outlined.btn.btn-primary:disabled,.form-wrapper .form-designer .formio-component-submit .v-btn--outlined.btn.btn-primary,.form-designer .form-wrapper .v-btn--outlined.btn.btn-primary[disabled=disabled],.form-wrapper .form-designer .v-btn--outlined.btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .form-wrapper .v-btn--outlined.btn.btn-primary:hover,.form-designer .component-preview .v-btn--outlined.btn.btn-primary:disabled,.form-designer .component-preview .formio-component-submit .v-btn--outlined.btn.btn-primary,.form-designer .formio-component-submit .component-preview .v-btn--outlined.btn.btn-primary,.component-preview .form-designer .v-btn--outlined.btn.btn-primary:disabled,.component-preview .form-designer .formio-component-submit .v-btn--outlined.btn.btn-primary,.form-designer .component-preview .v-btn--outlined.btn.btn-primary[disabled=disabled],.component-preview .form-designer .v-btn--outlined.btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .component-preview .v-btn--outlined.btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled] .form-designer .v-btn--outlined.btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled] .form-designer .v-btn--outlined.btn.btn-primary:hover,.form-wrapper .v-btn--outlined.v-btn--disabled.btn,.form-wrapper .v-btn--outlined.btn.btn-primary:disabled,.form-wrapper .v-btn--outlined.btn.btn-primary[disabled=disabled],.form-wrapper .component-preview .v-btn--outlined.btn.btn-primary:disabled,.component-preview .form-wrapper .v-btn--outlined.btn.btn-primary:disabled,.form-wrapper .component-preview .v-btn--outlined.btn.btn-primary[disabled=disabled],.component-preview .form-wrapper .v-btn--outlined.btn.btn-primary[disabled=disabled],.form-wrapper .btn.btn-primary[disabled=disabled] .form-wrapper .v-btn--outlined.btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled] .component-preview .v-btn--outlined.btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled] .form-wrapper .v-btn--outlined.btn.btn-primary:hover,.component-preview .v-btn--outlined.v-btn--disabled.btn,.component-preview .v-btn--outlined.btn.btn-primary:disabled,.component-preview .v-btn--outlined.btn.btn-primary[disabled=disabled],.component-preview .btn.btn-primary[disabled=disabled] .component-preview .v-btn--outlined.btn.btn-primary:hover{border-color:#00000042}.v-tooltip>.v-overlay__content{background:#616161e6!important}.nrmc-expand-collapse{width:100%;min-height:50px}.nrmc-expand-collapse .v-expansion-panel--active{margin-bottom:20px}.nrmc-expand-collapse .v-expansion-panel--active>.v-expansion-panel-title{min-height:50px}.nrmc-expand-collapse .v-expansion-panel-title{padding:10px;background-color:#efefef}.nrmc-expand-collapse .v-expansion-panel-title .icon{order:0}.nrmc-expand-collapse .v-expansion-panel-title .header{order:1;display:flex;align-items:center;justify-content:space-between;flex:1 auto}.v-stepper-header{box-shadow:none!important}.form-designer div[class^=col-]:nth-child(n+1),.form-wrapper div[class^=col-]:nth-child(n+1),.component-preview div[class^=col-]:nth-child(n+1){padding-top:0}.form-designer .card-header,.form-wrapper .card-header,.component-preview .card-header{font-weight:700;color:#313132;opacity:1}.form-designer .card-header .fa-minus-square-o:before,.form-designer .card-header .fa-plus-square-o:before,.form-wrapper .card-header .fa-minus-square-o:before,.form-wrapper .card-header .fa-plus-square-o:before,.component-preview .card-header .fa-minus-square-o:before,.component-preview .card-header .fa-plus-square-o:before{font-size:130%;color:#000}.form-designer .card-header .fa-minus-square-o:before,.form-wrapper .card-header .fa-minus-square-o:before,.component-preview .card-header .fa-minus-square-o:before{content:""}.form-designer .card-header .fa-plus-square-o:before,.form-wrapper .card-header .fa-plus-square-o:before,.component-preview .card-header .fa-plus-square-o:before{content:""}.form-designer .formio-component .table,.form-wrapper .formio-component .table,.component-preview .formio-component .table{word-break:break-word}.form-designer .btn.btn-danger,.form-wrapper .btn.btn-danger,.component-preview .btn.btn-danger{background-color:#e35f6c;border-color:#e35f6c}.form-designer .btn.btn-secondary,.form-wrapper .btn.btn-secondary,.component-preview .btn.btn-secondary{background-color:#848d94;border-color:#848d94}.form-designer .btn.btn-success,.form-wrapper .btn.btn-success,.component-preview .btn.btn-success{background-color:#1d9f63;border-color:#1d9f63}.form-designer .formio-error-wrapper,.form-wrapper .formio-error-wrapper,.component-preview .formio-error-wrapper{background-color:transparent}.form-designer .formio-error-wrapper,.form-designer .formio-warning-wrapper,.form-wrapper .formio-error-wrapper,.form-wrapper .formio-warning-wrapper,.component-preview .formio-error-wrapper,.component-preview .formio-warning-wrapper{padding:0}.form-designer .formio-component-simpletabs>.card,.form-wrapper .formio-component-simpletabs>.card,.component-preview .formio-component-simpletabs>.card{border:0}.form-designer .formio-component-simpletabs>.card>.card-body,.form-wrapper .formio-component-simpletabs>.card>.card-body,.component-preview .formio-component-simpletabs>.card>.card-body{border-style:solid;border-color:#00000020;border-width:0 1px 1px 1px;border-radius:0}.form-designer .formio-component-simpletabs>.card>.card-header,.form-wrapper .formio-component-simpletabs>.card>.card-header,.component-preview .formio-component-simpletabs>.card>.card-header{background:none}.form-designer .formio-component-simpletabs>.card>.card-header .nav-item,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item{background-color:#efefef;margin-right:3px}.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link{font-weight:400}.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link.active,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link.active,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link.active{color:#313132;background:#fff}.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .nav-link.active:hover,.form-wrapper .formio-component-simpletabs>.card>.card-header .nav-item .nav-link.active:hover,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .nav-link.active:hover{color:#313132;cursor:default;text-decoration:none}.form-designer .form-control::placeholder,.form-designer .form-control .choices__placeholder,.form-wrapper .form-control::placeholder,.form-wrapper .form-control .choices__placeholder,.component-preview .form-control::placeholder,.component-preview .form-control .choices__placeholder{color:#606060;opacity:inherit}.form-designer .form-control:not(.is-invalid),.form-wrapper .form-control:not(.is-invalid),.component-preview .form-control:not(.is-invalid){border:1px solid #606060}.form-designer .form-control.is-invalid,.form-designer .was-validated .form-control:invalid,.form-wrapper .form-control.is-invalid,.form-wrapper .was-validated .form-control:invalid,.component-preview .form-control.is-invalid,.component-preview .was-validated .form-control:invalid{background-image:none}.form-designer .input-group>.flatpickr-input.form-control+.form-control.input,.form-wrapper .input-group>.flatpickr-input.form-control+.form-control.input,.component-preview .input-group>.flatpickr-input.form-control+.form-control.input{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.form-designer .input-group>.flatpickr-input.form-control.is-invalid+.form-control.input,.form-wrapper .input-group>.flatpickr-input.form-control.is-invalid+.form-control.input,.component-preview .input-group>.flatpickr-input.form-control.is-invalid+.form-control.input{border:1px solid #dc3545}.form-designer .input-group>.flatpickr-input.form-control.is-invalid+.form-control.input:focus,.form-wrapper .input-group>.flatpickr-input.form-control.is-invalid+.form-control.input:focus,.component-preview .input-group>.flatpickr-input.form-control.is-invalid+.form-control.input:focus{border-color:#dc3545;-webkit-box-shadow:0 0 0 .2rem rgba(220,53,69,.25);box-shadow:0 0 0 .2rem #dc354540}.form-designer .btn.btn-primary,.form-wrapper .btn.btn-primary,.component-preview .btn.btn-primary{background-color:#036;border:none;color:#fff}.form-designer .btn.btn-primary:hover,.form-wrapper .btn.btn-primary:hover,.component-preview .btn.btn-primary:hover{background-color:#036;text-decoration:underline}.form-designer .btn.btn-primary:disabled,.form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .form-designer .btn.btn-primary:hover,.form-wrapper .btn.btn-primary:disabled,.form-wrapper .form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .form-wrapper .btn.btn-primary,.form-wrapper .form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .formio-component-submit .form-wrapper .btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .form-wrapper .btn.btn-primary:hover,.component-preview .btn.btn-primary:disabled,.component-preview .form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .component-preview .btn.btn-primary,.component-preview .form-designer .formio-component-submit .btn.btn-primary:hover,.form-designer .formio-component-submit .component-preview .btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled],.form-designer .btn.btn-primary[disabled=disabled] .component-preview .btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled] .form-designer .btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled] .form-wrapper .btn.btn-primary:hover,.form-wrapper .btn.btn-primary[disabled=disabled] .component-preview .btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled] .form-designer .btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled] .form-wrapper .btn.btn-primary:hover,.component-preview .btn.btn-primary[disabled=disabled] .component-preview .btn.btn-primary:hover{cursor:default;text-decoration:none;background-color:#0000001f;opacity:1;color:#00000042!important}.form-designer .formio-component-button .btn,.form-wrapper .formio-component-button .btn,.component-preview .formio-component-button .btn{text-transform:uppercase;padding:8px 16px;line-height:21px;font-weight:700;letter-spacing:.0892857143em;font-size:.875rem}.form-designer .formio-component-button,.form-wrapper .formio-component-button,.component-preview .formio-component-button{margin-top:1rem}.form-designer .tooltip-inner,.form-wrapper .tooltip-inner,.component-preview .tooltip-inner{background-color:#606060;border-radius:3px;box-shadow:0 2px 8px #afafaf80;font-size:.85em}.form-designer .form-text,.form-wrapper .form-text,.component-preview .form-text{font-size:.85em}.form-designer .invalid-feedback,.form-wrapper .invalid-feedback,.component-preview .invalid-feedback{font-size:100%}.form-designer .form-text.error,.form-wrapper .form-text.error,.component-preview .form-text.error{background:none!important;color:#d8292f}.form-designer .formio-component-datagrid label.field-required.control-label--hidden:after,.form-wrapper .formio-component-datagrid label.field-required.control-label--hidden:after,.component-preview .formio-component-datagrid label.field-required.control-label--hidden:after{content:""}.form-designer .choices__list--dropdown .choices__item:not(.is-selected),.form-wrapper .choices__list--dropdown .choices__item:not(.is-selected),.component-preview .choices__list--dropdown .choices__item:not(.is-selected){color:#313132}.form-designer .choices__list--dropdown .choices__item:hover,.form-wrapper .choices__list--dropdown .choices__item:hover,.component-preview .choices__list--dropdown .choices__item:hover{background-color:#3b99fc;color:#fff}.form-designer .choices__list--multiple .choices__item,.form-wrapper .choices__list--multiple .choices__item,.component-preview .choices__list--multiple .choices__item{margin-bottom:0;font-size:90%}.form-designer .choices__list--multiple .choices__item,.form-designer .choices__list--multiple .choices__button,.form-wrapper .choices__list--multiple .choices__item,.form-wrapper .choices__list--multiple .choices__button,.component-preview .choices__list--multiple .choices__item,.component-preview .choices__list--multiple .choices__button{background-color:#fff;color:#1a5a96;border-color:#1a5a96}.form-designer .choices__list--multiple .choices__item:hover,.form-designer .choices__list--multiple .choices__button:hover,.form-wrapper .choices__list--multiple .choices__item:hover,.form-wrapper .choices__list--multiple .choices__button:hover,.component-preview .choices__list--multiple .choices__item:hover,.component-preview .choices__list--multiple .choices__button:hover{background-color:#3b99fc;border-color:#3b99fc;color:#fff}.form-designer .choices__placeholder button,.form-wrapper .choices__placeholder button,.component-preview .choices__placeholder button{display:none}.form-designer .form-radio .form-check,.form-wrapper .form-radio .form-check,.component-preview .form-radio .form-check{margin-bottom:5px}.form-designer .form-radio .form-check .form-check-label,.form-wrapper .form-radio .form-check .form-check-label,.component-preview .form-radio .form-check .form-check-label{font-size:1em}.form-designer .form-radio .form-check .form-check-label .form-check-input,.form-wrapper .form-radio .form-check .form-check-label .form-check-input,.component-preview .form-radio .form-check .form-check-label .form-check-input{transform:scale(1.3)}.form-designer .form-radio .form-check .form-check-label span,.form-wrapper .form-radio .form-check .form-check-label span,.component-preview .form-radio .form-check .form-check-label span{margin-left:5px}.form-designer .drag-and-drop-alert.alert-info,.form-wrapper .drag-and-drop-alert.alert-info,.component-preview .drag-and-drop-alert.alert-info{border:2px dashed grey;background-color:transparent;color:gray;padding:30px}.form-designer .formio-component-submit .btn.btn-primary,.form-designer .formio-component-submit .btn.btn-primary:hover{background-color:#0000001f}.form-designer .formio-component-file .fileSelector{margin-left:24px}.formcomponents .builder-sidebar{top:125px}.formcomponents .builder-sidebar .form-builder-panel .formcomponent.btn-block{width:100%}.form-wrapper .formio-component-file .fileSelector,.form-wrapper .formio-component-file .file .row{margin-left:24px}.formio-dialog-content .component-edit-container{overflow:visible}.formio-dialog-content .component-edit-container .choices__list.choices__list--dropdown{overflow:auto}.formio-dialog-content .component-edit-container .choices__list.choices__list--dropdown div.choices__list{max-height:175px}.btn-primary.formcomponent.drag-copy,.btn-primary.formcomponent.drag-copy:hover,.formcomponent.drag-copy:active{background-color:#e4f2ff;color:#036;font-size:.8rem;border:none}.drag-container .btn-primary.formcomponent.drag-copy{opacity:.3;color:#fff;background:#036}.info-helper{color:#00000061;margin-top:2px}.info-helper:hover{color:#01254a}.v-tooltip>.v-overlay__content{pointer-events:auto!important}.preview_info_link_field_white{color:#fff!important;text-decoration:underline}.center_vertical_content{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:300px}.label .v-label{right:0!important;left:auto!important}.label span{margin-right:30px}.flex-xs-column-reverse{flex-direction:column-reverse}.flex-xs-column{flex-direction:column}.dir-rtl{direction:rtl!important;text-align:right}.dir-ltl{direction:ltr!important;text-align:left}.v-skeleton-loader{background:none!important;display:block!important}.submissions-table tbody tr:nth-child(odd) td{background-color:#f5f5f5!important}.v-table.v-table--hover>.v-table__wrapper>table>tbody>tr:hover td{background-color:#eee!important}.v-data-table,.v-data-table-server,.v-table{font-size:16px!important}.v-select .v-field__input{padding-top:0!important;padding-bottom:0!important;margin-top:0!important;margin-bottom:0!important}.v-select .v-list-item--density-default{min-height:38px!important}.vselect .v-label{opacity:1!important}.form-wrapper.disable-file-downloads .formio-form .formio-component-simplefile a[href],.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .form-wrapper.disable-file-downloads .formio-form .formio-component-simplefile [href].nav-link,.form-wrapper.disable-file-downloads .formio-form .formio-component-simplefile .formio-component-simpletabs>.card>.card-header .nav-item [href].nav-link,.form-wrapper.disable-file-downloads .formio-component-simpletabs>.card>.card-header .nav-item .formio-form .formio-component-simplefile [href].nav-link,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .form-wrapper.disable-file-downloads .formio-form .formio-component-simplefile [href].nav-link,.form-wrapper.disable-file-downloads .formio-form .formio-component-file a[href],.form-designer .formio-component-simpletabs>.card>.card-header .nav-item .form-wrapper.disable-file-downloads .formio-form .formio-component-file [href].nav-link,.form-wrapper.disable-file-downloads .formio-form .formio-component-file .formio-component-simpletabs>.card>.card-header .nav-item [href].nav-link,.form-wrapper.disable-file-downloads .formio-component-simpletabs>.card>.card-header .nav-item .formio-form .formio-component-file [href].nav-link,.component-preview .formio-component-simpletabs>.card>.card-header .nav-item .form-wrapper.disable-file-downloads .formio-form .formio-component-file [href].nav-link{pointer-events:none!important;color:#6c757d!important;text-decoration:none!important;cursor:not-allowed!important}.v-window,.v-stepper.v-sheet{overflow:visible!important}.status-overlay{position:fixed;z-index:9999;top:0;left:0;right:0;bottom:0;background:#000000b3;display:flex;align-items:center;justify-content:center;pointer-events:all}.status-overlay .status-content{background:#fff;border:1px solid #000;border-radius:8px;box-shadow:0 4px 8px #0003;padding:0;width:95vw;max-width:800px;min-width:320px;max-height:80vh;min-height:180px;overflow:auto;display:flex;flex-direction:column;position:relative}.status-overlay .status-content .status-header{font-size:1.25rem;font-weight:700;padding:1em .5em;border-top-left-radius:8px;border-top-right-radius:8px;box-shadow:0 1px #0003;margin-bottom:0;text-align:left;letter-spacing:.5px;height:60px;display:flex}.status-overlay .status-content .status-header i{margin-right:.5em;color:red}.status-overlay .status-content .status-footer{padding:1em .5em;border-bottom-left-radius:8px;border-bottom-right-radius:8px;box-shadow:0 -1px #0003;margin-top:auto;text-align:center;letter-spacing:.5px;height:60px;display:flex;align-items:right;justify-content:right}.status-overlay .status-content .chefs-unavailable-message,.status-overlay .status-content .moreinfo-intro,.status-overlay .status-content .moreinfo-outro{margin:1em .75em;font-size:1.1em;padding:.75em 1em}.status-overlay .status-content .moreinfo-outro{font-size:.95em}.status-overlay .status-content h2,.status-overlay .status-content .h2{margin-top:0}.status-overlay .status-content .info-links{font-size:.95em}.status-overlay .status-content .info-links button{color:#036;text-decoration:underline;background:none;border:none;cursor:pointer;padding:0;margin:0 .5em 0 0}.status-overlay .status-content .info-links button:hover{color:#005b96}.status-overlay .status-content .status-connections-table{width:90%;margin:1em auto;border-collapse:collapse;font-size:16px!important}.status-overlay .status-content .status-connections-table th,.status-overlay .status-content .status-connections-table td{padding:.5em 1em;border-bottom:1px solid #eee;text-align:left}.status-overlay .status-content .status-connections-table th{background:#f6f8fa;font-weight:700;color:#036!important;font-size:1.1em!important}.status-overlay .status-content .status-connections-table tr:hover td{background-color:#eee!important}@media (min-width: 600px){.status-overlay{padding-bottom:2.5em}.status-overlay .status-content{width:600px;min-width:400px;max-width:900px;min-height:200px}}@media (min-width: 900px){.status-overlay{padding-bottom:3em}.status-overlay .status-content{width:800px;min-width:600px;max-width:1100px;min-height:220px}}.notification-container[data-v-afc8daa4]{z-index:999;position:fixed;top:0;left:25%;margin-top:15px;width:50%}.v-icon{--v-icon-size-multiplier: 1;align-items:center;display:inline-flex;font-feature-settings:"liga";height:1em;justify-content:center;letter-spacing:normal;line-height:1;position:relative;text-indent:0;text-align:center;-webkit-user-select:none;user-select:none;vertical-align:middle;width:1em;min-width:1em}.v-icon--clickable{cursor:pointer}.v-icon--disabled{pointer-events:none;opacity:.38}.v-icon--size-x-small{font-size:calc(var(--v-icon-size-multiplier) * 1em)}.v-icon--size-small{font-size:calc(var(--v-icon-size-multiplier) * 1.25em)}.v-icon--size-default{font-size:calc(var(--v-icon-size-multiplier) * 1.5em)}.v-icon--size-large{font-size:calc(var(--v-icon-size-multiplier) * 1.75em)}.v-icon--size-x-large{font-size:calc(var(--v-icon-size-multiplier) * 2em)}.v-icon__svg{fill:currentColor;width:100%;height:100%}.v-icon--start{margin-inline-end:8px}.v-icon--end{margin-inline-start:8px}@media print{.elevation-20[data-v-2ea320ca]{box-shadow:0 0!important}}.gov-header .printHeader[data-v-2ea320ca]{align-items:center}.gov-header .printHeader img[data-v-2ea320ca]{width:10rem;height:3.5rem}.gov-header .printHeader .text-h6[data-v-2ea320ca]{color:inherit}@media not print{.gov-header[data-v-2ea320ca]{border-bottom:2px solid #fcba19}}.gov-header .text-h6[data-v-2ea320ca]{font-family:inherit!important;color:#fff;overflow:hidden;margin-bottom:0}@media (max-width: 959.98px){.gov-header .text-h6[data-v-2ea320ca]{font-size:1rem!important}}.v-container{width:100%;padding:16px;margin-right:auto;margin-left:auto}@media (min-width: 960px){.v-container{max-width:900px}}@media (min-width: 1280px){.v-container{max-width:1200px}}@media (min-width: 1920px){.v-container{max-width:1800px}}@media (min-width: 2560px){.v-container{max-width:2400px}}.v-container--fluid{max-width:100%}.v-container.fill-height{align-items:center;display:flex;flex-wrap:wrap}.v-row{display:flex;flex-wrap:wrap;flex:1 1 auto;margin:-12px}.v-row+.v-row{margin-top:12px}.v-row+.v-row--dense{margin-top:4px}.v-row--dense{margin:-4px}.v-row--dense>.v-col,.v-row--dense>[class*=v-col-]{padding:4px}.v-row.v-row--no-gutters{margin:0}.v-row.v-row--no-gutters>.v-col,.v-row.v-row--no-gutters>[class*=v-col-]{padding:0}.v-spacer{flex-grow:1}.v-col-xxl,.v-col-xxl-auto,.v-col-xxl-12,.v-col-xxl-11,.v-col-xxl-10,.v-col-xxl-9,.v-col-xxl-8,.v-col-xxl-7,.v-col-xxl-6,.v-col-xxl-5,.v-col-xxl-4,.v-col-xxl-3,.v-col-xxl-2,.v-col-xxl-1,.v-col-xl,.v-col-xl-auto,.v-col-xl-12,.v-col-xl-11,.v-col-xl-10,.v-col-xl-9,.v-col-xl-8,.v-col-xl-7,.v-col-xl-6,.v-col-xl-5,.v-col-xl-4,.v-col-xl-3,.v-col-xl-2,.v-col-xl-1,.v-col-lg,.v-col-lg-auto,.v-col-lg-12,.v-col-lg-11,.v-col-lg-10,.v-col-lg-9,.v-col-lg-8,.v-col-lg-7,.v-col-lg-6,.v-col-lg-5,.v-col-lg-4,.v-col-lg-3,.v-col-lg-2,.v-col-lg-1,.v-col-md,.v-col-md-auto,.v-col-md-12,.v-col-md-11,.v-col-md-10,.v-col-md-9,.v-col-md-8,.v-col-md-7,.v-col-md-6,.v-col-md-5,.v-col-md-4,.v-col-md-3,.v-col-md-2,.v-col-md-1,.v-col-sm,.v-col-sm-auto,.v-col-sm-12,.v-col-sm-11,.v-col-sm-10,.v-col-sm-9,.v-col-sm-8,.v-col-sm-7,.v-col-sm-6,.v-col-sm-5,.v-col-sm-4,.v-col-sm-3,.v-col-sm-2,.v-col-sm-1,.v-col,.v-col-auto,.v-col-12,.v-col-11,.v-col-10,.v-col-9,.v-col-8,.v-col-7,.v-col-6,.v-col-5,.v-col-4,.v-col-3,.v-col-2,.v-col-1{width:100%;padding:12px}.v-col{flex-basis:0;flex-grow:1;max-width:100%}.v-col-auto{flex:0 0 auto;width:auto;max-width:100%}.v-col-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.v-col-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.v-col-3{flex:0 0 25%;max-width:25%}.v-col-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.v-col-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.v-col-6{flex:0 0 50%;max-width:50%}.v-col-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.v-col-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.v-col-9{flex:0 0 75%;max-width:75%}.v-col-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.v-col-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.v-col-12{flex:0 0 100%;max-width:100%}.offset-1{margin-inline-start:8.3333333333%}.offset-2{margin-inline-start:16.6666666667%}.offset-3{margin-inline-start:25%}.offset-4{margin-inline-start:33.3333333333%}.offset-5{margin-inline-start:41.6666666667%}.offset-6{margin-inline-start:50%}.offset-7{margin-inline-start:58.3333333333%}.offset-8{margin-inline-start:66.6666666667%}.offset-9{margin-inline-start:75%}.offset-10{margin-inline-start:83.3333333333%}.offset-11{margin-inline-start:91.6666666667%}@media (min-width: 600px){.v-col-sm{flex-basis:0;flex-grow:1;max-width:100%}.v-col-sm-auto{flex:0 0 auto;width:auto;max-width:100%}.v-col-sm-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.v-col-sm-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.v-col-sm-3{flex:0 0 25%;max-width:25%}.v-col-sm-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.v-col-sm-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.v-col-sm-6{flex:0 0 50%;max-width:50%}.v-col-sm-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.v-col-sm-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.v-col-sm-9{flex:0 0 75%;max-width:75%}.v-col-sm-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.v-col-sm-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.v-col-sm-12{flex:0 0 100%;max-width:100%}.offset-sm-0{margin-inline-start:0}.offset-sm-1{margin-inline-start:8.3333333333%}.offset-sm-2{margin-inline-start:16.6666666667%}.offset-sm-3{margin-inline-start:25%}.offset-sm-4{margin-inline-start:33.3333333333%}.offset-sm-5{margin-inline-start:41.6666666667%}.offset-sm-6{margin-inline-start:50%}.offset-sm-7{margin-inline-start:58.3333333333%}.offset-sm-8{margin-inline-start:66.6666666667%}.offset-sm-9{margin-inline-start:75%}.offset-sm-10{margin-inline-start:83.3333333333%}.offset-sm-11{margin-inline-start:91.6666666667%}}@media (min-width: 960px){.v-col-md{flex-basis:0;flex-grow:1;max-width:100%}.v-col-md-auto{flex:0 0 auto;width:auto;max-width:100%}.v-col-md-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.v-col-md-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.v-col-md-3{flex:0 0 25%;max-width:25%}.v-col-md-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.v-col-md-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.v-col-md-6{flex:0 0 50%;max-width:50%}.v-col-md-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.v-col-md-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.v-col-md-9{flex:0 0 75%;max-width:75%}.v-col-md-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.v-col-md-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.v-col-md-12{flex:0 0 100%;max-width:100%}.offset-md-0{margin-inline-start:0}.offset-md-1{margin-inline-start:8.3333333333%}.offset-md-2{margin-inline-start:16.6666666667%}.offset-md-3{margin-inline-start:25%}.offset-md-4{margin-inline-start:33.3333333333%}.offset-md-5{margin-inline-start:41.6666666667%}.offset-md-6{margin-inline-start:50%}.offset-md-7{margin-inline-start:58.3333333333%}.offset-md-8{margin-inline-start:66.6666666667%}.offset-md-9{margin-inline-start:75%}.offset-md-10{margin-inline-start:83.3333333333%}.offset-md-11{margin-inline-start:91.6666666667%}}@media (min-width: 1280px){.v-col-lg{flex-basis:0;flex-grow:1;max-width:100%}.v-col-lg-auto{flex:0 0 auto;width:auto;max-width:100%}.v-col-lg-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.v-col-lg-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.v-col-lg-3{flex:0 0 25%;max-width:25%}.v-col-lg-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.v-col-lg-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.v-col-lg-6{flex:0 0 50%;max-width:50%}.v-col-lg-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.v-col-lg-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.v-col-lg-9{flex:0 0 75%;max-width:75%}.v-col-lg-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.v-col-lg-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.v-col-lg-12{flex:0 0 100%;max-width:100%}.offset-lg-0{margin-inline-start:0}.offset-lg-1{margin-inline-start:8.3333333333%}.offset-lg-2{margin-inline-start:16.6666666667%}.offset-lg-3{margin-inline-start:25%}.offset-lg-4{margin-inline-start:33.3333333333%}.offset-lg-5{margin-inline-start:41.6666666667%}.offset-lg-6{margin-inline-start:50%}.offset-lg-7{margin-inline-start:58.3333333333%}.offset-lg-8{margin-inline-start:66.6666666667%}.offset-lg-9{margin-inline-start:75%}.offset-lg-10{margin-inline-start:83.3333333333%}.offset-lg-11{margin-inline-start:91.6666666667%}}@media (min-width: 1920px){.v-col-xl{flex-basis:0;flex-grow:1;max-width:100%}.v-col-xl-auto{flex:0 0 auto;width:auto;max-width:100%}.v-col-xl-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.v-col-xl-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.v-col-xl-3{flex:0 0 25%;max-width:25%}.v-col-xl-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.v-col-xl-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.v-col-xl-6{flex:0 0 50%;max-width:50%}.v-col-xl-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.v-col-xl-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.v-col-xl-9{flex:0 0 75%;max-width:75%}.v-col-xl-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.v-col-xl-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.v-col-xl-12{flex:0 0 100%;max-width:100%}.offset-xl-0{margin-inline-start:0}.offset-xl-1{margin-inline-start:8.3333333333%}.offset-xl-2{margin-inline-start:16.6666666667%}.offset-xl-3{margin-inline-start:25%}.offset-xl-4{margin-inline-start:33.3333333333%}.offset-xl-5{margin-inline-start:41.6666666667%}.offset-xl-6{margin-inline-start:50%}.offset-xl-7{margin-inline-start:58.3333333333%}.offset-xl-8{margin-inline-start:66.6666666667%}.offset-xl-9{margin-inline-start:75%}.offset-xl-10{margin-inline-start:83.3333333333%}.offset-xl-11{margin-inline-start:91.6666666667%}}@media (min-width: 2560px){.v-col-xxl{flex-basis:0;flex-grow:1;max-width:100%}.v-col-xxl-auto{flex:0 0 auto;width:auto;max-width:100%}.v-col-xxl-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.v-col-xxl-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.v-col-xxl-3{flex:0 0 25%;max-width:25%}.v-col-xxl-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.v-col-xxl-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.v-col-xxl-6{flex:0 0 50%;max-width:50%}.v-col-xxl-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.v-col-xxl-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.v-col-xxl-9{flex:0 0 75%;max-width:75%}.v-col-xxl-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.v-col-xxl-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.v-col-xxl-12{flex:0 0 100%;max-width:100%}.offset-xxl-0{margin-inline-start:0}.offset-xxl-1{margin-inline-start:8.3333333333%}.offset-xxl-2{margin-inline-start:16.6666666667%}.offset-xxl-3{margin-inline-start:25%}.offset-xxl-4{margin-inline-start:33.3333333333%}.offset-xxl-5{margin-inline-start:41.6666666667%}.offset-xxl-6{margin-inline-start:50%}.offset-xxl-7{margin-inline-start:58.3333333333%}.offset-xxl-8{margin-inline-start:66.6666666667%}.offset-xxl-9{margin-inline-start:75%}.offset-xxl-10{margin-inline-start:83.3333333333%}.offset-xxl-11{margin-inline-start:91.6666666667%}}.v-img{--v-theme-overlay-multiplier: 3;z-index:0}.v-img--booting .v-responsive__sizer{transition:none}.v-img--rounded{border-radius:4px}.v-img__img,.v-img__picture,.v-img__gradient,.v-img__placeholder,.v-img__error{z-index:-1;position:absolute;top:0;left:0;width:100%;height:100%}.v-img__img--preload{filter:blur(4px)}.v-img__img--contain{object-fit:contain}.v-img__img--cover{object-fit:cover}.v-img__gradient{background-repeat:no-repeat}.v-responsive{display:flex;flex:1 0 auto;max-height:100%;max-width:100%;overflow:hidden;position:relative}.v-responsive--inline{display:inline-flex;flex:0 0 auto}.v-responsive__content{flex:1 0 0px;max-width:100%}.v-responsive__sizer~.v-responsive__content{margin-inline-start:-100%}.v-responsive__sizer{flex:1 0 0px;transition:padding-bottom .2s cubic-bezier(.4,0,.2,1);pointer-events:none}.v-toolbar{align-items:flex-start;display:flex;flex:none;flex-direction:column;justify-content:space-between;max-width:100%;position:relative;transition:.2s cubic-bezier(.4,0,.2,1);transition-property:height,width,transform,max-width,left,right,top,bottom,box-shadow;width:100%;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:0;background:rgb(var(--v-theme-surface-light));color:rgba(var(--v-theme-on-surface-light),var(--v-high-emphasis-opacity))}.v-toolbar--border{border-width:thin;box-shadow:none}.v-toolbar--absolute{position:absolute}.v-toolbar--collapse{max-width:112px;overflow:hidden;border-end-end-radius:24px}.v-toolbar--collapse .v-toolbar-title{display:none}.v-toolbar--flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-toolbar--floating{display:inline-flex}.v-toolbar--rounded{border-radius:4px}.v-toolbar__content,.v-toolbar__extension{align-items:center;display:flex;flex:0 0 auto;position:relative;transition:inherit;width:100%}.v-toolbar__content{overflow:hidden}.v-toolbar__content>.v-btn:first-child{margin-inline-start:10px}.v-toolbar__content>.v-btn:last-child{margin-inline-end:10px}.v-toolbar__content>.v-toolbar-title{margin-inline-start:16px}.v-toolbar--density-prominent .v-toolbar__content{align-items:flex-start}.v-toolbar__image{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;opacity:var(--v-toolbar-image-opacity, 1);transition-property:opacity}.v-toolbar__prepend,.v-toolbar__append{align-items:center;align-self:stretch;display:flex}.v-toolbar__prepend{margin-inline:10px auto}.v-toolbar__append{margin-inline:auto 10px}.v-toolbar-title{flex:1 1;min-width:0;font-size:1.25rem;font-weight:400;letter-spacing:0;line-height:1.75rem;text-transform:none}.v-toolbar--density-prominent .v-toolbar-title{align-self:flex-end;padding-bottom:6px;font-size:1.5rem;font-weight:400;letter-spacing:0;line-height:2.25rem;text-transform:none}.v-toolbar-title__placeholder{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.v-toolbar-items{display:flex;height:inherit;align-self:stretch}.v-toolbar-items>.v-btn{border-radius:0}.navigation-main[data-v-6af847e4]{box-shadow:0 6px 8px -4px #b3b1b3;display:flex;color:#fcba19;background-color:#38598a;width:100%;-webkit-box-shadow:0 6px 8px -4px #b3b1b3;-moz-box-shadow:0 6px 8px -4px #b3b1b3}.navigation-main .nav-holder[data-v-6af847e4]{padding:0}.navigation-main .nav-holder ul[data-v-6af847e4]{display:flex;flex-direction:row;margin:0;color:#fff;list-style:none;margin-left:-1.7rem}.navigation-main .nav-holder ul li a[data-v-6af847e4]{display:flex;font-weight:400;min-height:2rem;color:#fff;padding:.75rem 1rem;text-decoration:none}.navigation-main .nav-holder ul li a[data-v-6af847e4]:focus{outline:none;outline-offset:0}.navigation-main .nav-holder ul li a[data-v-6af847e4]:hover{text-decoration:underline}.navigation-main .nav-holder ul li~li[data-v-6af847e4]{border-left:1px solid #9b9b9b;margin:0}.navigation-main .nav-holder ul .router-link-exact-active[data-v-6af847e4]{background-color:#7ba2cc80;border-bottom:2px solid #fcba19;font-weight:700}.gov-footer[data-v-185ea54b]{background-color:#036!important;border-top:2px solid #fcba19;flex:none;flex-shrink:0;min-height:2.5rem;min-width:100%;padding-bottom:0;padding-top:0}.gov-footer a[data-v-185ea54b]{color:#fff;font-size:1rem}.gov-footer a[data-v-185ea54b]:focus{outline:none}.gov-footer .v-btn__content>span[data-v-185ea54b]{color:#fff;font-size:1rem;font-weight:400;text-decoration:none;text-transform:none}.v-btn{align-items:center;border-radius:4px;display:inline-grid;grid-template-areas:"prepend content append";grid-template-columns:max-content auto max-content;font-weight:500;justify-content:center;letter-spacing:.0892857143em;line-height:normal;max-width:100%;outline:none;position:relative;text-decoration:none;text-indent:.0892857143em;text-transform:uppercase;transition-property:box-shadow,transform,opacity,background;transition-duration:.28s;transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-user-select:none;user-select:none;vertical-align:middle;flex-shrink:0;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0}.v-btn--size-x-small{--v-btn-size: .625rem;--v-btn-height: 20px;font-size:var(--v-btn-size);min-width:36px;padding:0 8px}.v-btn--size-small{--v-btn-size: .75rem;--v-btn-height: 28px;font-size:var(--v-btn-size);min-width:50px;padding:0 12px}.v-btn--size-default{--v-btn-size: .875rem;--v-btn-height: 36px;font-size:var(--v-btn-size);min-width:64px;padding:0 16px}.v-btn--size-large{--v-btn-size: 1rem;--v-btn-height: 44px;font-size:var(--v-btn-size);min-width:78px;padding:0 20px}.v-btn--size-x-large{--v-btn-size: 1.125rem;--v-btn-height: 52px;font-size:var(--v-btn-size);min-width:92px;padding:0 24px}.v-btn.v-btn--density-default{height:calc(var(--v-btn-height) + 0px)}.v-btn.v-btn--density-comfortable{height:calc(var(--v-btn-height) + -8px)}.v-btn.v-btn--density-compact{height:calc(var(--v-btn-height) + -12px)}.v-btn--border{border-width:thin;box-shadow:none}.v-btn--absolute{position:absolute}.v-btn--fixed{position:fixed}.v-btn:hover>.v-btn__overlay{opacity:calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier))}.v-btn:focus-visible>.v-btn__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-btn:focus>.v-btn__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}}.v-btn--active>.v-btn__overlay,.v-btn[aria-haspopup=menu][aria-expanded=true]>.v-btn__overlay{opacity:calc(var(--v-activated-opacity) * var(--v-theme-overlay-multiplier))}.v-btn--active:hover>.v-btn__overlay,.v-btn[aria-haspopup=menu][aria-expanded=true]:hover>.v-btn__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}.v-btn--active:focus-visible>.v-btn__overlay,.v-btn[aria-haspopup=menu][aria-expanded=true]:focus-visible>.v-btn__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-btn--active:focus>.v-btn__overlay,.v-btn[aria-haspopup=menu][aria-expanded=true]:focus>.v-btn__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}}.v-btn--variant-plain,.v-btn--variant-outlined,.v-btn--variant-text,.v-btn--variant-tonal{background:transparent;color:inherit}.v-btn--variant-plain{opacity:.62}.v-btn--variant-plain:focus,.v-btn--variant-plain:hover{opacity:1}.v-btn--variant-plain .v-btn__overlay{display:none}.v-btn--variant-elevated,.v-btn--variant-flat{background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-btn--variant-elevated{box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-btn--variant-flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-btn--variant-outlined{border:thin solid currentColor}.v-btn--variant-text .v-btn__overlay{background:currentColor}.v-btn--variant-tonal .v-btn__underlay{background:currentColor;opacity:var(--v-activated-opacity);border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}@supports selector(:focus-visible){.v-btn:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;border:2px solid currentColor;border-radius:inherit;opacity:0;transition:opacity .2s ease-in-out}.v-btn:focus-visible:after{opacity:calc(.25 * var(--v-theme-overlay-multiplier))}}.v-btn--icon{border-radius:50%;min-width:0;padding:0}.v-btn--icon.v-btn--size-default{--v-btn-size: 1rem}.v-btn--icon.v-btn--density-default{width:calc(var(--v-btn-height) + 12px);height:calc(var(--v-btn-height) + 12px)}.v-btn--icon.v-btn--density-comfortable{width:calc(var(--v-btn-height) + 0px);height:calc(var(--v-btn-height) + 0px)}.v-btn--icon.v-btn--density-compact{width:calc(var(--v-btn-height) + -8px);height:calc(var(--v-btn-height) + -8px)}.v-btn--elevated:hover,.v-btn--elevated:focus{box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-btn--elevated:active{box-shadow:0 5px 5px -3px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 8px 10px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 3px 14px 2px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-btn--flat{box-shadow:none}.v-btn--block{display:flex;flex:1 0 auto;min-width:100%}.v-btn--disabled{pointer-events:none;opacity:.26}.v-btn--disabled:hover{opacity:.26}.v-btn--disabled.v-btn--variant-elevated,.v-btn--disabled.v-btn--variant-flat{box-shadow:none;opacity:1;color:rgba(var(--v-theme-on-surface),.26);background:rgb(var(--v-theme-surface))}.v-btn--disabled.v-btn--variant-elevated .v-btn__overlay,.v-btn--disabled.v-btn--variant-flat .v-btn__overlay{opacity:.4615384615}.v-btn--loading{pointer-events:none}.v-btn--loading .v-btn__content,.v-btn--loading .v-btn__prepend,.v-btn--loading .v-btn__append{opacity:0}.v-btn--stacked{grid-template-areas:"prepend" "content" "append";grid-template-columns:auto;grid-template-rows:max-content max-content max-content;justify-items:center;align-content:center}.v-btn--stacked .v-btn__content{flex-direction:column;line-height:1.25}.v-btn--stacked .v-btn__prepend,.v-btn--stacked .v-btn__append,.v-btn--stacked .v-btn__content>.v-icon--start,.v-btn--stacked .v-btn__content>.v-icon--end{margin-inline:0}.v-btn--stacked .v-btn__prepend,.v-btn--stacked .v-btn__content>.v-icon--start{margin-bottom:4px}.v-btn--stacked .v-btn__append,.v-btn--stacked .v-btn__content>.v-icon--end{margin-top:4px}.v-btn--stacked.v-btn--size-x-small{--v-btn-size: .625rem;--v-btn-height: 56px;font-size:var(--v-btn-size);min-width:56px;padding:0 12px}.v-btn--stacked.v-btn--size-small{--v-btn-size: .75rem;--v-btn-height: 64px;font-size:var(--v-btn-size);min-width:64px;padding:0 14px}.v-btn--stacked.v-btn--size-default{--v-btn-size: .875rem;--v-btn-height: 72px;font-size:var(--v-btn-size);min-width:72px;padding:0 16px}.v-btn--stacked.v-btn--size-large{--v-btn-size: 1rem;--v-btn-height: 80px;font-size:var(--v-btn-size);min-width:80px;padding:0 18px}.v-btn--stacked.v-btn--size-x-large{--v-btn-size: 1.125rem;--v-btn-height: 88px;font-size:var(--v-btn-size);min-width:88px;padding:0 20px}.v-btn--stacked.v-btn--density-default{height:calc(var(--v-btn-height) + 0px)}.v-btn--stacked.v-btn--density-comfortable{height:calc(var(--v-btn-height) + -16px)}.v-btn--stacked.v-btn--density-compact{height:calc(var(--v-btn-height) + -24px)}.v-btn--slim{padding:0 8px}.v-btn--rounded{border-radius:24px}.v-btn--rounded.v-btn--icon{border-radius:4px}.v-btn .v-icon{--v-icon-size-multiplier: .8571428571}.v-btn--icon .v-icon{--v-icon-size-multiplier: 1}.v-btn--stacked .v-icon{--v-icon-size-multiplier: 1.1428571429}.v-btn__loader{align-items:center;display:flex;height:100%;justify-content:center;left:0;position:absolute;top:0;width:100%}.v-btn__content,.v-btn__prepend,.v-btn__append{align-items:center;display:flex;transition:transform,opacity .2s cubic-bezier(.4,0,.2,1)}.v-btn__prepend{grid-area:prepend;margin-inline:calc(var(--v-btn-height) / -9) calc(var(--v-btn-height) / 4.5)}.v-btn__append{grid-area:append;margin-inline:calc(var(--v-btn-height) / 4.5) calc(var(--v-btn-height) / -9)}.v-btn__content{grid-area:content;justify-content:center;white-space:nowrap}.v-btn__content>.v-icon--start{margin-inline:calc(var(--v-btn-height) / -9) calc(var(--v-btn-height) / 4.5)}.v-btn__content>.v-icon--end{margin-inline:calc(var(--v-btn-height) / 4.5) calc(var(--v-btn-height) / -9)}.v-btn--stacked .v-btn__content{white-space:normal}.v-btn__overlay{background-color:currentColor;border-radius:inherit;opacity:0;transition:opacity .2s ease-in-out}.v-btn__overlay,.v-btn__underlay{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.v-card-actions .v-btn~.v-btn:not(.v-btn-toggle .v-btn){margin-inline-start:.5rem}.v-pagination .v-btn{border-radius:4px}.v-pagination .v-btn--rounded{border-radius:50%}.v-btn__overlay{transition:none}.v-pagination__item--is-active .v-btn__overlay{opacity:var(--v-border-opacity)}.v-btn-toggle>.v-btn.v-btn--active:not(.v-btn--disabled)>.v-btn__overlay{opacity:calc(var(--v-activated-opacity) * var(--v-theme-overlay-multiplier))}.v-btn-toggle>.v-btn.v-btn--active:not(.v-btn--disabled):hover>.v-btn__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}.v-btn-toggle>.v-btn.v-btn--active:not(.v-btn--disabled):focus-visible>.v-btn__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-btn-toggle>.v-btn.v-btn--active:not(.v-btn--disabled):focus>.v-btn__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}}.v-btn-group{display:inline-flex;flex-wrap:nowrap;max-width:100%;min-width:0;overflow:hidden;vertical-align:middle;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:4px;background:transparent;color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-btn-group--border{border-width:thin;box-shadow:none}.v-btn-group--density-default.v-btn-group{height:48px}.v-btn-group--density-comfortable.v-btn-group{height:40px}.v-btn-group--density-compact.v-btn-group{height:36px}.v-btn-group .v-btn{border-radius:0;border-color:inherit}.v-btn-group .v-btn:not(:last-child){border-inline-end:none}.v-btn-group .v-btn:not(:first-child){border-inline-start:none}.v-btn-group .v-btn:first-child{border-start-start-radius:inherit;border-end-start-radius:inherit}.v-btn-group .v-btn:last-child{border-start-end-radius:inherit;border-end-end-radius:inherit}.v-btn-group--divided .v-btn:not(:last-child){border-inline-end-width:thin;border-inline-end-style:solid;border-inline-end-color:rgba(var(--v-border-color),var(--v-border-opacity))}.v-btn-group--tile{border-radius:0}.v-progress-circular{align-items:center;display:inline-flex;justify-content:center;position:relative;vertical-align:middle}.v-progress-circular>svg{width:100%;height:100%;margin:auto;position:absolute;top:0;bottom:0;left:0;right:0;z-index:0}.v-progress-circular__content{align-items:center;display:flex;justify-content:center}.v-progress-circular__underlay{color:rgba(var(--v-border-color),var(--v-border-opacity));stroke:currentColor;z-index:1}.v-progress-circular__overlay{stroke:currentColor;transition:all .2s ease-in-out,stroke-width 0s;z-index:2}.v-progress-circular--size-x-small{height:16px;width:16px}.v-progress-circular--size-small{height:24px;width:24px}.v-progress-circular--size-default{height:32px;width:32px}.v-progress-circular--size-large{height:48px;width:48px}.v-progress-circular--size-x-large{height:64px;width:64px}.v-progress-circular--indeterminate>svg{animation:progress-circular-rotate 1.4s linear infinite;transform-origin:center center;transition:all .2s ease-in-out}.v-progress-circular--indeterminate .v-progress-circular__overlay{animation:progress-circular-dash 1.4s ease-in-out infinite,progress-circular-rotate 1.4s linear infinite;stroke-dasharray:25,200;stroke-dashoffset:0;stroke-linecap:round;transform-origin:center center;transform:rotate(-90deg)}.v-progress-circular--disable-shrink>svg{animation-duration:.7s}.v-progress-circular--disable-shrink .v-progress-circular__overlay{animation:none}.v-progress-circular--indeterminate:not(.v-progress-circular--visible)>svg,.v-progress-circular--indeterminate:not(.v-progress-circular--visible) .v-progress-circular__overlay{animation-play-state:paused!important}@keyframes progress-circular-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0px}50%{stroke-dasharray:100,200;stroke-dashoffset:-15px}to{stroke-dasharray:100,200;stroke-dashoffset:-124px}}@keyframes progress-circular-rotate{to{transform:rotate(270deg)}}.v-progress-linear{background:transparent;overflow:hidden;position:relative;transition:.2s cubic-bezier(.4,0,.2,1);width:100%}.v-progress-linear__background{background:currentColor;bottom:0;left:0;opacity:var(--v-border-opacity);position:absolute;top:0;transition-property:width,left,right;transition:inherit}.v-progress-linear__content{align-items:center;display:flex;height:100%;justify-content:center;left:0;pointer-events:none;position:absolute;top:0;width:100%}.v-progress-linear__determinate,.v-progress-linear__indeterminate{background:currentColor}.v-progress-linear__determinate{height:inherit;left:0;position:absolute;transition:inherit;transition-property:width,left,right}.v-progress-linear__indeterminate .long,.v-progress-linear__indeterminate .short{animation-play-state:paused;animation-duration:2.2s;animation-iteration-count:infinite;bottom:0;height:inherit;left:0;position:absolute;right:auto;top:0;width:auto}.v-progress-linear__indeterminate .long{animation-name:indeterminate-ltr}.v-progress-linear__indeterminate .short{animation-name:indeterminate-short-ltr}.v-progress-linear__stream{animation:stream .25s infinite linear;animation-play-state:paused;bottom:0;left:auto;opacity:.3;pointer-events:none;position:absolute;transition:inherit;transition-property:width,left,right}.v-progress-linear--reverse .v-progress-linear__background,.v-progress-linear--reverse .v-progress-linear__determinate,.v-progress-linear--reverse .v-progress-linear__content,.v-progress-linear--reverse .v-progress-linear__indeterminate .long,.v-progress-linear--reverse .v-progress-linear__indeterminate .short{left:auto;right:0}.v-progress-linear--reverse .v-progress-linear__indeterminate .long{animation-name:indeterminate-rtl}.v-progress-linear--reverse .v-progress-linear__indeterminate .short{animation-name:indeterminate-short-rtl}.v-progress-linear--reverse .v-progress-linear__stream{right:auto}.v-progress-linear--absolute,.v-progress-linear--fixed{left:0;z-index:1}.v-progress-linear--absolute{position:absolute}.v-progress-linear--fixed{position:fixed}.v-progress-linear--rounded{border-radius:9999px}.v-progress-linear--rounded.v-progress-linear--rounded-bar .v-progress-linear__determinate,.v-progress-linear--rounded.v-progress-linear--rounded-bar .v-progress-linear__indeterminate{border-radius:inherit}.v-progress-linear--striped .v-progress-linear__determinate{animation:progress-linear-stripes 1s infinite linear;background-image:linear-gradient(135deg,hsla(0,0%,100%,.25) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.25) 0,hsla(0,0%,100%,.25) 75%,transparent 0,transparent);background-repeat:repeat;background-size:var(--v-progress-linear-height)}.v-progress-linear--active .v-progress-linear__indeterminate .long,.v-progress-linear--active .v-progress-linear__indeterminate .short,.v-progress-linear--active .v-progress-linear__stream{animation-play-state:running}.v-progress-linear--rounded-bar .v-progress-linear__determinate,.v-progress-linear--rounded-bar .v-progress-linear__indeterminate,.v-progress-linear--rounded-bar .v-progress-linear__stream+.v-progress-linear__background{border-radius:9999px}.v-progress-linear--rounded-bar .v-progress-linear__determinate{border-start-start-radius:0;border-end-start-radius:0}@keyframes indeterminate-ltr{0%{left:-90%;right:100%}60%{left:-90%;right:100%}to{left:100%;right:-35%}}@keyframes indeterminate-rtl{0%{left:100%;right:-90%}60%{left:100%;right:-90%}to{left:-35%;right:100%}}@keyframes indeterminate-short-ltr{0%{left:-200%;right:100%}60%{left:107%;right:-8%}to{left:107%;right:-8%}}@keyframes indeterminate-short-rtl{0%{left:100%;right:-200%}60%{left:-8%;right:107%}to{left:-8%;right:107%}}@keyframes stream{to{transform:translate(var(--v-progress-linear-stream-to))}}@keyframes progress-linear-stripes{0%{background-position-x:var(--v-progress-linear-height)}}.v-ripple__container{color:inherit;border-radius:inherit;position:absolute;width:100%;height:100%;left:0;top:0;overflow:hidden;z-index:0;pointer-events:none;contain:strict}.v-ripple__animation{color:inherit;position:absolute;top:0;left:0;border-radius:50%;background:currentColor;opacity:0;pointer-events:none;overflow:hidden;will-change:transform,opacity}.v-ripple__animation--enter{transition:none;opacity:0}.v-ripple__animation--in{transition:transform .25s cubic-bezier(0,0,.2,1),opacity .1s cubic-bezier(0,0,.2,1);opacity:calc(.25 * var(--v-theme-overlay-multiplier))}.v-ripple__animation--out{transition:opacity .3s cubic-bezier(0,0,.2,1);opacity:0}.v-footer{align-items:center;display:flex;flex:1 1 auto;padding:8px 16px;position:relative;transition:.2s cubic-bezier(.4,0,.2,1);transition-property:height,width,transform,max-width,left,right,top,bottom;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:0;background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-footer--border{border-width:thin;box-shadow:none}.v-footer--absolute{position:absolute}.v-footer--fixed{position:fixed}.v-footer--rounded{border-radius:4px}.app[data-v-326bb0a3]{display:flex;flex-direction:column;min-height:100vh;-webkit-box-flex:1}.main[data-v-326bb0a3]{flex:1 0 auto}.main-wide[data-v-326bb0a3]{flex:1 0 auto;max-width:100%}@media (min-width: 1024px){.main-wide[data-v-326bb0a3]{padding-left:65px;padding-right:65px}}[data-v-326bb0a3] .v-btn--icon{border-radius:0}.v-layout{--v-scrollbar-offset: 0px;display:flex;flex:1 1 auto}.v-layout--full-height{--v-scrollbar-offset: inherit;height:100%}.v-layout-item{position:absolute;transition:.2s cubic-bezier(.4,0,.2,1)}.v-layout-item--absolute{position:absolute}.v-main{flex:1 0 auto;max-width:100%;transition:.2s cubic-bezier(.4,0,.2,1);padding-left:var(--v-layout-left);padding-right:var(--v-layout-right);padding-top:var(--v-layout-top);padding-bottom:var(--v-layout-bottom)}.v-main__scroller{max-width:100%;position:relative}.v-main--scrollable{display:flex;position:absolute;top:0;left:0;width:100%;height:100%}.v-main--scrollable>.v-main__scroller{flex:1 1 auto;overflow-y:auto;--v-layout-left: 0px;--v-layout-right: 0px;--v-layout-top: 0px;--v-layout-bottom: 0px}@keyframes v-shake{59%{margin-left:0}60%,80%{margin-left:2px}70%,90%{margin-left:-2px}}.bg-black{background-color:#000!important;color:#fff!important}.bg-white{background-color:#fff!important;color:#000!important}.bg-transparent{background-color:transparent!important;color:currentColor!important}.bg-red{background-color:#f44336!important;color:#fff!important}.bg-red-lighten-5{background-color:#ffebee!important;color:#000!important}.bg-red-lighten-4{background-color:#ffcdd2!important;color:#000!important}.bg-red-lighten-3{background-color:#ef9a9a!important;color:#000!important}.bg-red-lighten-2{background-color:#e57373!important;color:#fff!important}.bg-red-lighten-1{background-color:#ef5350!important;color:#fff!important}.bg-red-darken-1{background-color:#e53935!important;color:#fff!important}.bg-red-darken-2{background-color:#d32f2f!important;color:#fff!important}.bg-red-darken-3{background-color:#c62828!important;color:#fff!important}.bg-red-darken-4{background-color:#b71c1c!important;color:#fff!important}.bg-red-accent-1{background-color:#ff8a80!important;color:#000!important}.bg-red-accent-2{background-color:#ff5252!important;color:#fff!important}.bg-red-accent-3{background-color:#ff1744!important;color:#fff!important}.bg-red-accent-4{background-color:#d50000!important;color:#fff!important}.bg-pink{background-color:#e91e63!important;color:#fff!important}.bg-pink-lighten-5{background-color:#fce4ec!important;color:#000!important}.bg-pink-lighten-4{background-color:#f8bbd0!important;color:#000!important}.bg-pink-lighten-3{background-color:#f48fb1!important;color:#000!important}.bg-pink-lighten-2{background-color:#f06292!important;color:#fff!important}.bg-pink-lighten-1{background-color:#ec407a!important;color:#fff!important}.bg-pink-darken-1{background-color:#d81b60!important;color:#fff!important}.bg-pink-darken-2{background-color:#c2185b!important;color:#fff!important}.bg-pink-darken-3{background-color:#ad1457!important;color:#fff!important}.bg-pink-darken-4{background-color:#880e4f!important;color:#fff!important}.bg-pink-accent-1{background-color:#ff80ab!important;color:#fff!important}.bg-pink-accent-2{background-color:#ff4081!important;color:#fff!important}.bg-pink-accent-3{background-color:#f50057!important;color:#fff!important}.bg-pink-accent-4{background-color:#c51162!important;color:#fff!important}.bg-purple{background-color:#9c27b0!important;color:#fff!important}.bg-purple-lighten-5{background-color:#f3e5f5!important;color:#000!important}.bg-purple-lighten-4{background-color:#e1bee7!important;color:#000!important}.bg-purple-lighten-3{background-color:#ce93d8!important;color:#fff!important}.bg-purple-lighten-2{background-color:#ba68c8!important;color:#fff!important}.bg-purple-lighten-1{background-color:#ab47bc!important;color:#fff!important}.bg-purple-darken-1{background-color:#8e24aa!important;color:#fff!important}.bg-purple-darken-2{background-color:#7b1fa2!important;color:#fff!important}.bg-purple-darken-3{background-color:#6a1b9a!important;color:#fff!important}.bg-purple-darken-4{background-color:#4a148c!important;color:#fff!important}.bg-purple-accent-1{background-color:#ea80fc!important;color:#fff!important}.bg-purple-accent-2{background-color:#e040fb!important;color:#fff!important}.bg-purple-accent-3{background-color:#d500f9!important;color:#fff!important}.bg-purple-accent-4{background-color:#a0f!important;color:#fff!important}.bg-deep-purple{background-color:#673ab7!important;color:#fff!important}.bg-deep-purple-lighten-5{background-color:#ede7f6!important;color:#000!important}.bg-deep-purple-lighten-4{background-color:#d1c4e9!important;color:#000!important}.bg-deep-purple-lighten-3{background-color:#b39ddb!important;color:#fff!important}.bg-deep-purple-lighten-2{background-color:#9575cd!important;color:#fff!important}.bg-deep-purple-lighten-1{background-color:#7e57c2!important;color:#fff!important}.bg-deep-purple-darken-1{background-color:#5e35b1!important;color:#fff!important}.bg-deep-purple-darken-2{background-color:#512da8!important;color:#fff!important}.bg-deep-purple-darken-3{background-color:#4527a0!important;color:#fff!important}.bg-deep-purple-darken-4{background-color:#311b92!important;color:#fff!important}.bg-deep-purple-accent-1{background-color:#b388ff!important;color:#fff!important}.bg-deep-purple-accent-2{background-color:#7c4dff!important;color:#fff!important}.bg-deep-purple-accent-3{background-color:#651fff!important;color:#fff!important}.bg-deep-purple-accent-4{background-color:#6200ea!important;color:#fff!important}.bg-indigo{background-color:#3f51b5!important;color:#fff!important}.bg-indigo-lighten-5{background-color:#e8eaf6!important;color:#000!important}.bg-indigo-lighten-4{background-color:#c5cae9!important;color:#000!important}.bg-indigo-lighten-3{background-color:#9fa8da!important;color:#fff!important}.bg-indigo-lighten-2{background-color:#7986cb!important;color:#fff!important}.bg-indigo-lighten-1{background-color:#5c6bc0!important;color:#fff!important}.bg-indigo-darken-1{background-color:#3949ab!important;color:#fff!important}.bg-indigo-darken-2{background-color:#303f9f!important;color:#fff!important}.bg-indigo-darken-3{background-color:#283593!important;color:#fff!important}.bg-indigo-darken-4{background-color:#1a237e!important;color:#fff!important}.bg-indigo-accent-1{background-color:#8c9eff!important;color:#fff!important}.bg-indigo-accent-2{background-color:#536dfe!important;color:#fff!important}.bg-indigo-accent-3{background-color:#3d5afe!important;color:#fff!important}.bg-indigo-accent-4{background-color:#304ffe!important;color:#fff!important}.bg-blue{background-color:#2196f3!important;color:#fff!important}.bg-blue-lighten-5{background-color:#e3f2fd!important;color:#000!important}.bg-blue-lighten-4{background-color:#bbdefb!important;color:#000!important}.bg-blue-lighten-3{background-color:#90caf9!important;color:#000!important}.bg-blue-lighten-2{background-color:#64b5f6!important;color:#000!important}.bg-blue-lighten-1{background-color:#42a5f5!important;color:#fff!important}.bg-blue-darken-1{background-color:#1e88e5!important;color:#fff!important}.bg-blue-darken-2{background-color:#1976d2!important;color:#fff!important}.bg-blue-darken-3{background-color:#1565c0!important;color:#fff!important}.bg-blue-darken-4{background-color:#0d47a1!important;color:#fff!important}.bg-blue-accent-1{background-color:#82b1ff!important;color:#000!important}.bg-blue-accent-2{background-color:#448aff!important;color:#fff!important}.bg-blue-accent-3{background-color:#2979ff!important;color:#fff!important}.bg-blue-accent-4{background-color:#2962ff!important;color:#fff!important}.bg-light-blue{background-color:#03a9f4!important;color:#fff!important}.bg-light-blue-lighten-5{background-color:#e1f5fe!important;color:#000!important}.bg-light-blue-lighten-4{background-color:#b3e5fc!important;color:#000!important}.bg-light-blue-lighten-3{background-color:#81d4fa!important;color:#000!important}.bg-light-blue-lighten-2{background-color:#4fc3f7!important;color:#000!important}.bg-light-blue-lighten-1{background-color:#29b6f6!important;color:#000!important}.bg-light-blue-darken-1{background-color:#039be5!important;color:#fff!important}.bg-light-blue-darken-2{background-color:#0288d1!important;color:#fff!important}.bg-light-blue-darken-3{background-color:#0277bd!important;color:#fff!important}.bg-light-blue-darken-4{background-color:#01579b!important;color:#fff!important}.bg-light-blue-accent-1{background-color:#80d8ff!important;color:#000!important}.bg-light-blue-accent-2{background-color:#40c4ff!important;color:#000!important}.bg-light-blue-accent-3{background-color:#00b0ff!important;color:#fff!important}.bg-light-blue-accent-4{background-color:#0091ea!important;color:#fff!important}.bg-cyan{background-color:#00bcd4!important;color:#000!important}.bg-cyan-lighten-5{background-color:#e0f7fa!important;color:#000!important}.bg-cyan-lighten-4{background-color:#b2ebf2!important;color:#000!important}.bg-cyan-lighten-3{background-color:#80deea!important;color:#000!important}.bg-cyan-lighten-2{background-color:#4dd0e1!important;color:#000!important}.bg-cyan-lighten-1{background-color:#26c6da!important;color:#000!important}.bg-cyan-darken-1{background-color:#00acc1!important;color:#fff!important}.bg-cyan-darken-2{background-color:#0097a7!important;color:#fff!important}.bg-cyan-darken-3{background-color:#00838f!important;color:#fff!important}.bg-cyan-darken-4{background-color:#006064!important;color:#fff!important}.bg-cyan-accent-1{background-color:#84ffff!important;color:#000!important}.bg-cyan-accent-2{background-color:#18ffff!important;color:#000!important}.bg-cyan-accent-3{background-color:#00e5ff!important;color:#000!important}.bg-cyan-accent-4{background-color:#00b8d4!important;color:#fff!important}.bg-teal{background-color:#009688!important;color:#fff!important}.bg-teal-lighten-5{background-color:#e0f2f1!important;color:#000!important}.bg-teal-lighten-4{background-color:#b2dfdb!important;color:#000!important}.bg-teal-lighten-3{background-color:#80cbc4!important;color:#000!important}.bg-teal-lighten-2{background-color:#4db6ac!important;color:#fff!important}.bg-teal-lighten-1{background-color:#26a69a!important;color:#fff!important}.bg-teal-darken-1{background-color:#00897b!important;color:#fff!important}.bg-teal-darken-2{background-color:#00796b!important;color:#fff!important}.bg-teal-darken-3{background-color:#00695c!important;color:#fff!important}.bg-teal-darken-4{background-color:#004d40!important;color:#fff!important}.bg-teal-accent-1{background-color:#a7ffeb!important;color:#000!important}.bg-teal-accent-2{background-color:#64ffda!important;color:#000!important}.bg-teal-accent-3{background-color:#1de9b6!important;color:#000!important}.bg-teal-accent-4{background-color:#00bfa5!important;color:#fff!important}.bg-green{background-color:#4caf50!important;color:#fff!important}.bg-green-lighten-5{background-color:#e8f5e9!important;color:#000!important}.bg-green-lighten-4{background-color:#c8e6c9!important;color:#000!important}.bg-green-lighten-3{background-color:#a5d6a7!important;color:#000!important}.bg-green-lighten-2{background-color:#81c784!important;color:#000!important}.bg-green-lighten-1{background-color:#66bb6a!important;color:#fff!important}.bg-green-darken-1{background-color:#43a047!important;color:#fff!important}.bg-green-darken-2{background-color:#388e3c!important;color:#fff!important}.bg-green-darken-3{background-color:#2e7d32!important;color:#fff!important}.bg-green-darken-4{background-color:#1b5e20!important;color:#fff!important}.bg-green-accent-1{background-color:#b9f6ca!important;color:#000!important}.bg-green-accent-2{background-color:#69f0ae!important;color:#000!important}.bg-green-accent-3{background-color:#00e676!important;color:#000!important}.bg-green-accent-4{background-color:#00c853!important;color:#000!important}.bg-light-green{background-color:#8bc34a!important;color:#000!important}.bg-light-green-lighten-5{background-color:#f1f8e9!important;color:#000!important}.bg-light-green-lighten-4{background-color:#dcedc8!important;color:#000!important}.bg-light-green-lighten-3{background-color:#c5e1a5!important;color:#000!important}.bg-light-green-lighten-2{background-color:#aed581!important;color:#000!important}.bg-light-green-lighten-1{background-color:#9ccc65!important;color:#000!important}.bg-light-green-darken-1{background-color:#7cb342!important;color:#fff!important}.bg-light-green-darken-2{background-color:#689f38!important;color:#fff!important}.bg-light-green-darken-3{background-color:#558b2f!important;color:#fff!important}.bg-light-green-darken-4{background-color:#33691e!important;color:#fff!important}.bg-light-green-accent-1{background-color:#ccff90!important;color:#000!important}.bg-light-green-accent-2{background-color:#b2ff59!important;color:#000!important}.bg-light-green-accent-3{background-color:#76ff03!important;color:#000!important}.bg-light-green-accent-4{background-color:#64dd17!important;color:#000!important}.bg-lime{background-color:#cddc39!important;color:#000!important}.bg-lime-lighten-5{background-color:#f9fbe7!important;color:#000!important}.bg-lime-lighten-4{background-color:#f0f4c3!important;color:#000!important}.bg-lime-lighten-3{background-color:#e6ee9c!important;color:#000!important}.bg-lime-lighten-2{background-color:#dce775!important;color:#000!important}.bg-lime-lighten-1{background-color:#d4e157!important;color:#000!important}.bg-lime-darken-1{background-color:#c0ca33!important;color:#000!important}.bg-lime-darken-2{background-color:#afb42b!important;color:#000!important}.bg-lime-darken-3{background-color:#9e9d24!important;color:#fff!important}.bg-lime-darken-4{background-color:#827717!important;color:#fff!important}.bg-lime-accent-1{background-color:#f4ff81!important;color:#000!important}.bg-lime-accent-2{background-color:#eeff41!important;color:#000!important}.bg-lime-accent-3{background-color:#c6ff00!important;color:#000!important}.bg-lime-accent-4{background-color:#aeea00!important;color:#000!important}.bg-yellow{background-color:#ffeb3b!important;color:#000!important}.bg-yellow-lighten-5{background-color:#fffde7!important;color:#000!important}.bg-yellow-lighten-4{background-color:#fff9c4!important;color:#000!important}.bg-yellow-lighten-3{background-color:#fff59d!important;color:#000!important}.bg-yellow-lighten-2{background-color:#fff176!important;color:#000!important}.bg-yellow-lighten-1{background-color:#ffee58!important;color:#000!important}.bg-yellow-darken-1{background-color:#fdd835!important;color:#000!important}.bg-yellow-darken-2{background-color:#fbc02d!important;color:#000!important}.bg-yellow-darken-3{background-color:#f9a825!important;color:#000!important}.bg-yellow-darken-4{background-color:#f57f17!important;color:#fff!important}.bg-yellow-accent-1{background-color:#ffff8d!important;color:#000!important}.bg-yellow-accent-2{background-color:#ff0!important;color:#000!important}.bg-yellow-accent-3{background-color:#ffea00!important;color:#000!important}.bg-yellow-accent-4{background-color:#ffd600!important;color:#000!important}.bg-amber{background-color:#ffc107!important;color:#000!important}.bg-amber-lighten-5{background-color:#fff8e1!important;color:#000!important}.bg-amber-lighten-4{background-color:#ffecb3!important;color:#000!important}.bg-amber-lighten-3{background-color:#ffe082!important;color:#000!important}.bg-amber-lighten-2{background-color:#ffd54f!important;color:#000!important}.bg-amber-lighten-1{background-color:#ffca28!important;color:#000!important}.bg-amber-darken-1{background-color:#ffb300!important;color:#000!important}.bg-amber-darken-2{background-color:#ffa000!important;color:#000!important}.bg-amber-darken-3{background-color:#ff8f00!important;color:#000!important}.bg-amber-darken-4{background-color:#ff6f00!important;color:#fff!important}.bg-amber-accent-1{background-color:#ffe57f!important;color:#000!important}.bg-amber-accent-2{background-color:#ffd740!important;color:#000!important}.bg-amber-accent-3{background-color:#ffc400!important;color:#000!important}.bg-amber-accent-4{background-color:#ffab00!important;color:#000!important}.bg-orange{background-color:#ff9800!important;color:#000!important}.bg-orange-lighten-5{background-color:#fff3e0!important;color:#000!important}.bg-orange-lighten-4{background-color:#ffe0b2!important;color:#000!important}.bg-orange-lighten-3{background-color:#ffcc80!important;color:#000!important}.bg-orange-lighten-2{background-color:#ffb74d!important;color:#000!important}.bg-orange-lighten-1{background-color:#ffa726!important;color:#000!important}.bg-orange-darken-1{background-color:#fb8c00!important;color:#fff!important}.bg-orange-darken-2{background-color:#f57c00!important;color:#fff!important}.bg-orange-darken-3{background-color:#ef6c00!important;color:#fff!important}.bg-orange-darken-4{background-color:#e65100!important;color:#fff!important}.bg-orange-accent-1{background-color:#ffd180!important;color:#000!important}.bg-orange-accent-2{background-color:#ffab40!important;color:#000!important}.bg-orange-accent-3{background-color:#ff9100!important;color:#000!important}.bg-orange-accent-4{background-color:#ff6d00!important;color:#fff!important}.bg-deep-orange{background-color:#ff5722!important;color:#fff!important}.bg-deep-orange-lighten-5{background-color:#fbe9e7!important;color:#000!important}.bg-deep-orange-lighten-4{background-color:#ffccbc!important;color:#000!important}.bg-deep-orange-lighten-3{background-color:#ffab91!important;color:#000!important}.bg-deep-orange-lighten-2{background-color:#ff8a65!important;color:#000!important}.bg-deep-orange-lighten-1{background-color:#ff7043!important;color:#fff!important}.bg-deep-orange-darken-1{background-color:#f4511e!important;color:#fff!important}.bg-deep-orange-darken-2{background-color:#e64a19!important;color:#fff!important}.bg-deep-orange-darken-3{background-color:#d84315!important;color:#fff!important}.bg-deep-orange-darken-4{background-color:#bf360c!important;color:#fff!important}.bg-deep-orange-accent-1{background-color:#ff9e80!important;color:#000!important}.bg-deep-orange-accent-2{background-color:#ff6e40!important;color:#fff!important}.bg-deep-orange-accent-3{background-color:#ff3d00!important;color:#fff!important}.bg-deep-orange-accent-4{background-color:#dd2c00!important;color:#fff!important}.bg-brown{background-color:#795548!important;color:#fff!important}.bg-brown-lighten-5{background-color:#efebe9!important;color:#000!important}.bg-brown-lighten-4{background-color:#d7ccc8!important;color:#000!important}.bg-brown-lighten-3{background-color:#bcaaa4!important;color:#000!important}.bg-brown-lighten-2{background-color:#a1887f!important;color:#fff!important}.bg-brown-lighten-1{background-color:#8d6e63!important;color:#fff!important}.bg-brown-darken-1{background-color:#6d4c41!important;color:#fff!important}.bg-brown-darken-2{background-color:#5d4037!important;color:#fff!important}.bg-brown-darken-3{background-color:#4e342e!important;color:#fff!important}.bg-brown-darken-4{background-color:#3e2723!important;color:#fff!important}.bg-blue-grey{background-color:#607d8b!important;color:#fff!important}.bg-blue-grey-lighten-5{background-color:#eceff1!important;color:#000!important}.bg-blue-grey-lighten-4{background-color:#cfd8dc!important;color:#000!important}.bg-blue-grey-lighten-3{background-color:#b0bec5!important;color:#000!important}.bg-blue-grey-lighten-2{background-color:#90a4ae!important;color:#fff!important}.bg-blue-grey-lighten-1{background-color:#78909c!important;color:#fff!important}.bg-blue-grey-darken-1{background-color:#546e7a!important;color:#fff!important}.bg-blue-grey-darken-2{background-color:#455a64!important;color:#fff!important}.bg-blue-grey-darken-3{background-color:#37474f!important;color:#fff!important}.bg-blue-grey-darken-4{background-color:#263238!important;color:#fff!important}.bg-grey{background-color:#9e9e9e!important;color:#fff!important}.bg-grey-lighten-5{background-color:#fafafa!important;color:#000!important}.bg-grey-lighten-4{background-color:#f5f5f5!important;color:#000!important}.bg-grey-lighten-3{background-color:#eee!important;color:#000!important}.bg-grey-lighten-2{background-color:#e0e0e0!important;color:#000!important}.bg-grey-lighten-1{background-color:#bdbdbd!important;color:#000!important}.bg-grey-darken-1{background-color:#757575!important;color:#fff!important}.bg-grey-darken-2{background-color:#616161!important;color:#fff!important}.bg-grey-darken-3{background-color:#424242!important;color:#fff!important}.bg-grey-darken-4{background-color:#212121!important;color:#fff!important}.bg-shades-black{background-color:#000!important;color:#fff!important}.bg-shades-white{background-color:#fff!important;color:#000!important}.bg-shades-transparent{background-color:transparent!important;color:currentColor!important}.text-black{color:#000!important}.text-white{color:#fff!important}.text-transparent{color:transparent!important}.text-red{color:#f44336!important}.text-red-lighten-5{color:#ffebee!important}.text-red-lighten-4{color:#ffcdd2!important}.text-red-lighten-3{color:#ef9a9a!important}.text-red-lighten-2{color:#e57373!important}.text-red-lighten-1{color:#ef5350!important}.text-red-darken-1{color:#e53935!important}.text-red-darken-2{color:#d32f2f!important}.text-red-darken-3{color:#c62828!important}.text-red-darken-4{color:#b71c1c!important}.text-red-accent-1{color:#ff8a80!important}.text-red-accent-2{color:#ff5252!important}.text-red-accent-3{color:#ff1744!important}.text-red-accent-4{color:#d50000!important}.text-pink{color:#e91e63!important}.text-pink-lighten-5{color:#fce4ec!important}.text-pink-lighten-4{color:#f8bbd0!important}.text-pink-lighten-3{color:#f48fb1!important}.text-pink-lighten-2{color:#f06292!important}.text-pink-lighten-1{color:#ec407a!important}.text-pink-darken-1{color:#d81b60!important}.text-pink-darken-2{color:#c2185b!important}.text-pink-darken-3{color:#ad1457!important}.text-pink-darken-4{color:#880e4f!important}.text-pink-accent-1{color:#ff80ab!important}.text-pink-accent-2{color:#ff4081!important}.text-pink-accent-3{color:#f50057!important}.text-pink-accent-4{color:#c51162!important}.text-purple{color:#9c27b0!important}.text-purple-lighten-5{color:#f3e5f5!important}.text-purple-lighten-4{color:#e1bee7!important}.text-purple-lighten-3{color:#ce93d8!important}.text-purple-lighten-2{color:#ba68c8!important}.text-purple-lighten-1{color:#ab47bc!important}.text-purple-darken-1{color:#8e24aa!important}.text-purple-darken-2{color:#7b1fa2!important}.text-purple-darken-3{color:#6a1b9a!important}.text-purple-darken-4{color:#4a148c!important}.text-purple-accent-1{color:#ea80fc!important}.text-purple-accent-2{color:#e040fb!important}.text-purple-accent-3{color:#d500f9!important}.text-purple-accent-4{color:#a0f!important}.text-deep-purple{color:#673ab7!important}.text-deep-purple-lighten-5{color:#ede7f6!important}.text-deep-purple-lighten-4{color:#d1c4e9!important}.text-deep-purple-lighten-3{color:#b39ddb!important}.text-deep-purple-lighten-2{color:#9575cd!important}.text-deep-purple-lighten-1{color:#7e57c2!important}.text-deep-purple-darken-1{color:#5e35b1!important}.text-deep-purple-darken-2{color:#512da8!important}.text-deep-purple-darken-3{color:#4527a0!important}.text-deep-purple-darken-4{color:#311b92!important}.text-deep-purple-accent-1{color:#b388ff!important}.text-deep-purple-accent-2{color:#7c4dff!important}.text-deep-purple-accent-3{color:#651fff!important}.text-deep-purple-accent-4{color:#6200ea!important}.text-indigo{color:#3f51b5!important}.text-indigo-lighten-5{color:#e8eaf6!important}.text-indigo-lighten-4{color:#c5cae9!important}.text-indigo-lighten-3{color:#9fa8da!important}.text-indigo-lighten-2{color:#7986cb!important}.text-indigo-lighten-1{color:#5c6bc0!important}.text-indigo-darken-1{color:#3949ab!important}.text-indigo-darken-2{color:#303f9f!important}.text-indigo-darken-3{color:#283593!important}.text-indigo-darken-4{color:#1a237e!important}.text-indigo-accent-1{color:#8c9eff!important}.text-indigo-accent-2{color:#536dfe!important}.text-indigo-accent-3{color:#3d5afe!important}.text-indigo-accent-4{color:#304ffe!important}.text-blue{color:#2196f3!important}.text-blue-lighten-5{color:#e3f2fd!important}.text-blue-lighten-4{color:#bbdefb!important}.text-blue-lighten-3{color:#90caf9!important}.text-blue-lighten-2{color:#64b5f6!important}.text-blue-lighten-1{color:#42a5f5!important}.text-blue-darken-1{color:#1e88e5!important}.text-blue-darken-2{color:#1976d2!important}.text-blue-darken-3{color:#1565c0!important}.text-blue-darken-4{color:#0d47a1!important}.text-blue-accent-1{color:#82b1ff!important}.text-blue-accent-2{color:#448aff!important}.text-blue-accent-3{color:#2979ff!important}.text-blue-accent-4{color:#2962ff!important}.text-light-blue{color:#03a9f4!important}.text-light-blue-lighten-5{color:#e1f5fe!important}.text-light-blue-lighten-4{color:#b3e5fc!important}.text-light-blue-lighten-3{color:#81d4fa!important}.text-light-blue-lighten-2{color:#4fc3f7!important}.text-light-blue-lighten-1{color:#29b6f6!important}.text-light-blue-darken-1{color:#039be5!important}.text-light-blue-darken-2{color:#0288d1!important}.text-light-blue-darken-3{color:#0277bd!important}.text-light-blue-darken-4{color:#01579b!important}.text-light-blue-accent-1{color:#80d8ff!important}.text-light-blue-accent-2{color:#40c4ff!important}.text-light-blue-accent-3{color:#00b0ff!important}.text-light-blue-accent-4{color:#0091ea!important}.text-cyan{color:#00bcd4!important}.text-cyan-lighten-5{color:#e0f7fa!important}.text-cyan-lighten-4{color:#b2ebf2!important}.text-cyan-lighten-3{color:#80deea!important}.text-cyan-lighten-2{color:#4dd0e1!important}.text-cyan-lighten-1{color:#26c6da!important}.text-cyan-darken-1{color:#00acc1!important}.text-cyan-darken-2{color:#0097a7!important}.text-cyan-darken-3{color:#00838f!important}.text-cyan-darken-4{color:#006064!important}.text-cyan-accent-1{color:#84ffff!important}.text-cyan-accent-2{color:#18ffff!important}.text-cyan-accent-3{color:#00e5ff!important}.text-cyan-accent-4{color:#00b8d4!important}.text-teal{color:#009688!important}.text-teal-lighten-5{color:#e0f2f1!important}.text-teal-lighten-4{color:#b2dfdb!important}.text-teal-lighten-3{color:#80cbc4!important}.text-teal-lighten-2{color:#4db6ac!important}.text-teal-lighten-1{color:#26a69a!important}.text-teal-darken-1{color:#00897b!important}.text-teal-darken-2{color:#00796b!important}.text-teal-darken-3{color:#00695c!important}.text-teal-darken-4{color:#004d40!important}.text-teal-accent-1{color:#a7ffeb!important}.text-teal-accent-2{color:#64ffda!important}.text-teal-accent-3{color:#1de9b6!important}.text-teal-accent-4{color:#00bfa5!important}.text-green{color:#4caf50!important}.text-green-lighten-5{color:#e8f5e9!important}.text-green-lighten-4{color:#c8e6c9!important}.text-green-lighten-3{color:#a5d6a7!important}.text-green-lighten-2{color:#81c784!important}.text-green-lighten-1{color:#66bb6a!important}.text-green-darken-1{color:#43a047!important}.text-green-darken-2{color:#388e3c!important}.text-green-darken-3{color:#2e7d32!important}.text-green-darken-4{color:#1b5e20!important}.text-green-accent-1{color:#b9f6ca!important}.text-green-accent-2{color:#69f0ae!important}.text-green-accent-3{color:#00e676!important}.text-green-accent-4{color:#00c853!important}.text-light-green{color:#8bc34a!important}.text-light-green-lighten-5{color:#f1f8e9!important}.text-light-green-lighten-4{color:#dcedc8!important}.text-light-green-lighten-3{color:#c5e1a5!important}.text-light-green-lighten-2{color:#aed581!important}.text-light-green-lighten-1{color:#9ccc65!important}.text-light-green-darken-1{color:#7cb342!important}.text-light-green-darken-2{color:#689f38!important}.text-light-green-darken-3{color:#558b2f!important}.text-light-green-darken-4{color:#33691e!important}.text-light-green-accent-1{color:#ccff90!important}.text-light-green-accent-2{color:#b2ff59!important}.text-light-green-accent-3{color:#76ff03!important}.text-light-green-accent-4{color:#64dd17!important}.text-lime{color:#cddc39!important}.text-lime-lighten-5{color:#f9fbe7!important}.text-lime-lighten-4{color:#f0f4c3!important}.text-lime-lighten-3{color:#e6ee9c!important}.text-lime-lighten-2{color:#dce775!important}.text-lime-lighten-1{color:#d4e157!important}.text-lime-darken-1{color:#c0ca33!important}.text-lime-darken-2{color:#afb42b!important}.text-lime-darken-3{color:#9e9d24!important}.text-lime-darken-4{color:#827717!important}.text-lime-accent-1{color:#f4ff81!important}.text-lime-accent-2{color:#eeff41!important}.text-lime-accent-3{color:#c6ff00!important}.text-lime-accent-4{color:#aeea00!important}.text-yellow{color:#ffeb3b!important}.text-yellow-lighten-5{color:#fffde7!important}.text-yellow-lighten-4{color:#fff9c4!important}.text-yellow-lighten-3{color:#fff59d!important}.text-yellow-lighten-2{color:#fff176!important}.text-yellow-lighten-1{color:#ffee58!important}.text-yellow-darken-1{color:#fdd835!important}.text-yellow-darken-2{color:#fbc02d!important}.text-yellow-darken-3{color:#f9a825!important}.text-yellow-darken-4{color:#f57f17!important}.text-yellow-accent-1{color:#ffff8d!important}.text-yellow-accent-2{color:#ff0!important}.text-yellow-accent-3{color:#ffea00!important}.text-yellow-accent-4{color:#ffd600!important}.text-amber{color:#ffc107!important}.text-amber-lighten-5{color:#fff8e1!important}.text-amber-lighten-4{color:#ffecb3!important}.text-amber-lighten-3{color:#ffe082!important}.text-amber-lighten-2{color:#ffd54f!important}.text-amber-lighten-1{color:#ffca28!important}.text-amber-darken-1{color:#ffb300!important}.text-amber-darken-2{color:#ffa000!important}.text-amber-darken-3{color:#ff8f00!important}.text-amber-darken-4{color:#ff6f00!important}.text-amber-accent-1{color:#ffe57f!important}.text-amber-accent-2{color:#ffd740!important}.text-amber-accent-3{color:#ffc400!important}.text-amber-accent-4{color:#ffab00!important}.text-orange{color:#ff9800!important}.text-orange-lighten-5{color:#fff3e0!important}.text-orange-lighten-4{color:#ffe0b2!important}.text-orange-lighten-3{color:#ffcc80!important}.text-orange-lighten-2{color:#ffb74d!important}.text-orange-lighten-1{color:#ffa726!important}.text-orange-darken-1{color:#fb8c00!important}.text-orange-darken-2{color:#f57c00!important}.text-orange-darken-3{color:#ef6c00!important}.text-orange-darken-4{color:#e65100!important}.text-orange-accent-1{color:#ffd180!important}.text-orange-accent-2{color:#ffab40!important}.text-orange-accent-3{color:#ff9100!important}.text-orange-accent-4{color:#ff6d00!important}.text-deep-orange{color:#ff5722!important}.text-deep-orange-lighten-5{color:#fbe9e7!important}.text-deep-orange-lighten-4{color:#ffccbc!important}.text-deep-orange-lighten-3{color:#ffab91!important}.text-deep-orange-lighten-2{color:#ff8a65!important}.text-deep-orange-lighten-1{color:#ff7043!important}.text-deep-orange-darken-1{color:#f4511e!important}.text-deep-orange-darken-2{color:#e64a19!important}.text-deep-orange-darken-3{color:#d84315!important}.text-deep-orange-darken-4{color:#bf360c!important}.text-deep-orange-accent-1{color:#ff9e80!important}.text-deep-orange-accent-2{color:#ff6e40!important}.text-deep-orange-accent-3{color:#ff3d00!important}.text-deep-orange-accent-4{color:#dd2c00!important}.text-brown{color:#795548!important}.text-brown-lighten-5{color:#efebe9!important}.text-brown-lighten-4{color:#d7ccc8!important}.text-brown-lighten-3{color:#bcaaa4!important}.text-brown-lighten-2{color:#a1887f!important}.text-brown-lighten-1{color:#8d6e63!important}.text-brown-darken-1{color:#6d4c41!important}.text-brown-darken-2{color:#5d4037!important}.text-brown-darken-3{color:#4e342e!important}.text-brown-darken-4{color:#3e2723!important}.text-blue-grey{color:#607d8b!important}.text-blue-grey-lighten-5{color:#eceff1!important}.text-blue-grey-lighten-4{color:#cfd8dc!important}.text-blue-grey-lighten-3{color:#b0bec5!important}.text-blue-grey-lighten-2{color:#90a4ae!important}.text-blue-grey-lighten-1{color:#78909c!important}.text-blue-grey-darken-1{color:#546e7a!important}.text-blue-grey-darken-2{color:#455a64!important}.text-blue-grey-darken-3{color:#37474f!important}.text-blue-grey-darken-4{color:#263238!important}.text-grey{color:#9e9e9e!important}.text-grey-lighten-5{color:#fafafa!important}.text-grey-lighten-4{color:#f5f5f5!important}.text-grey-lighten-3{color:#eee!important}.text-grey-lighten-2{color:#e0e0e0!important}.text-grey-lighten-1{color:#bdbdbd!important}.text-grey-darken-1{color:#757575!important}.text-grey-darken-2{color:#616161!important}.text-grey-darken-3{color:#424242!important}.text-grey-darken-4{color:#212121!important}.text-shades-black{color:#000!important}.text-shades-white{color:#fff!important}.text-shades-transparent{color:transparent!important}/*! + * ress.css • v2.0.4 + * MIT License + * github.com/filipelinhares/ress + */html{box-sizing:border-box;overflow-y:scroll;-webkit-text-size-adjust:100%;word-break:normal;-moz-tab-size:4;tab-size:4}*,:before,:after{background-repeat:no-repeat;box-sizing:inherit}:before,:after{text-decoration:inherit;vertical-align:inherit}*{padding:0;margin:0}hr{overflow:visible;height:0}details,main{display:block}summary{display:list-item}small{font-size:80%}[hidden]{display:none}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}a{background-color:transparent}a:active,a:hover{outline-width:0}code,kbd,pre,samp{font-family:monospace,monospace}pre{font-size:1em}b,strong{font-weight:bolder}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}input{border-radius:0}[disabled]{cursor:default}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto;resize:vertical}button,input,optgroup,select,textarea{font:inherit}optgroup{font-weight:700}button{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit],[role=button]{cursor:pointer;color:inherit}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{outline:1px dotted ButtonText}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button,input,select,textarea{background-color:transparent;border-style:none}select{-moz-appearance:none;-webkit-appearance:none}select::-ms-expand{display:none}select::-ms-value{color:currentColor}legend{border:0;color:inherit;display:table;white-space:normal;max-width:100%}::-webkit-file-upload-button{-webkit-appearance:button;color:inherit;font:inherit}::-ms-clear,::-ms-reveal{display:none}img{border-style:none}progress{vertical-align:baseline}@media screen{[hidden~=screen]{display:inherit}[hidden~=screen]:not(:active):not(:focus):not(:target){position:absolute!important;clip:rect(0 0 0 0)!important}}[aria-busy=true]{cursor:progress}[aria-controls]{cursor:pointer}[aria-disabled=true]{cursor:default}.dialog-transition-enter-active,.dialog-bottom-transition-enter-active,.dialog-top-transition-enter-active{transition-duration:225ms!important;transition-timing-function:cubic-bezier(0,0,.2,1)!important}.dialog-transition-leave-active,.dialog-bottom-transition-leave-active,.dialog-top-transition-leave-active{transition-duration:125ms!important;transition-timing-function:cubic-bezier(.4,0,1,1)!important}.dialog-transition-enter-active,.dialog-transition-leave-active,.dialog-bottom-transition-enter-active,.dialog-bottom-transition-leave-active,.dialog-top-transition-enter-active,.dialog-top-transition-leave-active{transition-property:transform,opacity!important;pointer-events:none}.dialog-transition-enter-from,.dialog-transition-leave-to{transform:scale(.9);opacity:0}.dialog-transition-enter-to,.dialog-transition-leave-from{opacity:1}.dialog-bottom-transition-enter-from,.dialog-bottom-transition-leave-to{transform:translateY(calc(50vh + 50%))}.dialog-top-transition-enter-from,.dialog-top-transition-leave-to{transform:translateY(calc(-50vh - 50%))}.picker-transition-enter-active,.picker-reverse-transition-enter-active,.picker-transition-leave-active,.picker-reverse-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.picker-transition-move,.picker-reverse-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.picker-transition-enter-from,.picker-transition-leave-to,.picker-reverse-transition-enter-from,.picker-reverse-transition-leave-to{opacity:0}.picker-transition-leave-from,.picker-transition-leave-active,.picker-transition-leave-to,.picker-reverse-transition-leave-from,.picker-reverse-transition-leave-active,.picker-reverse-transition-leave-to{position:absolute!important}.picker-transition-enter-active,.picker-transition-leave-active,.picker-reverse-transition-enter-active,.picker-reverse-transition-leave-active{transition-property:transform,opacity!important}.picker-transition-enter-active,.picker-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.picker-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.picker-transition-enter-from{transform:translateY(100%)}.picker-transition-leave-to{transform:translateY(-100%)}.picker-reverse-transition-enter-active,.picker-reverse-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.picker-reverse-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.picker-reverse-transition-enter-from{transform:translateY(-100%)}.picker-reverse-transition-leave-to{transform:translateY(100%)}.expand-transition-enter-active,.expand-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.expand-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.expand-transition-enter-active,.expand-transition-leave-active{transition-property:height!important}.expand-x-transition-enter-active,.expand-x-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.expand-x-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.expand-x-transition-enter-active,.expand-x-transition-leave-active{transition-property:width!important}.scale-transition-enter-active,.scale-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scale-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scale-transition-leave-to{opacity:0}.scale-transition-leave-active{transition-duration:.1s!important}.scale-transition-enter-from{opacity:0;transform:scale(0)}.scale-transition-enter-active,.scale-transition-leave-active{transition-property:transform,opacity!important}.scale-rotate-transition-enter-active,.scale-rotate-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scale-rotate-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scale-rotate-transition-leave-to{opacity:0}.scale-rotate-transition-leave-active{transition-duration:.1s!important}.scale-rotate-transition-enter-from{opacity:0;transform:scale(0) rotate(-45deg)}.scale-rotate-transition-enter-active,.scale-rotate-transition-leave-active{transition-property:transform,opacity!important}.scale-rotate-reverse-transition-enter-active,.scale-rotate-reverse-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scale-rotate-reverse-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scale-rotate-reverse-transition-leave-to{opacity:0}.scale-rotate-reverse-transition-leave-active{transition-duration:.1s!important}.scale-rotate-reverse-transition-enter-from{opacity:0;transform:scale(0) rotate(45deg)}.scale-rotate-reverse-transition-enter-active,.scale-rotate-reverse-transition-leave-active{transition-property:transform,opacity!important}.message-transition-enter-active,.message-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.message-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.message-transition-enter-from,.message-transition-leave-to{opacity:0;transform:translateY(-15px)}.message-transition-leave-from,.message-transition-leave-active{position:absolute}.message-transition-enter-active,.message-transition-leave-active{transition-property:transform,opacity!important}.slide-y-transition-enter-active,.slide-y-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-y-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-y-transition-enter-from,.slide-y-transition-leave-to{opacity:0;transform:translateY(-15px)}.slide-y-transition-enter-active,.slide-y-transition-leave-active{transition-property:transform,opacity!important}.slide-y-reverse-transition-enter-active,.slide-y-reverse-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-y-reverse-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-y-reverse-transition-enter-from,.slide-y-reverse-transition-leave-to{opacity:0;transform:translateY(15px)}.slide-y-reverse-transition-enter-active,.slide-y-reverse-transition-leave-active{transition-property:transform,opacity!important}.scroll-y-transition-enter-active,.scroll-y-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-y-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-y-transition-enter-from,.scroll-y-transition-leave-to{opacity:0}.scroll-y-transition-enter-from{transform:translateY(-15px)}.scroll-y-transition-leave-to{transform:translateY(15px)}.scroll-y-transition-enter-active,.scroll-y-transition-leave-active{transition-property:transform,opacity!important}.scroll-y-reverse-transition-enter-active,.scroll-y-reverse-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-y-reverse-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-y-reverse-transition-enter-from,.scroll-y-reverse-transition-leave-to{opacity:0}.scroll-y-reverse-transition-enter-from{transform:translateY(15px)}.scroll-y-reverse-transition-leave-to{transform:translateY(-15px)}.scroll-y-reverse-transition-enter-active,.scroll-y-reverse-transition-leave-active{transition-property:transform,opacity!important}.scroll-x-transition-enter-active,.scroll-x-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-x-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-x-transition-enter-from,.scroll-x-transition-leave-to{opacity:0}.scroll-x-transition-enter-from{transform:translate(-15px)}.scroll-x-transition-leave-to{transform:translate(15px)}.scroll-x-transition-enter-active,.scroll-x-transition-leave-active{transition-property:transform,opacity!important}.scroll-x-reverse-transition-enter-active,.scroll-x-reverse-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-x-reverse-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.scroll-x-reverse-transition-enter-from,.scroll-x-reverse-transition-leave-to{opacity:0}.scroll-x-reverse-transition-enter-from{transform:translate(15px)}.scroll-x-reverse-transition-leave-to{transform:translate(-15px)}.scroll-x-reverse-transition-enter-active,.scroll-x-reverse-transition-leave-active{transition-property:transform,opacity!important}.slide-x-transition-enter-active,.slide-x-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-x-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-x-transition-enter-from,.slide-x-transition-leave-to{opacity:0;transform:translate(-15px)}.slide-x-transition-enter-active,.slide-x-transition-leave-active{transition-property:transform,opacity!important}.slide-x-reverse-transition-enter-active,.slide-x-reverse-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-x-reverse-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.slide-x-reverse-transition-enter-from,.slide-x-reverse-transition-leave-to{opacity:0;transform:translate(15px)}.slide-x-reverse-transition-enter-active,.slide-x-reverse-transition-leave-active{transition-property:transform,opacity!important}.fade-transition-enter-active,.fade-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.fade-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.fade-transition-enter-from,.fade-transition-leave-to{opacity:0!important}.fade-transition-enter-active,.fade-transition-leave-active{transition-property:opacity!important}.fab-transition-enter-active,.fab-transition-leave-active{transition-duration:.3s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.fab-transition-move{transition-duration:.5s!important;transition-property:transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.fab-transition-enter-from,.fab-transition-leave-to{transform:scale(0) rotate(-45deg)}.fab-transition-enter-active,.fab-transition-leave-active{transition-property:transform!important}.v-locale--is-rtl{direction:rtl}.v-locale--is-ltr{direction:ltr}.blockquote{padding:16px 0 16px 24px;font-size:18px;font-weight:300}html{font-family:Roboto,sans-serif;line-height:1.5;font-size:1rem;overflow-x:hidden;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:rgba(0,0,0,0)}html.overflow-y-hidden{overflow-y:hidden!important}:root{--v-theme-overlay-multiplier: 1;--v-scrollbar-offset: 0px}@supports (-webkit-touch-callout: none){body{cursor:pointer}}@media only print{.hidden-print-only{display:none!important}}@media only screen{.hidden-screen-only{display:none!important}}@media (max-width: 599.98px){.hidden-xs{display:none!important}}@media (min-width: 600px) and (max-width: 959.98px){.hidden-sm{display:none!important}}@media (min-width: 960px) and (max-width: 1279.98px){.hidden-md{display:none!important}}@media (min-width: 1280px) and (max-width: 1919.98px){.hidden-lg{display:none!important}}@media (min-width: 1920px) and (max-width: 2559.98px){.hidden-xl{display:none!important}}@media (min-width: 2560px){.hidden-xxl{display:none!important}}@media (min-width: 600px){.hidden-sm-and-up{display:none!important}}@media (min-width: 960px){.hidden-md-and-up{display:none!important}}@media (min-width: 1280px){.hidden-lg-and-up{display:none!important}}@media (min-width: 1920px){.hidden-xl-and-up{display:none!important}}@media (max-width: 959.98px){.hidden-sm-and-down{display:none!important}}@media (max-width: 1279.98px){.hidden-md-and-down{display:none!important}}@media (max-width: 1919.98px){.hidden-lg-and-down{display:none!important}}@media (max-width: 2559.98px){.hidden-xl-and-down{display:none!important}}.elevation-24{box-shadow:0 11px 15px -7px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 24px 38px 3px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 9px 46px 8px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-23{box-shadow:0 11px 14px -7px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 23px 36px 3px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 9px 44px 8px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-22{box-shadow:0 10px 14px -6px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 22px 35px 3px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 8px 42px 7px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-21{box-shadow:0 10px 13px -6px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 21px 33px 3px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 8px 40px 7px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-20{box-shadow:0 10px 13px -6px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 20px 31px 3px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 8px 38px 7px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-19{box-shadow:0 9px 12px -6px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 19px 29px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 7px 36px 6px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-18{box-shadow:0 9px 11px -5px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 18px 28px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 7px 34px 6px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-17{box-shadow:0 8px 11px -5px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 17px 26px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 6px 32px 5px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-16{box-shadow:0 8px 10px -5px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 16px 24px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 6px 30px 5px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-15{box-shadow:0 8px 9px -5px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 15px 22px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 6px 28px 5px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-14{box-shadow:0 7px 9px -4px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 14px 21px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 5px 26px 4px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-13{box-shadow:0 7px 8px -4px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 13px 19px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 5px 24px 4px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-12{box-shadow:0 7px 8px -4px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 12px 17px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 5px 22px 4px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-11{box-shadow:0 6px 7px -4px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 11px 15px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 4px 20px 3px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-10{box-shadow:0 6px 6px -3px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 10px 14px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 4px 18px 3px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-9{box-shadow:0 5px 6px -3px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 9px 12px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 3px 16px 2px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-8{box-shadow:0 5px 5px -3px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 8px 10px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 3px 14px 2px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-7{box-shadow:0 4px 5px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 7px 10px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 2px 16px 1px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-6{box-shadow:0 3px 5px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 6px 10px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 18px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-5{box-shadow:0 3px 5px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 5px 8px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 14px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-4{box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-3{box-shadow:0 3px 3px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 3px 4px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 8px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-2{box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-1{box-shadow:0 2px 1px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 1px 1px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 3px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.elevation-0{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))!important}.d-sr-only,.d-sr-only-focusable:not(:focus){border:0!important;clip:rect(0,0,0,0)!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!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}.float-none{float:none!important}.float-left{float:left!important}.float-right{float:right!important}.v-locale--is-rtl .float-end{float:left!important}.v-locale--is-rtl .float-start,.v-locale--is-ltr .float-end{float:right!important}.v-locale--is-ltr .float-start{float:left!important}.flex-fill,.flex-1-1{flex:1 1 auto!important}.flex-1-0{flex:1 0 auto!important}.flex-0-1{flex:0 1 auto!important}.flex-0-0{flex:0 0 auto!important}.flex-1-1-100{flex:1 1 100%!important}.flex-1-0-100{flex:1 0 100%!important}.flex-0-1-100{flex:0 1 100%!important}.flex-0-0-100{flex:0 0 100%!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-start{justify-content:flex-start!important}.justify-end{justify-content:flex-end!important}.justify-center{justify-content:center!important}.justify-space-between{justify-content:space-between!important}.justify-space-around{justify-content:space-around!important}.justify-space-evenly{justify-content:space-evenly!important}.align-start{align-items:flex-start!important}.align-end{align-items:flex-end!important}.align-center{align-items:center!important}.align-baseline{align-items:baseline!important}.align-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-space-between{align-content:space-between!important}.align-content-space-around{align-content:space-around!important}.align-content-space-evenly{align-content:space-evenly!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-6{order:6!important}.order-7{order:7!important}.order-8{order:8!important}.order-9{order:9!important}.order-10{order:10!important}.order-11{order:11!important}.order-12{order:12!important}.order-last{order:13!important}.ga-0{gap:0px!important}.ga-1{gap:4px!important}.ga-2{gap:8px!important}.ga-3{gap:12px!important}.ga-4{gap:16px!important}.ga-5{gap:20px!important}.ga-6{gap:24px!important}.ga-7{gap:28px!important}.ga-8{gap:32px!important}.ga-9{gap:36px!important}.ga-10{gap:40px!important}.ga-11{gap:44px!important}.ga-12{gap:48px!important}.ga-13{gap:52px!important}.ga-14{gap:56px!important}.ga-15{gap:60px!important}.ga-16{gap:64px!important}.ga-auto{gap:auto!important}.gr-0{row-gap:0px!important}.gr-1{row-gap:4px!important}.gr-2{row-gap:8px!important}.gr-3{row-gap:12px!important}.gr-4{row-gap:16px!important}.gr-5{row-gap:20px!important}.gr-6{row-gap:24px!important}.gr-7{row-gap:28px!important}.gr-8{row-gap:32px!important}.gr-9{row-gap:36px!important}.gr-10{row-gap:40px!important}.gr-11{row-gap:44px!important}.gr-12{row-gap:48px!important}.gr-13{row-gap:52px!important}.gr-14{row-gap:56px!important}.gr-15{row-gap:60px!important}.gr-16{row-gap:64px!important}.gr-auto{row-gap:auto!important}.gc-0{column-gap:0px!important}.gc-1{column-gap:4px!important}.gc-2{column-gap:8px!important}.gc-3{column-gap:12px!important}.gc-4{column-gap:16px!important}.gc-5{column-gap:20px!important}.gc-6{column-gap:24px!important}.gc-7{column-gap:28px!important}.gc-8{column-gap:32px!important}.gc-9{column-gap:36px!important}.gc-10{column-gap:40px!important}.gc-11{column-gap:44px!important}.gc-12{column-gap:48px!important}.gc-13{column-gap:52px!important}.gc-14{column-gap:56px!important}.gc-15{column-gap:60px!important}.gc-16{column-gap:64px!important}.gc-auto{column-gap:auto!important}.ma-0{margin:0!important}.ma-1{margin:4px!important}.ma-2{margin:8px!important}.ma-3{margin:12px!important}.ma-4{margin:16px!important}.ma-5{margin:20px!important}.ma-6{margin:24px!important}.ma-7{margin:28px!important}.ma-8{margin:32px!important}.ma-9{margin:36px!important}.ma-10{margin:40px!important}.ma-11{margin:44px!important}.ma-12{margin:48px!important}.ma-13{margin:52px!important}.ma-14{margin:56px!important}.ma-15{margin:60px!important}.ma-16{margin:64px!important}.ma-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:4px!important;margin-left:4px!important}.mx-2{margin-right:8px!important;margin-left:8px!important}.mx-3{margin-right:12px!important;margin-left:12px!important}.mx-4{margin-right:16px!important;margin-left:16px!important}.mx-5{margin-right:20px!important;margin-left:20px!important}.mx-6{margin-right:24px!important;margin-left:24px!important}.mx-7{margin-right:28px!important;margin-left:28px!important}.mx-8{margin-right:32px!important;margin-left:32px!important}.mx-9{margin-right:36px!important;margin-left:36px!important}.mx-10{margin-right:40px!important;margin-left:40px!important}.mx-11{margin-right:44px!important;margin-left:44px!important}.mx-12{margin-right:48px!important;margin-left:48px!important}.mx-13{margin-right:52px!important;margin-left:52px!important}.mx-14{margin-right:56px!important;margin-left:56px!important}.mx-15{margin-right:60px!important;margin-left:60px!important}.mx-16{margin-right:64px!important;margin-left:64px!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:4px!important;margin-bottom:4px!important}.my-2{margin-top:8px!important;margin-bottom:8px!important}.my-3{margin-top:12px!important;margin-bottom:12px!important}.my-4{margin-top:16px!important;margin-bottom:16px!important}.my-5{margin-top:20px!important;margin-bottom:20px!important}.my-6{margin-top:24px!important;margin-bottom:24px!important}.my-7{margin-top:28px!important;margin-bottom:28px!important}.my-8{margin-top:32px!important;margin-bottom:32px!important}.my-9{margin-top:36px!important;margin-bottom:36px!important}.my-10{margin-top:40px!important;margin-bottom:40px!important}.my-11{margin-top:44px!important;margin-bottom:44px!important}.my-12{margin-top:48px!important;margin-bottom:48px!important}.my-13{margin-top:52px!important;margin-bottom:52px!important}.my-14{margin-top:56px!important;margin-bottom:56px!important}.my-15{margin-top:60px!important;margin-bottom:60px!important}.my-16{margin-top:64px!important;margin-bottom:64px!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:4px!important}.mt-2{margin-top:8px!important}.mt-3{margin-top:12px!important}.mt-4{margin-top:16px!important}.mt-5{margin-top:20px!important}.mt-6{margin-top:24px!important}.mt-7{margin-top:28px!important}.mt-8{margin-top:32px!important}.mt-9{margin-top:36px!important}.mt-10{margin-top:40px!important}.mt-11{margin-top:44px!important}.mt-12{margin-top:48px!important}.mt-13{margin-top:52px!important}.mt-14{margin-top:56px!important}.mt-15{margin-top:60px!important}.mt-16{margin-top:64px!important}.mt-auto{margin-top:auto!important}.mr-0{margin-right:0!important}.mr-1{margin-right:4px!important}.mr-2{margin-right:8px!important}.mr-3{margin-right:12px!important}.mr-4{margin-right:16px!important}.mr-5{margin-right:20px!important}.mr-6{margin-right:24px!important}.mr-7{margin-right:28px!important}.mr-8{margin-right:32px!important}.mr-9{margin-right:36px!important}.mr-10{margin-right:40px!important}.mr-11{margin-right:44px!important}.mr-12{margin-right:48px!important}.mr-13{margin-right:52px!important}.mr-14{margin-right:56px!important}.mr-15{margin-right:60px!important}.mr-16{margin-right:64px!important}.mr-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:4px!important}.mb-2{margin-bottom:8px!important}.mb-3{margin-bottom:12px!important}.mb-4{margin-bottom:16px!important}.mb-5{margin-bottom:20px!important}.mb-6{margin-bottom:24px!important}.mb-7{margin-bottom:28px!important}.mb-8{margin-bottom:32px!important}.mb-9{margin-bottom:36px!important}.mb-10{margin-bottom:40px!important}.mb-11{margin-bottom:44px!important}.mb-12{margin-bottom:48px!important}.mb-13{margin-bottom:52px!important}.mb-14{margin-bottom:56px!important}.mb-15{margin-bottom:60px!important}.mb-16{margin-bottom:64px!important}.mb-auto{margin-bottom:auto!important}.ml-0{margin-left:0!important}.ml-1{margin-left:4px!important}.ml-2{margin-left:8px!important}.ml-3{margin-left:12px!important}.ml-4{margin-left:16px!important}.ml-5{margin-left:20px!important}.ml-6{margin-left:24px!important}.ml-7{margin-left:28px!important}.ml-8{margin-left:32px!important}.ml-9{margin-left:36px!important}.ml-10{margin-left:40px!important}.ml-11{margin-left:44px!important}.ml-12{margin-left:48px!important}.ml-13{margin-left:52px!important}.ml-14{margin-left:56px!important}.ml-15{margin-left:60px!important}.ml-16{margin-left:64px!important}.ml-auto{margin-left:auto!important}.ms-0{margin-inline-start:0px!important}.ms-1{margin-inline-start:4px!important}.ms-2{margin-inline-start:8px!important}.ms-3{margin-inline-start:12px!important}.ms-4{margin-inline-start:16px!important}.ms-5{margin-inline-start:20px!important}.ms-6{margin-inline-start:24px!important}.ms-7{margin-inline-start:28px!important}.ms-8{margin-inline-start:32px!important}.ms-9{margin-inline-start:36px!important}.ms-10{margin-inline-start:40px!important}.ms-11{margin-inline-start:44px!important}.ms-12{margin-inline-start:48px!important}.ms-13{margin-inline-start:52px!important}.ms-14{margin-inline-start:56px!important}.ms-15{margin-inline-start:60px!important}.ms-16{margin-inline-start:64px!important}.ms-auto{margin-inline-start:auto!important}.me-0{margin-inline-end:0px!important}.me-1{margin-inline-end:4px!important}.me-2{margin-inline-end:8px!important}.me-3{margin-inline-end:12px!important}.me-4{margin-inline-end:16px!important}.me-5{margin-inline-end:20px!important}.me-6{margin-inline-end:24px!important}.me-7{margin-inline-end:28px!important}.me-8{margin-inline-end:32px!important}.me-9{margin-inline-end:36px!important}.me-10{margin-inline-end:40px!important}.me-11{margin-inline-end:44px!important}.me-12{margin-inline-end:48px!important}.me-13{margin-inline-end:52px!important}.me-14{margin-inline-end:56px!important}.me-15{margin-inline-end:60px!important}.me-16{margin-inline-end:64px!important}.me-auto{margin-inline-end:auto!important}.ma-n1{margin:-4px!important}.ma-n2{margin:-8px!important}.ma-n3{margin:-12px!important}.ma-n4{margin:-16px!important}.ma-n5{margin:-20px!important}.ma-n6{margin:-24px!important}.ma-n7{margin:-28px!important}.ma-n8{margin:-32px!important}.ma-n9{margin:-36px!important}.ma-n10{margin:-40px!important}.ma-n11{margin:-44px!important}.ma-n12{margin:-48px!important}.ma-n13{margin:-52px!important}.ma-n14{margin:-56px!important}.ma-n15{margin:-60px!important}.ma-n16{margin:-64px!important}.mx-n1{margin-right:-4px!important;margin-left:-4px!important}.mx-n2{margin-right:-8px!important;margin-left:-8px!important}.mx-n3{margin-right:-12px!important;margin-left:-12px!important}.mx-n4{margin-right:-16px!important;margin-left:-16px!important}.mx-n5{margin-right:-20px!important;margin-left:-20px!important}.mx-n6{margin-right:-24px!important;margin-left:-24px!important}.mx-n7{margin-right:-28px!important;margin-left:-28px!important}.mx-n8{margin-right:-32px!important;margin-left:-32px!important}.mx-n9{margin-right:-36px!important;margin-left:-36px!important}.mx-n10{margin-right:-40px!important;margin-left:-40px!important}.mx-n11{margin-right:-44px!important;margin-left:-44px!important}.mx-n12{margin-right:-48px!important;margin-left:-48px!important}.mx-n13{margin-right:-52px!important;margin-left:-52px!important}.mx-n14{margin-right:-56px!important;margin-left:-56px!important}.mx-n15{margin-right:-60px!important;margin-left:-60px!important}.mx-n16{margin-right:-64px!important;margin-left:-64px!important}.my-n1{margin-top:-4px!important;margin-bottom:-4px!important}.my-n2{margin-top:-8px!important;margin-bottom:-8px!important}.my-n3{margin-top:-12px!important;margin-bottom:-12px!important}.my-n4{margin-top:-16px!important;margin-bottom:-16px!important}.my-n5{margin-top:-20px!important;margin-bottom:-20px!important}.my-n6{margin-top:-24px!important;margin-bottom:-24px!important}.my-n7{margin-top:-28px!important;margin-bottom:-28px!important}.my-n8{margin-top:-32px!important;margin-bottom:-32px!important}.my-n9{margin-top:-36px!important;margin-bottom:-36px!important}.my-n10{margin-top:-40px!important;margin-bottom:-40px!important}.my-n11{margin-top:-44px!important;margin-bottom:-44px!important}.my-n12{margin-top:-48px!important;margin-bottom:-48px!important}.my-n13{margin-top:-52px!important;margin-bottom:-52px!important}.my-n14{margin-top:-56px!important;margin-bottom:-56px!important}.my-n15{margin-top:-60px!important;margin-bottom:-60px!important}.my-n16{margin-top:-64px!important;margin-bottom:-64px!important}.mt-n1{margin-top:-4px!important}.mt-n2{margin-top:-8px!important}.mt-n3{margin-top:-12px!important}.mt-n4{margin-top:-16px!important}.mt-n5{margin-top:-20px!important}.mt-n6{margin-top:-24px!important}.mt-n7{margin-top:-28px!important}.mt-n8{margin-top:-32px!important}.mt-n9{margin-top:-36px!important}.mt-n10{margin-top:-40px!important}.mt-n11{margin-top:-44px!important}.mt-n12{margin-top:-48px!important}.mt-n13{margin-top:-52px!important}.mt-n14{margin-top:-56px!important}.mt-n15{margin-top:-60px!important}.mt-n16{margin-top:-64px!important}.mr-n1{margin-right:-4px!important}.mr-n2{margin-right:-8px!important}.mr-n3{margin-right:-12px!important}.mr-n4{margin-right:-16px!important}.mr-n5{margin-right:-20px!important}.mr-n6{margin-right:-24px!important}.mr-n7{margin-right:-28px!important}.mr-n8{margin-right:-32px!important}.mr-n9{margin-right:-36px!important}.mr-n10{margin-right:-40px!important}.mr-n11{margin-right:-44px!important}.mr-n12{margin-right:-48px!important}.mr-n13{margin-right:-52px!important}.mr-n14{margin-right:-56px!important}.mr-n15{margin-right:-60px!important}.mr-n16{margin-right:-64px!important}.mb-n1{margin-bottom:-4px!important}.mb-n2{margin-bottom:-8px!important}.mb-n3{margin-bottom:-12px!important}.mb-n4{margin-bottom:-16px!important}.mb-n5{margin-bottom:-20px!important}.mb-n6{margin-bottom:-24px!important}.mb-n7{margin-bottom:-28px!important}.mb-n8{margin-bottom:-32px!important}.mb-n9{margin-bottom:-36px!important}.mb-n10{margin-bottom:-40px!important}.mb-n11{margin-bottom:-44px!important}.mb-n12{margin-bottom:-48px!important}.mb-n13{margin-bottom:-52px!important}.mb-n14{margin-bottom:-56px!important}.mb-n15{margin-bottom:-60px!important}.mb-n16{margin-bottom:-64px!important}.ml-n1{margin-left:-4px!important}.ml-n2{margin-left:-8px!important}.ml-n3{margin-left:-12px!important}.ml-n4{margin-left:-16px!important}.ml-n5{margin-left:-20px!important}.ml-n6{margin-left:-24px!important}.ml-n7{margin-left:-28px!important}.ml-n8{margin-left:-32px!important}.ml-n9{margin-left:-36px!important}.ml-n10{margin-left:-40px!important}.ml-n11{margin-left:-44px!important}.ml-n12{margin-left:-48px!important}.ml-n13{margin-left:-52px!important}.ml-n14{margin-left:-56px!important}.ml-n15{margin-left:-60px!important}.ml-n16{margin-left:-64px!important}.ms-n1{margin-inline-start:-4px!important}.ms-n2{margin-inline-start:-8px!important}.ms-n3{margin-inline-start:-12px!important}.ms-n4{margin-inline-start:-16px!important}.ms-n5{margin-inline-start:-20px!important}.ms-n6{margin-inline-start:-24px!important}.ms-n7{margin-inline-start:-28px!important}.ms-n8{margin-inline-start:-32px!important}.ms-n9{margin-inline-start:-36px!important}.ms-n10{margin-inline-start:-40px!important}.ms-n11{margin-inline-start:-44px!important}.ms-n12{margin-inline-start:-48px!important}.ms-n13{margin-inline-start:-52px!important}.ms-n14{margin-inline-start:-56px!important}.ms-n15{margin-inline-start:-60px!important}.ms-n16{margin-inline-start:-64px!important}.me-n1{margin-inline-end:-4px!important}.me-n2{margin-inline-end:-8px!important}.me-n3{margin-inline-end:-12px!important}.me-n4{margin-inline-end:-16px!important}.me-n5{margin-inline-end:-20px!important}.me-n6{margin-inline-end:-24px!important}.me-n7{margin-inline-end:-28px!important}.me-n8{margin-inline-end:-32px!important}.me-n9{margin-inline-end:-36px!important}.me-n10{margin-inline-end:-40px!important}.me-n11{margin-inline-end:-44px!important}.me-n12{margin-inline-end:-48px!important}.me-n13{margin-inline-end:-52px!important}.me-n14{margin-inline-end:-56px!important}.me-n15{margin-inline-end:-60px!important}.me-n16{margin-inline-end:-64px!important}.pa-0{padding:0!important}.pa-1{padding:4px!important}.pa-2{padding:8px!important}.pa-3{padding:12px!important}.pa-4{padding:16px!important}.pa-5{padding:20px!important}.pa-6{padding:24px!important}.pa-7{padding:28px!important}.pa-8{padding:32px!important}.pa-9{padding:36px!important}.pa-10{padding:40px!important}.pa-11{padding:44px!important}.pa-12{padding:48px!important}.pa-13{padding:52px!important}.pa-14{padding:56px!important}.pa-15{padding:60px!important}.pa-16{padding:64px!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:4px!important;padding-left:4px!important}.px-2{padding-right:8px!important;padding-left:8px!important}.px-3{padding-right:12px!important;padding-left:12px!important}.px-4{padding-right:16px!important;padding-left:16px!important}.px-5{padding-right:20px!important;padding-left:20px!important}.px-6{padding-right:24px!important;padding-left:24px!important}.px-7{padding-right:28px!important;padding-left:28px!important}.px-8{padding-right:32px!important;padding-left:32px!important}.px-9{padding-right:36px!important;padding-left:36px!important}.px-10{padding-right:40px!important;padding-left:40px!important}.px-11{padding-right:44px!important;padding-left:44px!important}.px-12{padding-right:48px!important;padding-left:48px!important}.px-13{padding-right:52px!important;padding-left:52px!important}.px-14{padding-right:56px!important;padding-left:56px!important}.px-15{padding-right:60px!important;padding-left:60px!important}.px-16{padding-right:64px!important;padding-left:64px!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:4px!important;padding-bottom:4px!important}.py-2{padding-top:8px!important;padding-bottom:8px!important}.py-3{padding-top:12px!important;padding-bottom:12px!important}.py-4{padding-top:16px!important;padding-bottom:16px!important}.py-5{padding-top:20px!important;padding-bottom:20px!important}.py-6{padding-top:24px!important;padding-bottom:24px!important}.py-7{padding-top:28px!important;padding-bottom:28px!important}.py-8{padding-top:32px!important;padding-bottom:32px!important}.py-9{padding-top:36px!important;padding-bottom:36px!important}.py-10{padding-top:40px!important;padding-bottom:40px!important}.py-11{padding-top:44px!important;padding-bottom:44px!important}.py-12{padding-top:48px!important;padding-bottom:48px!important}.py-13{padding-top:52px!important;padding-bottom:52px!important}.py-14{padding-top:56px!important;padding-bottom:56px!important}.py-15{padding-top:60px!important;padding-bottom:60px!important}.py-16{padding-top:64px!important;padding-bottom:64px!important}.pt-0{padding-top:0!important}.pt-1{padding-top:4px!important}.pt-2{padding-top:8px!important}.pt-3{padding-top:12px!important}.pt-4{padding-top:16px!important}.pt-5{padding-top:20px!important}.pt-6{padding-top:24px!important}.pt-7{padding-top:28px!important}.pt-8{padding-top:32px!important}.pt-9{padding-top:36px!important}.pt-10{padding-top:40px!important}.pt-11{padding-top:44px!important}.pt-12{padding-top:48px!important}.pt-13{padding-top:52px!important}.pt-14{padding-top:56px!important}.pt-15{padding-top:60px!important}.pt-16{padding-top:64px!important}.pr-0{padding-right:0!important}.pr-1{padding-right:4px!important}.pr-2{padding-right:8px!important}.pr-3{padding-right:12px!important}.pr-4{padding-right:16px!important}.pr-5{padding-right:20px!important}.pr-6{padding-right:24px!important}.pr-7{padding-right:28px!important}.pr-8{padding-right:32px!important}.pr-9{padding-right:36px!important}.pr-10{padding-right:40px!important}.pr-11{padding-right:44px!important}.pr-12{padding-right:48px!important}.pr-13{padding-right:52px!important}.pr-14{padding-right:56px!important}.pr-15{padding-right:60px!important}.pr-16{padding-right:64px!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:4px!important}.pb-2{padding-bottom:8px!important}.pb-3{padding-bottom:12px!important}.pb-4{padding-bottom:16px!important}.pb-5{padding-bottom:20px!important}.pb-6{padding-bottom:24px!important}.pb-7{padding-bottom:28px!important}.pb-8{padding-bottom:32px!important}.pb-9{padding-bottom:36px!important}.pb-10{padding-bottom:40px!important}.pb-11{padding-bottom:44px!important}.pb-12{padding-bottom:48px!important}.pb-13{padding-bottom:52px!important}.pb-14{padding-bottom:56px!important}.pb-15{padding-bottom:60px!important}.pb-16{padding-bottom:64px!important}.pl-0{padding-left:0!important}.pl-1{padding-left:4px!important}.pl-2{padding-left:8px!important}.pl-3{padding-left:12px!important}.pl-4{padding-left:16px!important}.pl-5{padding-left:20px!important}.pl-6{padding-left:24px!important}.pl-7{padding-left:28px!important}.pl-8{padding-left:32px!important}.pl-9{padding-left:36px!important}.pl-10{padding-left:40px!important}.pl-11{padding-left:44px!important}.pl-12{padding-left:48px!important}.pl-13{padding-left:52px!important}.pl-14{padding-left:56px!important}.pl-15{padding-left:60px!important}.pl-16{padding-left:64px!important}.ps-0{padding-inline-start:0px!important}.ps-1{padding-inline-start:4px!important}.ps-2{padding-inline-start:8px!important}.ps-3{padding-inline-start:12px!important}.ps-4{padding-inline-start:16px!important}.ps-5{padding-inline-start:20px!important}.ps-6{padding-inline-start:24px!important}.ps-7{padding-inline-start:28px!important}.ps-8{padding-inline-start:32px!important}.ps-9{padding-inline-start:36px!important}.ps-10{padding-inline-start:40px!important}.ps-11{padding-inline-start:44px!important}.ps-12{padding-inline-start:48px!important}.ps-13{padding-inline-start:52px!important}.ps-14{padding-inline-start:56px!important}.ps-15{padding-inline-start:60px!important}.ps-16{padding-inline-start:64px!important}.pe-0{padding-inline-end:0px!important}.pe-1{padding-inline-end:4px!important}.pe-2{padding-inline-end:8px!important}.pe-3{padding-inline-end:12px!important}.pe-4{padding-inline-end:16px!important}.pe-5{padding-inline-end:20px!important}.pe-6{padding-inline-end:24px!important}.pe-7{padding-inline-end:28px!important}.pe-8{padding-inline-end:32px!important}.pe-9{padding-inline-end:36px!important}.pe-10{padding-inline-end:40px!important}.pe-11{padding-inline-end:44px!important}.pe-12{padding-inline-end:48px!important}.pe-13{padding-inline-end:52px!important}.pe-14{padding-inline-end:56px!important}.pe-15{padding-inline-end:60px!important}.pe-16{padding-inline-end:64px!important}.rounded-0{border-radius:0!important}.rounded-sm{border-radius:2px!important}.rounded{border-radius:4px!important}.rounded-lg{border-radius:8px!important}.rounded-xl{border-radius:24px!important}.rounded-pill{border-radius:9999px!important}.rounded-circle{border-radius:50%!important}.rounded-shaped{border-radius:24px 0!important}.rounded-t-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-t-sm{border-top-left-radius:2px!important;border-top-right-radius:2px!important}.rounded-t{border-top-left-radius:4px!important;border-top-right-radius:4px!important}.rounded-t-lg{border-top-left-radius:8px!important;border-top-right-radius:8px!important}.rounded-t-xl{border-top-left-radius:24px!important;border-top-right-radius:24px!important}.rounded-t-pill{border-top-left-radius:9999px!important;border-top-right-radius:9999px!important}.rounded-t-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-t-shaped{border-top-left-radius:24px!important;border-top-right-radius:0!important}.v-locale--is-ltr .rounded-e-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.v-locale--is-rtl .rounded-e-0{border-top-left-radius:0!important;border-bottom-left-radius:0!important}.v-locale--is-ltr .rounded-e-sm{border-top-right-radius:2px!important;border-bottom-right-radius:2px!important}.v-locale--is-rtl .rounded-e-sm{border-top-left-radius:2px!important;border-bottom-left-radius:2px!important}.v-locale--is-ltr .rounded-e{border-top-right-radius:4px!important;border-bottom-right-radius:4px!important}.v-locale--is-rtl .rounded-e{border-top-left-radius:4px!important;border-bottom-left-radius:4px!important}.v-locale--is-ltr .rounded-e-lg{border-top-right-radius:8px!important;border-bottom-right-radius:8px!important}.v-locale--is-rtl .rounded-e-lg{border-top-left-radius:8px!important;border-bottom-left-radius:8px!important}.v-locale--is-ltr .rounded-e-xl{border-top-right-radius:24px!important;border-bottom-right-radius:24px!important}.v-locale--is-rtl .rounded-e-xl{border-top-left-radius:24px!important;border-bottom-left-radius:24px!important}.v-locale--is-ltr .rounded-e-pill{border-top-right-radius:9999px!important;border-bottom-right-radius:9999px!important}.v-locale--is-rtl .rounded-e-pill{border-top-left-radius:9999px!important;border-bottom-left-radius:9999px!important}.v-locale--is-ltr .rounded-e-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.v-locale--is-rtl .rounded-e-circle{border-top-left-radius:50%!important;border-bottom-left-radius:50%!important}.v-locale--is-ltr .rounded-e-shaped{border-top-right-radius:24px!important;border-bottom-right-radius:0!important}.v-locale--is-rtl .rounded-e-shaped{border-top-left-radius:24px!important;border-bottom-left-radius:0!important}.rounded-b-0{border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}.rounded-b-sm{border-bottom-left-radius:2px!important;border-bottom-right-radius:2px!important}.rounded-b{border-bottom-left-radius:4px!important;border-bottom-right-radius:4px!important}.rounded-b-lg{border-bottom-left-radius:8px!important;border-bottom-right-radius:8px!important}.rounded-b-xl{border-bottom-left-radius:24px!important;border-bottom-right-radius:24px!important}.rounded-b-pill{border-bottom-left-radius:9999px!important;border-bottom-right-radius:9999px!important}.rounded-b-circle{border-bottom-left-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-b-shaped{border-bottom-left-radius:24px!important;border-bottom-right-radius:0!important}.v-locale--is-ltr .rounded-s-0{border-top-left-radius:0!important;border-bottom-left-radius:0!important}.v-locale--is-rtl .rounded-s-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.v-locale--is-ltr .rounded-s-sm{border-top-left-radius:2px!important;border-bottom-left-radius:2px!important}.v-locale--is-rtl .rounded-s-sm{border-top-right-radius:2px!important;border-bottom-right-radius:2px!important}.v-locale--is-ltr .rounded-s{border-top-left-radius:4px!important;border-bottom-left-radius:4px!important}.v-locale--is-rtl .rounded-s{border-top-right-radius:4px!important;border-bottom-right-radius:4px!important}.v-locale--is-ltr .rounded-s-lg{border-top-left-radius:8px!important;border-bottom-left-radius:8px!important}.v-locale--is-rtl .rounded-s-lg{border-top-right-radius:8px!important;border-bottom-right-radius:8px!important}.v-locale--is-ltr .rounded-s-xl{border-top-left-radius:24px!important;border-bottom-left-radius:24px!important}.v-locale--is-rtl .rounded-s-xl{border-top-right-radius:24px!important;border-bottom-right-radius:24px!important}.v-locale--is-ltr .rounded-s-pill{border-top-left-radius:9999px!important;border-bottom-left-radius:9999px!important}.v-locale--is-rtl .rounded-s-pill{border-top-right-radius:9999px!important;border-bottom-right-radius:9999px!important}.v-locale--is-ltr .rounded-s-circle{border-top-left-radius:50%!important;border-bottom-left-radius:50%!important}.v-locale--is-rtl .rounded-s-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.v-locale--is-ltr .rounded-s-shaped{border-top-left-radius:24px!important;border-bottom-left-radius:0!important}.v-locale--is-rtl .rounded-s-shaped{border-top-right-radius:24px!important;border-bottom-right-radius:0!important}.v-locale--is-ltr .rounded-ts-0{border-top-left-radius:0!important}.v-locale--is-rtl .rounded-ts-0{border-top-right-radius:0!important}.v-locale--is-ltr .rounded-ts-sm{border-top-left-radius:2px!important}.v-locale--is-rtl .rounded-ts-sm{border-top-right-radius:2px!important}.v-locale--is-ltr .rounded-ts{border-top-left-radius:4px!important}.v-locale--is-rtl .rounded-ts{border-top-right-radius:4px!important}.v-locale--is-ltr .rounded-ts-lg{border-top-left-radius:8px!important}.v-locale--is-rtl .rounded-ts-lg{border-top-right-radius:8px!important}.v-locale--is-ltr .rounded-ts-xl{border-top-left-radius:24px!important}.v-locale--is-rtl .rounded-ts-xl{border-top-right-radius:24px!important}.v-locale--is-ltr .rounded-ts-pill{border-top-left-radius:9999px!important}.v-locale--is-rtl .rounded-ts-pill{border-top-right-radius:9999px!important}.v-locale--is-ltr .rounded-ts-circle{border-top-left-radius:50%!important}.v-locale--is-rtl .rounded-ts-circle{border-top-right-radius:50%!important}.v-locale--is-ltr .rounded-ts-shaped{border-top-left-radius:24px 0!important}.v-locale--is-rtl .rounded-ts-shaped{border-top-right-radius:24px 0!important}.v-locale--is-ltr .rounded-te-0{border-top-right-radius:0!important}.v-locale--is-rtl .rounded-te-0{border-top-left-radius:0!important}.v-locale--is-ltr .rounded-te-sm{border-top-right-radius:2px!important}.v-locale--is-rtl .rounded-te-sm{border-top-left-radius:2px!important}.v-locale--is-ltr .rounded-te{border-top-right-radius:4px!important}.v-locale--is-rtl .rounded-te{border-top-left-radius:4px!important}.v-locale--is-ltr .rounded-te-lg{border-top-right-radius:8px!important}.v-locale--is-rtl .rounded-te-lg{border-top-left-radius:8px!important}.v-locale--is-ltr .rounded-te-xl{border-top-right-radius:24px!important}.v-locale--is-rtl .rounded-te-xl{border-top-left-radius:24px!important}.v-locale--is-ltr .rounded-te-pill{border-top-right-radius:9999px!important}.v-locale--is-rtl .rounded-te-pill{border-top-left-radius:9999px!important}.v-locale--is-ltr .rounded-te-circle{border-top-right-radius:50%!important}.v-locale--is-rtl .rounded-te-circle{border-top-left-radius:50%!important}.v-locale--is-ltr .rounded-te-shaped{border-top-right-radius:24px 0!important}.v-locale--is-rtl .rounded-te-shaped{border-top-left-radius:24px 0!important}.v-locale--is-ltr .rounded-be-0{border-bottom-right-radius:0!important}.v-locale--is-rtl .rounded-be-0{border-bottom-left-radius:0!important}.v-locale--is-ltr .rounded-be-sm{border-bottom-right-radius:2px!important}.v-locale--is-rtl .rounded-be-sm{border-bottom-left-radius:2px!important}.v-locale--is-ltr .rounded-be{border-bottom-right-radius:4px!important}.v-locale--is-rtl .rounded-be{border-bottom-left-radius:4px!important}.v-locale--is-ltr .rounded-be-lg{border-bottom-right-radius:8px!important}.v-locale--is-rtl .rounded-be-lg{border-bottom-left-radius:8px!important}.v-locale--is-ltr .rounded-be-xl{border-bottom-right-radius:24px!important}.v-locale--is-rtl .rounded-be-xl{border-bottom-left-radius:24px!important}.v-locale--is-ltr .rounded-be-pill{border-bottom-right-radius:9999px!important}.v-locale--is-rtl .rounded-be-pill{border-bottom-left-radius:9999px!important}.v-locale--is-ltr .rounded-be-circle{border-bottom-right-radius:50%!important}.v-locale--is-rtl .rounded-be-circle{border-bottom-left-radius:50%!important}.v-locale--is-ltr .rounded-be-shaped{border-bottom-right-radius:24px 0!important}.v-locale--is-rtl .rounded-be-shaped{border-bottom-left-radius:24px 0!important}.v-locale--is-ltr .rounded-bs-0{border-bottom-left-radius:0!important}.v-locale--is-rtl .rounded-bs-0{border-bottom-right-radius:0!important}.v-locale--is-ltr .rounded-bs-sm{border-bottom-left-radius:2px!important}.v-locale--is-rtl .rounded-bs-sm{border-bottom-right-radius:2px!important}.v-locale--is-ltr .rounded-bs{border-bottom-left-radius:4px!important}.v-locale--is-rtl .rounded-bs{border-bottom-right-radius:4px!important}.v-locale--is-ltr .rounded-bs-lg{border-bottom-left-radius:8px!important}.v-locale--is-rtl .rounded-bs-lg{border-bottom-right-radius:8px!important}.v-locale--is-ltr .rounded-bs-xl{border-bottom-left-radius:24px!important}.v-locale--is-rtl .rounded-bs-xl{border-bottom-right-radius:24px!important}.v-locale--is-ltr .rounded-bs-pill{border-bottom-left-radius:9999px!important}.v-locale--is-rtl .rounded-bs-pill{border-bottom-right-radius:9999px!important}.v-locale--is-ltr .rounded-bs-circle{border-bottom-left-radius:50%!important}.v-locale--is-rtl .rounded-bs-circle{border-bottom-right-radius:50%!important}.v-locale--is-ltr .rounded-bs-shaped{border-bottom-left-radius:24px 0!important}.v-locale--is-rtl .rounded-bs-shaped{border-bottom-right-radius:24px 0!important}.border-0{border-width:0!important;border-style:solid!important;border-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border{border-width:thin!important;border-style:solid!important;border-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-sm{border-width:1px!important;border-style:solid!important;border-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-md{border-width:2px!important;border-style:solid!important;border-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-lg{border-width:4px!important;border-style:solid!important;border-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-xl{border-width:8px!important;border-style:solid!important;border-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-opacity-0{--v-border-opacity: 0 !important}.border-opacity{--v-border-opacity: .12 !important}.border-opacity-25{--v-border-opacity: .25 !important}.border-opacity-50{--v-border-opacity: .5 !important}.border-opacity-75{--v-border-opacity: .75 !important}.border-opacity-100{--v-border-opacity: 1 !important}.border-t-0{border-block-start-width:0!important;border-block-start-style:solid!important;border-block-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-t{border-block-start-width:thin!important;border-block-start-style:solid!important;border-block-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-t-sm{border-block-start-width:1px!important;border-block-start-style:solid!important;border-block-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-t-md{border-block-start-width:2px!important;border-block-start-style:solid!important;border-block-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-t-lg{border-block-start-width:4px!important;border-block-start-style:solid!important;border-block-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-t-xl{border-block-start-width:8px!important;border-block-start-style:solid!important;border-block-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-e-0{border-inline-end-width:0!important;border-inline-end-style:solid!important;border-inline-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-e{border-inline-end-width:thin!important;border-inline-end-style:solid!important;border-inline-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-e-sm{border-inline-end-width:1px!important;border-inline-end-style:solid!important;border-inline-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-e-md{border-inline-end-width:2px!important;border-inline-end-style:solid!important;border-inline-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-e-lg{border-inline-end-width:4px!important;border-inline-end-style:solid!important;border-inline-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-e-xl{border-inline-end-width:8px!important;border-inline-end-style:solid!important;border-inline-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-b-0{border-block-end-width:0!important;border-block-end-style:solid!important;border-block-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-b{border-block-end-width:thin!important;border-block-end-style:solid!important;border-block-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-b-sm{border-block-end-width:1px!important;border-block-end-style:solid!important;border-block-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-b-md{border-block-end-width:2px!important;border-block-end-style:solid!important;border-block-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-b-lg{border-block-end-width:4px!important;border-block-end-style:solid!important;border-block-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-b-xl{border-block-end-width:8px!important;border-block-end-style:solid!important;border-block-end-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-s-0{border-inline-start-width:0!important;border-inline-start-style:solid!important;border-inline-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-s{border-inline-start-width:thin!important;border-inline-start-style:solid!important;border-inline-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-s-sm{border-inline-start-width:1px!important;border-inline-start-style:solid!important;border-inline-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-s-md{border-inline-start-width:2px!important;border-inline-start-style:solid!important;border-inline-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-s-lg{border-inline-start-width:4px!important;border-inline-start-style:solid!important;border-inline-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-s-xl{border-inline-start-width:8px!important;border-inline-start-style:solid!important;border-inline-start-color:rgba(var(--v-border-color),var(--v-border-opacity))!important}.border-solid{border-style:solid!important}.border-dashed{border-style:dashed!important}.border-dotted{border-style:dotted!important}.border-double{border-style:double!important}.border-none{border-style:none!important}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}.text-justify{text-align:justify!important}.text-start{text-align:start!important}.text-end{text-align:end!important}.text-decoration-line-through{text-decoration:line-through!important}.text-decoration-none{text-decoration:none!important}.text-decoration-overline{text-decoration:overline!important}.text-decoration-underline{text-decoration:underline!important}.text-wrap{white-space:normal!important}.text-no-wrap{white-space:nowrap!important}.text-pre{white-space:pre!important}.text-pre-line{white-space:pre-line!important}.text-pre-wrap{white-space:pre-wrap!important}.text-break{overflow-wrap:break-word!important;word-break:break-word!important}.text-high-emphasis{color:rgba(var(--v-theme-on-background),var(--v-high-emphasis-opacity))!important}.text-medium-emphasis{color:rgba(var(--v-theme-on-background),var(--v-medium-emphasis-opacity))!important}.text-disabled{color:rgba(var(--v-theme-on-background),var(--v-disabled-opacity))!important}.text-truncate{white-space:nowrap!important;overflow:hidden!important;text-overflow:ellipsis!important}.text-h1{font-size:6rem!important;font-weight:300;line-height:6rem;letter-spacing:-.015625em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-h2{font-size:3.75rem!important;font-weight:300;line-height:3.75rem;letter-spacing:-.0083333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-h3{font-size:3rem!important;font-weight:400;line-height:3.125rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-h4{font-size:2.125rem!important;font-weight:400;line-height:2.5rem;letter-spacing:.0073529412em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-h5{font-size:1.5rem!important;font-weight:400;line-height:2rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-h6{font-size:1.25rem!important;font-weight:500;line-height:2rem;letter-spacing:.0125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-subtitle-1{font-size:1rem!important;font-weight:400;line-height:1.75rem;letter-spacing:.009375em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-subtitle-2{font-size:.875rem!important;font-weight:500;line-height:1.375rem;letter-spacing:.0071428571em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-body-1{font-size:1rem!important;font-weight:400;line-height:1.5rem;letter-spacing:.03125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-body-2{font-size:.875rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0178571429em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-button{font-size:.875rem!important;font-weight:500;line-height:2.25rem;letter-spacing:.0892857143em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}.text-caption{font-size:.75rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0333333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-overline{font-size:.75rem!important;font-weight:500;line-height:2rem;letter-spacing:.1666666667em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}.text-none{text-transform:none!important}.text-capitalize{text-transform:capitalize!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.font-weight-thin{font-weight:100!important}.font-weight-light{font-weight:300!important}.font-weight-regular{font-weight:400!important}.font-weight-medium{font-weight:500!important}.font-weight-bold{font-weight:700!important}.font-weight-black{font-weight:900!important}.font-italic{font-style:italic!important}.text-mono{font-family:monospace!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-fixed{position:fixed!important}.position-absolute{position:absolute!important}.position-sticky{position:sticky!important}.cursor-auto{cursor:auto!important}.cursor-default{cursor:default!important}.cursor-pointer{cursor:pointer!important}.cursor-wait{cursor:wait!important}.cursor-text{cursor:text!important}.cursor-move{cursor:move!important}.cursor-help{cursor:help!important}.cursor-not-allowed{cursor:not-allowed!important}.cursor-progress{cursor:progress!important}.cursor-grab{cursor:grab!important}.cursor-grabbing{cursor:grabbing!important}.cursor-none{cursor:none!important}.fill-height{height:100%!important}.h-auto{height:auto!important}.h-screen{height:100vh!important}.h-0{height:0!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-screen{height:100dvh!important}.w-auto{width:auto!important}.w-0{width:0!important}.w-25{width:25%!important}.w-33{width:33%!important}.w-50{width:50%!important}.w-66{width:66%!important}.w-75{width:75%!important}.w-100{width:100%!important}@media (min-width: 600px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!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}.float-sm-none{float:none!important}.float-sm-left{float:left!important}.float-sm-right{float:right!important}.v-locale--is-rtl .float-sm-end{float:left!important}.v-locale--is-rtl .float-sm-start,.v-locale--is-ltr .float-sm-end{float:right!important}.v-locale--is-ltr .float-sm-start{float:left!important}.flex-sm-fill,.flex-sm-1-1{flex:1 1 auto!important}.flex-sm-1-0{flex:1 0 auto!important}.flex-sm-0-1{flex:0 1 auto!important}.flex-sm-0-0{flex:0 0 auto!important}.flex-sm-1-1-100{flex:1 1 100%!important}.flex-sm-1-0-100{flex:1 0 100%!important}.flex-sm-0-1-100{flex:0 1 100%!important}.flex-sm-0-0-100{flex:0 0 100%!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-sm-start{justify-content:flex-start!important}.justify-sm-end{justify-content:flex-end!important}.justify-sm-center{justify-content:center!important}.justify-sm-space-between{justify-content:space-between!important}.justify-sm-space-around{justify-content:space-around!important}.justify-sm-space-evenly{justify-content:space-evenly!important}.align-sm-start{align-items:flex-start!important}.align-sm-end{align-items:flex-end!important}.align-sm-center{align-items:center!important}.align-sm-baseline{align-items:baseline!important}.align-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-space-between{align-content:space-between!important}.align-content-sm-space-around{align-content:space-around!important}.align-content-sm-space-evenly{align-content:space-evenly!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-6{order:6!important}.order-sm-7{order:7!important}.order-sm-8{order:8!important}.order-sm-9{order:9!important}.order-sm-10{order:10!important}.order-sm-11{order:11!important}.order-sm-12{order:12!important}.order-sm-last{order:13!important}.ga-sm-0{gap:0px!important}.ga-sm-1{gap:4px!important}.ga-sm-2{gap:8px!important}.ga-sm-3{gap:12px!important}.ga-sm-4{gap:16px!important}.ga-sm-5{gap:20px!important}.ga-sm-6{gap:24px!important}.ga-sm-7{gap:28px!important}.ga-sm-8{gap:32px!important}.ga-sm-9{gap:36px!important}.ga-sm-10{gap:40px!important}.ga-sm-11{gap:44px!important}.ga-sm-12{gap:48px!important}.ga-sm-13{gap:52px!important}.ga-sm-14{gap:56px!important}.ga-sm-15{gap:60px!important}.ga-sm-16{gap:64px!important}.ga-sm-auto{gap:auto!important}.gr-sm-0{row-gap:0px!important}.gr-sm-1{row-gap:4px!important}.gr-sm-2{row-gap:8px!important}.gr-sm-3{row-gap:12px!important}.gr-sm-4{row-gap:16px!important}.gr-sm-5{row-gap:20px!important}.gr-sm-6{row-gap:24px!important}.gr-sm-7{row-gap:28px!important}.gr-sm-8{row-gap:32px!important}.gr-sm-9{row-gap:36px!important}.gr-sm-10{row-gap:40px!important}.gr-sm-11{row-gap:44px!important}.gr-sm-12{row-gap:48px!important}.gr-sm-13{row-gap:52px!important}.gr-sm-14{row-gap:56px!important}.gr-sm-15{row-gap:60px!important}.gr-sm-16{row-gap:64px!important}.gr-sm-auto{row-gap:auto!important}.gc-sm-0{column-gap:0px!important}.gc-sm-1{column-gap:4px!important}.gc-sm-2{column-gap:8px!important}.gc-sm-3{column-gap:12px!important}.gc-sm-4{column-gap:16px!important}.gc-sm-5{column-gap:20px!important}.gc-sm-6{column-gap:24px!important}.gc-sm-7{column-gap:28px!important}.gc-sm-8{column-gap:32px!important}.gc-sm-9{column-gap:36px!important}.gc-sm-10{column-gap:40px!important}.gc-sm-11{column-gap:44px!important}.gc-sm-12{column-gap:48px!important}.gc-sm-13{column-gap:52px!important}.gc-sm-14{column-gap:56px!important}.gc-sm-15{column-gap:60px!important}.gc-sm-16{column-gap:64px!important}.gc-sm-auto{column-gap:auto!important}.ma-sm-0{margin:0!important}.ma-sm-1{margin:4px!important}.ma-sm-2{margin:8px!important}.ma-sm-3{margin:12px!important}.ma-sm-4{margin:16px!important}.ma-sm-5{margin:20px!important}.ma-sm-6{margin:24px!important}.ma-sm-7{margin:28px!important}.ma-sm-8{margin:32px!important}.ma-sm-9{margin:36px!important}.ma-sm-10{margin:40px!important}.ma-sm-11{margin:44px!important}.ma-sm-12{margin:48px!important}.ma-sm-13{margin:52px!important}.ma-sm-14{margin:56px!important}.ma-sm-15{margin:60px!important}.ma-sm-16{margin:64px!important}.ma-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:4px!important;margin-left:4px!important}.mx-sm-2{margin-right:8px!important;margin-left:8px!important}.mx-sm-3{margin-right:12px!important;margin-left:12px!important}.mx-sm-4{margin-right:16px!important;margin-left:16px!important}.mx-sm-5{margin-right:20px!important;margin-left:20px!important}.mx-sm-6{margin-right:24px!important;margin-left:24px!important}.mx-sm-7{margin-right:28px!important;margin-left:28px!important}.mx-sm-8{margin-right:32px!important;margin-left:32px!important}.mx-sm-9{margin-right:36px!important;margin-left:36px!important}.mx-sm-10{margin-right:40px!important;margin-left:40px!important}.mx-sm-11{margin-right:44px!important;margin-left:44px!important}.mx-sm-12{margin-right:48px!important;margin-left:48px!important}.mx-sm-13{margin-right:52px!important;margin-left:52px!important}.mx-sm-14{margin-right:56px!important;margin-left:56px!important}.mx-sm-15{margin-right:60px!important;margin-left:60px!important}.mx-sm-16{margin-right:64px!important;margin-left:64px!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:4px!important;margin-bottom:4px!important}.my-sm-2{margin-top:8px!important;margin-bottom:8px!important}.my-sm-3{margin-top:12px!important;margin-bottom:12px!important}.my-sm-4{margin-top:16px!important;margin-bottom:16px!important}.my-sm-5{margin-top:20px!important;margin-bottom:20px!important}.my-sm-6{margin-top:24px!important;margin-bottom:24px!important}.my-sm-7{margin-top:28px!important;margin-bottom:28px!important}.my-sm-8{margin-top:32px!important;margin-bottom:32px!important}.my-sm-9{margin-top:36px!important;margin-bottom:36px!important}.my-sm-10{margin-top:40px!important;margin-bottom:40px!important}.my-sm-11{margin-top:44px!important;margin-bottom:44px!important}.my-sm-12{margin-top:48px!important;margin-bottom:48px!important}.my-sm-13{margin-top:52px!important;margin-bottom:52px!important}.my-sm-14{margin-top:56px!important;margin-bottom:56px!important}.my-sm-15{margin-top:60px!important;margin-bottom:60px!important}.my-sm-16{margin-top:64px!important;margin-bottom:64px!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:4px!important}.mt-sm-2{margin-top:8px!important}.mt-sm-3{margin-top:12px!important}.mt-sm-4{margin-top:16px!important}.mt-sm-5{margin-top:20px!important}.mt-sm-6{margin-top:24px!important}.mt-sm-7{margin-top:28px!important}.mt-sm-8{margin-top:32px!important}.mt-sm-9{margin-top:36px!important}.mt-sm-10{margin-top:40px!important}.mt-sm-11{margin-top:44px!important}.mt-sm-12{margin-top:48px!important}.mt-sm-13{margin-top:52px!important}.mt-sm-14{margin-top:56px!important}.mt-sm-15{margin-top:60px!important}.mt-sm-16{margin-top:64px!important}.mt-sm-auto{margin-top:auto!important}.mr-sm-0{margin-right:0!important}.mr-sm-1{margin-right:4px!important}.mr-sm-2{margin-right:8px!important}.mr-sm-3{margin-right:12px!important}.mr-sm-4{margin-right:16px!important}.mr-sm-5{margin-right:20px!important}.mr-sm-6{margin-right:24px!important}.mr-sm-7{margin-right:28px!important}.mr-sm-8{margin-right:32px!important}.mr-sm-9{margin-right:36px!important}.mr-sm-10{margin-right:40px!important}.mr-sm-11{margin-right:44px!important}.mr-sm-12{margin-right:48px!important}.mr-sm-13{margin-right:52px!important}.mr-sm-14{margin-right:56px!important}.mr-sm-15{margin-right:60px!important}.mr-sm-16{margin-right:64px!important}.mr-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:4px!important}.mb-sm-2{margin-bottom:8px!important}.mb-sm-3{margin-bottom:12px!important}.mb-sm-4{margin-bottom:16px!important}.mb-sm-5{margin-bottom:20px!important}.mb-sm-6{margin-bottom:24px!important}.mb-sm-7{margin-bottom:28px!important}.mb-sm-8{margin-bottom:32px!important}.mb-sm-9{margin-bottom:36px!important}.mb-sm-10{margin-bottom:40px!important}.mb-sm-11{margin-bottom:44px!important}.mb-sm-12{margin-bottom:48px!important}.mb-sm-13{margin-bottom:52px!important}.mb-sm-14{margin-bottom:56px!important}.mb-sm-15{margin-bottom:60px!important}.mb-sm-16{margin-bottom:64px!important}.mb-sm-auto{margin-bottom:auto!important}.ml-sm-0{margin-left:0!important}.ml-sm-1{margin-left:4px!important}.ml-sm-2{margin-left:8px!important}.ml-sm-3{margin-left:12px!important}.ml-sm-4{margin-left:16px!important}.ml-sm-5{margin-left:20px!important}.ml-sm-6{margin-left:24px!important}.ml-sm-7{margin-left:28px!important}.ml-sm-8{margin-left:32px!important}.ml-sm-9{margin-left:36px!important}.ml-sm-10{margin-left:40px!important}.ml-sm-11{margin-left:44px!important}.ml-sm-12{margin-left:48px!important}.ml-sm-13{margin-left:52px!important}.ml-sm-14{margin-left:56px!important}.ml-sm-15{margin-left:60px!important}.ml-sm-16{margin-left:64px!important}.ml-sm-auto{margin-left:auto!important}.ms-sm-0{margin-inline-start:0px!important}.ms-sm-1{margin-inline-start:4px!important}.ms-sm-2{margin-inline-start:8px!important}.ms-sm-3{margin-inline-start:12px!important}.ms-sm-4{margin-inline-start:16px!important}.ms-sm-5{margin-inline-start:20px!important}.ms-sm-6{margin-inline-start:24px!important}.ms-sm-7{margin-inline-start:28px!important}.ms-sm-8{margin-inline-start:32px!important}.ms-sm-9{margin-inline-start:36px!important}.ms-sm-10{margin-inline-start:40px!important}.ms-sm-11{margin-inline-start:44px!important}.ms-sm-12{margin-inline-start:48px!important}.ms-sm-13{margin-inline-start:52px!important}.ms-sm-14{margin-inline-start:56px!important}.ms-sm-15{margin-inline-start:60px!important}.ms-sm-16{margin-inline-start:64px!important}.ms-sm-auto{margin-inline-start:auto!important}.me-sm-0{margin-inline-end:0px!important}.me-sm-1{margin-inline-end:4px!important}.me-sm-2{margin-inline-end:8px!important}.me-sm-3{margin-inline-end:12px!important}.me-sm-4{margin-inline-end:16px!important}.me-sm-5{margin-inline-end:20px!important}.me-sm-6{margin-inline-end:24px!important}.me-sm-7{margin-inline-end:28px!important}.me-sm-8{margin-inline-end:32px!important}.me-sm-9{margin-inline-end:36px!important}.me-sm-10{margin-inline-end:40px!important}.me-sm-11{margin-inline-end:44px!important}.me-sm-12{margin-inline-end:48px!important}.me-sm-13{margin-inline-end:52px!important}.me-sm-14{margin-inline-end:56px!important}.me-sm-15{margin-inline-end:60px!important}.me-sm-16{margin-inline-end:64px!important}.me-sm-auto{margin-inline-end:auto!important}.ma-sm-n1{margin:-4px!important}.ma-sm-n2{margin:-8px!important}.ma-sm-n3{margin:-12px!important}.ma-sm-n4{margin:-16px!important}.ma-sm-n5{margin:-20px!important}.ma-sm-n6{margin:-24px!important}.ma-sm-n7{margin:-28px!important}.ma-sm-n8{margin:-32px!important}.ma-sm-n9{margin:-36px!important}.ma-sm-n10{margin:-40px!important}.ma-sm-n11{margin:-44px!important}.ma-sm-n12{margin:-48px!important}.ma-sm-n13{margin:-52px!important}.ma-sm-n14{margin:-56px!important}.ma-sm-n15{margin:-60px!important}.ma-sm-n16{margin:-64px!important}.mx-sm-n1{margin-right:-4px!important;margin-left:-4px!important}.mx-sm-n2{margin-right:-8px!important;margin-left:-8px!important}.mx-sm-n3{margin-right:-12px!important;margin-left:-12px!important}.mx-sm-n4{margin-right:-16px!important;margin-left:-16px!important}.mx-sm-n5{margin-right:-20px!important;margin-left:-20px!important}.mx-sm-n6{margin-right:-24px!important;margin-left:-24px!important}.mx-sm-n7{margin-right:-28px!important;margin-left:-28px!important}.mx-sm-n8{margin-right:-32px!important;margin-left:-32px!important}.mx-sm-n9{margin-right:-36px!important;margin-left:-36px!important}.mx-sm-n10{margin-right:-40px!important;margin-left:-40px!important}.mx-sm-n11{margin-right:-44px!important;margin-left:-44px!important}.mx-sm-n12{margin-right:-48px!important;margin-left:-48px!important}.mx-sm-n13{margin-right:-52px!important;margin-left:-52px!important}.mx-sm-n14{margin-right:-56px!important;margin-left:-56px!important}.mx-sm-n15{margin-right:-60px!important;margin-left:-60px!important}.mx-sm-n16{margin-right:-64px!important;margin-left:-64px!important}.my-sm-n1{margin-top:-4px!important;margin-bottom:-4px!important}.my-sm-n2{margin-top:-8px!important;margin-bottom:-8px!important}.my-sm-n3{margin-top:-12px!important;margin-bottom:-12px!important}.my-sm-n4{margin-top:-16px!important;margin-bottom:-16px!important}.my-sm-n5{margin-top:-20px!important;margin-bottom:-20px!important}.my-sm-n6{margin-top:-24px!important;margin-bottom:-24px!important}.my-sm-n7{margin-top:-28px!important;margin-bottom:-28px!important}.my-sm-n8{margin-top:-32px!important;margin-bottom:-32px!important}.my-sm-n9{margin-top:-36px!important;margin-bottom:-36px!important}.my-sm-n10{margin-top:-40px!important;margin-bottom:-40px!important}.my-sm-n11{margin-top:-44px!important;margin-bottom:-44px!important}.my-sm-n12{margin-top:-48px!important;margin-bottom:-48px!important}.my-sm-n13{margin-top:-52px!important;margin-bottom:-52px!important}.my-sm-n14{margin-top:-56px!important;margin-bottom:-56px!important}.my-sm-n15{margin-top:-60px!important;margin-bottom:-60px!important}.my-sm-n16{margin-top:-64px!important;margin-bottom:-64px!important}.mt-sm-n1{margin-top:-4px!important}.mt-sm-n2{margin-top:-8px!important}.mt-sm-n3{margin-top:-12px!important}.mt-sm-n4{margin-top:-16px!important}.mt-sm-n5{margin-top:-20px!important}.mt-sm-n6{margin-top:-24px!important}.mt-sm-n7{margin-top:-28px!important}.mt-sm-n8{margin-top:-32px!important}.mt-sm-n9{margin-top:-36px!important}.mt-sm-n10{margin-top:-40px!important}.mt-sm-n11{margin-top:-44px!important}.mt-sm-n12{margin-top:-48px!important}.mt-sm-n13{margin-top:-52px!important}.mt-sm-n14{margin-top:-56px!important}.mt-sm-n15{margin-top:-60px!important}.mt-sm-n16{margin-top:-64px!important}.mr-sm-n1{margin-right:-4px!important}.mr-sm-n2{margin-right:-8px!important}.mr-sm-n3{margin-right:-12px!important}.mr-sm-n4{margin-right:-16px!important}.mr-sm-n5{margin-right:-20px!important}.mr-sm-n6{margin-right:-24px!important}.mr-sm-n7{margin-right:-28px!important}.mr-sm-n8{margin-right:-32px!important}.mr-sm-n9{margin-right:-36px!important}.mr-sm-n10{margin-right:-40px!important}.mr-sm-n11{margin-right:-44px!important}.mr-sm-n12{margin-right:-48px!important}.mr-sm-n13{margin-right:-52px!important}.mr-sm-n14{margin-right:-56px!important}.mr-sm-n15{margin-right:-60px!important}.mr-sm-n16{margin-right:-64px!important}.mb-sm-n1{margin-bottom:-4px!important}.mb-sm-n2{margin-bottom:-8px!important}.mb-sm-n3{margin-bottom:-12px!important}.mb-sm-n4{margin-bottom:-16px!important}.mb-sm-n5{margin-bottom:-20px!important}.mb-sm-n6{margin-bottom:-24px!important}.mb-sm-n7{margin-bottom:-28px!important}.mb-sm-n8{margin-bottom:-32px!important}.mb-sm-n9{margin-bottom:-36px!important}.mb-sm-n10{margin-bottom:-40px!important}.mb-sm-n11{margin-bottom:-44px!important}.mb-sm-n12{margin-bottom:-48px!important}.mb-sm-n13{margin-bottom:-52px!important}.mb-sm-n14{margin-bottom:-56px!important}.mb-sm-n15{margin-bottom:-60px!important}.mb-sm-n16{margin-bottom:-64px!important}.ml-sm-n1{margin-left:-4px!important}.ml-sm-n2{margin-left:-8px!important}.ml-sm-n3{margin-left:-12px!important}.ml-sm-n4{margin-left:-16px!important}.ml-sm-n5{margin-left:-20px!important}.ml-sm-n6{margin-left:-24px!important}.ml-sm-n7{margin-left:-28px!important}.ml-sm-n8{margin-left:-32px!important}.ml-sm-n9{margin-left:-36px!important}.ml-sm-n10{margin-left:-40px!important}.ml-sm-n11{margin-left:-44px!important}.ml-sm-n12{margin-left:-48px!important}.ml-sm-n13{margin-left:-52px!important}.ml-sm-n14{margin-left:-56px!important}.ml-sm-n15{margin-left:-60px!important}.ml-sm-n16{margin-left:-64px!important}.ms-sm-n1{margin-inline-start:-4px!important}.ms-sm-n2{margin-inline-start:-8px!important}.ms-sm-n3{margin-inline-start:-12px!important}.ms-sm-n4{margin-inline-start:-16px!important}.ms-sm-n5{margin-inline-start:-20px!important}.ms-sm-n6{margin-inline-start:-24px!important}.ms-sm-n7{margin-inline-start:-28px!important}.ms-sm-n8{margin-inline-start:-32px!important}.ms-sm-n9{margin-inline-start:-36px!important}.ms-sm-n10{margin-inline-start:-40px!important}.ms-sm-n11{margin-inline-start:-44px!important}.ms-sm-n12{margin-inline-start:-48px!important}.ms-sm-n13{margin-inline-start:-52px!important}.ms-sm-n14{margin-inline-start:-56px!important}.ms-sm-n15{margin-inline-start:-60px!important}.ms-sm-n16{margin-inline-start:-64px!important}.me-sm-n1{margin-inline-end:-4px!important}.me-sm-n2{margin-inline-end:-8px!important}.me-sm-n3{margin-inline-end:-12px!important}.me-sm-n4{margin-inline-end:-16px!important}.me-sm-n5{margin-inline-end:-20px!important}.me-sm-n6{margin-inline-end:-24px!important}.me-sm-n7{margin-inline-end:-28px!important}.me-sm-n8{margin-inline-end:-32px!important}.me-sm-n9{margin-inline-end:-36px!important}.me-sm-n10{margin-inline-end:-40px!important}.me-sm-n11{margin-inline-end:-44px!important}.me-sm-n12{margin-inline-end:-48px!important}.me-sm-n13{margin-inline-end:-52px!important}.me-sm-n14{margin-inline-end:-56px!important}.me-sm-n15{margin-inline-end:-60px!important}.me-sm-n16{margin-inline-end:-64px!important}.pa-sm-0{padding:0!important}.pa-sm-1{padding:4px!important}.pa-sm-2{padding:8px!important}.pa-sm-3{padding:12px!important}.pa-sm-4{padding:16px!important}.pa-sm-5{padding:20px!important}.pa-sm-6{padding:24px!important}.pa-sm-7{padding:28px!important}.pa-sm-8{padding:32px!important}.pa-sm-9{padding:36px!important}.pa-sm-10{padding:40px!important}.pa-sm-11{padding:44px!important}.pa-sm-12{padding:48px!important}.pa-sm-13{padding:52px!important}.pa-sm-14{padding:56px!important}.pa-sm-15{padding:60px!important}.pa-sm-16{padding:64px!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:4px!important;padding-left:4px!important}.px-sm-2{padding-right:8px!important;padding-left:8px!important}.px-sm-3{padding-right:12px!important;padding-left:12px!important}.px-sm-4{padding-right:16px!important;padding-left:16px!important}.px-sm-5{padding-right:20px!important;padding-left:20px!important}.px-sm-6{padding-right:24px!important;padding-left:24px!important}.px-sm-7{padding-right:28px!important;padding-left:28px!important}.px-sm-8{padding-right:32px!important;padding-left:32px!important}.px-sm-9{padding-right:36px!important;padding-left:36px!important}.px-sm-10{padding-right:40px!important;padding-left:40px!important}.px-sm-11{padding-right:44px!important;padding-left:44px!important}.px-sm-12{padding-right:48px!important;padding-left:48px!important}.px-sm-13{padding-right:52px!important;padding-left:52px!important}.px-sm-14{padding-right:56px!important;padding-left:56px!important}.px-sm-15{padding-right:60px!important;padding-left:60px!important}.px-sm-16{padding-right:64px!important;padding-left:64px!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:4px!important;padding-bottom:4px!important}.py-sm-2{padding-top:8px!important;padding-bottom:8px!important}.py-sm-3{padding-top:12px!important;padding-bottom:12px!important}.py-sm-4{padding-top:16px!important;padding-bottom:16px!important}.py-sm-5{padding-top:20px!important;padding-bottom:20px!important}.py-sm-6{padding-top:24px!important;padding-bottom:24px!important}.py-sm-7{padding-top:28px!important;padding-bottom:28px!important}.py-sm-8{padding-top:32px!important;padding-bottom:32px!important}.py-sm-9{padding-top:36px!important;padding-bottom:36px!important}.py-sm-10{padding-top:40px!important;padding-bottom:40px!important}.py-sm-11{padding-top:44px!important;padding-bottom:44px!important}.py-sm-12{padding-top:48px!important;padding-bottom:48px!important}.py-sm-13{padding-top:52px!important;padding-bottom:52px!important}.py-sm-14{padding-top:56px!important;padding-bottom:56px!important}.py-sm-15{padding-top:60px!important;padding-bottom:60px!important}.py-sm-16{padding-top:64px!important;padding-bottom:64px!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:4px!important}.pt-sm-2{padding-top:8px!important}.pt-sm-3{padding-top:12px!important}.pt-sm-4{padding-top:16px!important}.pt-sm-5{padding-top:20px!important}.pt-sm-6{padding-top:24px!important}.pt-sm-7{padding-top:28px!important}.pt-sm-8{padding-top:32px!important}.pt-sm-9{padding-top:36px!important}.pt-sm-10{padding-top:40px!important}.pt-sm-11{padding-top:44px!important}.pt-sm-12{padding-top:48px!important}.pt-sm-13{padding-top:52px!important}.pt-sm-14{padding-top:56px!important}.pt-sm-15{padding-top:60px!important}.pt-sm-16{padding-top:64px!important}.pr-sm-0{padding-right:0!important}.pr-sm-1{padding-right:4px!important}.pr-sm-2{padding-right:8px!important}.pr-sm-3{padding-right:12px!important}.pr-sm-4{padding-right:16px!important}.pr-sm-5{padding-right:20px!important}.pr-sm-6{padding-right:24px!important}.pr-sm-7{padding-right:28px!important}.pr-sm-8{padding-right:32px!important}.pr-sm-9{padding-right:36px!important}.pr-sm-10{padding-right:40px!important}.pr-sm-11{padding-right:44px!important}.pr-sm-12{padding-right:48px!important}.pr-sm-13{padding-right:52px!important}.pr-sm-14{padding-right:56px!important}.pr-sm-15{padding-right:60px!important}.pr-sm-16{padding-right:64px!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:4px!important}.pb-sm-2{padding-bottom:8px!important}.pb-sm-3{padding-bottom:12px!important}.pb-sm-4{padding-bottom:16px!important}.pb-sm-5{padding-bottom:20px!important}.pb-sm-6{padding-bottom:24px!important}.pb-sm-7{padding-bottom:28px!important}.pb-sm-8{padding-bottom:32px!important}.pb-sm-9{padding-bottom:36px!important}.pb-sm-10{padding-bottom:40px!important}.pb-sm-11{padding-bottom:44px!important}.pb-sm-12{padding-bottom:48px!important}.pb-sm-13{padding-bottom:52px!important}.pb-sm-14{padding-bottom:56px!important}.pb-sm-15{padding-bottom:60px!important}.pb-sm-16{padding-bottom:64px!important}.pl-sm-0{padding-left:0!important}.pl-sm-1{padding-left:4px!important}.pl-sm-2{padding-left:8px!important}.pl-sm-3{padding-left:12px!important}.pl-sm-4{padding-left:16px!important}.pl-sm-5{padding-left:20px!important}.pl-sm-6{padding-left:24px!important}.pl-sm-7{padding-left:28px!important}.pl-sm-8{padding-left:32px!important}.pl-sm-9{padding-left:36px!important}.pl-sm-10{padding-left:40px!important}.pl-sm-11{padding-left:44px!important}.pl-sm-12{padding-left:48px!important}.pl-sm-13{padding-left:52px!important}.pl-sm-14{padding-left:56px!important}.pl-sm-15{padding-left:60px!important}.pl-sm-16{padding-left:64px!important}.ps-sm-0{padding-inline-start:0px!important}.ps-sm-1{padding-inline-start:4px!important}.ps-sm-2{padding-inline-start:8px!important}.ps-sm-3{padding-inline-start:12px!important}.ps-sm-4{padding-inline-start:16px!important}.ps-sm-5{padding-inline-start:20px!important}.ps-sm-6{padding-inline-start:24px!important}.ps-sm-7{padding-inline-start:28px!important}.ps-sm-8{padding-inline-start:32px!important}.ps-sm-9{padding-inline-start:36px!important}.ps-sm-10{padding-inline-start:40px!important}.ps-sm-11{padding-inline-start:44px!important}.ps-sm-12{padding-inline-start:48px!important}.ps-sm-13{padding-inline-start:52px!important}.ps-sm-14{padding-inline-start:56px!important}.ps-sm-15{padding-inline-start:60px!important}.ps-sm-16{padding-inline-start:64px!important}.pe-sm-0{padding-inline-end:0px!important}.pe-sm-1{padding-inline-end:4px!important}.pe-sm-2{padding-inline-end:8px!important}.pe-sm-3{padding-inline-end:12px!important}.pe-sm-4{padding-inline-end:16px!important}.pe-sm-5{padding-inline-end:20px!important}.pe-sm-6{padding-inline-end:24px!important}.pe-sm-7{padding-inline-end:28px!important}.pe-sm-8{padding-inline-end:32px!important}.pe-sm-9{padding-inline-end:36px!important}.pe-sm-10{padding-inline-end:40px!important}.pe-sm-11{padding-inline-end:44px!important}.pe-sm-12{padding-inline-end:48px!important}.pe-sm-13{padding-inline-end:52px!important}.pe-sm-14{padding-inline-end:56px!important}.pe-sm-15{padding-inline-end:60px!important}.pe-sm-16{padding-inline-end:64px!important}.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}.text-sm-justify{text-align:justify!important}.text-sm-start{text-align:start!important}.text-sm-end{text-align:end!important}.text-sm-h1{font-size:6rem!important;font-weight:300;line-height:6rem;letter-spacing:-.015625em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-h2{font-size:3.75rem!important;font-weight:300;line-height:3.75rem;letter-spacing:-.0083333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-h3{font-size:3rem!important;font-weight:400;line-height:3.125rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-h4{font-size:2.125rem!important;font-weight:400;line-height:2.5rem;letter-spacing:.0073529412em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-h5{font-size:1.5rem!important;font-weight:400;line-height:2rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-h6{font-size:1.25rem!important;font-weight:500;line-height:2rem;letter-spacing:.0125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-subtitle-1{font-size:1rem!important;font-weight:400;line-height:1.75rem;letter-spacing:.009375em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-subtitle-2{font-size:.875rem!important;font-weight:500;line-height:1.375rem;letter-spacing:.0071428571em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-body-1{font-size:1rem!important;font-weight:400;line-height:1.5rem;letter-spacing:.03125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-body-2{font-size:.875rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0178571429em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-button{font-size:.875rem!important;font-weight:500;line-height:2.25rem;letter-spacing:.0892857143em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}.text-sm-caption{font-size:.75rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0333333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-sm-overline{font-size:.75rem!important;font-weight:500;line-height:2rem;letter-spacing:.1666666667em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}}@media (min-width: 960px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!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}.float-md-none{float:none!important}.float-md-left{float:left!important}.float-md-right{float:right!important}.v-locale--is-rtl .float-md-end{float:left!important}.v-locale--is-rtl .float-md-start,.v-locale--is-ltr .float-md-end{float:right!important}.v-locale--is-ltr .float-md-start{float:left!important}.flex-md-fill,.flex-md-1-1{flex:1 1 auto!important}.flex-md-1-0{flex:1 0 auto!important}.flex-md-0-1{flex:0 1 auto!important}.flex-md-0-0{flex:0 0 auto!important}.flex-md-1-1-100{flex:1 1 100%!important}.flex-md-1-0-100{flex:1 0 100%!important}.flex-md-0-1-100{flex:0 1 100%!important}.flex-md-0-0-100{flex:0 0 100%!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-md-start{justify-content:flex-start!important}.justify-md-end{justify-content:flex-end!important}.justify-md-center{justify-content:center!important}.justify-md-space-between{justify-content:space-between!important}.justify-md-space-around{justify-content:space-around!important}.justify-md-space-evenly{justify-content:space-evenly!important}.align-md-start{align-items:flex-start!important}.align-md-end{align-items:flex-end!important}.align-md-center{align-items:center!important}.align-md-baseline{align-items:baseline!important}.align-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-space-between{align-content:space-between!important}.align-content-md-space-around{align-content:space-around!important}.align-content-md-space-evenly{align-content:space-evenly!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-6{order:6!important}.order-md-7{order:7!important}.order-md-8{order:8!important}.order-md-9{order:9!important}.order-md-10{order:10!important}.order-md-11{order:11!important}.order-md-12{order:12!important}.order-md-last{order:13!important}.ga-md-0{gap:0px!important}.ga-md-1{gap:4px!important}.ga-md-2{gap:8px!important}.ga-md-3{gap:12px!important}.ga-md-4{gap:16px!important}.ga-md-5{gap:20px!important}.ga-md-6{gap:24px!important}.ga-md-7{gap:28px!important}.ga-md-8{gap:32px!important}.ga-md-9{gap:36px!important}.ga-md-10{gap:40px!important}.ga-md-11{gap:44px!important}.ga-md-12{gap:48px!important}.ga-md-13{gap:52px!important}.ga-md-14{gap:56px!important}.ga-md-15{gap:60px!important}.ga-md-16{gap:64px!important}.ga-md-auto{gap:auto!important}.gr-md-0{row-gap:0px!important}.gr-md-1{row-gap:4px!important}.gr-md-2{row-gap:8px!important}.gr-md-3{row-gap:12px!important}.gr-md-4{row-gap:16px!important}.gr-md-5{row-gap:20px!important}.gr-md-6{row-gap:24px!important}.gr-md-7{row-gap:28px!important}.gr-md-8{row-gap:32px!important}.gr-md-9{row-gap:36px!important}.gr-md-10{row-gap:40px!important}.gr-md-11{row-gap:44px!important}.gr-md-12{row-gap:48px!important}.gr-md-13{row-gap:52px!important}.gr-md-14{row-gap:56px!important}.gr-md-15{row-gap:60px!important}.gr-md-16{row-gap:64px!important}.gr-md-auto{row-gap:auto!important}.gc-md-0{column-gap:0px!important}.gc-md-1{column-gap:4px!important}.gc-md-2{column-gap:8px!important}.gc-md-3{column-gap:12px!important}.gc-md-4{column-gap:16px!important}.gc-md-5{column-gap:20px!important}.gc-md-6{column-gap:24px!important}.gc-md-7{column-gap:28px!important}.gc-md-8{column-gap:32px!important}.gc-md-9{column-gap:36px!important}.gc-md-10{column-gap:40px!important}.gc-md-11{column-gap:44px!important}.gc-md-12{column-gap:48px!important}.gc-md-13{column-gap:52px!important}.gc-md-14{column-gap:56px!important}.gc-md-15{column-gap:60px!important}.gc-md-16{column-gap:64px!important}.gc-md-auto{column-gap:auto!important}.ma-md-0{margin:0!important}.ma-md-1{margin:4px!important}.ma-md-2{margin:8px!important}.ma-md-3{margin:12px!important}.ma-md-4{margin:16px!important}.ma-md-5{margin:20px!important}.ma-md-6{margin:24px!important}.ma-md-7{margin:28px!important}.ma-md-8{margin:32px!important}.ma-md-9{margin:36px!important}.ma-md-10{margin:40px!important}.ma-md-11{margin:44px!important}.ma-md-12{margin:48px!important}.ma-md-13{margin:52px!important}.ma-md-14{margin:56px!important}.ma-md-15{margin:60px!important}.ma-md-16{margin:64px!important}.ma-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:4px!important;margin-left:4px!important}.mx-md-2{margin-right:8px!important;margin-left:8px!important}.mx-md-3{margin-right:12px!important;margin-left:12px!important}.mx-md-4{margin-right:16px!important;margin-left:16px!important}.mx-md-5{margin-right:20px!important;margin-left:20px!important}.mx-md-6{margin-right:24px!important;margin-left:24px!important}.mx-md-7{margin-right:28px!important;margin-left:28px!important}.mx-md-8{margin-right:32px!important;margin-left:32px!important}.mx-md-9{margin-right:36px!important;margin-left:36px!important}.mx-md-10{margin-right:40px!important;margin-left:40px!important}.mx-md-11{margin-right:44px!important;margin-left:44px!important}.mx-md-12{margin-right:48px!important;margin-left:48px!important}.mx-md-13{margin-right:52px!important;margin-left:52px!important}.mx-md-14{margin-right:56px!important;margin-left:56px!important}.mx-md-15{margin-right:60px!important;margin-left:60px!important}.mx-md-16{margin-right:64px!important;margin-left:64px!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:4px!important;margin-bottom:4px!important}.my-md-2{margin-top:8px!important;margin-bottom:8px!important}.my-md-3{margin-top:12px!important;margin-bottom:12px!important}.my-md-4{margin-top:16px!important;margin-bottom:16px!important}.my-md-5{margin-top:20px!important;margin-bottom:20px!important}.my-md-6{margin-top:24px!important;margin-bottom:24px!important}.my-md-7{margin-top:28px!important;margin-bottom:28px!important}.my-md-8{margin-top:32px!important;margin-bottom:32px!important}.my-md-9{margin-top:36px!important;margin-bottom:36px!important}.my-md-10{margin-top:40px!important;margin-bottom:40px!important}.my-md-11{margin-top:44px!important;margin-bottom:44px!important}.my-md-12{margin-top:48px!important;margin-bottom:48px!important}.my-md-13{margin-top:52px!important;margin-bottom:52px!important}.my-md-14{margin-top:56px!important;margin-bottom:56px!important}.my-md-15{margin-top:60px!important;margin-bottom:60px!important}.my-md-16{margin-top:64px!important;margin-bottom:64px!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:4px!important}.mt-md-2{margin-top:8px!important}.mt-md-3{margin-top:12px!important}.mt-md-4{margin-top:16px!important}.mt-md-5{margin-top:20px!important}.mt-md-6{margin-top:24px!important}.mt-md-7{margin-top:28px!important}.mt-md-8{margin-top:32px!important}.mt-md-9{margin-top:36px!important}.mt-md-10{margin-top:40px!important}.mt-md-11{margin-top:44px!important}.mt-md-12{margin-top:48px!important}.mt-md-13{margin-top:52px!important}.mt-md-14{margin-top:56px!important}.mt-md-15{margin-top:60px!important}.mt-md-16{margin-top:64px!important}.mt-md-auto{margin-top:auto!important}.mr-md-0{margin-right:0!important}.mr-md-1{margin-right:4px!important}.mr-md-2{margin-right:8px!important}.mr-md-3{margin-right:12px!important}.mr-md-4{margin-right:16px!important}.mr-md-5{margin-right:20px!important}.mr-md-6{margin-right:24px!important}.mr-md-7{margin-right:28px!important}.mr-md-8{margin-right:32px!important}.mr-md-9{margin-right:36px!important}.mr-md-10{margin-right:40px!important}.mr-md-11{margin-right:44px!important}.mr-md-12{margin-right:48px!important}.mr-md-13{margin-right:52px!important}.mr-md-14{margin-right:56px!important}.mr-md-15{margin-right:60px!important}.mr-md-16{margin-right:64px!important}.mr-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:4px!important}.mb-md-2{margin-bottom:8px!important}.mb-md-3{margin-bottom:12px!important}.mb-md-4{margin-bottom:16px!important}.mb-md-5{margin-bottom:20px!important}.mb-md-6{margin-bottom:24px!important}.mb-md-7{margin-bottom:28px!important}.mb-md-8{margin-bottom:32px!important}.mb-md-9{margin-bottom:36px!important}.mb-md-10{margin-bottom:40px!important}.mb-md-11{margin-bottom:44px!important}.mb-md-12{margin-bottom:48px!important}.mb-md-13{margin-bottom:52px!important}.mb-md-14{margin-bottom:56px!important}.mb-md-15{margin-bottom:60px!important}.mb-md-16{margin-bottom:64px!important}.mb-md-auto{margin-bottom:auto!important}.ml-md-0{margin-left:0!important}.ml-md-1{margin-left:4px!important}.ml-md-2{margin-left:8px!important}.ml-md-3{margin-left:12px!important}.ml-md-4{margin-left:16px!important}.ml-md-5{margin-left:20px!important}.ml-md-6{margin-left:24px!important}.ml-md-7{margin-left:28px!important}.ml-md-8{margin-left:32px!important}.ml-md-9{margin-left:36px!important}.ml-md-10{margin-left:40px!important}.ml-md-11{margin-left:44px!important}.ml-md-12{margin-left:48px!important}.ml-md-13{margin-left:52px!important}.ml-md-14{margin-left:56px!important}.ml-md-15{margin-left:60px!important}.ml-md-16{margin-left:64px!important}.ml-md-auto{margin-left:auto!important}.ms-md-0{margin-inline-start:0px!important}.ms-md-1{margin-inline-start:4px!important}.ms-md-2{margin-inline-start:8px!important}.ms-md-3{margin-inline-start:12px!important}.ms-md-4{margin-inline-start:16px!important}.ms-md-5{margin-inline-start:20px!important}.ms-md-6{margin-inline-start:24px!important}.ms-md-7{margin-inline-start:28px!important}.ms-md-8{margin-inline-start:32px!important}.ms-md-9{margin-inline-start:36px!important}.ms-md-10{margin-inline-start:40px!important}.ms-md-11{margin-inline-start:44px!important}.ms-md-12{margin-inline-start:48px!important}.ms-md-13{margin-inline-start:52px!important}.ms-md-14{margin-inline-start:56px!important}.ms-md-15{margin-inline-start:60px!important}.ms-md-16{margin-inline-start:64px!important}.ms-md-auto{margin-inline-start:auto!important}.me-md-0{margin-inline-end:0px!important}.me-md-1{margin-inline-end:4px!important}.me-md-2{margin-inline-end:8px!important}.me-md-3{margin-inline-end:12px!important}.me-md-4{margin-inline-end:16px!important}.me-md-5{margin-inline-end:20px!important}.me-md-6{margin-inline-end:24px!important}.me-md-7{margin-inline-end:28px!important}.me-md-8{margin-inline-end:32px!important}.me-md-9{margin-inline-end:36px!important}.me-md-10{margin-inline-end:40px!important}.me-md-11{margin-inline-end:44px!important}.me-md-12{margin-inline-end:48px!important}.me-md-13{margin-inline-end:52px!important}.me-md-14{margin-inline-end:56px!important}.me-md-15{margin-inline-end:60px!important}.me-md-16{margin-inline-end:64px!important}.me-md-auto{margin-inline-end:auto!important}.ma-md-n1{margin:-4px!important}.ma-md-n2{margin:-8px!important}.ma-md-n3{margin:-12px!important}.ma-md-n4{margin:-16px!important}.ma-md-n5{margin:-20px!important}.ma-md-n6{margin:-24px!important}.ma-md-n7{margin:-28px!important}.ma-md-n8{margin:-32px!important}.ma-md-n9{margin:-36px!important}.ma-md-n10{margin:-40px!important}.ma-md-n11{margin:-44px!important}.ma-md-n12{margin:-48px!important}.ma-md-n13{margin:-52px!important}.ma-md-n14{margin:-56px!important}.ma-md-n15{margin:-60px!important}.ma-md-n16{margin:-64px!important}.mx-md-n1{margin-right:-4px!important;margin-left:-4px!important}.mx-md-n2{margin-right:-8px!important;margin-left:-8px!important}.mx-md-n3{margin-right:-12px!important;margin-left:-12px!important}.mx-md-n4{margin-right:-16px!important;margin-left:-16px!important}.mx-md-n5{margin-right:-20px!important;margin-left:-20px!important}.mx-md-n6{margin-right:-24px!important;margin-left:-24px!important}.mx-md-n7{margin-right:-28px!important;margin-left:-28px!important}.mx-md-n8{margin-right:-32px!important;margin-left:-32px!important}.mx-md-n9{margin-right:-36px!important;margin-left:-36px!important}.mx-md-n10{margin-right:-40px!important;margin-left:-40px!important}.mx-md-n11{margin-right:-44px!important;margin-left:-44px!important}.mx-md-n12{margin-right:-48px!important;margin-left:-48px!important}.mx-md-n13{margin-right:-52px!important;margin-left:-52px!important}.mx-md-n14{margin-right:-56px!important;margin-left:-56px!important}.mx-md-n15{margin-right:-60px!important;margin-left:-60px!important}.mx-md-n16{margin-right:-64px!important;margin-left:-64px!important}.my-md-n1{margin-top:-4px!important;margin-bottom:-4px!important}.my-md-n2{margin-top:-8px!important;margin-bottom:-8px!important}.my-md-n3{margin-top:-12px!important;margin-bottom:-12px!important}.my-md-n4{margin-top:-16px!important;margin-bottom:-16px!important}.my-md-n5{margin-top:-20px!important;margin-bottom:-20px!important}.my-md-n6{margin-top:-24px!important;margin-bottom:-24px!important}.my-md-n7{margin-top:-28px!important;margin-bottom:-28px!important}.my-md-n8{margin-top:-32px!important;margin-bottom:-32px!important}.my-md-n9{margin-top:-36px!important;margin-bottom:-36px!important}.my-md-n10{margin-top:-40px!important;margin-bottom:-40px!important}.my-md-n11{margin-top:-44px!important;margin-bottom:-44px!important}.my-md-n12{margin-top:-48px!important;margin-bottom:-48px!important}.my-md-n13{margin-top:-52px!important;margin-bottom:-52px!important}.my-md-n14{margin-top:-56px!important;margin-bottom:-56px!important}.my-md-n15{margin-top:-60px!important;margin-bottom:-60px!important}.my-md-n16{margin-top:-64px!important;margin-bottom:-64px!important}.mt-md-n1{margin-top:-4px!important}.mt-md-n2{margin-top:-8px!important}.mt-md-n3{margin-top:-12px!important}.mt-md-n4{margin-top:-16px!important}.mt-md-n5{margin-top:-20px!important}.mt-md-n6{margin-top:-24px!important}.mt-md-n7{margin-top:-28px!important}.mt-md-n8{margin-top:-32px!important}.mt-md-n9{margin-top:-36px!important}.mt-md-n10{margin-top:-40px!important}.mt-md-n11{margin-top:-44px!important}.mt-md-n12{margin-top:-48px!important}.mt-md-n13{margin-top:-52px!important}.mt-md-n14{margin-top:-56px!important}.mt-md-n15{margin-top:-60px!important}.mt-md-n16{margin-top:-64px!important}.mr-md-n1{margin-right:-4px!important}.mr-md-n2{margin-right:-8px!important}.mr-md-n3{margin-right:-12px!important}.mr-md-n4{margin-right:-16px!important}.mr-md-n5{margin-right:-20px!important}.mr-md-n6{margin-right:-24px!important}.mr-md-n7{margin-right:-28px!important}.mr-md-n8{margin-right:-32px!important}.mr-md-n9{margin-right:-36px!important}.mr-md-n10{margin-right:-40px!important}.mr-md-n11{margin-right:-44px!important}.mr-md-n12{margin-right:-48px!important}.mr-md-n13{margin-right:-52px!important}.mr-md-n14{margin-right:-56px!important}.mr-md-n15{margin-right:-60px!important}.mr-md-n16{margin-right:-64px!important}.mb-md-n1{margin-bottom:-4px!important}.mb-md-n2{margin-bottom:-8px!important}.mb-md-n3{margin-bottom:-12px!important}.mb-md-n4{margin-bottom:-16px!important}.mb-md-n5{margin-bottom:-20px!important}.mb-md-n6{margin-bottom:-24px!important}.mb-md-n7{margin-bottom:-28px!important}.mb-md-n8{margin-bottom:-32px!important}.mb-md-n9{margin-bottom:-36px!important}.mb-md-n10{margin-bottom:-40px!important}.mb-md-n11{margin-bottom:-44px!important}.mb-md-n12{margin-bottom:-48px!important}.mb-md-n13{margin-bottom:-52px!important}.mb-md-n14{margin-bottom:-56px!important}.mb-md-n15{margin-bottom:-60px!important}.mb-md-n16{margin-bottom:-64px!important}.ml-md-n1{margin-left:-4px!important}.ml-md-n2{margin-left:-8px!important}.ml-md-n3{margin-left:-12px!important}.ml-md-n4{margin-left:-16px!important}.ml-md-n5{margin-left:-20px!important}.ml-md-n6{margin-left:-24px!important}.ml-md-n7{margin-left:-28px!important}.ml-md-n8{margin-left:-32px!important}.ml-md-n9{margin-left:-36px!important}.ml-md-n10{margin-left:-40px!important}.ml-md-n11{margin-left:-44px!important}.ml-md-n12{margin-left:-48px!important}.ml-md-n13{margin-left:-52px!important}.ml-md-n14{margin-left:-56px!important}.ml-md-n15{margin-left:-60px!important}.ml-md-n16{margin-left:-64px!important}.ms-md-n1{margin-inline-start:-4px!important}.ms-md-n2{margin-inline-start:-8px!important}.ms-md-n3{margin-inline-start:-12px!important}.ms-md-n4{margin-inline-start:-16px!important}.ms-md-n5{margin-inline-start:-20px!important}.ms-md-n6{margin-inline-start:-24px!important}.ms-md-n7{margin-inline-start:-28px!important}.ms-md-n8{margin-inline-start:-32px!important}.ms-md-n9{margin-inline-start:-36px!important}.ms-md-n10{margin-inline-start:-40px!important}.ms-md-n11{margin-inline-start:-44px!important}.ms-md-n12{margin-inline-start:-48px!important}.ms-md-n13{margin-inline-start:-52px!important}.ms-md-n14{margin-inline-start:-56px!important}.ms-md-n15{margin-inline-start:-60px!important}.ms-md-n16{margin-inline-start:-64px!important}.me-md-n1{margin-inline-end:-4px!important}.me-md-n2{margin-inline-end:-8px!important}.me-md-n3{margin-inline-end:-12px!important}.me-md-n4{margin-inline-end:-16px!important}.me-md-n5{margin-inline-end:-20px!important}.me-md-n6{margin-inline-end:-24px!important}.me-md-n7{margin-inline-end:-28px!important}.me-md-n8{margin-inline-end:-32px!important}.me-md-n9{margin-inline-end:-36px!important}.me-md-n10{margin-inline-end:-40px!important}.me-md-n11{margin-inline-end:-44px!important}.me-md-n12{margin-inline-end:-48px!important}.me-md-n13{margin-inline-end:-52px!important}.me-md-n14{margin-inline-end:-56px!important}.me-md-n15{margin-inline-end:-60px!important}.me-md-n16{margin-inline-end:-64px!important}.pa-md-0{padding:0!important}.pa-md-1{padding:4px!important}.pa-md-2{padding:8px!important}.pa-md-3{padding:12px!important}.pa-md-4{padding:16px!important}.pa-md-5{padding:20px!important}.pa-md-6{padding:24px!important}.pa-md-7{padding:28px!important}.pa-md-8{padding:32px!important}.pa-md-9{padding:36px!important}.pa-md-10{padding:40px!important}.pa-md-11{padding:44px!important}.pa-md-12{padding:48px!important}.pa-md-13{padding:52px!important}.pa-md-14{padding:56px!important}.pa-md-15{padding:60px!important}.pa-md-16{padding:64px!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:4px!important;padding-left:4px!important}.px-md-2{padding-right:8px!important;padding-left:8px!important}.px-md-3{padding-right:12px!important;padding-left:12px!important}.px-md-4{padding-right:16px!important;padding-left:16px!important}.px-md-5{padding-right:20px!important;padding-left:20px!important}.px-md-6{padding-right:24px!important;padding-left:24px!important}.px-md-7{padding-right:28px!important;padding-left:28px!important}.px-md-8{padding-right:32px!important;padding-left:32px!important}.px-md-9{padding-right:36px!important;padding-left:36px!important}.px-md-10{padding-right:40px!important;padding-left:40px!important}.px-md-11{padding-right:44px!important;padding-left:44px!important}.px-md-12{padding-right:48px!important;padding-left:48px!important}.px-md-13{padding-right:52px!important;padding-left:52px!important}.px-md-14{padding-right:56px!important;padding-left:56px!important}.px-md-15{padding-right:60px!important;padding-left:60px!important}.px-md-16{padding-right:64px!important;padding-left:64px!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:4px!important;padding-bottom:4px!important}.py-md-2{padding-top:8px!important;padding-bottom:8px!important}.py-md-3{padding-top:12px!important;padding-bottom:12px!important}.py-md-4{padding-top:16px!important;padding-bottom:16px!important}.py-md-5{padding-top:20px!important;padding-bottom:20px!important}.py-md-6{padding-top:24px!important;padding-bottom:24px!important}.py-md-7{padding-top:28px!important;padding-bottom:28px!important}.py-md-8{padding-top:32px!important;padding-bottom:32px!important}.py-md-9{padding-top:36px!important;padding-bottom:36px!important}.py-md-10{padding-top:40px!important;padding-bottom:40px!important}.py-md-11{padding-top:44px!important;padding-bottom:44px!important}.py-md-12{padding-top:48px!important;padding-bottom:48px!important}.py-md-13{padding-top:52px!important;padding-bottom:52px!important}.py-md-14{padding-top:56px!important;padding-bottom:56px!important}.py-md-15{padding-top:60px!important;padding-bottom:60px!important}.py-md-16{padding-top:64px!important;padding-bottom:64px!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:4px!important}.pt-md-2{padding-top:8px!important}.pt-md-3{padding-top:12px!important}.pt-md-4{padding-top:16px!important}.pt-md-5{padding-top:20px!important}.pt-md-6{padding-top:24px!important}.pt-md-7{padding-top:28px!important}.pt-md-8{padding-top:32px!important}.pt-md-9{padding-top:36px!important}.pt-md-10{padding-top:40px!important}.pt-md-11{padding-top:44px!important}.pt-md-12{padding-top:48px!important}.pt-md-13{padding-top:52px!important}.pt-md-14{padding-top:56px!important}.pt-md-15{padding-top:60px!important}.pt-md-16{padding-top:64px!important}.pr-md-0{padding-right:0!important}.pr-md-1{padding-right:4px!important}.pr-md-2{padding-right:8px!important}.pr-md-3{padding-right:12px!important}.pr-md-4{padding-right:16px!important}.pr-md-5{padding-right:20px!important}.pr-md-6{padding-right:24px!important}.pr-md-7{padding-right:28px!important}.pr-md-8{padding-right:32px!important}.pr-md-9{padding-right:36px!important}.pr-md-10{padding-right:40px!important}.pr-md-11{padding-right:44px!important}.pr-md-12{padding-right:48px!important}.pr-md-13{padding-right:52px!important}.pr-md-14{padding-right:56px!important}.pr-md-15{padding-right:60px!important}.pr-md-16{padding-right:64px!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:4px!important}.pb-md-2{padding-bottom:8px!important}.pb-md-3{padding-bottom:12px!important}.pb-md-4{padding-bottom:16px!important}.pb-md-5{padding-bottom:20px!important}.pb-md-6{padding-bottom:24px!important}.pb-md-7{padding-bottom:28px!important}.pb-md-8{padding-bottom:32px!important}.pb-md-9{padding-bottom:36px!important}.pb-md-10{padding-bottom:40px!important}.pb-md-11{padding-bottom:44px!important}.pb-md-12{padding-bottom:48px!important}.pb-md-13{padding-bottom:52px!important}.pb-md-14{padding-bottom:56px!important}.pb-md-15{padding-bottom:60px!important}.pb-md-16{padding-bottom:64px!important}.pl-md-0{padding-left:0!important}.pl-md-1{padding-left:4px!important}.pl-md-2{padding-left:8px!important}.pl-md-3{padding-left:12px!important}.pl-md-4{padding-left:16px!important}.pl-md-5{padding-left:20px!important}.pl-md-6{padding-left:24px!important}.pl-md-7{padding-left:28px!important}.pl-md-8{padding-left:32px!important}.pl-md-9{padding-left:36px!important}.pl-md-10{padding-left:40px!important}.pl-md-11{padding-left:44px!important}.pl-md-12{padding-left:48px!important}.pl-md-13{padding-left:52px!important}.pl-md-14{padding-left:56px!important}.pl-md-15{padding-left:60px!important}.pl-md-16{padding-left:64px!important}.ps-md-0{padding-inline-start:0px!important}.ps-md-1{padding-inline-start:4px!important}.ps-md-2{padding-inline-start:8px!important}.ps-md-3{padding-inline-start:12px!important}.ps-md-4{padding-inline-start:16px!important}.ps-md-5{padding-inline-start:20px!important}.ps-md-6{padding-inline-start:24px!important}.ps-md-7{padding-inline-start:28px!important}.ps-md-8{padding-inline-start:32px!important}.ps-md-9{padding-inline-start:36px!important}.ps-md-10{padding-inline-start:40px!important}.ps-md-11{padding-inline-start:44px!important}.ps-md-12{padding-inline-start:48px!important}.ps-md-13{padding-inline-start:52px!important}.ps-md-14{padding-inline-start:56px!important}.ps-md-15{padding-inline-start:60px!important}.ps-md-16{padding-inline-start:64px!important}.pe-md-0{padding-inline-end:0px!important}.pe-md-1{padding-inline-end:4px!important}.pe-md-2{padding-inline-end:8px!important}.pe-md-3{padding-inline-end:12px!important}.pe-md-4{padding-inline-end:16px!important}.pe-md-5{padding-inline-end:20px!important}.pe-md-6{padding-inline-end:24px!important}.pe-md-7{padding-inline-end:28px!important}.pe-md-8{padding-inline-end:32px!important}.pe-md-9{padding-inline-end:36px!important}.pe-md-10{padding-inline-end:40px!important}.pe-md-11{padding-inline-end:44px!important}.pe-md-12{padding-inline-end:48px!important}.pe-md-13{padding-inline-end:52px!important}.pe-md-14{padding-inline-end:56px!important}.pe-md-15{padding-inline-end:60px!important}.pe-md-16{padding-inline-end:64px!important}.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}.text-md-justify{text-align:justify!important}.text-md-start{text-align:start!important}.text-md-end{text-align:end!important}.text-md-h1{font-size:6rem!important;font-weight:300;line-height:6rem;letter-spacing:-.015625em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-h2{font-size:3.75rem!important;font-weight:300;line-height:3.75rem;letter-spacing:-.0083333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-h3{font-size:3rem!important;font-weight:400;line-height:3.125rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-h4{font-size:2.125rem!important;font-weight:400;line-height:2.5rem;letter-spacing:.0073529412em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-h5{font-size:1.5rem!important;font-weight:400;line-height:2rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-h6{font-size:1.25rem!important;font-weight:500;line-height:2rem;letter-spacing:.0125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-subtitle-1{font-size:1rem!important;font-weight:400;line-height:1.75rem;letter-spacing:.009375em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-subtitle-2{font-size:.875rem!important;font-weight:500;line-height:1.375rem;letter-spacing:.0071428571em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-body-1{font-size:1rem!important;font-weight:400;line-height:1.5rem;letter-spacing:.03125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-body-2{font-size:.875rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0178571429em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-button{font-size:.875rem!important;font-weight:500;line-height:2.25rem;letter-spacing:.0892857143em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}.text-md-caption{font-size:.75rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0333333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-md-overline{font-size:.75rem!important;font-weight:500;line-height:2rem;letter-spacing:.1666666667em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}}@media (min-width: 1280px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!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}.float-lg-none{float:none!important}.float-lg-left{float:left!important}.float-lg-right{float:right!important}.v-locale--is-rtl .float-lg-end{float:left!important}.v-locale--is-rtl .float-lg-start,.v-locale--is-ltr .float-lg-end{float:right!important}.v-locale--is-ltr .float-lg-start{float:left!important}.flex-lg-fill,.flex-lg-1-1{flex:1 1 auto!important}.flex-lg-1-0{flex:1 0 auto!important}.flex-lg-0-1{flex:0 1 auto!important}.flex-lg-0-0{flex:0 0 auto!important}.flex-lg-1-1-100{flex:1 1 100%!important}.flex-lg-1-0-100{flex:1 0 100%!important}.flex-lg-0-1-100{flex:0 1 100%!important}.flex-lg-0-0-100{flex:0 0 100%!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-lg-start{justify-content:flex-start!important}.justify-lg-end{justify-content:flex-end!important}.justify-lg-center{justify-content:center!important}.justify-lg-space-between{justify-content:space-between!important}.justify-lg-space-around{justify-content:space-around!important}.justify-lg-space-evenly{justify-content:space-evenly!important}.align-lg-start{align-items:flex-start!important}.align-lg-end{align-items:flex-end!important}.align-lg-center{align-items:center!important}.align-lg-baseline{align-items:baseline!important}.align-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-space-between{align-content:space-between!important}.align-content-lg-space-around{align-content:space-around!important}.align-content-lg-space-evenly{align-content:space-evenly!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-6{order:6!important}.order-lg-7{order:7!important}.order-lg-8{order:8!important}.order-lg-9{order:9!important}.order-lg-10{order:10!important}.order-lg-11{order:11!important}.order-lg-12{order:12!important}.order-lg-last{order:13!important}.ga-lg-0{gap:0px!important}.ga-lg-1{gap:4px!important}.ga-lg-2{gap:8px!important}.ga-lg-3{gap:12px!important}.ga-lg-4{gap:16px!important}.ga-lg-5{gap:20px!important}.ga-lg-6{gap:24px!important}.ga-lg-7{gap:28px!important}.ga-lg-8{gap:32px!important}.ga-lg-9{gap:36px!important}.ga-lg-10{gap:40px!important}.ga-lg-11{gap:44px!important}.ga-lg-12{gap:48px!important}.ga-lg-13{gap:52px!important}.ga-lg-14{gap:56px!important}.ga-lg-15{gap:60px!important}.ga-lg-16{gap:64px!important}.ga-lg-auto{gap:auto!important}.gr-lg-0{row-gap:0px!important}.gr-lg-1{row-gap:4px!important}.gr-lg-2{row-gap:8px!important}.gr-lg-3{row-gap:12px!important}.gr-lg-4{row-gap:16px!important}.gr-lg-5{row-gap:20px!important}.gr-lg-6{row-gap:24px!important}.gr-lg-7{row-gap:28px!important}.gr-lg-8{row-gap:32px!important}.gr-lg-9{row-gap:36px!important}.gr-lg-10{row-gap:40px!important}.gr-lg-11{row-gap:44px!important}.gr-lg-12{row-gap:48px!important}.gr-lg-13{row-gap:52px!important}.gr-lg-14{row-gap:56px!important}.gr-lg-15{row-gap:60px!important}.gr-lg-16{row-gap:64px!important}.gr-lg-auto{row-gap:auto!important}.gc-lg-0{column-gap:0px!important}.gc-lg-1{column-gap:4px!important}.gc-lg-2{column-gap:8px!important}.gc-lg-3{column-gap:12px!important}.gc-lg-4{column-gap:16px!important}.gc-lg-5{column-gap:20px!important}.gc-lg-6{column-gap:24px!important}.gc-lg-7{column-gap:28px!important}.gc-lg-8{column-gap:32px!important}.gc-lg-9{column-gap:36px!important}.gc-lg-10{column-gap:40px!important}.gc-lg-11{column-gap:44px!important}.gc-lg-12{column-gap:48px!important}.gc-lg-13{column-gap:52px!important}.gc-lg-14{column-gap:56px!important}.gc-lg-15{column-gap:60px!important}.gc-lg-16{column-gap:64px!important}.gc-lg-auto{column-gap:auto!important}.ma-lg-0{margin:0!important}.ma-lg-1{margin:4px!important}.ma-lg-2{margin:8px!important}.ma-lg-3{margin:12px!important}.ma-lg-4{margin:16px!important}.ma-lg-5{margin:20px!important}.ma-lg-6{margin:24px!important}.ma-lg-7{margin:28px!important}.ma-lg-8{margin:32px!important}.ma-lg-9{margin:36px!important}.ma-lg-10{margin:40px!important}.ma-lg-11{margin:44px!important}.ma-lg-12{margin:48px!important}.ma-lg-13{margin:52px!important}.ma-lg-14{margin:56px!important}.ma-lg-15{margin:60px!important}.ma-lg-16{margin:64px!important}.ma-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:4px!important;margin-left:4px!important}.mx-lg-2{margin-right:8px!important;margin-left:8px!important}.mx-lg-3{margin-right:12px!important;margin-left:12px!important}.mx-lg-4{margin-right:16px!important;margin-left:16px!important}.mx-lg-5{margin-right:20px!important;margin-left:20px!important}.mx-lg-6{margin-right:24px!important;margin-left:24px!important}.mx-lg-7{margin-right:28px!important;margin-left:28px!important}.mx-lg-8{margin-right:32px!important;margin-left:32px!important}.mx-lg-9{margin-right:36px!important;margin-left:36px!important}.mx-lg-10{margin-right:40px!important;margin-left:40px!important}.mx-lg-11{margin-right:44px!important;margin-left:44px!important}.mx-lg-12{margin-right:48px!important;margin-left:48px!important}.mx-lg-13{margin-right:52px!important;margin-left:52px!important}.mx-lg-14{margin-right:56px!important;margin-left:56px!important}.mx-lg-15{margin-right:60px!important;margin-left:60px!important}.mx-lg-16{margin-right:64px!important;margin-left:64px!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:4px!important;margin-bottom:4px!important}.my-lg-2{margin-top:8px!important;margin-bottom:8px!important}.my-lg-3{margin-top:12px!important;margin-bottom:12px!important}.my-lg-4{margin-top:16px!important;margin-bottom:16px!important}.my-lg-5{margin-top:20px!important;margin-bottom:20px!important}.my-lg-6{margin-top:24px!important;margin-bottom:24px!important}.my-lg-7{margin-top:28px!important;margin-bottom:28px!important}.my-lg-8{margin-top:32px!important;margin-bottom:32px!important}.my-lg-9{margin-top:36px!important;margin-bottom:36px!important}.my-lg-10{margin-top:40px!important;margin-bottom:40px!important}.my-lg-11{margin-top:44px!important;margin-bottom:44px!important}.my-lg-12{margin-top:48px!important;margin-bottom:48px!important}.my-lg-13{margin-top:52px!important;margin-bottom:52px!important}.my-lg-14{margin-top:56px!important;margin-bottom:56px!important}.my-lg-15{margin-top:60px!important;margin-bottom:60px!important}.my-lg-16{margin-top:64px!important;margin-bottom:64px!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:4px!important}.mt-lg-2{margin-top:8px!important}.mt-lg-3{margin-top:12px!important}.mt-lg-4{margin-top:16px!important}.mt-lg-5{margin-top:20px!important}.mt-lg-6{margin-top:24px!important}.mt-lg-7{margin-top:28px!important}.mt-lg-8{margin-top:32px!important}.mt-lg-9{margin-top:36px!important}.mt-lg-10{margin-top:40px!important}.mt-lg-11{margin-top:44px!important}.mt-lg-12{margin-top:48px!important}.mt-lg-13{margin-top:52px!important}.mt-lg-14{margin-top:56px!important}.mt-lg-15{margin-top:60px!important}.mt-lg-16{margin-top:64px!important}.mt-lg-auto{margin-top:auto!important}.mr-lg-0{margin-right:0!important}.mr-lg-1{margin-right:4px!important}.mr-lg-2{margin-right:8px!important}.mr-lg-3{margin-right:12px!important}.mr-lg-4{margin-right:16px!important}.mr-lg-5{margin-right:20px!important}.mr-lg-6{margin-right:24px!important}.mr-lg-7{margin-right:28px!important}.mr-lg-8{margin-right:32px!important}.mr-lg-9{margin-right:36px!important}.mr-lg-10{margin-right:40px!important}.mr-lg-11{margin-right:44px!important}.mr-lg-12{margin-right:48px!important}.mr-lg-13{margin-right:52px!important}.mr-lg-14{margin-right:56px!important}.mr-lg-15{margin-right:60px!important}.mr-lg-16{margin-right:64px!important}.mr-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:4px!important}.mb-lg-2{margin-bottom:8px!important}.mb-lg-3{margin-bottom:12px!important}.mb-lg-4{margin-bottom:16px!important}.mb-lg-5{margin-bottom:20px!important}.mb-lg-6{margin-bottom:24px!important}.mb-lg-7{margin-bottom:28px!important}.mb-lg-8{margin-bottom:32px!important}.mb-lg-9{margin-bottom:36px!important}.mb-lg-10{margin-bottom:40px!important}.mb-lg-11{margin-bottom:44px!important}.mb-lg-12{margin-bottom:48px!important}.mb-lg-13{margin-bottom:52px!important}.mb-lg-14{margin-bottom:56px!important}.mb-lg-15{margin-bottom:60px!important}.mb-lg-16{margin-bottom:64px!important}.mb-lg-auto{margin-bottom:auto!important}.ml-lg-0{margin-left:0!important}.ml-lg-1{margin-left:4px!important}.ml-lg-2{margin-left:8px!important}.ml-lg-3{margin-left:12px!important}.ml-lg-4{margin-left:16px!important}.ml-lg-5{margin-left:20px!important}.ml-lg-6{margin-left:24px!important}.ml-lg-7{margin-left:28px!important}.ml-lg-8{margin-left:32px!important}.ml-lg-9{margin-left:36px!important}.ml-lg-10{margin-left:40px!important}.ml-lg-11{margin-left:44px!important}.ml-lg-12{margin-left:48px!important}.ml-lg-13{margin-left:52px!important}.ml-lg-14{margin-left:56px!important}.ml-lg-15{margin-left:60px!important}.ml-lg-16{margin-left:64px!important}.ml-lg-auto{margin-left:auto!important}.ms-lg-0{margin-inline-start:0px!important}.ms-lg-1{margin-inline-start:4px!important}.ms-lg-2{margin-inline-start:8px!important}.ms-lg-3{margin-inline-start:12px!important}.ms-lg-4{margin-inline-start:16px!important}.ms-lg-5{margin-inline-start:20px!important}.ms-lg-6{margin-inline-start:24px!important}.ms-lg-7{margin-inline-start:28px!important}.ms-lg-8{margin-inline-start:32px!important}.ms-lg-9{margin-inline-start:36px!important}.ms-lg-10{margin-inline-start:40px!important}.ms-lg-11{margin-inline-start:44px!important}.ms-lg-12{margin-inline-start:48px!important}.ms-lg-13{margin-inline-start:52px!important}.ms-lg-14{margin-inline-start:56px!important}.ms-lg-15{margin-inline-start:60px!important}.ms-lg-16{margin-inline-start:64px!important}.ms-lg-auto{margin-inline-start:auto!important}.me-lg-0{margin-inline-end:0px!important}.me-lg-1{margin-inline-end:4px!important}.me-lg-2{margin-inline-end:8px!important}.me-lg-3{margin-inline-end:12px!important}.me-lg-4{margin-inline-end:16px!important}.me-lg-5{margin-inline-end:20px!important}.me-lg-6{margin-inline-end:24px!important}.me-lg-7{margin-inline-end:28px!important}.me-lg-8{margin-inline-end:32px!important}.me-lg-9{margin-inline-end:36px!important}.me-lg-10{margin-inline-end:40px!important}.me-lg-11{margin-inline-end:44px!important}.me-lg-12{margin-inline-end:48px!important}.me-lg-13{margin-inline-end:52px!important}.me-lg-14{margin-inline-end:56px!important}.me-lg-15{margin-inline-end:60px!important}.me-lg-16{margin-inline-end:64px!important}.me-lg-auto{margin-inline-end:auto!important}.ma-lg-n1{margin:-4px!important}.ma-lg-n2{margin:-8px!important}.ma-lg-n3{margin:-12px!important}.ma-lg-n4{margin:-16px!important}.ma-lg-n5{margin:-20px!important}.ma-lg-n6{margin:-24px!important}.ma-lg-n7{margin:-28px!important}.ma-lg-n8{margin:-32px!important}.ma-lg-n9{margin:-36px!important}.ma-lg-n10{margin:-40px!important}.ma-lg-n11{margin:-44px!important}.ma-lg-n12{margin:-48px!important}.ma-lg-n13{margin:-52px!important}.ma-lg-n14{margin:-56px!important}.ma-lg-n15{margin:-60px!important}.ma-lg-n16{margin:-64px!important}.mx-lg-n1{margin-right:-4px!important;margin-left:-4px!important}.mx-lg-n2{margin-right:-8px!important;margin-left:-8px!important}.mx-lg-n3{margin-right:-12px!important;margin-left:-12px!important}.mx-lg-n4{margin-right:-16px!important;margin-left:-16px!important}.mx-lg-n5{margin-right:-20px!important;margin-left:-20px!important}.mx-lg-n6{margin-right:-24px!important;margin-left:-24px!important}.mx-lg-n7{margin-right:-28px!important;margin-left:-28px!important}.mx-lg-n8{margin-right:-32px!important;margin-left:-32px!important}.mx-lg-n9{margin-right:-36px!important;margin-left:-36px!important}.mx-lg-n10{margin-right:-40px!important;margin-left:-40px!important}.mx-lg-n11{margin-right:-44px!important;margin-left:-44px!important}.mx-lg-n12{margin-right:-48px!important;margin-left:-48px!important}.mx-lg-n13{margin-right:-52px!important;margin-left:-52px!important}.mx-lg-n14{margin-right:-56px!important;margin-left:-56px!important}.mx-lg-n15{margin-right:-60px!important;margin-left:-60px!important}.mx-lg-n16{margin-right:-64px!important;margin-left:-64px!important}.my-lg-n1{margin-top:-4px!important;margin-bottom:-4px!important}.my-lg-n2{margin-top:-8px!important;margin-bottom:-8px!important}.my-lg-n3{margin-top:-12px!important;margin-bottom:-12px!important}.my-lg-n4{margin-top:-16px!important;margin-bottom:-16px!important}.my-lg-n5{margin-top:-20px!important;margin-bottom:-20px!important}.my-lg-n6{margin-top:-24px!important;margin-bottom:-24px!important}.my-lg-n7{margin-top:-28px!important;margin-bottom:-28px!important}.my-lg-n8{margin-top:-32px!important;margin-bottom:-32px!important}.my-lg-n9{margin-top:-36px!important;margin-bottom:-36px!important}.my-lg-n10{margin-top:-40px!important;margin-bottom:-40px!important}.my-lg-n11{margin-top:-44px!important;margin-bottom:-44px!important}.my-lg-n12{margin-top:-48px!important;margin-bottom:-48px!important}.my-lg-n13{margin-top:-52px!important;margin-bottom:-52px!important}.my-lg-n14{margin-top:-56px!important;margin-bottom:-56px!important}.my-lg-n15{margin-top:-60px!important;margin-bottom:-60px!important}.my-lg-n16{margin-top:-64px!important;margin-bottom:-64px!important}.mt-lg-n1{margin-top:-4px!important}.mt-lg-n2{margin-top:-8px!important}.mt-lg-n3{margin-top:-12px!important}.mt-lg-n4{margin-top:-16px!important}.mt-lg-n5{margin-top:-20px!important}.mt-lg-n6{margin-top:-24px!important}.mt-lg-n7{margin-top:-28px!important}.mt-lg-n8{margin-top:-32px!important}.mt-lg-n9{margin-top:-36px!important}.mt-lg-n10{margin-top:-40px!important}.mt-lg-n11{margin-top:-44px!important}.mt-lg-n12{margin-top:-48px!important}.mt-lg-n13{margin-top:-52px!important}.mt-lg-n14{margin-top:-56px!important}.mt-lg-n15{margin-top:-60px!important}.mt-lg-n16{margin-top:-64px!important}.mr-lg-n1{margin-right:-4px!important}.mr-lg-n2{margin-right:-8px!important}.mr-lg-n3{margin-right:-12px!important}.mr-lg-n4{margin-right:-16px!important}.mr-lg-n5{margin-right:-20px!important}.mr-lg-n6{margin-right:-24px!important}.mr-lg-n7{margin-right:-28px!important}.mr-lg-n8{margin-right:-32px!important}.mr-lg-n9{margin-right:-36px!important}.mr-lg-n10{margin-right:-40px!important}.mr-lg-n11{margin-right:-44px!important}.mr-lg-n12{margin-right:-48px!important}.mr-lg-n13{margin-right:-52px!important}.mr-lg-n14{margin-right:-56px!important}.mr-lg-n15{margin-right:-60px!important}.mr-lg-n16{margin-right:-64px!important}.mb-lg-n1{margin-bottom:-4px!important}.mb-lg-n2{margin-bottom:-8px!important}.mb-lg-n3{margin-bottom:-12px!important}.mb-lg-n4{margin-bottom:-16px!important}.mb-lg-n5{margin-bottom:-20px!important}.mb-lg-n6{margin-bottom:-24px!important}.mb-lg-n7{margin-bottom:-28px!important}.mb-lg-n8{margin-bottom:-32px!important}.mb-lg-n9{margin-bottom:-36px!important}.mb-lg-n10{margin-bottom:-40px!important}.mb-lg-n11{margin-bottom:-44px!important}.mb-lg-n12{margin-bottom:-48px!important}.mb-lg-n13{margin-bottom:-52px!important}.mb-lg-n14{margin-bottom:-56px!important}.mb-lg-n15{margin-bottom:-60px!important}.mb-lg-n16{margin-bottom:-64px!important}.ml-lg-n1{margin-left:-4px!important}.ml-lg-n2{margin-left:-8px!important}.ml-lg-n3{margin-left:-12px!important}.ml-lg-n4{margin-left:-16px!important}.ml-lg-n5{margin-left:-20px!important}.ml-lg-n6{margin-left:-24px!important}.ml-lg-n7{margin-left:-28px!important}.ml-lg-n8{margin-left:-32px!important}.ml-lg-n9{margin-left:-36px!important}.ml-lg-n10{margin-left:-40px!important}.ml-lg-n11{margin-left:-44px!important}.ml-lg-n12{margin-left:-48px!important}.ml-lg-n13{margin-left:-52px!important}.ml-lg-n14{margin-left:-56px!important}.ml-lg-n15{margin-left:-60px!important}.ml-lg-n16{margin-left:-64px!important}.ms-lg-n1{margin-inline-start:-4px!important}.ms-lg-n2{margin-inline-start:-8px!important}.ms-lg-n3{margin-inline-start:-12px!important}.ms-lg-n4{margin-inline-start:-16px!important}.ms-lg-n5{margin-inline-start:-20px!important}.ms-lg-n6{margin-inline-start:-24px!important}.ms-lg-n7{margin-inline-start:-28px!important}.ms-lg-n8{margin-inline-start:-32px!important}.ms-lg-n9{margin-inline-start:-36px!important}.ms-lg-n10{margin-inline-start:-40px!important}.ms-lg-n11{margin-inline-start:-44px!important}.ms-lg-n12{margin-inline-start:-48px!important}.ms-lg-n13{margin-inline-start:-52px!important}.ms-lg-n14{margin-inline-start:-56px!important}.ms-lg-n15{margin-inline-start:-60px!important}.ms-lg-n16{margin-inline-start:-64px!important}.me-lg-n1{margin-inline-end:-4px!important}.me-lg-n2{margin-inline-end:-8px!important}.me-lg-n3{margin-inline-end:-12px!important}.me-lg-n4{margin-inline-end:-16px!important}.me-lg-n5{margin-inline-end:-20px!important}.me-lg-n6{margin-inline-end:-24px!important}.me-lg-n7{margin-inline-end:-28px!important}.me-lg-n8{margin-inline-end:-32px!important}.me-lg-n9{margin-inline-end:-36px!important}.me-lg-n10{margin-inline-end:-40px!important}.me-lg-n11{margin-inline-end:-44px!important}.me-lg-n12{margin-inline-end:-48px!important}.me-lg-n13{margin-inline-end:-52px!important}.me-lg-n14{margin-inline-end:-56px!important}.me-lg-n15{margin-inline-end:-60px!important}.me-lg-n16{margin-inline-end:-64px!important}.pa-lg-0{padding:0!important}.pa-lg-1{padding:4px!important}.pa-lg-2{padding:8px!important}.pa-lg-3{padding:12px!important}.pa-lg-4{padding:16px!important}.pa-lg-5{padding:20px!important}.pa-lg-6{padding:24px!important}.pa-lg-7{padding:28px!important}.pa-lg-8{padding:32px!important}.pa-lg-9{padding:36px!important}.pa-lg-10{padding:40px!important}.pa-lg-11{padding:44px!important}.pa-lg-12{padding:48px!important}.pa-lg-13{padding:52px!important}.pa-lg-14{padding:56px!important}.pa-lg-15{padding:60px!important}.pa-lg-16{padding:64px!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:4px!important;padding-left:4px!important}.px-lg-2{padding-right:8px!important;padding-left:8px!important}.px-lg-3{padding-right:12px!important;padding-left:12px!important}.px-lg-4{padding-right:16px!important;padding-left:16px!important}.px-lg-5{padding-right:20px!important;padding-left:20px!important}.px-lg-6{padding-right:24px!important;padding-left:24px!important}.px-lg-7{padding-right:28px!important;padding-left:28px!important}.px-lg-8{padding-right:32px!important;padding-left:32px!important}.px-lg-9{padding-right:36px!important;padding-left:36px!important}.px-lg-10{padding-right:40px!important;padding-left:40px!important}.px-lg-11{padding-right:44px!important;padding-left:44px!important}.px-lg-12{padding-right:48px!important;padding-left:48px!important}.px-lg-13{padding-right:52px!important;padding-left:52px!important}.px-lg-14{padding-right:56px!important;padding-left:56px!important}.px-lg-15{padding-right:60px!important;padding-left:60px!important}.px-lg-16{padding-right:64px!important;padding-left:64px!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:4px!important;padding-bottom:4px!important}.py-lg-2{padding-top:8px!important;padding-bottom:8px!important}.py-lg-3{padding-top:12px!important;padding-bottom:12px!important}.py-lg-4{padding-top:16px!important;padding-bottom:16px!important}.py-lg-5{padding-top:20px!important;padding-bottom:20px!important}.py-lg-6{padding-top:24px!important;padding-bottom:24px!important}.py-lg-7{padding-top:28px!important;padding-bottom:28px!important}.py-lg-8{padding-top:32px!important;padding-bottom:32px!important}.py-lg-9{padding-top:36px!important;padding-bottom:36px!important}.py-lg-10{padding-top:40px!important;padding-bottom:40px!important}.py-lg-11{padding-top:44px!important;padding-bottom:44px!important}.py-lg-12{padding-top:48px!important;padding-bottom:48px!important}.py-lg-13{padding-top:52px!important;padding-bottom:52px!important}.py-lg-14{padding-top:56px!important;padding-bottom:56px!important}.py-lg-15{padding-top:60px!important;padding-bottom:60px!important}.py-lg-16{padding-top:64px!important;padding-bottom:64px!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:4px!important}.pt-lg-2{padding-top:8px!important}.pt-lg-3{padding-top:12px!important}.pt-lg-4{padding-top:16px!important}.pt-lg-5{padding-top:20px!important}.pt-lg-6{padding-top:24px!important}.pt-lg-7{padding-top:28px!important}.pt-lg-8{padding-top:32px!important}.pt-lg-9{padding-top:36px!important}.pt-lg-10{padding-top:40px!important}.pt-lg-11{padding-top:44px!important}.pt-lg-12{padding-top:48px!important}.pt-lg-13{padding-top:52px!important}.pt-lg-14{padding-top:56px!important}.pt-lg-15{padding-top:60px!important}.pt-lg-16{padding-top:64px!important}.pr-lg-0{padding-right:0!important}.pr-lg-1{padding-right:4px!important}.pr-lg-2{padding-right:8px!important}.pr-lg-3{padding-right:12px!important}.pr-lg-4{padding-right:16px!important}.pr-lg-5{padding-right:20px!important}.pr-lg-6{padding-right:24px!important}.pr-lg-7{padding-right:28px!important}.pr-lg-8{padding-right:32px!important}.pr-lg-9{padding-right:36px!important}.pr-lg-10{padding-right:40px!important}.pr-lg-11{padding-right:44px!important}.pr-lg-12{padding-right:48px!important}.pr-lg-13{padding-right:52px!important}.pr-lg-14{padding-right:56px!important}.pr-lg-15{padding-right:60px!important}.pr-lg-16{padding-right:64px!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:4px!important}.pb-lg-2{padding-bottom:8px!important}.pb-lg-3{padding-bottom:12px!important}.pb-lg-4{padding-bottom:16px!important}.pb-lg-5{padding-bottom:20px!important}.pb-lg-6{padding-bottom:24px!important}.pb-lg-7{padding-bottom:28px!important}.pb-lg-8{padding-bottom:32px!important}.pb-lg-9{padding-bottom:36px!important}.pb-lg-10{padding-bottom:40px!important}.pb-lg-11{padding-bottom:44px!important}.pb-lg-12{padding-bottom:48px!important}.pb-lg-13{padding-bottom:52px!important}.pb-lg-14{padding-bottom:56px!important}.pb-lg-15{padding-bottom:60px!important}.pb-lg-16{padding-bottom:64px!important}.pl-lg-0{padding-left:0!important}.pl-lg-1{padding-left:4px!important}.pl-lg-2{padding-left:8px!important}.pl-lg-3{padding-left:12px!important}.pl-lg-4{padding-left:16px!important}.pl-lg-5{padding-left:20px!important}.pl-lg-6{padding-left:24px!important}.pl-lg-7{padding-left:28px!important}.pl-lg-8{padding-left:32px!important}.pl-lg-9{padding-left:36px!important}.pl-lg-10{padding-left:40px!important}.pl-lg-11{padding-left:44px!important}.pl-lg-12{padding-left:48px!important}.pl-lg-13{padding-left:52px!important}.pl-lg-14{padding-left:56px!important}.pl-lg-15{padding-left:60px!important}.pl-lg-16{padding-left:64px!important}.ps-lg-0{padding-inline-start:0px!important}.ps-lg-1{padding-inline-start:4px!important}.ps-lg-2{padding-inline-start:8px!important}.ps-lg-3{padding-inline-start:12px!important}.ps-lg-4{padding-inline-start:16px!important}.ps-lg-5{padding-inline-start:20px!important}.ps-lg-6{padding-inline-start:24px!important}.ps-lg-7{padding-inline-start:28px!important}.ps-lg-8{padding-inline-start:32px!important}.ps-lg-9{padding-inline-start:36px!important}.ps-lg-10{padding-inline-start:40px!important}.ps-lg-11{padding-inline-start:44px!important}.ps-lg-12{padding-inline-start:48px!important}.ps-lg-13{padding-inline-start:52px!important}.ps-lg-14{padding-inline-start:56px!important}.ps-lg-15{padding-inline-start:60px!important}.ps-lg-16{padding-inline-start:64px!important}.pe-lg-0{padding-inline-end:0px!important}.pe-lg-1{padding-inline-end:4px!important}.pe-lg-2{padding-inline-end:8px!important}.pe-lg-3{padding-inline-end:12px!important}.pe-lg-4{padding-inline-end:16px!important}.pe-lg-5{padding-inline-end:20px!important}.pe-lg-6{padding-inline-end:24px!important}.pe-lg-7{padding-inline-end:28px!important}.pe-lg-8{padding-inline-end:32px!important}.pe-lg-9{padding-inline-end:36px!important}.pe-lg-10{padding-inline-end:40px!important}.pe-lg-11{padding-inline-end:44px!important}.pe-lg-12{padding-inline-end:48px!important}.pe-lg-13{padding-inline-end:52px!important}.pe-lg-14{padding-inline-end:56px!important}.pe-lg-15{padding-inline-end:60px!important}.pe-lg-16{padding-inline-end:64px!important}.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}.text-lg-justify{text-align:justify!important}.text-lg-start{text-align:start!important}.text-lg-end{text-align:end!important}.text-lg-h1{font-size:6rem!important;font-weight:300;line-height:6rem;letter-spacing:-.015625em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-h2{font-size:3.75rem!important;font-weight:300;line-height:3.75rem;letter-spacing:-.0083333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-h3{font-size:3rem!important;font-weight:400;line-height:3.125rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-h4{font-size:2.125rem!important;font-weight:400;line-height:2.5rem;letter-spacing:.0073529412em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-h5{font-size:1.5rem!important;font-weight:400;line-height:2rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-h6{font-size:1.25rem!important;font-weight:500;line-height:2rem;letter-spacing:.0125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-subtitle-1{font-size:1rem!important;font-weight:400;line-height:1.75rem;letter-spacing:.009375em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-subtitle-2{font-size:.875rem!important;font-weight:500;line-height:1.375rem;letter-spacing:.0071428571em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-body-1{font-size:1rem!important;font-weight:400;line-height:1.5rem;letter-spacing:.03125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-body-2{font-size:.875rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0178571429em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-button{font-size:.875rem!important;font-weight:500;line-height:2.25rem;letter-spacing:.0892857143em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}.text-lg-caption{font-size:.75rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0333333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-lg-overline{font-size:.75rem!important;font-weight:500;line-height:2rem;letter-spacing:.1666666667em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}}@media (min-width: 1920px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!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}.float-xl-none{float:none!important}.float-xl-left{float:left!important}.float-xl-right{float:right!important}.v-locale--is-rtl .float-xl-end{float:left!important}.v-locale--is-rtl .float-xl-start,.v-locale--is-ltr .float-xl-end{float:right!important}.v-locale--is-ltr .float-xl-start{float:left!important}.flex-xl-fill,.flex-xl-1-1{flex:1 1 auto!important}.flex-xl-1-0{flex:1 0 auto!important}.flex-xl-0-1{flex:0 1 auto!important}.flex-xl-0-0{flex:0 0 auto!important}.flex-xl-1-1-100{flex:1 1 100%!important}.flex-xl-1-0-100{flex:1 0 100%!important}.flex-xl-0-1-100{flex:0 1 100%!important}.flex-xl-0-0-100{flex:0 0 100%!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-xl-start{justify-content:flex-start!important}.justify-xl-end{justify-content:flex-end!important}.justify-xl-center{justify-content:center!important}.justify-xl-space-between{justify-content:space-between!important}.justify-xl-space-around{justify-content:space-around!important}.justify-xl-space-evenly{justify-content:space-evenly!important}.align-xl-start{align-items:flex-start!important}.align-xl-end{align-items:flex-end!important}.align-xl-center{align-items:center!important}.align-xl-baseline{align-items:baseline!important}.align-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-space-between{align-content:space-between!important}.align-content-xl-space-around{align-content:space-around!important}.align-content-xl-space-evenly{align-content:space-evenly!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-6{order:6!important}.order-xl-7{order:7!important}.order-xl-8{order:8!important}.order-xl-9{order:9!important}.order-xl-10{order:10!important}.order-xl-11{order:11!important}.order-xl-12{order:12!important}.order-xl-last{order:13!important}.ga-xl-0{gap:0px!important}.ga-xl-1{gap:4px!important}.ga-xl-2{gap:8px!important}.ga-xl-3{gap:12px!important}.ga-xl-4{gap:16px!important}.ga-xl-5{gap:20px!important}.ga-xl-6{gap:24px!important}.ga-xl-7{gap:28px!important}.ga-xl-8{gap:32px!important}.ga-xl-9{gap:36px!important}.ga-xl-10{gap:40px!important}.ga-xl-11{gap:44px!important}.ga-xl-12{gap:48px!important}.ga-xl-13{gap:52px!important}.ga-xl-14{gap:56px!important}.ga-xl-15{gap:60px!important}.ga-xl-16{gap:64px!important}.ga-xl-auto{gap:auto!important}.gr-xl-0{row-gap:0px!important}.gr-xl-1{row-gap:4px!important}.gr-xl-2{row-gap:8px!important}.gr-xl-3{row-gap:12px!important}.gr-xl-4{row-gap:16px!important}.gr-xl-5{row-gap:20px!important}.gr-xl-6{row-gap:24px!important}.gr-xl-7{row-gap:28px!important}.gr-xl-8{row-gap:32px!important}.gr-xl-9{row-gap:36px!important}.gr-xl-10{row-gap:40px!important}.gr-xl-11{row-gap:44px!important}.gr-xl-12{row-gap:48px!important}.gr-xl-13{row-gap:52px!important}.gr-xl-14{row-gap:56px!important}.gr-xl-15{row-gap:60px!important}.gr-xl-16{row-gap:64px!important}.gr-xl-auto{row-gap:auto!important}.gc-xl-0{column-gap:0px!important}.gc-xl-1{column-gap:4px!important}.gc-xl-2{column-gap:8px!important}.gc-xl-3{column-gap:12px!important}.gc-xl-4{column-gap:16px!important}.gc-xl-5{column-gap:20px!important}.gc-xl-6{column-gap:24px!important}.gc-xl-7{column-gap:28px!important}.gc-xl-8{column-gap:32px!important}.gc-xl-9{column-gap:36px!important}.gc-xl-10{column-gap:40px!important}.gc-xl-11{column-gap:44px!important}.gc-xl-12{column-gap:48px!important}.gc-xl-13{column-gap:52px!important}.gc-xl-14{column-gap:56px!important}.gc-xl-15{column-gap:60px!important}.gc-xl-16{column-gap:64px!important}.gc-xl-auto{column-gap:auto!important}.ma-xl-0{margin:0!important}.ma-xl-1{margin:4px!important}.ma-xl-2{margin:8px!important}.ma-xl-3{margin:12px!important}.ma-xl-4{margin:16px!important}.ma-xl-5{margin:20px!important}.ma-xl-6{margin:24px!important}.ma-xl-7{margin:28px!important}.ma-xl-8{margin:32px!important}.ma-xl-9{margin:36px!important}.ma-xl-10{margin:40px!important}.ma-xl-11{margin:44px!important}.ma-xl-12{margin:48px!important}.ma-xl-13{margin:52px!important}.ma-xl-14{margin:56px!important}.ma-xl-15{margin:60px!important}.ma-xl-16{margin:64px!important}.ma-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:4px!important;margin-left:4px!important}.mx-xl-2{margin-right:8px!important;margin-left:8px!important}.mx-xl-3{margin-right:12px!important;margin-left:12px!important}.mx-xl-4{margin-right:16px!important;margin-left:16px!important}.mx-xl-5{margin-right:20px!important;margin-left:20px!important}.mx-xl-6{margin-right:24px!important;margin-left:24px!important}.mx-xl-7{margin-right:28px!important;margin-left:28px!important}.mx-xl-8{margin-right:32px!important;margin-left:32px!important}.mx-xl-9{margin-right:36px!important;margin-left:36px!important}.mx-xl-10{margin-right:40px!important;margin-left:40px!important}.mx-xl-11{margin-right:44px!important;margin-left:44px!important}.mx-xl-12{margin-right:48px!important;margin-left:48px!important}.mx-xl-13{margin-right:52px!important;margin-left:52px!important}.mx-xl-14{margin-right:56px!important;margin-left:56px!important}.mx-xl-15{margin-right:60px!important;margin-left:60px!important}.mx-xl-16{margin-right:64px!important;margin-left:64px!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:4px!important;margin-bottom:4px!important}.my-xl-2{margin-top:8px!important;margin-bottom:8px!important}.my-xl-3{margin-top:12px!important;margin-bottom:12px!important}.my-xl-4{margin-top:16px!important;margin-bottom:16px!important}.my-xl-5{margin-top:20px!important;margin-bottom:20px!important}.my-xl-6{margin-top:24px!important;margin-bottom:24px!important}.my-xl-7{margin-top:28px!important;margin-bottom:28px!important}.my-xl-8{margin-top:32px!important;margin-bottom:32px!important}.my-xl-9{margin-top:36px!important;margin-bottom:36px!important}.my-xl-10{margin-top:40px!important;margin-bottom:40px!important}.my-xl-11{margin-top:44px!important;margin-bottom:44px!important}.my-xl-12{margin-top:48px!important;margin-bottom:48px!important}.my-xl-13{margin-top:52px!important;margin-bottom:52px!important}.my-xl-14{margin-top:56px!important;margin-bottom:56px!important}.my-xl-15{margin-top:60px!important;margin-bottom:60px!important}.my-xl-16{margin-top:64px!important;margin-bottom:64px!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:4px!important}.mt-xl-2{margin-top:8px!important}.mt-xl-3{margin-top:12px!important}.mt-xl-4{margin-top:16px!important}.mt-xl-5{margin-top:20px!important}.mt-xl-6{margin-top:24px!important}.mt-xl-7{margin-top:28px!important}.mt-xl-8{margin-top:32px!important}.mt-xl-9{margin-top:36px!important}.mt-xl-10{margin-top:40px!important}.mt-xl-11{margin-top:44px!important}.mt-xl-12{margin-top:48px!important}.mt-xl-13{margin-top:52px!important}.mt-xl-14{margin-top:56px!important}.mt-xl-15{margin-top:60px!important}.mt-xl-16{margin-top:64px!important}.mt-xl-auto{margin-top:auto!important}.mr-xl-0{margin-right:0!important}.mr-xl-1{margin-right:4px!important}.mr-xl-2{margin-right:8px!important}.mr-xl-3{margin-right:12px!important}.mr-xl-4{margin-right:16px!important}.mr-xl-5{margin-right:20px!important}.mr-xl-6{margin-right:24px!important}.mr-xl-7{margin-right:28px!important}.mr-xl-8{margin-right:32px!important}.mr-xl-9{margin-right:36px!important}.mr-xl-10{margin-right:40px!important}.mr-xl-11{margin-right:44px!important}.mr-xl-12{margin-right:48px!important}.mr-xl-13{margin-right:52px!important}.mr-xl-14{margin-right:56px!important}.mr-xl-15{margin-right:60px!important}.mr-xl-16{margin-right:64px!important}.mr-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:4px!important}.mb-xl-2{margin-bottom:8px!important}.mb-xl-3{margin-bottom:12px!important}.mb-xl-4{margin-bottom:16px!important}.mb-xl-5{margin-bottom:20px!important}.mb-xl-6{margin-bottom:24px!important}.mb-xl-7{margin-bottom:28px!important}.mb-xl-8{margin-bottom:32px!important}.mb-xl-9{margin-bottom:36px!important}.mb-xl-10{margin-bottom:40px!important}.mb-xl-11{margin-bottom:44px!important}.mb-xl-12{margin-bottom:48px!important}.mb-xl-13{margin-bottom:52px!important}.mb-xl-14{margin-bottom:56px!important}.mb-xl-15{margin-bottom:60px!important}.mb-xl-16{margin-bottom:64px!important}.mb-xl-auto{margin-bottom:auto!important}.ml-xl-0{margin-left:0!important}.ml-xl-1{margin-left:4px!important}.ml-xl-2{margin-left:8px!important}.ml-xl-3{margin-left:12px!important}.ml-xl-4{margin-left:16px!important}.ml-xl-5{margin-left:20px!important}.ml-xl-6{margin-left:24px!important}.ml-xl-7{margin-left:28px!important}.ml-xl-8{margin-left:32px!important}.ml-xl-9{margin-left:36px!important}.ml-xl-10{margin-left:40px!important}.ml-xl-11{margin-left:44px!important}.ml-xl-12{margin-left:48px!important}.ml-xl-13{margin-left:52px!important}.ml-xl-14{margin-left:56px!important}.ml-xl-15{margin-left:60px!important}.ml-xl-16{margin-left:64px!important}.ml-xl-auto{margin-left:auto!important}.ms-xl-0{margin-inline-start:0px!important}.ms-xl-1{margin-inline-start:4px!important}.ms-xl-2{margin-inline-start:8px!important}.ms-xl-3{margin-inline-start:12px!important}.ms-xl-4{margin-inline-start:16px!important}.ms-xl-5{margin-inline-start:20px!important}.ms-xl-6{margin-inline-start:24px!important}.ms-xl-7{margin-inline-start:28px!important}.ms-xl-8{margin-inline-start:32px!important}.ms-xl-9{margin-inline-start:36px!important}.ms-xl-10{margin-inline-start:40px!important}.ms-xl-11{margin-inline-start:44px!important}.ms-xl-12{margin-inline-start:48px!important}.ms-xl-13{margin-inline-start:52px!important}.ms-xl-14{margin-inline-start:56px!important}.ms-xl-15{margin-inline-start:60px!important}.ms-xl-16{margin-inline-start:64px!important}.ms-xl-auto{margin-inline-start:auto!important}.me-xl-0{margin-inline-end:0px!important}.me-xl-1{margin-inline-end:4px!important}.me-xl-2{margin-inline-end:8px!important}.me-xl-3{margin-inline-end:12px!important}.me-xl-4{margin-inline-end:16px!important}.me-xl-5{margin-inline-end:20px!important}.me-xl-6{margin-inline-end:24px!important}.me-xl-7{margin-inline-end:28px!important}.me-xl-8{margin-inline-end:32px!important}.me-xl-9{margin-inline-end:36px!important}.me-xl-10{margin-inline-end:40px!important}.me-xl-11{margin-inline-end:44px!important}.me-xl-12{margin-inline-end:48px!important}.me-xl-13{margin-inline-end:52px!important}.me-xl-14{margin-inline-end:56px!important}.me-xl-15{margin-inline-end:60px!important}.me-xl-16{margin-inline-end:64px!important}.me-xl-auto{margin-inline-end:auto!important}.ma-xl-n1{margin:-4px!important}.ma-xl-n2{margin:-8px!important}.ma-xl-n3{margin:-12px!important}.ma-xl-n4{margin:-16px!important}.ma-xl-n5{margin:-20px!important}.ma-xl-n6{margin:-24px!important}.ma-xl-n7{margin:-28px!important}.ma-xl-n8{margin:-32px!important}.ma-xl-n9{margin:-36px!important}.ma-xl-n10{margin:-40px!important}.ma-xl-n11{margin:-44px!important}.ma-xl-n12{margin:-48px!important}.ma-xl-n13{margin:-52px!important}.ma-xl-n14{margin:-56px!important}.ma-xl-n15{margin:-60px!important}.ma-xl-n16{margin:-64px!important}.mx-xl-n1{margin-right:-4px!important;margin-left:-4px!important}.mx-xl-n2{margin-right:-8px!important;margin-left:-8px!important}.mx-xl-n3{margin-right:-12px!important;margin-left:-12px!important}.mx-xl-n4{margin-right:-16px!important;margin-left:-16px!important}.mx-xl-n5{margin-right:-20px!important;margin-left:-20px!important}.mx-xl-n6{margin-right:-24px!important;margin-left:-24px!important}.mx-xl-n7{margin-right:-28px!important;margin-left:-28px!important}.mx-xl-n8{margin-right:-32px!important;margin-left:-32px!important}.mx-xl-n9{margin-right:-36px!important;margin-left:-36px!important}.mx-xl-n10{margin-right:-40px!important;margin-left:-40px!important}.mx-xl-n11{margin-right:-44px!important;margin-left:-44px!important}.mx-xl-n12{margin-right:-48px!important;margin-left:-48px!important}.mx-xl-n13{margin-right:-52px!important;margin-left:-52px!important}.mx-xl-n14{margin-right:-56px!important;margin-left:-56px!important}.mx-xl-n15{margin-right:-60px!important;margin-left:-60px!important}.mx-xl-n16{margin-right:-64px!important;margin-left:-64px!important}.my-xl-n1{margin-top:-4px!important;margin-bottom:-4px!important}.my-xl-n2{margin-top:-8px!important;margin-bottom:-8px!important}.my-xl-n3{margin-top:-12px!important;margin-bottom:-12px!important}.my-xl-n4{margin-top:-16px!important;margin-bottom:-16px!important}.my-xl-n5{margin-top:-20px!important;margin-bottom:-20px!important}.my-xl-n6{margin-top:-24px!important;margin-bottom:-24px!important}.my-xl-n7{margin-top:-28px!important;margin-bottom:-28px!important}.my-xl-n8{margin-top:-32px!important;margin-bottom:-32px!important}.my-xl-n9{margin-top:-36px!important;margin-bottom:-36px!important}.my-xl-n10{margin-top:-40px!important;margin-bottom:-40px!important}.my-xl-n11{margin-top:-44px!important;margin-bottom:-44px!important}.my-xl-n12{margin-top:-48px!important;margin-bottom:-48px!important}.my-xl-n13{margin-top:-52px!important;margin-bottom:-52px!important}.my-xl-n14{margin-top:-56px!important;margin-bottom:-56px!important}.my-xl-n15{margin-top:-60px!important;margin-bottom:-60px!important}.my-xl-n16{margin-top:-64px!important;margin-bottom:-64px!important}.mt-xl-n1{margin-top:-4px!important}.mt-xl-n2{margin-top:-8px!important}.mt-xl-n3{margin-top:-12px!important}.mt-xl-n4{margin-top:-16px!important}.mt-xl-n5{margin-top:-20px!important}.mt-xl-n6{margin-top:-24px!important}.mt-xl-n7{margin-top:-28px!important}.mt-xl-n8{margin-top:-32px!important}.mt-xl-n9{margin-top:-36px!important}.mt-xl-n10{margin-top:-40px!important}.mt-xl-n11{margin-top:-44px!important}.mt-xl-n12{margin-top:-48px!important}.mt-xl-n13{margin-top:-52px!important}.mt-xl-n14{margin-top:-56px!important}.mt-xl-n15{margin-top:-60px!important}.mt-xl-n16{margin-top:-64px!important}.mr-xl-n1{margin-right:-4px!important}.mr-xl-n2{margin-right:-8px!important}.mr-xl-n3{margin-right:-12px!important}.mr-xl-n4{margin-right:-16px!important}.mr-xl-n5{margin-right:-20px!important}.mr-xl-n6{margin-right:-24px!important}.mr-xl-n7{margin-right:-28px!important}.mr-xl-n8{margin-right:-32px!important}.mr-xl-n9{margin-right:-36px!important}.mr-xl-n10{margin-right:-40px!important}.mr-xl-n11{margin-right:-44px!important}.mr-xl-n12{margin-right:-48px!important}.mr-xl-n13{margin-right:-52px!important}.mr-xl-n14{margin-right:-56px!important}.mr-xl-n15{margin-right:-60px!important}.mr-xl-n16{margin-right:-64px!important}.mb-xl-n1{margin-bottom:-4px!important}.mb-xl-n2{margin-bottom:-8px!important}.mb-xl-n3{margin-bottom:-12px!important}.mb-xl-n4{margin-bottom:-16px!important}.mb-xl-n5{margin-bottom:-20px!important}.mb-xl-n6{margin-bottom:-24px!important}.mb-xl-n7{margin-bottom:-28px!important}.mb-xl-n8{margin-bottom:-32px!important}.mb-xl-n9{margin-bottom:-36px!important}.mb-xl-n10{margin-bottom:-40px!important}.mb-xl-n11{margin-bottom:-44px!important}.mb-xl-n12{margin-bottom:-48px!important}.mb-xl-n13{margin-bottom:-52px!important}.mb-xl-n14{margin-bottom:-56px!important}.mb-xl-n15{margin-bottom:-60px!important}.mb-xl-n16{margin-bottom:-64px!important}.ml-xl-n1{margin-left:-4px!important}.ml-xl-n2{margin-left:-8px!important}.ml-xl-n3{margin-left:-12px!important}.ml-xl-n4{margin-left:-16px!important}.ml-xl-n5{margin-left:-20px!important}.ml-xl-n6{margin-left:-24px!important}.ml-xl-n7{margin-left:-28px!important}.ml-xl-n8{margin-left:-32px!important}.ml-xl-n9{margin-left:-36px!important}.ml-xl-n10{margin-left:-40px!important}.ml-xl-n11{margin-left:-44px!important}.ml-xl-n12{margin-left:-48px!important}.ml-xl-n13{margin-left:-52px!important}.ml-xl-n14{margin-left:-56px!important}.ml-xl-n15{margin-left:-60px!important}.ml-xl-n16{margin-left:-64px!important}.ms-xl-n1{margin-inline-start:-4px!important}.ms-xl-n2{margin-inline-start:-8px!important}.ms-xl-n3{margin-inline-start:-12px!important}.ms-xl-n4{margin-inline-start:-16px!important}.ms-xl-n5{margin-inline-start:-20px!important}.ms-xl-n6{margin-inline-start:-24px!important}.ms-xl-n7{margin-inline-start:-28px!important}.ms-xl-n8{margin-inline-start:-32px!important}.ms-xl-n9{margin-inline-start:-36px!important}.ms-xl-n10{margin-inline-start:-40px!important}.ms-xl-n11{margin-inline-start:-44px!important}.ms-xl-n12{margin-inline-start:-48px!important}.ms-xl-n13{margin-inline-start:-52px!important}.ms-xl-n14{margin-inline-start:-56px!important}.ms-xl-n15{margin-inline-start:-60px!important}.ms-xl-n16{margin-inline-start:-64px!important}.me-xl-n1{margin-inline-end:-4px!important}.me-xl-n2{margin-inline-end:-8px!important}.me-xl-n3{margin-inline-end:-12px!important}.me-xl-n4{margin-inline-end:-16px!important}.me-xl-n5{margin-inline-end:-20px!important}.me-xl-n6{margin-inline-end:-24px!important}.me-xl-n7{margin-inline-end:-28px!important}.me-xl-n8{margin-inline-end:-32px!important}.me-xl-n9{margin-inline-end:-36px!important}.me-xl-n10{margin-inline-end:-40px!important}.me-xl-n11{margin-inline-end:-44px!important}.me-xl-n12{margin-inline-end:-48px!important}.me-xl-n13{margin-inline-end:-52px!important}.me-xl-n14{margin-inline-end:-56px!important}.me-xl-n15{margin-inline-end:-60px!important}.me-xl-n16{margin-inline-end:-64px!important}.pa-xl-0{padding:0!important}.pa-xl-1{padding:4px!important}.pa-xl-2{padding:8px!important}.pa-xl-3{padding:12px!important}.pa-xl-4{padding:16px!important}.pa-xl-5{padding:20px!important}.pa-xl-6{padding:24px!important}.pa-xl-7{padding:28px!important}.pa-xl-8{padding:32px!important}.pa-xl-9{padding:36px!important}.pa-xl-10{padding:40px!important}.pa-xl-11{padding:44px!important}.pa-xl-12{padding:48px!important}.pa-xl-13{padding:52px!important}.pa-xl-14{padding:56px!important}.pa-xl-15{padding:60px!important}.pa-xl-16{padding:64px!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:4px!important;padding-left:4px!important}.px-xl-2{padding-right:8px!important;padding-left:8px!important}.px-xl-3{padding-right:12px!important;padding-left:12px!important}.px-xl-4{padding-right:16px!important;padding-left:16px!important}.px-xl-5{padding-right:20px!important;padding-left:20px!important}.px-xl-6{padding-right:24px!important;padding-left:24px!important}.px-xl-7{padding-right:28px!important;padding-left:28px!important}.px-xl-8{padding-right:32px!important;padding-left:32px!important}.px-xl-9{padding-right:36px!important;padding-left:36px!important}.px-xl-10{padding-right:40px!important;padding-left:40px!important}.px-xl-11{padding-right:44px!important;padding-left:44px!important}.px-xl-12{padding-right:48px!important;padding-left:48px!important}.px-xl-13{padding-right:52px!important;padding-left:52px!important}.px-xl-14{padding-right:56px!important;padding-left:56px!important}.px-xl-15{padding-right:60px!important;padding-left:60px!important}.px-xl-16{padding-right:64px!important;padding-left:64px!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:4px!important;padding-bottom:4px!important}.py-xl-2{padding-top:8px!important;padding-bottom:8px!important}.py-xl-3{padding-top:12px!important;padding-bottom:12px!important}.py-xl-4{padding-top:16px!important;padding-bottom:16px!important}.py-xl-5{padding-top:20px!important;padding-bottom:20px!important}.py-xl-6{padding-top:24px!important;padding-bottom:24px!important}.py-xl-7{padding-top:28px!important;padding-bottom:28px!important}.py-xl-8{padding-top:32px!important;padding-bottom:32px!important}.py-xl-9{padding-top:36px!important;padding-bottom:36px!important}.py-xl-10{padding-top:40px!important;padding-bottom:40px!important}.py-xl-11{padding-top:44px!important;padding-bottom:44px!important}.py-xl-12{padding-top:48px!important;padding-bottom:48px!important}.py-xl-13{padding-top:52px!important;padding-bottom:52px!important}.py-xl-14{padding-top:56px!important;padding-bottom:56px!important}.py-xl-15{padding-top:60px!important;padding-bottom:60px!important}.py-xl-16{padding-top:64px!important;padding-bottom:64px!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:4px!important}.pt-xl-2{padding-top:8px!important}.pt-xl-3{padding-top:12px!important}.pt-xl-4{padding-top:16px!important}.pt-xl-5{padding-top:20px!important}.pt-xl-6{padding-top:24px!important}.pt-xl-7{padding-top:28px!important}.pt-xl-8{padding-top:32px!important}.pt-xl-9{padding-top:36px!important}.pt-xl-10{padding-top:40px!important}.pt-xl-11{padding-top:44px!important}.pt-xl-12{padding-top:48px!important}.pt-xl-13{padding-top:52px!important}.pt-xl-14{padding-top:56px!important}.pt-xl-15{padding-top:60px!important}.pt-xl-16{padding-top:64px!important}.pr-xl-0{padding-right:0!important}.pr-xl-1{padding-right:4px!important}.pr-xl-2{padding-right:8px!important}.pr-xl-3{padding-right:12px!important}.pr-xl-4{padding-right:16px!important}.pr-xl-5{padding-right:20px!important}.pr-xl-6{padding-right:24px!important}.pr-xl-7{padding-right:28px!important}.pr-xl-8{padding-right:32px!important}.pr-xl-9{padding-right:36px!important}.pr-xl-10{padding-right:40px!important}.pr-xl-11{padding-right:44px!important}.pr-xl-12{padding-right:48px!important}.pr-xl-13{padding-right:52px!important}.pr-xl-14{padding-right:56px!important}.pr-xl-15{padding-right:60px!important}.pr-xl-16{padding-right:64px!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:4px!important}.pb-xl-2{padding-bottom:8px!important}.pb-xl-3{padding-bottom:12px!important}.pb-xl-4{padding-bottom:16px!important}.pb-xl-5{padding-bottom:20px!important}.pb-xl-6{padding-bottom:24px!important}.pb-xl-7{padding-bottom:28px!important}.pb-xl-8{padding-bottom:32px!important}.pb-xl-9{padding-bottom:36px!important}.pb-xl-10{padding-bottom:40px!important}.pb-xl-11{padding-bottom:44px!important}.pb-xl-12{padding-bottom:48px!important}.pb-xl-13{padding-bottom:52px!important}.pb-xl-14{padding-bottom:56px!important}.pb-xl-15{padding-bottom:60px!important}.pb-xl-16{padding-bottom:64px!important}.pl-xl-0{padding-left:0!important}.pl-xl-1{padding-left:4px!important}.pl-xl-2{padding-left:8px!important}.pl-xl-3{padding-left:12px!important}.pl-xl-4{padding-left:16px!important}.pl-xl-5{padding-left:20px!important}.pl-xl-6{padding-left:24px!important}.pl-xl-7{padding-left:28px!important}.pl-xl-8{padding-left:32px!important}.pl-xl-9{padding-left:36px!important}.pl-xl-10{padding-left:40px!important}.pl-xl-11{padding-left:44px!important}.pl-xl-12{padding-left:48px!important}.pl-xl-13{padding-left:52px!important}.pl-xl-14{padding-left:56px!important}.pl-xl-15{padding-left:60px!important}.pl-xl-16{padding-left:64px!important}.ps-xl-0{padding-inline-start:0px!important}.ps-xl-1{padding-inline-start:4px!important}.ps-xl-2{padding-inline-start:8px!important}.ps-xl-3{padding-inline-start:12px!important}.ps-xl-4{padding-inline-start:16px!important}.ps-xl-5{padding-inline-start:20px!important}.ps-xl-6{padding-inline-start:24px!important}.ps-xl-7{padding-inline-start:28px!important}.ps-xl-8{padding-inline-start:32px!important}.ps-xl-9{padding-inline-start:36px!important}.ps-xl-10{padding-inline-start:40px!important}.ps-xl-11{padding-inline-start:44px!important}.ps-xl-12{padding-inline-start:48px!important}.ps-xl-13{padding-inline-start:52px!important}.ps-xl-14{padding-inline-start:56px!important}.ps-xl-15{padding-inline-start:60px!important}.ps-xl-16{padding-inline-start:64px!important}.pe-xl-0{padding-inline-end:0px!important}.pe-xl-1{padding-inline-end:4px!important}.pe-xl-2{padding-inline-end:8px!important}.pe-xl-3{padding-inline-end:12px!important}.pe-xl-4{padding-inline-end:16px!important}.pe-xl-5{padding-inline-end:20px!important}.pe-xl-6{padding-inline-end:24px!important}.pe-xl-7{padding-inline-end:28px!important}.pe-xl-8{padding-inline-end:32px!important}.pe-xl-9{padding-inline-end:36px!important}.pe-xl-10{padding-inline-end:40px!important}.pe-xl-11{padding-inline-end:44px!important}.pe-xl-12{padding-inline-end:48px!important}.pe-xl-13{padding-inline-end:52px!important}.pe-xl-14{padding-inline-end:56px!important}.pe-xl-15{padding-inline-end:60px!important}.pe-xl-16{padding-inline-end:64px!important}.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}.text-xl-justify{text-align:justify!important}.text-xl-start{text-align:start!important}.text-xl-end{text-align:end!important}.text-xl-h1{font-size:6rem!important;font-weight:300;line-height:6rem;letter-spacing:-.015625em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-h2{font-size:3.75rem!important;font-weight:300;line-height:3.75rem;letter-spacing:-.0083333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-h3{font-size:3rem!important;font-weight:400;line-height:3.125rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-h4{font-size:2.125rem!important;font-weight:400;line-height:2.5rem;letter-spacing:.0073529412em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-h5{font-size:1.5rem!important;font-weight:400;line-height:2rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-h6{font-size:1.25rem!important;font-weight:500;line-height:2rem;letter-spacing:.0125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-subtitle-1{font-size:1rem!important;font-weight:400;line-height:1.75rem;letter-spacing:.009375em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-subtitle-2{font-size:.875rem!important;font-weight:500;line-height:1.375rem;letter-spacing:.0071428571em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-body-1{font-size:1rem!important;font-weight:400;line-height:1.5rem;letter-spacing:.03125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-body-2{font-size:.875rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0178571429em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-button{font-size:.875rem!important;font-weight:500;line-height:2.25rem;letter-spacing:.0892857143em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}.text-xl-caption{font-size:.75rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0333333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xl-overline{font-size:.75rem!important;font-weight:500;line-height:2rem;letter-spacing:.1666666667em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}}@media (min-width: 2560px){.d-xxl-none{display:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!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}.float-xxl-none{float:none!important}.float-xxl-left{float:left!important}.float-xxl-right{float:right!important}.v-locale--is-rtl .float-xxl-end{float:left!important}.v-locale--is-rtl .float-xxl-start,.v-locale--is-ltr .float-xxl-end{float:right!important}.v-locale--is-ltr .float-xxl-start{float:left!important}.flex-xxl-fill,.flex-xxl-1-1{flex:1 1 auto!important}.flex-xxl-1-0{flex:1 0 auto!important}.flex-xxl-0-1{flex:0 1 auto!important}.flex-xxl-0-0{flex:0 0 auto!important}.flex-xxl-1-1-100{flex:1 1 100%!important}.flex-xxl-1-0-100{flex:1 0 100%!important}.flex-xxl-0-1-100{flex:0 1 100%!important}.flex-xxl-0-0-100{flex:0 0 100%!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-xxl-start{justify-content:flex-start!important}.justify-xxl-end{justify-content:flex-end!important}.justify-xxl-center{justify-content:center!important}.justify-xxl-space-between{justify-content:space-between!important}.justify-xxl-space-around{justify-content:space-around!important}.justify-xxl-space-evenly{justify-content:space-evenly!important}.align-xxl-start{align-items:flex-start!important}.align-xxl-end{align-items:flex-end!important}.align-xxl-center{align-items:center!important}.align-xxl-baseline{align-items:baseline!important}.align-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-space-between{align-content:space-between!important}.align-content-xxl-space-around{align-content:space-around!important}.align-content-xxl-space-evenly{align-content:space-evenly!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-6{order:6!important}.order-xxl-7{order:7!important}.order-xxl-8{order:8!important}.order-xxl-9{order:9!important}.order-xxl-10{order:10!important}.order-xxl-11{order:11!important}.order-xxl-12{order:12!important}.order-xxl-last{order:13!important}.ga-xxl-0{gap:0px!important}.ga-xxl-1{gap:4px!important}.ga-xxl-2{gap:8px!important}.ga-xxl-3{gap:12px!important}.ga-xxl-4{gap:16px!important}.ga-xxl-5{gap:20px!important}.ga-xxl-6{gap:24px!important}.ga-xxl-7{gap:28px!important}.ga-xxl-8{gap:32px!important}.ga-xxl-9{gap:36px!important}.ga-xxl-10{gap:40px!important}.ga-xxl-11{gap:44px!important}.ga-xxl-12{gap:48px!important}.ga-xxl-13{gap:52px!important}.ga-xxl-14{gap:56px!important}.ga-xxl-15{gap:60px!important}.ga-xxl-16{gap:64px!important}.ga-xxl-auto{gap:auto!important}.gr-xxl-0{row-gap:0px!important}.gr-xxl-1{row-gap:4px!important}.gr-xxl-2{row-gap:8px!important}.gr-xxl-3{row-gap:12px!important}.gr-xxl-4{row-gap:16px!important}.gr-xxl-5{row-gap:20px!important}.gr-xxl-6{row-gap:24px!important}.gr-xxl-7{row-gap:28px!important}.gr-xxl-8{row-gap:32px!important}.gr-xxl-9{row-gap:36px!important}.gr-xxl-10{row-gap:40px!important}.gr-xxl-11{row-gap:44px!important}.gr-xxl-12{row-gap:48px!important}.gr-xxl-13{row-gap:52px!important}.gr-xxl-14{row-gap:56px!important}.gr-xxl-15{row-gap:60px!important}.gr-xxl-16{row-gap:64px!important}.gr-xxl-auto{row-gap:auto!important}.gc-xxl-0{column-gap:0px!important}.gc-xxl-1{column-gap:4px!important}.gc-xxl-2{column-gap:8px!important}.gc-xxl-3{column-gap:12px!important}.gc-xxl-4{column-gap:16px!important}.gc-xxl-5{column-gap:20px!important}.gc-xxl-6{column-gap:24px!important}.gc-xxl-7{column-gap:28px!important}.gc-xxl-8{column-gap:32px!important}.gc-xxl-9{column-gap:36px!important}.gc-xxl-10{column-gap:40px!important}.gc-xxl-11{column-gap:44px!important}.gc-xxl-12{column-gap:48px!important}.gc-xxl-13{column-gap:52px!important}.gc-xxl-14{column-gap:56px!important}.gc-xxl-15{column-gap:60px!important}.gc-xxl-16{column-gap:64px!important}.gc-xxl-auto{column-gap:auto!important}.ma-xxl-0{margin:0!important}.ma-xxl-1{margin:4px!important}.ma-xxl-2{margin:8px!important}.ma-xxl-3{margin:12px!important}.ma-xxl-4{margin:16px!important}.ma-xxl-5{margin:20px!important}.ma-xxl-6{margin:24px!important}.ma-xxl-7{margin:28px!important}.ma-xxl-8{margin:32px!important}.ma-xxl-9{margin:36px!important}.ma-xxl-10{margin:40px!important}.ma-xxl-11{margin:44px!important}.ma-xxl-12{margin:48px!important}.ma-xxl-13{margin:52px!important}.ma-xxl-14{margin:56px!important}.ma-xxl-15{margin:60px!important}.ma-xxl-16{margin:64px!important}.ma-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:4px!important;margin-left:4px!important}.mx-xxl-2{margin-right:8px!important;margin-left:8px!important}.mx-xxl-3{margin-right:12px!important;margin-left:12px!important}.mx-xxl-4{margin-right:16px!important;margin-left:16px!important}.mx-xxl-5{margin-right:20px!important;margin-left:20px!important}.mx-xxl-6{margin-right:24px!important;margin-left:24px!important}.mx-xxl-7{margin-right:28px!important;margin-left:28px!important}.mx-xxl-8{margin-right:32px!important;margin-left:32px!important}.mx-xxl-9{margin-right:36px!important;margin-left:36px!important}.mx-xxl-10{margin-right:40px!important;margin-left:40px!important}.mx-xxl-11{margin-right:44px!important;margin-left:44px!important}.mx-xxl-12{margin-right:48px!important;margin-left:48px!important}.mx-xxl-13{margin-right:52px!important;margin-left:52px!important}.mx-xxl-14{margin-right:56px!important;margin-left:56px!important}.mx-xxl-15{margin-right:60px!important;margin-left:60px!important}.mx-xxl-16{margin-right:64px!important;margin-left:64px!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:4px!important;margin-bottom:4px!important}.my-xxl-2{margin-top:8px!important;margin-bottom:8px!important}.my-xxl-3{margin-top:12px!important;margin-bottom:12px!important}.my-xxl-4{margin-top:16px!important;margin-bottom:16px!important}.my-xxl-5{margin-top:20px!important;margin-bottom:20px!important}.my-xxl-6{margin-top:24px!important;margin-bottom:24px!important}.my-xxl-7{margin-top:28px!important;margin-bottom:28px!important}.my-xxl-8{margin-top:32px!important;margin-bottom:32px!important}.my-xxl-9{margin-top:36px!important;margin-bottom:36px!important}.my-xxl-10{margin-top:40px!important;margin-bottom:40px!important}.my-xxl-11{margin-top:44px!important;margin-bottom:44px!important}.my-xxl-12{margin-top:48px!important;margin-bottom:48px!important}.my-xxl-13{margin-top:52px!important;margin-bottom:52px!important}.my-xxl-14{margin-top:56px!important;margin-bottom:56px!important}.my-xxl-15{margin-top:60px!important;margin-bottom:60px!important}.my-xxl-16{margin-top:64px!important;margin-bottom:64px!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:4px!important}.mt-xxl-2{margin-top:8px!important}.mt-xxl-3{margin-top:12px!important}.mt-xxl-4{margin-top:16px!important}.mt-xxl-5{margin-top:20px!important}.mt-xxl-6{margin-top:24px!important}.mt-xxl-7{margin-top:28px!important}.mt-xxl-8{margin-top:32px!important}.mt-xxl-9{margin-top:36px!important}.mt-xxl-10{margin-top:40px!important}.mt-xxl-11{margin-top:44px!important}.mt-xxl-12{margin-top:48px!important}.mt-xxl-13{margin-top:52px!important}.mt-xxl-14{margin-top:56px!important}.mt-xxl-15{margin-top:60px!important}.mt-xxl-16{margin-top:64px!important}.mt-xxl-auto{margin-top:auto!important}.mr-xxl-0{margin-right:0!important}.mr-xxl-1{margin-right:4px!important}.mr-xxl-2{margin-right:8px!important}.mr-xxl-3{margin-right:12px!important}.mr-xxl-4{margin-right:16px!important}.mr-xxl-5{margin-right:20px!important}.mr-xxl-6{margin-right:24px!important}.mr-xxl-7{margin-right:28px!important}.mr-xxl-8{margin-right:32px!important}.mr-xxl-9{margin-right:36px!important}.mr-xxl-10{margin-right:40px!important}.mr-xxl-11{margin-right:44px!important}.mr-xxl-12{margin-right:48px!important}.mr-xxl-13{margin-right:52px!important}.mr-xxl-14{margin-right:56px!important}.mr-xxl-15{margin-right:60px!important}.mr-xxl-16{margin-right:64px!important}.mr-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:4px!important}.mb-xxl-2{margin-bottom:8px!important}.mb-xxl-3{margin-bottom:12px!important}.mb-xxl-4{margin-bottom:16px!important}.mb-xxl-5{margin-bottom:20px!important}.mb-xxl-6{margin-bottom:24px!important}.mb-xxl-7{margin-bottom:28px!important}.mb-xxl-8{margin-bottom:32px!important}.mb-xxl-9{margin-bottom:36px!important}.mb-xxl-10{margin-bottom:40px!important}.mb-xxl-11{margin-bottom:44px!important}.mb-xxl-12{margin-bottom:48px!important}.mb-xxl-13{margin-bottom:52px!important}.mb-xxl-14{margin-bottom:56px!important}.mb-xxl-15{margin-bottom:60px!important}.mb-xxl-16{margin-bottom:64px!important}.mb-xxl-auto{margin-bottom:auto!important}.ml-xxl-0{margin-left:0!important}.ml-xxl-1{margin-left:4px!important}.ml-xxl-2{margin-left:8px!important}.ml-xxl-3{margin-left:12px!important}.ml-xxl-4{margin-left:16px!important}.ml-xxl-5{margin-left:20px!important}.ml-xxl-6{margin-left:24px!important}.ml-xxl-7{margin-left:28px!important}.ml-xxl-8{margin-left:32px!important}.ml-xxl-9{margin-left:36px!important}.ml-xxl-10{margin-left:40px!important}.ml-xxl-11{margin-left:44px!important}.ml-xxl-12{margin-left:48px!important}.ml-xxl-13{margin-left:52px!important}.ml-xxl-14{margin-left:56px!important}.ml-xxl-15{margin-left:60px!important}.ml-xxl-16{margin-left:64px!important}.ml-xxl-auto{margin-left:auto!important}.ms-xxl-0{margin-inline-start:0px!important}.ms-xxl-1{margin-inline-start:4px!important}.ms-xxl-2{margin-inline-start:8px!important}.ms-xxl-3{margin-inline-start:12px!important}.ms-xxl-4{margin-inline-start:16px!important}.ms-xxl-5{margin-inline-start:20px!important}.ms-xxl-6{margin-inline-start:24px!important}.ms-xxl-7{margin-inline-start:28px!important}.ms-xxl-8{margin-inline-start:32px!important}.ms-xxl-9{margin-inline-start:36px!important}.ms-xxl-10{margin-inline-start:40px!important}.ms-xxl-11{margin-inline-start:44px!important}.ms-xxl-12{margin-inline-start:48px!important}.ms-xxl-13{margin-inline-start:52px!important}.ms-xxl-14{margin-inline-start:56px!important}.ms-xxl-15{margin-inline-start:60px!important}.ms-xxl-16{margin-inline-start:64px!important}.ms-xxl-auto{margin-inline-start:auto!important}.me-xxl-0{margin-inline-end:0px!important}.me-xxl-1{margin-inline-end:4px!important}.me-xxl-2{margin-inline-end:8px!important}.me-xxl-3{margin-inline-end:12px!important}.me-xxl-4{margin-inline-end:16px!important}.me-xxl-5{margin-inline-end:20px!important}.me-xxl-6{margin-inline-end:24px!important}.me-xxl-7{margin-inline-end:28px!important}.me-xxl-8{margin-inline-end:32px!important}.me-xxl-9{margin-inline-end:36px!important}.me-xxl-10{margin-inline-end:40px!important}.me-xxl-11{margin-inline-end:44px!important}.me-xxl-12{margin-inline-end:48px!important}.me-xxl-13{margin-inline-end:52px!important}.me-xxl-14{margin-inline-end:56px!important}.me-xxl-15{margin-inline-end:60px!important}.me-xxl-16{margin-inline-end:64px!important}.me-xxl-auto{margin-inline-end:auto!important}.ma-xxl-n1{margin:-4px!important}.ma-xxl-n2{margin:-8px!important}.ma-xxl-n3{margin:-12px!important}.ma-xxl-n4{margin:-16px!important}.ma-xxl-n5{margin:-20px!important}.ma-xxl-n6{margin:-24px!important}.ma-xxl-n7{margin:-28px!important}.ma-xxl-n8{margin:-32px!important}.ma-xxl-n9{margin:-36px!important}.ma-xxl-n10{margin:-40px!important}.ma-xxl-n11{margin:-44px!important}.ma-xxl-n12{margin:-48px!important}.ma-xxl-n13{margin:-52px!important}.ma-xxl-n14{margin:-56px!important}.ma-xxl-n15{margin:-60px!important}.ma-xxl-n16{margin:-64px!important}.mx-xxl-n1{margin-right:-4px!important;margin-left:-4px!important}.mx-xxl-n2{margin-right:-8px!important;margin-left:-8px!important}.mx-xxl-n3{margin-right:-12px!important;margin-left:-12px!important}.mx-xxl-n4{margin-right:-16px!important;margin-left:-16px!important}.mx-xxl-n5{margin-right:-20px!important;margin-left:-20px!important}.mx-xxl-n6{margin-right:-24px!important;margin-left:-24px!important}.mx-xxl-n7{margin-right:-28px!important;margin-left:-28px!important}.mx-xxl-n8{margin-right:-32px!important;margin-left:-32px!important}.mx-xxl-n9{margin-right:-36px!important;margin-left:-36px!important}.mx-xxl-n10{margin-right:-40px!important;margin-left:-40px!important}.mx-xxl-n11{margin-right:-44px!important;margin-left:-44px!important}.mx-xxl-n12{margin-right:-48px!important;margin-left:-48px!important}.mx-xxl-n13{margin-right:-52px!important;margin-left:-52px!important}.mx-xxl-n14{margin-right:-56px!important;margin-left:-56px!important}.mx-xxl-n15{margin-right:-60px!important;margin-left:-60px!important}.mx-xxl-n16{margin-right:-64px!important;margin-left:-64px!important}.my-xxl-n1{margin-top:-4px!important;margin-bottom:-4px!important}.my-xxl-n2{margin-top:-8px!important;margin-bottom:-8px!important}.my-xxl-n3{margin-top:-12px!important;margin-bottom:-12px!important}.my-xxl-n4{margin-top:-16px!important;margin-bottom:-16px!important}.my-xxl-n5{margin-top:-20px!important;margin-bottom:-20px!important}.my-xxl-n6{margin-top:-24px!important;margin-bottom:-24px!important}.my-xxl-n7{margin-top:-28px!important;margin-bottom:-28px!important}.my-xxl-n8{margin-top:-32px!important;margin-bottom:-32px!important}.my-xxl-n9{margin-top:-36px!important;margin-bottom:-36px!important}.my-xxl-n10{margin-top:-40px!important;margin-bottom:-40px!important}.my-xxl-n11{margin-top:-44px!important;margin-bottom:-44px!important}.my-xxl-n12{margin-top:-48px!important;margin-bottom:-48px!important}.my-xxl-n13{margin-top:-52px!important;margin-bottom:-52px!important}.my-xxl-n14{margin-top:-56px!important;margin-bottom:-56px!important}.my-xxl-n15{margin-top:-60px!important;margin-bottom:-60px!important}.my-xxl-n16{margin-top:-64px!important;margin-bottom:-64px!important}.mt-xxl-n1{margin-top:-4px!important}.mt-xxl-n2{margin-top:-8px!important}.mt-xxl-n3{margin-top:-12px!important}.mt-xxl-n4{margin-top:-16px!important}.mt-xxl-n5{margin-top:-20px!important}.mt-xxl-n6{margin-top:-24px!important}.mt-xxl-n7{margin-top:-28px!important}.mt-xxl-n8{margin-top:-32px!important}.mt-xxl-n9{margin-top:-36px!important}.mt-xxl-n10{margin-top:-40px!important}.mt-xxl-n11{margin-top:-44px!important}.mt-xxl-n12{margin-top:-48px!important}.mt-xxl-n13{margin-top:-52px!important}.mt-xxl-n14{margin-top:-56px!important}.mt-xxl-n15{margin-top:-60px!important}.mt-xxl-n16{margin-top:-64px!important}.mr-xxl-n1{margin-right:-4px!important}.mr-xxl-n2{margin-right:-8px!important}.mr-xxl-n3{margin-right:-12px!important}.mr-xxl-n4{margin-right:-16px!important}.mr-xxl-n5{margin-right:-20px!important}.mr-xxl-n6{margin-right:-24px!important}.mr-xxl-n7{margin-right:-28px!important}.mr-xxl-n8{margin-right:-32px!important}.mr-xxl-n9{margin-right:-36px!important}.mr-xxl-n10{margin-right:-40px!important}.mr-xxl-n11{margin-right:-44px!important}.mr-xxl-n12{margin-right:-48px!important}.mr-xxl-n13{margin-right:-52px!important}.mr-xxl-n14{margin-right:-56px!important}.mr-xxl-n15{margin-right:-60px!important}.mr-xxl-n16{margin-right:-64px!important}.mb-xxl-n1{margin-bottom:-4px!important}.mb-xxl-n2{margin-bottom:-8px!important}.mb-xxl-n3{margin-bottom:-12px!important}.mb-xxl-n4{margin-bottom:-16px!important}.mb-xxl-n5{margin-bottom:-20px!important}.mb-xxl-n6{margin-bottom:-24px!important}.mb-xxl-n7{margin-bottom:-28px!important}.mb-xxl-n8{margin-bottom:-32px!important}.mb-xxl-n9{margin-bottom:-36px!important}.mb-xxl-n10{margin-bottom:-40px!important}.mb-xxl-n11{margin-bottom:-44px!important}.mb-xxl-n12{margin-bottom:-48px!important}.mb-xxl-n13{margin-bottom:-52px!important}.mb-xxl-n14{margin-bottom:-56px!important}.mb-xxl-n15{margin-bottom:-60px!important}.mb-xxl-n16{margin-bottom:-64px!important}.ml-xxl-n1{margin-left:-4px!important}.ml-xxl-n2{margin-left:-8px!important}.ml-xxl-n3{margin-left:-12px!important}.ml-xxl-n4{margin-left:-16px!important}.ml-xxl-n5{margin-left:-20px!important}.ml-xxl-n6{margin-left:-24px!important}.ml-xxl-n7{margin-left:-28px!important}.ml-xxl-n8{margin-left:-32px!important}.ml-xxl-n9{margin-left:-36px!important}.ml-xxl-n10{margin-left:-40px!important}.ml-xxl-n11{margin-left:-44px!important}.ml-xxl-n12{margin-left:-48px!important}.ml-xxl-n13{margin-left:-52px!important}.ml-xxl-n14{margin-left:-56px!important}.ml-xxl-n15{margin-left:-60px!important}.ml-xxl-n16{margin-left:-64px!important}.ms-xxl-n1{margin-inline-start:-4px!important}.ms-xxl-n2{margin-inline-start:-8px!important}.ms-xxl-n3{margin-inline-start:-12px!important}.ms-xxl-n4{margin-inline-start:-16px!important}.ms-xxl-n5{margin-inline-start:-20px!important}.ms-xxl-n6{margin-inline-start:-24px!important}.ms-xxl-n7{margin-inline-start:-28px!important}.ms-xxl-n8{margin-inline-start:-32px!important}.ms-xxl-n9{margin-inline-start:-36px!important}.ms-xxl-n10{margin-inline-start:-40px!important}.ms-xxl-n11{margin-inline-start:-44px!important}.ms-xxl-n12{margin-inline-start:-48px!important}.ms-xxl-n13{margin-inline-start:-52px!important}.ms-xxl-n14{margin-inline-start:-56px!important}.ms-xxl-n15{margin-inline-start:-60px!important}.ms-xxl-n16{margin-inline-start:-64px!important}.me-xxl-n1{margin-inline-end:-4px!important}.me-xxl-n2{margin-inline-end:-8px!important}.me-xxl-n3{margin-inline-end:-12px!important}.me-xxl-n4{margin-inline-end:-16px!important}.me-xxl-n5{margin-inline-end:-20px!important}.me-xxl-n6{margin-inline-end:-24px!important}.me-xxl-n7{margin-inline-end:-28px!important}.me-xxl-n8{margin-inline-end:-32px!important}.me-xxl-n9{margin-inline-end:-36px!important}.me-xxl-n10{margin-inline-end:-40px!important}.me-xxl-n11{margin-inline-end:-44px!important}.me-xxl-n12{margin-inline-end:-48px!important}.me-xxl-n13{margin-inline-end:-52px!important}.me-xxl-n14{margin-inline-end:-56px!important}.me-xxl-n15{margin-inline-end:-60px!important}.me-xxl-n16{margin-inline-end:-64px!important}.pa-xxl-0{padding:0!important}.pa-xxl-1{padding:4px!important}.pa-xxl-2{padding:8px!important}.pa-xxl-3{padding:12px!important}.pa-xxl-4{padding:16px!important}.pa-xxl-5{padding:20px!important}.pa-xxl-6{padding:24px!important}.pa-xxl-7{padding:28px!important}.pa-xxl-8{padding:32px!important}.pa-xxl-9{padding:36px!important}.pa-xxl-10{padding:40px!important}.pa-xxl-11{padding:44px!important}.pa-xxl-12{padding:48px!important}.pa-xxl-13{padding:52px!important}.pa-xxl-14{padding:56px!important}.pa-xxl-15{padding:60px!important}.pa-xxl-16{padding:64px!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:4px!important;padding-left:4px!important}.px-xxl-2{padding-right:8px!important;padding-left:8px!important}.px-xxl-3{padding-right:12px!important;padding-left:12px!important}.px-xxl-4{padding-right:16px!important;padding-left:16px!important}.px-xxl-5{padding-right:20px!important;padding-left:20px!important}.px-xxl-6{padding-right:24px!important;padding-left:24px!important}.px-xxl-7{padding-right:28px!important;padding-left:28px!important}.px-xxl-8{padding-right:32px!important;padding-left:32px!important}.px-xxl-9{padding-right:36px!important;padding-left:36px!important}.px-xxl-10{padding-right:40px!important;padding-left:40px!important}.px-xxl-11{padding-right:44px!important;padding-left:44px!important}.px-xxl-12{padding-right:48px!important;padding-left:48px!important}.px-xxl-13{padding-right:52px!important;padding-left:52px!important}.px-xxl-14{padding-right:56px!important;padding-left:56px!important}.px-xxl-15{padding-right:60px!important;padding-left:60px!important}.px-xxl-16{padding-right:64px!important;padding-left:64px!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:4px!important;padding-bottom:4px!important}.py-xxl-2{padding-top:8px!important;padding-bottom:8px!important}.py-xxl-3{padding-top:12px!important;padding-bottom:12px!important}.py-xxl-4{padding-top:16px!important;padding-bottom:16px!important}.py-xxl-5{padding-top:20px!important;padding-bottom:20px!important}.py-xxl-6{padding-top:24px!important;padding-bottom:24px!important}.py-xxl-7{padding-top:28px!important;padding-bottom:28px!important}.py-xxl-8{padding-top:32px!important;padding-bottom:32px!important}.py-xxl-9{padding-top:36px!important;padding-bottom:36px!important}.py-xxl-10{padding-top:40px!important;padding-bottom:40px!important}.py-xxl-11{padding-top:44px!important;padding-bottom:44px!important}.py-xxl-12{padding-top:48px!important;padding-bottom:48px!important}.py-xxl-13{padding-top:52px!important;padding-bottom:52px!important}.py-xxl-14{padding-top:56px!important;padding-bottom:56px!important}.py-xxl-15{padding-top:60px!important;padding-bottom:60px!important}.py-xxl-16{padding-top:64px!important;padding-bottom:64px!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:4px!important}.pt-xxl-2{padding-top:8px!important}.pt-xxl-3{padding-top:12px!important}.pt-xxl-4{padding-top:16px!important}.pt-xxl-5{padding-top:20px!important}.pt-xxl-6{padding-top:24px!important}.pt-xxl-7{padding-top:28px!important}.pt-xxl-8{padding-top:32px!important}.pt-xxl-9{padding-top:36px!important}.pt-xxl-10{padding-top:40px!important}.pt-xxl-11{padding-top:44px!important}.pt-xxl-12{padding-top:48px!important}.pt-xxl-13{padding-top:52px!important}.pt-xxl-14{padding-top:56px!important}.pt-xxl-15{padding-top:60px!important}.pt-xxl-16{padding-top:64px!important}.pr-xxl-0{padding-right:0!important}.pr-xxl-1{padding-right:4px!important}.pr-xxl-2{padding-right:8px!important}.pr-xxl-3{padding-right:12px!important}.pr-xxl-4{padding-right:16px!important}.pr-xxl-5{padding-right:20px!important}.pr-xxl-6{padding-right:24px!important}.pr-xxl-7{padding-right:28px!important}.pr-xxl-8{padding-right:32px!important}.pr-xxl-9{padding-right:36px!important}.pr-xxl-10{padding-right:40px!important}.pr-xxl-11{padding-right:44px!important}.pr-xxl-12{padding-right:48px!important}.pr-xxl-13{padding-right:52px!important}.pr-xxl-14{padding-right:56px!important}.pr-xxl-15{padding-right:60px!important}.pr-xxl-16{padding-right:64px!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:4px!important}.pb-xxl-2{padding-bottom:8px!important}.pb-xxl-3{padding-bottom:12px!important}.pb-xxl-4{padding-bottom:16px!important}.pb-xxl-5{padding-bottom:20px!important}.pb-xxl-6{padding-bottom:24px!important}.pb-xxl-7{padding-bottom:28px!important}.pb-xxl-8{padding-bottom:32px!important}.pb-xxl-9{padding-bottom:36px!important}.pb-xxl-10{padding-bottom:40px!important}.pb-xxl-11{padding-bottom:44px!important}.pb-xxl-12{padding-bottom:48px!important}.pb-xxl-13{padding-bottom:52px!important}.pb-xxl-14{padding-bottom:56px!important}.pb-xxl-15{padding-bottom:60px!important}.pb-xxl-16{padding-bottom:64px!important}.pl-xxl-0{padding-left:0!important}.pl-xxl-1{padding-left:4px!important}.pl-xxl-2{padding-left:8px!important}.pl-xxl-3{padding-left:12px!important}.pl-xxl-4{padding-left:16px!important}.pl-xxl-5{padding-left:20px!important}.pl-xxl-6{padding-left:24px!important}.pl-xxl-7{padding-left:28px!important}.pl-xxl-8{padding-left:32px!important}.pl-xxl-9{padding-left:36px!important}.pl-xxl-10{padding-left:40px!important}.pl-xxl-11{padding-left:44px!important}.pl-xxl-12{padding-left:48px!important}.pl-xxl-13{padding-left:52px!important}.pl-xxl-14{padding-left:56px!important}.pl-xxl-15{padding-left:60px!important}.pl-xxl-16{padding-left:64px!important}.ps-xxl-0{padding-inline-start:0px!important}.ps-xxl-1{padding-inline-start:4px!important}.ps-xxl-2{padding-inline-start:8px!important}.ps-xxl-3{padding-inline-start:12px!important}.ps-xxl-4{padding-inline-start:16px!important}.ps-xxl-5{padding-inline-start:20px!important}.ps-xxl-6{padding-inline-start:24px!important}.ps-xxl-7{padding-inline-start:28px!important}.ps-xxl-8{padding-inline-start:32px!important}.ps-xxl-9{padding-inline-start:36px!important}.ps-xxl-10{padding-inline-start:40px!important}.ps-xxl-11{padding-inline-start:44px!important}.ps-xxl-12{padding-inline-start:48px!important}.ps-xxl-13{padding-inline-start:52px!important}.ps-xxl-14{padding-inline-start:56px!important}.ps-xxl-15{padding-inline-start:60px!important}.ps-xxl-16{padding-inline-start:64px!important}.pe-xxl-0{padding-inline-end:0px!important}.pe-xxl-1{padding-inline-end:4px!important}.pe-xxl-2{padding-inline-end:8px!important}.pe-xxl-3{padding-inline-end:12px!important}.pe-xxl-4{padding-inline-end:16px!important}.pe-xxl-5{padding-inline-end:20px!important}.pe-xxl-6{padding-inline-end:24px!important}.pe-xxl-7{padding-inline-end:28px!important}.pe-xxl-8{padding-inline-end:32px!important}.pe-xxl-9{padding-inline-end:36px!important}.pe-xxl-10{padding-inline-end:40px!important}.pe-xxl-11{padding-inline-end:44px!important}.pe-xxl-12{padding-inline-end:48px!important}.pe-xxl-13{padding-inline-end:52px!important}.pe-xxl-14{padding-inline-end:56px!important}.pe-xxl-15{padding-inline-end:60px!important}.pe-xxl-16{padding-inline-end:64px!important}.text-xxl-left{text-align:left!important}.text-xxl-right{text-align:right!important}.text-xxl-center{text-align:center!important}.text-xxl-justify{text-align:justify!important}.text-xxl-start{text-align:start!important}.text-xxl-end{text-align:end!important}.text-xxl-h1{font-size:6rem!important;font-weight:300;line-height:6rem;letter-spacing:-.015625em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-h2{font-size:3.75rem!important;font-weight:300;line-height:3.75rem;letter-spacing:-.0083333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-h3{font-size:3rem!important;font-weight:400;line-height:3.125rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-h4{font-size:2.125rem!important;font-weight:400;line-height:2.5rem;letter-spacing:.0073529412em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-h5{font-size:1.5rem!important;font-weight:400;line-height:2rem;letter-spacing:normal!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-h6{font-size:1.25rem!important;font-weight:500;line-height:2rem;letter-spacing:.0125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-subtitle-1{font-size:1rem!important;font-weight:400;line-height:1.75rem;letter-spacing:.009375em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-subtitle-2{font-size:.875rem!important;font-weight:500;line-height:1.375rem;letter-spacing:.0071428571em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-body-1{font-size:1rem!important;font-weight:400;line-height:1.5rem;letter-spacing:.03125em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-body-2{font-size:.875rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0178571429em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-button{font-size:.875rem!important;font-weight:500;line-height:2.25rem;letter-spacing:.0892857143em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}.text-xxl-caption{font-size:.75rem!important;font-weight:400;line-height:1.25rem;letter-spacing:.0333333333em!important;font-family:Roboto,sans-serif;text-transform:none!important}.text-xxl-overline{font-size:.75rem!important;font-weight:500;line-height:2rem;letter-spacing:.1666666667em!important;font-family:Roboto,sans-serif;text-transform:uppercase!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!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}.float-print-none{float:none!important}.float-print-left{float:left!important}.float-print-right{float:right!important}.v-locale--is-rtl .float-print-end{float:left!important}.v-locale--is-rtl .float-print-start,.v-locale--is-ltr .float-print-end{float:right!important}.v-locale--is-ltr .float-print-start{float:left!important}}.v-application{display:flex;background:rgb(var(--v-theme-background));color:rgba(var(--v-theme-on-background),var(--v-high-emphasis-opacity))}.v-application__wrap{backface-visibility:hidden;display:flex;flex-direction:column;flex:1 1 auto;max-width:100%;min-height:100vh;min-height:100dvh;position:relative}.v-app-bar{display:flex}.v-app-bar.v-toolbar{background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-app-bar.v-toolbar:not(.v-toolbar--flat){box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-app-bar:not(.v-toolbar--absolute){padding-inline-end:var(--v-scrollbar-offset)}.v-alert{display:grid;flex:1 1;grid-template-areas:"prepend content append close" ". content . .";grid-template-columns:max-content auto max-content max-content;position:relative;padding:16px;overflow:hidden;--v-border-color: currentColor;border-radius:4px}.v-alert--absolute{position:absolute}.v-alert--fixed{position:fixed}.v-alert--sticky{position:sticky}.v-alert--variant-plain,.v-alert--variant-outlined,.v-alert--variant-text,.v-alert--variant-tonal{background:transparent;color:inherit}.v-alert--variant-plain{opacity:.62}.v-alert--variant-plain:focus,.v-alert--variant-plain:hover{opacity:1}.v-alert--variant-plain .v-alert__overlay{display:none}.v-alert--variant-elevated,.v-alert--variant-flat{background:rgb(var(--v-theme-surface-light));color:rgba(var(--v-theme-on-surface-light),var(--v-high-emphasis-opacity))}.v-alert--variant-elevated{box-shadow:0 2px 1px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 1px 1px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 3px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-alert--variant-flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-alert--variant-outlined{border:thin solid currentColor}.v-alert--variant-text .v-alert__overlay{background:currentColor}.v-alert--variant-tonal .v-alert__underlay{background:currentColor;opacity:var(--v-activated-opacity);border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.v-alert--prominent{grid-template-areas:"prepend content append close" "prepend content . ."}.v-alert.v-alert--border{--v-border-opacity: .38}.v-alert.v-alert--border.v-alert--border-start{padding-inline-start:24px}.v-alert.v-alert--border.v-alert--border-end{padding-inline-end:24px}.v-alert--variant-plain{transition:.2s opacity cubic-bezier(.4,0,.2,1)}.v-alert--density-default{padding-bottom:16px;padding-top:16px}.v-alert--density-default.v-alert--border-top{padding-top:24px}.v-alert--density-default.v-alert--border-bottom{padding-bottom:24px}.v-alert--density-comfortable{padding-bottom:12px;padding-top:12px}.v-alert--density-comfortable.v-alert--border-top{padding-top:20px}.v-alert--density-comfortable.v-alert--border-bottom{padding-bottom:20px}.v-alert--density-compact{padding-bottom:8px;padding-top:8px}.v-alert--density-compact.v-alert--border-top{padding-top:16px}.v-alert--density-compact.v-alert--border-bottom{padding-bottom:16px}.v-alert__border{border-radius:inherit;bottom:0;left:0;opacity:var(--v-border-opacity);position:absolute;pointer-events:none;right:0;top:0;width:100%;border-color:currentColor;border-style:solid;border-width:0}.v-alert__border--border{border-width:8px;box-shadow:none}.v-alert--border-start .v-alert__border{border-inline-start-width:8px}.v-alert--border-end .v-alert__border{border-inline-end-width:8px}.v-alert--border-top .v-alert__border{border-top-width:8px}.v-alert--border-bottom .v-alert__border{border-bottom-width:8px}.v-alert__close{flex:0 1 auto;grid-area:close}.v-alert__content{align-self:center;grid-area:content;overflow:hidden}.v-alert__append,.v-alert__close{align-self:flex-start;margin-inline-start:16px}.v-alert__append{align-self:flex-start;grid-area:append}.v-alert__append+.v-alert__close{margin-inline-start:16px}.v-alert__prepend{align-self:flex-start;display:flex;align-items:center;grid-area:prepend;margin-inline-end:16px}.v-alert--prominent .v-alert__prepend{align-self:center}.v-alert__underlay{grid-area:none;position:absolute}.v-alert--border-start .v-alert__underlay{border-top-left-radius:0;border-bottom-left-radius:0}.v-alert--border-end .v-alert__underlay{border-top-right-radius:0;border-bottom-right-radius:0}.v-alert--border-top .v-alert__underlay{border-top-left-radius:0;border-top-right-radius:0}.v-alert--border-bottom .v-alert__underlay{border-bottom-left-radius:0;border-bottom-right-radius:0}.v-alert-title{align-items:center;align-self:center;display:flex;font-size:1.25rem;font-weight:500;-webkit-hyphens:auto;hyphens:auto;letter-spacing:.0125em;line-height:1.75rem;overflow-wrap:normal;text-transform:none;word-break:normal;word-wrap:break-word}.v-autocomplete .v-field .v-text-field__prefix,.v-autocomplete .v-field .v-text-field__suffix,.v-autocomplete .v-field .v-field__input,.v-autocomplete .v-field.v-field{cursor:text}.v-autocomplete .v-field .v-field__input>input{flex:1 1}.v-autocomplete .v-field input{min-width:64px}.v-autocomplete .v-field:not(.v-field--focused) input{min-width:0}.v-autocomplete .v-field--dirty .v-autocomplete__selection{margin-inline-end:2px}.v-autocomplete .v-autocomplete__selection-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.v-autocomplete__content{overflow:hidden;box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:4px}.v-autocomplete__mask{background:rgb(var(--v-theme-surface-light))}.v-autocomplete__selection{display:inline-flex;align-items:center;height:1.5rem;letter-spacing:inherit;line-height:inherit;max-width:calc(100% - 4px)}.v-autocomplete__selection:first-child{margin-inline-start:0}.v-autocomplete--chips.v-input--density-compact .v-field--variant-solo .v-label.v-field-label--floating,.v-autocomplete--chips.v-input--density-compact .v-field--variant-solo-inverted .v-label.v-field-label--floating,.v-autocomplete--chips.v-input--density-compact .v-field--variant-filled .v-label.v-field-label--floating,.v-autocomplete--chips.v-input--density-compact .v-field--variant-solo-filled .v-label.v-field-label--floating{top:0}.v-autocomplete--selecting-index .v-autocomplete__selection{opacity:var(--v-medium-emphasis-opacity)}.v-autocomplete--selecting-index .v-autocomplete__selection--selected{opacity:1}.v-autocomplete--selecting-index .v-field__input>input{caret-color:transparent}.v-autocomplete--single:not(.v-autocomplete--selection-slot).v-text-field input{flex:1 1;position:absolute;left:0;right:0;width:100%;padding-inline:inherit}.v-autocomplete--single:not(.v-autocomplete--selection-slot) .v-field--active input{transition:none}.v-autocomplete--single:not(.v-autocomplete--selection-slot) .v-field--dirty:not(.v-field--focused) input{opacity:0}.v-autocomplete--single:not(.v-autocomplete--selection-slot) .v-field--focused .v-autocomplete__selection{opacity:0}.v-autocomplete__menu-icon{margin-inline-start:4px;transition:.2s cubic-bezier(.4,0,.2,1)}.v-autocomplete--active-menu .v-autocomplete__menu-icon{opacity:var(--v-high-emphasis-opacity);transform:rotate(180deg)}.v-avatar{flex:none;align-items:center;display:inline-flex;justify-content:center;line-height:normal;overflow:hidden;position:relative;text-align:center;transition:.2s cubic-bezier(.4,0,.2,1);transition-property:width,height;vertical-align:middle;border-radius:50%}.v-avatar.v-avatar--size-x-small{--v-avatar-height: 24px}.v-avatar.v-avatar--size-small{--v-avatar-height: 32px}.v-avatar.v-avatar--size-default{--v-avatar-height: 40px}.v-avatar.v-avatar--size-large{--v-avatar-height: 48px}.v-avatar.v-avatar--size-x-large{--v-avatar-height: 56px}.v-avatar.v-avatar--density-default{height:calc(var(--v-avatar-height) + 0px);width:calc(var(--v-avatar-height) + 0px)}.v-avatar.v-avatar--density-comfortable{height:calc(var(--v-avatar-height) + -4px);width:calc(var(--v-avatar-height) + -4px)}.v-avatar.v-avatar--density-compact{height:calc(var(--v-avatar-height) + -8px);width:calc(var(--v-avatar-height) + -8px)}.v-avatar--variant-plain,.v-avatar--variant-outlined,.v-avatar--variant-text,.v-avatar--variant-tonal{background:transparent;color:inherit}.v-avatar--variant-plain{opacity:.62}.v-avatar--variant-plain:focus,.v-avatar--variant-plain:hover{opacity:1}.v-avatar--variant-plain .v-avatar__overlay{display:none}.v-avatar--variant-elevated,.v-avatar--variant-flat{background:var(--v-theme-surface);color:rgba(var(--v-theme-on-surface),var(--v-medium-emphasis-opacity))}.v-avatar--variant-elevated{box-shadow:0 2px 1px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 1px 1px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 3px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-avatar--variant-flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-avatar--variant-outlined{border:thin solid currentColor}.v-avatar--variant-text .v-avatar__overlay{background:currentColor}.v-avatar--variant-tonal .v-avatar__underlay{background:currentColor;opacity:var(--v-activated-opacity);border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.v-avatar--rounded{border-radius:4px}.v-avatar--start{margin-inline-end:8px}.v-avatar--end{margin-inline-start:8px}.v-avatar .v-img{height:100%;width:100%}.v-checkbox.v-input{flex:0 1 auto}.v-checkbox .v-selection-control{min-height:var(--v-input-control-height)}.v-selection-control{align-items:center;contain:layout;display:flex;flex:1 0;grid-area:control;position:relative;-webkit-user-select:none;user-select:none}.v-selection-control .v-label{white-space:normal;word-break:break-word;height:100%}.v-selection-control--disabled{opacity:var(--v-disabled-opacity);pointer-events:none}.v-selection-control--error .v-label,.v-selection-control--disabled .v-label{opacity:1}.v-selection-control--error:not(.v-selection-control--disabled) .v-label{color:rgb(var(--v-theme-error))}.v-selection-control--inline{display:inline-flex;flex:0 0 auto;min-width:0;max-width:100%}.v-selection-control--inline .v-label{width:auto}.v-selection-control--density-default{--v-selection-control-size: 40px}.v-selection-control--density-comfortable{--v-selection-control-size: 36px}.v-selection-control--density-compact{--v-selection-control-size: 28px}.v-selection-control__wrapper{width:var(--v-selection-control-size);height:var(--v-selection-control-size);display:inline-flex;align-items:center;position:relative;justify-content:center;flex:none}.v-selection-control__input{width:var(--v-selection-control-size);height:var(--v-selection-control-size);align-items:center;display:flex;flex:none;justify-content:center;position:relative;border-radius:50%}.v-selection-control__input input{cursor:pointer;position:absolute;left:0;top:0;width:100%;height:100%;opacity:0}.v-selection-control__input:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;border-radius:100%;background-color:currentColor;opacity:0;pointer-events:none}.v-selection-control__input:hover:before{opacity:calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier))}.v-selection-control__input>.v-icon{opacity:var(--v-medium-emphasis-opacity)}.v-selection-control--disabled .v-selection-control__input>.v-icon,.v-selection-control--dirty .v-selection-control__input>.v-icon,.v-selection-control--error .v-selection-control__input>.v-icon{opacity:1}.v-selection-control--error:not(.v-selection-control--disabled) .v-selection-control__input>.v-icon{color:rgb(var(--v-theme-error))}.v-selection-control--focus-visible .v-selection-control__input:before{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}.v-label{align-items:center;color:inherit;display:inline-flex;font-size:1rem;letter-spacing:.009375em;min-width:0;opacity:var(--v-medium-emphasis-opacity);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.v-label--clickable{cursor:pointer}.v-selection-control-group{grid-area:control;display:flex;flex-direction:column}.v-selection-control-group--inline{flex-direction:row;flex-wrap:wrap}.v-input{display:grid;flex:1 1 auto;font-size:1rem;font-weight:400;line-height:1.5}.v-input--disabled{pointer-events:none}.v-input--density-default{--v-input-control-height: 56px;--v-input-padding-top: 16px}.v-input--density-comfortable{--v-input-control-height: 48px;--v-input-padding-top: 12px}.v-input--density-compact{--v-input-control-height: 40px;--v-input-padding-top: 8px}.v-input--vertical{grid-template-areas:"append" "control" "prepend";grid-template-rows:max-content auto max-content;grid-template-columns:min-content}.v-input--vertical .v-input__prepend{margin-block-start:16px}.v-input--vertical .v-input__append{margin-block-end:16px}.v-input--horizontal{grid-template-areas:"prepend control append" "a messages b";grid-template-columns:max-content minmax(0,1fr) max-content;grid-template-rows:auto auto}.v-input--horizontal .v-input__prepend{margin-inline-end:16px}.v-input--horizontal .v-input__append{margin-inline-start:16px}.v-input__details{align-items:flex-end;display:flex;font-size:.75rem;font-weight:400;grid-area:messages;letter-spacing:.0333333333em;line-height:normal;min-height:22px;padding-top:6px;overflow:hidden;justify-content:space-between}.v-input__details>.v-icon,.v-input__prepend>.v-icon,.v-input__append>.v-icon{opacity:var(--v-medium-emphasis-opacity)}.v-input--disabled .v-input__details>.v-icon,.v-input--disabled .v-input__details .v-messages,.v-input--error .v-input__details>.v-icon,.v-input--error .v-input__details .v-messages,.v-input--disabled .v-input__prepend>.v-icon,.v-input--disabled .v-input__prepend .v-messages,.v-input--error .v-input__prepend>.v-icon,.v-input--error .v-input__prepend .v-messages,.v-input--disabled .v-input__append>.v-icon,.v-input--disabled .v-input__append .v-messages,.v-input--error .v-input__append>.v-icon,.v-input--error .v-input__append .v-messages{opacity:1}.v-input--disabled .v-input__details,.v-input--disabled .v-input__prepend,.v-input--disabled .v-input__append{opacity:var(--v-disabled-opacity)}.v-input--error:not(.v-input--disabled) .v-input__details>.v-icon,.v-input--error:not(.v-input--disabled) .v-input__details .v-messages,.v-input--error:not(.v-input--disabled) .v-input__prepend>.v-icon,.v-input--error:not(.v-input--disabled) .v-input__prepend .v-messages,.v-input--error:not(.v-input--disabled) .v-input__append>.v-icon,.v-input--error:not(.v-input--disabled) .v-input__append .v-messages{color:rgb(var(--v-theme-error))}.v-input__prepend,.v-input__append{display:flex;align-items:flex-start;padding-top:var(--v-input-padding-top)}.v-input--center-affix .v-input__prepend,.v-input--center-affix .v-input__append{align-items:center;padding-top:0}.v-input__prepend{grid-area:prepend}.v-input__append{grid-area:append}.v-input__control{display:flex;grid-area:control}.v-input--hide-spin-buttons input::-webkit-outer-spin-button,.v-input--hide-spin-buttons input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.v-input--hide-spin-buttons input[type=number]{-moz-appearance:textfield}.v-input--plain-underlined .v-input__prepend,.v-input--plain-underlined .v-input__append{align-items:flex-start}.v-input--density-default.v-input--plain-underlined .v-input__prepend,.v-input--density-default.v-input--plain-underlined .v-input__append{padding-top:calc(var(--v-input-padding-top) + 4px)}.v-input--density-comfortable.v-input--plain-underlined .v-input__prepend,.v-input--density-comfortable.v-input--plain-underlined .v-input__append{padding-top:calc(var(--v-input-padding-top) + 2px)}.v-input--density-compact.v-input--plain-underlined .v-input__prepend,.v-input--density-compact.v-input--plain-underlined .v-input__append{padding-top:calc(var(--v-input-padding-top) + 0px)}.v-messages{flex:1 1 auto;font-size:12px;min-height:14px;min-width:1px;opacity:var(--v-medium-emphasis-opacity);position:relative}.v-messages__message{line-height:12px;word-break:break-word;overflow-wrap:break-word;word-wrap:break-word;-webkit-hyphens:auto;hyphens:auto;transition-duration:.15s}.v-chip{align-items:center;display:inline-flex;font-weight:400;max-width:100%;min-width:0;overflow:hidden;position:relative;text-decoration:none;white-space:nowrap;vertical-align:middle;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;border-radius:9999px}.v-chip .v-icon{--v-icon-size-multiplier: .8571428571}.v-chip.v-chip--size-x-small{--v-chip-size: .625rem;--v-chip-height: 20px;font-size:.625rem;padding:0 8px}.v-chip.v-chip--size-x-small .v-avatar{--v-avatar-height: 14px}.v-chip--pill.v-chip.v-chip--size-x-small .v-avatar{--v-avatar-height: 20px}.v-chip.v-chip--size-x-small .v-avatar--start{margin-inline-start:-5.6px;margin-inline-end:4px}.v-chip--pill.v-chip.v-chip--size-x-small .v-avatar--start{margin-inline-start:-8px}.v-chip.v-chip--size-x-small .v-avatar--end{margin-inline-start:4px;margin-inline-end:-5.6px}.v-chip--pill.v-chip.v-chip--size-x-small .v-avatar--end{margin-inline-end:-8px}.v-chip--pill.v-chip.v-chip--size-x-small .v-avatar--end+.v-chip__close{margin-inline-start:12px}.v-chip.v-chip--size-x-small .v-icon--start,.v-chip.v-chip--size-x-small .v-chip__filter{margin-inline-start:-4px;margin-inline-end:4px}.v-chip.v-chip--size-x-small .v-icon--end,.v-chip.v-chip--size-x-small .v-chip__close{margin-inline-start:4px;margin-inline-end:-4px}.v-chip.v-chip--size-x-small .v-icon--end+.v-chip__close,.v-chip.v-chip--size-x-small .v-avatar--end+.v-chip__close,.v-chip.v-chip--size-x-small .v-chip__append+.v-chip__close{margin-inline-start:8px}.v-chip.v-chip--size-small{--v-chip-size: .75rem;--v-chip-height: 26px;font-size:.75rem;padding:0 10px}.v-chip.v-chip--size-small .v-avatar{--v-avatar-height: 20px}.v-chip--pill.v-chip.v-chip--size-small .v-avatar{--v-avatar-height: 26px}.v-chip.v-chip--size-small .v-avatar--start{margin-inline-start:-7px;margin-inline-end:5px}.v-chip--pill.v-chip.v-chip--size-small .v-avatar--start{margin-inline-start:-10px}.v-chip.v-chip--size-small .v-avatar--end{margin-inline-start:5px;margin-inline-end:-7px}.v-chip--pill.v-chip.v-chip--size-small .v-avatar--end{margin-inline-end:-10px}.v-chip--pill.v-chip.v-chip--size-small .v-avatar--end+.v-chip__close{margin-inline-start:15px}.v-chip.v-chip--size-small .v-icon--start,.v-chip.v-chip--size-small .v-chip__filter{margin-inline-start:-5px;margin-inline-end:5px}.v-chip.v-chip--size-small .v-icon--end,.v-chip.v-chip--size-small .v-chip__close{margin-inline-start:5px;margin-inline-end:-5px}.v-chip.v-chip--size-small .v-icon--end+.v-chip__close,.v-chip.v-chip--size-small .v-avatar--end+.v-chip__close,.v-chip.v-chip--size-small .v-chip__append+.v-chip__close{margin-inline-start:10px}.v-chip.v-chip--size-default{--v-chip-size: .875rem;--v-chip-height: 32px;font-size:.875rem;padding:0 12px}.v-chip.v-chip--size-default .v-avatar{--v-avatar-height: 26px}.v-chip--pill.v-chip.v-chip--size-default .v-avatar{--v-avatar-height: 32px}.v-chip.v-chip--size-default .v-avatar--start{margin-inline-start:-8.4px;margin-inline-end:6px}.v-chip--pill.v-chip.v-chip--size-default .v-avatar--start{margin-inline-start:-12px}.v-chip.v-chip--size-default .v-avatar--end{margin-inline-start:6px;margin-inline-end:-8.4px}.v-chip--pill.v-chip.v-chip--size-default .v-avatar--end{margin-inline-end:-12px}.v-chip--pill.v-chip.v-chip--size-default .v-avatar--end+.v-chip__close{margin-inline-start:18px}.v-chip.v-chip--size-default .v-icon--start,.v-chip.v-chip--size-default .v-chip__filter{margin-inline-start:-6px;margin-inline-end:6px}.v-chip.v-chip--size-default .v-icon--end,.v-chip.v-chip--size-default .v-chip__close{margin-inline-start:6px;margin-inline-end:-6px}.v-chip.v-chip--size-default .v-icon--end+.v-chip__close,.v-chip.v-chip--size-default .v-avatar--end+.v-chip__close,.v-chip.v-chip--size-default .v-chip__append+.v-chip__close{margin-inline-start:12px}.v-chip.v-chip--size-large{--v-chip-size: 1rem;--v-chip-height: 38px;font-size:1rem;padding:0 14px}.v-chip.v-chip--size-large .v-avatar{--v-avatar-height: 32px}.v-chip--pill.v-chip.v-chip--size-large .v-avatar{--v-avatar-height: 38px}.v-chip.v-chip--size-large .v-avatar--start{margin-inline-start:-9.8px;margin-inline-end:7px}.v-chip--pill.v-chip.v-chip--size-large .v-avatar--start{margin-inline-start:-14px}.v-chip.v-chip--size-large .v-avatar--end{margin-inline-start:7px;margin-inline-end:-9.8px}.v-chip--pill.v-chip.v-chip--size-large .v-avatar--end{margin-inline-end:-14px}.v-chip--pill.v-chip.v-chip--size-large .v-avatar--end+.v-chip__close{margin-inline-start:21px}.v-chip.v-chip--size-large .v-icon--start,.v-chip.v-chip--size-large .v-chip__filter{margin-inline-start:-7px;margin-inline-end:7px}.v-chip.v-chip--size-large .v-icon--end,.v-chip.v-chip--size-large .v-chip__close{margin-inline-start:7px;margin-inline-end:-7px}.v-chip.v-chip--size-large .v-icon--end+.v-chip__close,.v-chip.v-chip--size-large .v-avatar--end+.v-chip__close,.v-chip.v-chip--size-large .v-chip__append+.v-chip__close{margin-inline-start:14px}.v-chip.v-chip--size-x-large{--v-chip-size: 1.125rem;--v-chip-height: 44px;font-size:1.125rem;padding:0 17px}.v-chip.v-chip--size-x-large .v-avatar{--v-avatar-height: 38px}.v-chip--pill.v-chip.v-chip--size-x-large .v-avatar{--v-avatar-height: 44px}.v-chip.v-chip--size-x-large .v-avatar--start{margin-inline-start:-11.9px;margin-inline-end:8.5px}.v-chip--pill.v-chip.v-chip--size-x-large .v-avatar--start{margin-inline-start:-17px}.v-chip.v-chip--size-x-large .v-avatar--end{margin-inline-start:8.5px;margin-inline-end:-11.9px}.v-chip--pill.v-chip.v-chip--size-x-large .v-avatar--end{margin-inline-end:-17px}.v-chip--pill.v-chip.v-chip--size-x-large .v-avatar--end+.v-chip__close{margin-inline-start:25.5px}.v-chip.v-chip--size-x-large .v-icon--start,.v-chip.v-chip--size-x-large .v-chip__filter{margin-inline-start:-8.5px;margin-inline-end:8.5px}.v-chip.v-chip--size-x-large .v-icon--end,.v-chip.v-chip--size-x-large .v-chip__close{margin-inline-start:8.5px;margin-inline-end:-8.5px}.v-chip.v-chip--size-x-large .v-icon--end+.v-chip__close,.v-chip.v-chip--size-x-large .v-avatar--end+.v-chip__close,.v-chip.v-chip--size-x-large .v-chip__append+.v-chip__close{margin-inline-start:17px}.v-chip.v-chip--density-default{height:calc(var(--v-chip-height) + 0px)}.v-chip.v-chip--density-comfortable{height:calc(var(--v-chip-height) + -4px)}.v-chip.v-chip--density-compact{height:calc(var(--v-chip-height) + -8px)}.v-chip:hover>.v-chip__overlay{opacity:calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier))}.v-chip:focus-visible>.v-chip__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-chip:focus>.v-chip__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}}.v-chip--active>.v-chip__overlay,.v-chip[aria-haspopup=menu][aria-expanded=true]>.v-chip__overlay{opacity:calc(var(--v-activated-opacity) * var(--v-theme-overlay-multiplier))}.v-chip--active:hover>.v-chip__overlay,.v-chip[aria-haspopup=menu][aria-expanded=true]:hover>.v-chip__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}.v-chip--active:focus-visible>.v-chip__overlay,.v-chip[aria-haspopup=menu][aria-expanded=true]:focus-visible>.v-chip__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-chip--active:focus>.v-chip__overlay,.v-chip[aria-haspopup=menu][aria-expanded=true]:focus>.v-chip__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}}.v-chip--variant-plain,.v-chip--variant-outlined,.v-chip--variant-text,.v-chip--variant-tonal{background:transparent;color:inherit}.v-chip--variant-plain{opacity:.26}.v-chip--variant-plain:focus,.v-chip--variant-plain:hover{opacity:1}.v-chip--variant-plain .v-chip__overlay{display:none}.v-chip--variant-elevated,.v-chip--variant-flat{background:rgb(var(--v-theme-surface-variant));color:rgb(var(--v-theme-on-surface-variant))}.v-chip--variant-elevated{box-shadow:0 2px 1px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 1px 1px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 3px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-chip--variant-flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-chip--variant-outlined{border:thin solid currentColor}.v-chip--variant-text .v-chip__overlay{background:currentColor}.v-chip--variant-tonal .v-chip__underlay{background:currentColor;opacity:var(--v-activated-opacity);border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.v-chip--border{border-width:thin}.v-chip--link{cursor:pointer}.v-chip--filter{-webkit-user-select:none;user-select:none}.v-chip__content{align-items:center;display:inline-flex}.v-autocomplete__selection .v-chip__content,.v-combobox__selection .v-chip__content,.v-select__selection .v-chip__content{overflow:hidden}.v-chip__filter,.v-chip__prepend,.v-chip__append,.v-chip__close{align-items:center;display:inline-flex}.v-chip__close{cursor:pointer;flex:0 1 auto;font-size:18px;max-height:18px;max-width:18px;-webkit-user-select:none;user-select:none}.v-chip__close .v-icon{font-size:inherit}.v-chip__filter{transition:.15s cubic-bezier(.4,0,.2,1)}.v-chip__overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:currentColor;border-radius:inherit;pointer-events:none;opacity:0;transition:opacity .2s ease-in-out}.v-chip--disabled{opacity:.3;pointer-events:none;-webkit-user-select:none;user-select:none}.v-chip--label{border-radius:4px}.v-chip-group{display:flex;max-width:100%;min-width:0;overflow-x:auto;padding:4px 0}.v-chip-group .v-chip{margin:4px 8px 4px 0}.v-chip-group .v-chip.v-chip--selected:not(.v-chip--disabled) .v-chip__overlay{opacity:var(--v-activated-opacity)}.v-chip-group--column .v-slide-group__content{white-space:normal;flex-wrap:wrap;max-width:100%}.v-slide-group{display:flex;overflow:hidden}.v-slide-group__next,.v-slide-group__prev{align-items:center;display:flex;flex:0 1 52px;justify-content:center;min-width:52px;cursor:pointer}.v-slide-group__next--disabled,.v-slide-group__prev--disabled{pointer-events:none;opacity:var(--v-disabled-opacity)}.v-slide-group__content{display:flex;flex:1 0 auto;position:relative;transition:.2s all cubic-bezier(.4,0,.2,1);white-space:nowrap}.v-slide-group__content>*{white-space:initial}.v-slide-group__container{contain:content;display:flex;flex:1 1 auto;overflow:hidden}.v-slide-group--vertical,.v-slide-group--vertical .v-slide-group__container,.v-slide-group--vertical .v-slide-group__content{flex-direction:column}.v-list{overflow:auto;padding:8px 0;position:relative;outline:none;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:0;background:rgba(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-list--border{border-width:thin;box-shadow:none}.v-list--disabled{pointer-events:none;-webkit-user-select:none;user-select:none}.v-list--nav{padding-inline:8px}.v-list--rounded{border-radius:4px}.v-list--subheader{padding-top:0}.v-list-img{border-radius:inherit;display:flex;height:100%;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:-1}.v-list-subheader{align-items:center;background:inherit;color:rgba(var(--v-theme-on-surface),var(--v-medium-emphasis-opacity));display:flex;font-size:.875rem;font-weight:400;line-height:1.375rem;padding-inline-end:16px;min-height:40px;transition:.2s min-height cubic-bezier(.4,0,.2,1)}.v-list-subheader__text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.v-list--density-default .v-list-subheader{min-height:40px;padding-inline-start:calc(16px + var(--indent-padding))!important}.v-list--density-comfortable .v-list-subheader{min-height:36px;padding-inline-start:calc(16px + var(--indent-padding))!important}.v-list--density-compact .v-list-subheader{min-height:32px;padding-inline-start:calc(16px + var(--indent-padding))!important}.v-list-subheader--inset{--indent-padding: 56px}.v-list--nav .v-list-subheader{font-size:.75rem}.v-list-subheader--sticky{background:inherit;left:0;position:sticky;top:0;z-index:1}.v-list__overlay{background-color:currentColor;border-radius:inherit;bottom:0;left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;transition:opacity .2s ease-in-out}.v-list-item{align-items:center;display:grid;flex:none;grid-template-areas:"prepend content append";grid-template-columns:max-content 1fr auto;outline:none;max-width:100%;padding:4px 16px;position:relative;text-decoration:none;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;border-radius:0}.v-list-item--border{border-width:thin;box-shadow:none}.v-list-item:hover>.v-list-item__overlay{opacity:calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier))}.v-list-item:focus-visible>.v-list-item__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-list-item:focus>.v-list-item__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}}.v-list-item--active>.v-list-item__overlay,.v-list-item[aria-haspopup=menu][aria-expanded=true]>.v-list-item__overlay{opacity:calc(var(--v-activated-opacity) * var(--v-theme-overlay-multiplier))}.v-list-item--active:hover>.v-list-item__overlay,.v-list-item[aria-haspopup=menu][aria-expanded=true]:hover>.v-list-item__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}.v-list-item--active:focus-visible>.v-list-item__overlay,.v-list-item[aria-haspopup=menu][aria-expanded=true]:focus-visible>.v-list-item__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-list-item--active:focus>.v-list-item__overlay,.v-list-item[aria-haspopup=menu][aria-expanded=true]:focus>.v-list-item__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}}.v-list-item--variant-plain,.v-list-item--variant-outlined,.v-list-item--variant-text,.v-list-item--variant-tonal{background:transparent;color:inherit}.v-list-item--variant-plain{opacity:.62}.v-list-item--variant-plain:focus,.v-list-item--variant-plain:hover{opacity:1}.v-list-item--variant-plain .v-list-item__overlay{display:none}.v-list-item--variant-elevated,.v-list-item--variant-flat{background:rgba(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-list-item--variant-elevated{box-shadow:0 2px 1px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 1px 1px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 3px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-list-item--variant-flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-list-item--variant-outlined{border:thin solid currentColor}.v-list-item--variant-text .v-list-item__overlay{background:currentColor}.v-list-item--variant-tonal .v-list-item__underlay{background:currentColor;opacity:var(--v-activated-opacity);border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}@supports selector(:focus-visible){.v-list-item:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;border:2px solid currentColor;border-radius:4px;opacity:0;transition:opacity .2s ease-in-out}.v-list-item:focus-visible:after{opacity:calc(.15 * var(--v-theme-overlay-multiplier))}}.v-list-item__prepend>.v-badge .v-icon,.v-list-item__prepend>.v-icon,.v-list-item__append>.v-badge .v-icon,.v-list-item__append>.v-icon{opacity:var(--v-medium-emphasis-opacity)}.v-list-item--active .v-list-item__prepend>.v-badge .v-icon,.v-list-item--active .v-list-item__prepend>.v-icon,.v-list-item--active .v-list-item__append>.v-badge .v-icon,.v-list-item--active .v-list-item__append>.v-icon{opacity:1}.v-list-item--active:not(.v-list-item--link) .v-list-item__overlay{opacity:calc(var(--v-activated-opacity) * var(--v-theme-overlay-multiplier))}.v-list-item--rounded{border-radius:4px}.v-list-item--disabled{pointer-events:none;-webkit-user-select:none;user-select:none;opacity:.6}.v-list-item--link{cursor:pointer}.v-navigation-drawer--rail:not(.v-navigation-drawer--expand-on-hover) .v-list-item .v-avatar,.v-navigation-drawer--rail.v-navigation-drawer--expand-on-hover:not(.v-navigation-drawer--is-hovering) .v-list-item .v-avatar{--v-avatar-height: 24px}.v-list-item__prepend{align-items:center;align-self:center;display:flex;grid-area:prepend}.v-list-item__prepend>.v-badge~.v-list-item__spacer,.v-list-item__prepend>.v-icon~.v-list-item__spacer,.v-list-item__prepend>.v-tooltip~.v-list-item__spacer{width:32px}.v-list-item__prepend>.v-avatar~.v-list-item__spacer{width:16px}.v-list-item__prepend>.v-list-item-action~.v-list-item__spacer{width:16px}.v-list-item--slim .v-list-item__prepend>.v-badge~.v-list-item__spacer,.v-list-item--slim .v-list-item__prepend>.v-icon~.v-list-item__spacer,.v-list-item--slim .v-list-item__prepend>.v-tooltip~.v-list-item__spacer{width:20px}.v-list-item--slim .v-list-item__prepend>.v-avatar~.v-list-item__spacer{width:4px}.v-list-item--slim .v-list-item__prepend>.v-list-item-action~.v-list-item__spacer{width:4px}.v-list-item--three-line .v-list-item__prepend{align-self:start}.v-list-item__append{align-self:center;display:flex;align-items:center;grid-area:append}.v-list-item__append .v-list-item__spacer{order:-1;transition:.15s width cubic-bezier(.4,0,.2,1)}.v-list-item__append>.v-badge~.v-list-item__spacer,.v-list-item__append>.v-icon~.v-list-item__spacer,.v-list-item__append>.v-tooltip~.v-list-item__spacer{width:32px}.v-list-item__append>.v-avatar~.v-list-item__spacer{width:16px}.v-list-item__append>.v-list-item-action~.v-list-item__spacer{width:16px}.v-list-item--slim .v-list-item__append>.v-badge~.v-list-item__spacer,.v-list-item--slim .v-list-item__append>.v-icon~.v-list-item__spacer,.v-list-item--slim .v-list-item__append>.v-tooltip~.v-list-item__spacer{width:20px}.v-list-item--slim .v-list-item__append>.v-avatar~.v-list-item__spacer{width:4px}.v-list-item--slim .v-list-item__append>.v-list-item-action~.v-list-item__spacer{width:4px}.v-list-item--three-line .v-list-item__append{align-self:start}.v-list-item__content{align-self:center;grid-area:content;overflow:hidden}.v-list-item-action{align-self:center;display:flex;align-items:center;flex:none;transition:inherit;transition-property:height,width}.v-list-item-action--start{margin-inline-end:8px;margin-inline-start:-8px}.v-list-item-action--end{margin-inline-start:8px;margin-inline-end:-8px}.v-list-item-media{margin-top:0;margin-bottom:0}.v-list-item-media--start{margin-inline-end:16px}.v-list-item-media--end{margin-inline-start:16px}.v-list-item--two-line .v-list-item-media{margin-top:-4px;margin-bottom:-4px}.v-list-item--three-line .v-list-item-media{margin-top:0;margin-bottom:0}.v-list-item-subtitle{-webkit-box-orient:vertical;display:-webkit-box;opacity:var(--v-medium-emphasis-opacity);overflow:hidden;padding:0;text-overflow:ellipsis;overflow-wrap:break-word;word-break:initial;font-size:.875rem;font-weight:400;letter-spacing:.0178571429em;line-height:1rem;text-transform:none}.v-list-item--one-line .v-list-item-subtitle{-webkit-line-clamp:1}.v-list-item--two-line .v-list-item-subtitle{-webkit-line-clamp:2}.v-list-item--three-line .v-list-item-subtitle{-webkit-line-clamp:3}.v-list-item--nav .v-list-item-subtitle{font-size:.75rem;font-weight:400;letter-spacing:.0178571429em;line-height:1rem}.v-list-item-title{-webkit-hyphens:auto;hyphens:auto;overflow-wrap:normal;overflow:hidden;padding:0;white-space:nowrap;text-overflow:ellipsis;word-break:normal;word-wrap:break-word;font-size:1rem;font-weight:400;letter-spacing:.009375em;line-height:1.5rem;text-transform:none}.v-list-item--nav .v-list-item-title{font-size:.8125rem;font-weight:500;letter-spacing:normal;line-height:1rem}.v-list-item--density-default{min-height:40px}.v-list-item--density-default.v-list-item--one-line{min-height:48px;padding-top:4px;padding-bottom:4px}.v-list-item--density-default.v-list-item--two-line{min-height:64px;padding-top:12px;padding-bottom:12px}.v-list-item--density-default.v-list-item--three-line{min-height:88px;padding-top:16px;padding-bottom:16px}.v-list-item--density-default.v-list-item--three-line .v-list-item__prepend,.v-list-item--density-default.v-list-item--three-line .v-list-item__append{padding-top:8px}.v-list-item--density-default:not(.v-list-item--nav).v-list-item--one-line{padding-inline:16px}.v-list-item--density-default:not(.v-list-item--nav).v-list-item--two-line{padding-inline:16px}.v-list-item--density-default:not(.v-list-item--nav).v-list-item--three-line{padding-inline:16px}.v-list-item--density-comfortable{min-height:36px}.v-list-item--density-comfortable.v-list-item--one-line{min-height:44px}.v-list-item--density-comfortable.v-list-item--two-line{min-height:60px;padding-top:8px;padding-bottom:8px}.v-list-item--density-comfortable.v-list-item--three-line{min-height:84px;padding-top:12px;padding-bottom:12px}.v-list-item--density-comfortable.v-list-item--three-line .v-list-item__prepend,.v-list-item--density-comfortable.v-list-item--three-line .v-list-item__append{padding-top:6px}.v-list-item--density-comfortable:not(.v-list-item--nav).v-list-item--one-line{padding-inline:16px}.v-list-item--density-comfortable:not(.v-list-item--nav).v-list-item--two-line{padding-inline:16px}.v-list-item--density-comfortable:not(.v-list-item--nav).v-list-item--three-line{padding-inline:16px}.v-list-item--density-compact{min-height:32px}.v-list-item--density-compact.v-list-item--one-line{min-height:40px}.v-list-item--density-compact.v-list-item--two-line{min-height:56px;padding-top:4px;padding-bottom:4px}.v-list-item--density-compact.v-list-item--three-line{min-height:80px;padding-top:8px;padding-bottom:8px}.v-list-item--density-compact.v-list-item--three-line .v-list-item__prepend,.v-list-item--density-compact.v-list-item--three-line .v-list-item__append{padding-top:4px}.v-list-item--density-compact:not(.v-list-item--nav).v-list-item--one-line{padding-inline:16px}.v-list-item--density-compact:not(.v-list-item--nav).v-list-item--two-line{padding-inline:16px}.v-list-item--density-compact:not(.v-list-item--nav).v-list-item--three-line{padding-inline:16px}.v-list-item--nav{padding-inline:8px}.v-list .v-list-item--nav:not(:only-child){margin-bottom:4px}.v-list-item__underlay{position:absolute}.v-list-item__overlay{background-color:currentColor;border-radius:inherit;bottom:0;left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;transition:opacity .2s ease-in-out}.v-list-item--active.v-list-item--variant-elevated .v-list-item__overlay{--v-theme-overlay-multiplier: 0}.v-list{--indent-padding: 0px}.v-list--nav{--indent-padding: -8px}.v-list-group{--list-indent-size: 16px;--parent-padding: var(--indent-padding);--prepend-width: 40px}.v-list--slim .v-list-group{--prepend-width: 28px}.v-list-group--fluid{--list-indent-size: 0px}.v-list-group--prepend{--parent-padding: calc(var(--indent-padding) + var(--prepend-width))}.v-list-group--fluid.v-list-group--prepend{--parent-padding: var(--indent-padding)}.v-list-group__items{--indent-padding: calc(var(--parent-padding) + var(--list-indent-size))}.v-list-group__items .v-list-item{padding-inline-start:calc(16px + var(--indent-padding))!important}.v-list-group__header.v-list-item--active:not(:focus-visible) .v-list-item__overlay{opacity:0}.v-list-group__header.v-list-item--active:hover .v-list-item__overlay{opacity:calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier))}.v-divider{display:block;flex:1 1 100%;height:0px;max-height:0px;opacity:var(--v-border-opacity);transition:inherit;border-style:solid;border-width:thin 0 0 0}.v-divider--vertical{align-self:stretch;border-width:0 thin 0 0;display:inline-flex;height:100%;margin-left:-1px;max-height:100%;max-width:0px;vertical-align:text-bottom;width:0px}.v-divider--inset:not(.v-divider--vertical){max-width:calc(100% - 72px);margin-inline-start:72px}.v-divider--inset.v-divider--vertical{margin-bottom:8px;margin-top:8px;max-height:calc(100% - 16px)}.v-menu>.v-overlay__content{display:flex;flex-direction:column;border-radius:4px}.v-menu>.v-overlay__content>.v-card,.v-menu>.v-overlay__content>.v-sheet,.v-menu>.v-overlay__content>.v-list{background:rgb(var(--v-theme-surface));border-radius:inherit;overflow:auto;height:100%;box-shadow:0 5px 5px -3px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 8px 10px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 3px 14px 2px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-overlay-container{contain:layout;left:0;pointer-events:none;position:absolute;top:0;display:contents}.v-overlay-scroll-blocked{padding-inline-end:var(--v-scrollbar-offset)}.v-overlay-scroll-blocked:not(html){overflow-y:hidden!important}html.v-overlay-scroll-blocked{position:fixed;top:var(--v-body-scroll-y);left:var(--v-body-scroll-x);width:100%;height:100%}.v-overlay{border-radius:inherit;display:flex;left:0;pointer-events:none;position:fixed;top:0;bottom:0;right:0}.v-overlay__content{outline:none;position:absolute;pointer-events:auto;contain:layout}.v-overlay__scrim{pointer-events:auto;background:rgb(var(--v-theme-on-surface));border-radius:inherit;bottom:0;left:0;opacity:var(--v-overlay-opacity, .32);position:fixed;right:0;top:0}.v-overlay--absolute,.v-overlay--contained .v-overlay__scrim{position:absolute}.v-overlay--scroll-blocked{padding-inline-end:var(--v-scrollbar-offset)}.v-select .v-field .v-text-field__prefix,.v-select .v-field .v-text-field__suffix,.v-select .v-field .v-field__input,.v-select .v-field.v-field{cursor:pointer}.v-select .v-field .v-field__input>input{align-self:flex-start;opacity:1;flex:0 0;position:absolute;width:100%;transition:none;pointer-events:none;caret-color:transparent}.v-select .v-field--dirty .v-select__selection{margin-inline-end:2px}.v-select .v-select__selection-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.v-select__content{overflow:hidden;box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:4px}.v-select__selection{display:inline-flex;align-items:center;letter-spacing:inherit;line-height:inherit;max-width:100%}.v-select .v-select__selection:first-child{margin-inline-start:0}.v-select--selected .v-field .v-field__input>input{opacity:0}.v-select__menu-icon{margin-inline-start:4px;transition:.2s cubic-bezier(.4,0,.2,1)}.v-select--active-menu .v-select__menu-icon{opacity:var(--v-high-emphasis-opacity);transform:rotate(180deg)}.v-text-field input{color:inherit;opacity:0;flex:1;transition:.15s opacity cubic-bezier(.4,0,.2,1);min-width:0}.v-text-field input:focus,.v-text-field input:active{outline:none}.v-text-field input:invalid{box-shadow:none}.v-text-field .v-field{cursor:text}.v-text-field--prefixed.v-text-field .v-field__input{--v-field-padding-start: 6px}.v-text-field--suffixed.v-text-field .v-field__input{--v-field-padding-end: 0}.v-text-field .v-input__details{padding-inline:16px}.v-input--plain-underlined.v-text-field .v-input__details{padding-inline:0}.v-text-field .v-field--no-label input,.v-text-field .v-field--active input{opacity:1}.v-text-field .v-field--single-line input{transition:none}.v-text-field__prefix,.v-text-field__suffix{align-items:center;color:rgba(var(--v-theme-on-surface),var(--v-medium-emphasis-opacity));cursor:default;display:flex;opacity:0;transition:inherit;white-space:nowrap;min-height:max(var(--v-input-control-height, 56px),1.5rem + var(--v-field-input-padding-top) + var(--v-field-input-padding-bottom));padding-top:calc(var(--v-field-padding-top, 4px) + var(--v-input-padding-top, 0));padding-bottom:var(--v-field-padding-bottom, 6px)}.v-field--active .v-text-field__prefix,.v-field--active .v-text-field__suffix{opacity:1}.v-field--disabled .v-text-field__prefix,.v-field--disabled .v-text-field__suffix{color:rgba(var(--v-theme-on-surface),var(--v-disabled-opacity))}.v-text-field__prefix{padding-inline-start:var(--v-field-padding-start)}.v-text-field__suffix{padding-inline-end:var(--v-field-padding-end)}.v-counter{color:rgba(var(--v-theme-on-surface),var(--v-medium-emphasis-opacity));flex:0 1 auto;font-size:12px;transition-duration:.15s}.v-field{display:grid;grid-template-areas:"prepend-inner field clear append-inner";grid-template-columns:min-content minmax(0,1fr) min-content min-content;font-size:16px;letter-spacing:.009375em;max-width:100%;border-radius:4px;contain:layout;flex:1 0;grid-area:control;position:relative;--v-field-padding-start: 16px;--v-field-padding-end: 16px;--v-field-padding-top: 8px;--v-field-padding-bottom: 4px;--v-field-input-padding-top: calc(var(--v-field-padding-top, 8px) + var(--v-input-padding-top, 0));--v-field-input-padding-bottom: var(--v-field-padding-bottom, 4px)}.v-field--disabled{opacity:var(--v-disabled-opacity);pointer-events:none}.v-field .v-chip{--v-chip-height: 24px}.v-field--prepended{padding-inline-start:12px}.v-field--appended{padding-inline-end:12px}.v-field--variant-solo,.v-field--variant-solo-filled,.v-field--variant-solo-inverted{background:rgb(var(--v-theme-surface));border-color:transparent;color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity));box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-field--variant-solo-inverted.v-field--focused{color:rgb(var(--v-theme-on-surface-variant))}.v-field--variant-filled{border-bottom-left-radius:0;border-bottom-right-radius:0}.v-input--density-default .v-field--variant-solo,.v-input--density-default .v-field--variant-solo-inverted,.v-input--density-default .v-field--variant-solo-filled,.v-input--density-default .v-field--variant-filled{--v-input-control-height: 56px;--v-field-padding-bottom: 4px}.v-input--density-comfortable .v-field--variant-solo,.v-input--density-comfortable .v-field--variant-solo-inverted,.v-input--density-comfortable .v-field--variant-solo-filled,.v-input--density-comfortable .v-field--variant-filled{--v-input-control-height: 48px;--v-field-padding-bottom: 0px}.v-input--density-compact .v-field--variant-solo,.v-input--density-compact .v-field--variant-solo-inverted,.v-input--density-compact .v-field--variant-solo-filled,.v-input--density-compact .v-field--variant-filled{--v-input-control-height: 40px;--v-field-padding-bottom: 0px}.v-field--variant-outlined,.v-field--single-line,.v-field--no-label{--v-field-padding-top: 0px}.v-input--density-default .v-field--variant-outlined,.v-input--density-default .v-field--single-line,.v-input--density-default .v-field--no-label{--v-field-padding-bottom: 16px}.v-input--density-comfortable .v-field--variant-outlined,.v-input--density-comfortable .v-field--single-line,.v-input--density-comfortable .v-field--no-label{--v-field-padding-bottom: 12px}.v-input--density-compact .v-field--variant-outlined,.v-input--density-compact .v-field--single-line,.v-input--density-compact .v-field--no-label{--v-field-padding-bottom: 8px}.v-field--variant-plain,.v-field--variant-underlined{border-radius:0;padding:0}.v-field--variant-plain.v-field,.v-field--variant-underlined.v-field{--v-field-padding-start: 0px;--v-field-padding-end: 0px}.v-input--density-default .v-field--variant-plain,.v-input--density-default .v-field--variant-underlined{--v-input-control-height: 48px;--v-field-padding-top: 4px;--v-field-padding-bottom: 4px}.v-input--density-comfortable .v-field--variant-plain,.v-input--density-comfortable .v-field--variant-underlined{--v-input-control-height: 40px;--v-field-padding-top: 2px;--v-field-padding-bottom: 0px}.v-input--density-compact .v-field--variant-plain,.v-input--density-compact .v-field--variant-underlined{--v-input-control-height: 32px;--v-field-padding-top: 0px;--v-field-padding-bottom: 0px}.v-field--flat{box-shadow:none}.v-field--rounded{border-radius:24px}.v-field.v-field--prepended{--v-field-padding-start: 6px}.v-field.v-field--appended{--v-field-padding-end: 6px}.v-field__input{align-items:center;color:inherit;column-gap:2px;display:flex;flex-wrap:wrap;letter-spacing:.009375em;opacity:var(--v-high-emphasis-opacity);min-height:max(var(--v-input-control-height, 56px),1.5rem + var(--v-field-input-padding-top) + var(--v-field-input-padding-bottom));min-width:0;padding-inline:var(--v-field-padding-start) var(--v-field-padding-end);padding-top:var(--v-field-input-padding-top);padding-bottom:var(--v-field-input-padding-bottom);position:relative;width:100%}.v-input--density-default .v-field__input{row-gap:8px}.v-input--density-comfortable .v-field__input{row-gap:6px}.v-input--density-compact .v-field__input{row-gap:4px}.v-field__input input{letter-spacing:inherit}.v-field__input input::placeholder,input.v-field__input::placeholder,textarea.v-field__input::placeholder{color:currentColor;opacity:var(--v-disabled-opacity)}.v-field__input:focus,.v-field__input:active{outline:none}.v-field__input:invalid{box-shadow:none}.v-field__field{flex:1 0;grid-area:field;position:relative;align-items:flex-start;display:flex}.v-field__prepend-inner{grid-area:prepend-inner;padding-inline-end:var(--v-field-padding-after)}.v-field__clearable{grid-area:clear}.v-field__append-inner{grid-area:append-inner;padding-inline-start:var(--v-field-padding-after)}.v-field__append-inner,.v-field__clearable,.v-field__prepend-inner{display:flex;align-items:flex-start;padding-top:var(--v-input-padding-top, 8px)}.v-field--center-affix .v-field__append-inner,.v-field--center-affix .v-field__clearable,.v-field--center-affix .v-field__prepend-inner{align-items:center;padding-top:0}.v-field.v-field--variant-underlined .v-field__append-inner,.v-field.v-field--variant-underlined .v-field__clearable,.v-field.v-field--variant-underlined .v-field__prepend-inner,.v-field.v-field--variant-plain .v-field__append-inner,.v-field.v-field--variant-plain .v-field__clearable,.v-field.v-field--variant-plain .v-field__prepend-inner{align-items:flex-start;padding-top:calc(var(--v-field-padding-top, 8px) + var(--v-input-padding-top, 0));padding-bottom:var(--v-field-padding-bottom, 4px)}.v-field--focused .v-field__prepend-inner,.v-field--focused .v-field__append-inner{opacity:1}.v-field__prepend-inner>.v-icon,.v-field__append-inner>.v-icon,.v-field__clearable>.v-icon{opacity:var(--v-medium-emphasis-opacity)}.v-field--disabled .v-field__prepend-inner>.v-icon,.v-field--error .v-field__prepend-inner>.v-icon,.v-field--disabled .v-field__append-inner>.v-icon,.v-field--error .v-field__append-inner>.v-icon,.v-field--disabled .v-field__clearable>.v-icon,.v-field--error .v-field__clearable>.v-icon{opacity:1}.v-field--error:not(.v-field--disabled) .v-field__prepend-inner>.v-icon,.v-field--error:not(.v-field--disabled) .v-field__append-inner>.v-icon,.v-field--error:not(.v-field--disabled) .v-field__clearable>.v-icon{color:rgb(var(--v-theme-error))}.v-field__clearable{cursor:pointer;opacity:0;overflow:hidden;margin-inline:4px;transition:.15s cubic-bezier(.4,0,.2,1);transition-property:opacity,transform,width}.v-field--focused .v-field__clearable,.v-field--persistent-clear .v-field__clearable{opacity:1}@media (hover: hover){.v-field:hover .v-field__clearable{opacity:1}}@media (hover: none){.v-field__clearable{opacity:1}}.v-label.v-field-label{contain:layout paint;display:block;margin-inline-start:var(--v-field-padding-start);margin-inline-end:var(--v-field-padding-end);max-width:calc(100% - var(--v-field-padding-start) - var(--v-field-padding-end));pointer-events:none;position:absolute;top:var(--v-input-padding-top);transform-origin:left center;transition:.15s cubic-bezier(.4,0,.2,1);transition-property:opacity,transform;z-index:1}.v-field--variant-underlined .v-label.v-field-label,.v-field--variant-plain .v-label.v-field-label{top:calc(var(--v-input-padding-top) + var(--v-field-padding-top))}.v-field--center-affix .v-label.v-field-label{top:50%;transform:translateY(-50%)}.v-field--active .v-label.v-field-label{visibility:hidden}.v-field--focused .v-label.v-field-label,.v-field--error .v-label.v-field-label{opacity:1}.v-field--error:not(.v-field--disabled) .v-label.v-field-label{color:rgb(var(--v-theme-error))}.v-label.v-field-label--floating{--v-field-label-scale: .75em;font-size:var(--v-field-label-scale);visibility:hidden;max-width:100%}.v-field--center-affix .v-label.v-field-label--floating{transform:none}.v-field.v-field--active .v-label.v-field-label--floating{visibility:unset}.v-input--density-default .v-field--variant-solo .v-label.v-field-label--floating,.v-input--density-default .v-field--variant-solo-inverted .v-label.v-field-label--floating,.v-input--density-default .v-field--variant-filled .v-label.v-field-label--floating,.v-input--density-default .v-field--variant-solo-filled .v-label.v-field-label--floating{top:7px}.v-input--density-comfortable .v-field--variant-solo .v-label.v-field-label--floating,.v-input--density-comfortable .v-field--variant-solo-inverted .v-label.v-field-label--floating,.v-input--density-comfortable .v-field--variant-filled .v-label.v-field-label--floating,.v-input--density-comfortable .v-field--variant-solo-filled .v-label.v-field-label--floating{top:5px}.v-input--density-compact .v-field--variant-solo .v-label.v-field-label--floating,.v-input--density-compact .v-field--variant-solo-inverted .v-label.v-field-label--floating,.v-input--density-compact .v-field--variant-filled .v-label.v-field-label--floating,.v-input--density-compact .v-field--variant-solo-filled .v-label.v-field-label--floating{top:3px}.v-field--variant-plain .v-label.v-field-label--floating,.v-field--variant-underlined .v-label.v-field-label--floating{transform:translateY(-16px);margin:0;top:var(--v-input-padding-top)}.v-field--variant-outlined .v-label.v-field-label--floating{transform:translateY(-50%);transform-origin:center;position:static;margin:0 4px}.v-field__outline{--v-field-border-width: 1px;--v-field-border-opacity: .38;align-items:stretch;contain:layout;display:flex;height:100%;left:0;pointer-events:none;position:absolute;right:0;width:100%}@media (hover: hover){.v-field:hover .v-field__outline{--v-field-border-opacity: var(--v-high-emphasis-opacity)}}.v-field--error:not(.v-field--disabled) .v-field__outline{color:rgb(var(--v-theme-error))}.v-field.v-field--focused .v-field__outline,.v-input.v-input--error .v-field__outline{--v-field-border-opacity: 1}.v-field--variant-outlined.v-field--focused .v-field__outline{--v-field-border-width: 2px}.v-field--variant-filled .v-field__outline:before,.v-field--variant-underlined .v-field__outline:before{border-color:currentColor;border-style:solid;border-width:0 0 var(--v-field-border-width);opacity:var(--v-field-border-opacity);transition:opacity .25s cubic-bezier(.4,0,.2,1);content:"";position:absolute;top:0;left:0;width:100%;height:100%}.v-field--variant-filled .v-field__outline:after,.v-field--variant-underlined .v-field__outline:after{border-color:currentColor;border-style:solid;border-width:0 0 2px;transform:scaleX(0);transition:transform .15s cubic-bezier(.4,0,.2,1);content:"";position:absolute;top:0;left:0;width:100%;height:100%}.v-field--focused.v-field--variant-filled .v-field__outline:after,.v-field--focused.v-field--variant-underlined .v-field__outline:after{transform:scaleX(1)}.v-field--variant-outlined .v-field__outline{border-radius:inherit}.v-field--variant-outlined .v-field__outline__start,.v-field--variant-outlined .v-field__outline__notch:before,.v-field--variant-outlined .v-field__outline__notch:after,.v-field--variant-outlined .v-field__outline__end{border:0 solid currentColor;opacity:var(--v-field-border-opacity);transition:opacity .25s cubic-bezier(.4,0,.2,1)}.v-field--variant-outlined .v-field__outline__start{flex:0 0 12px;border-top-width:var(--v-field-border-width);border-bottom-width:var(--v-field-border-width);border-inline-start-width:var(--v-field-border-width);border-start-start-radius:inherit;border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:inherit}.v-field--rounded.v-field--variant-outlined .v-field__outline__start,[class^=rounded-].v-field--variant-outlined .v-field__outline__start,[class*=" rounded-"].v-field--variant-outlined .v-field__outline__start{flex-basis:calc(var(--v-input-control-height) / 2 + 2px)}.v-field--reverse.v-field--variant-outlined .v-field__outline__start{border-start-start-radius:0;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:0;border-inline-end-width:var(--v-field-border-width);border-inline-start-width:0}.v-field--variant-outlined .v-field__outline__notch{flex:none;position:relative;max-width:calc(100% - 12px)}.v-field--variant-outlined .v-field__outline__notch:before,.v-field--variant-outlined .v-field__outline__notch:after{opacity:var(--v-field-border-opacity);transition:opacity .25s cubic-bezier(.4,0,.2,1);content:"";position:absolute;top:0;left:0;width:100%;height:100%}.v-field--variant-outlined .v-field__outline__notch:before{border-width:var(--v-field-border-width) 0 0}.v-field--variant-outlined .v-field__outline__notch:after{bottom:0;border-width:0 0 var(--v-field-border-width)}.v-field--active.v-field--variant-outlined .v-field__outline__notch:before{opacity:0}.v-field--variant-outlined .v-field__outline__end{flex:1;border-top-width:var(--v-field-border-width);border-bottom-width:var(--v-field-border-width);border-inline-end-width:var(--v-field-border-width);border-start-start-radius:0;border-start-end-radius:inherit;border-end-end-radius:inherit;border-end-start-radius:0}.v-field--reverse.v-field--variant-outlined .v-field__outline__end{border-start-start-radius:inherit;border-start-end-radius:0;border-end-end-radius:0;border-end-start-radius:inherit;border-inline-end-width:0;border-inline-start-width:var(--v-field-border-width)}.v-field__loader{top:calc(100% - 2px);left:0;position:absolute;right:0;width:100%;border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;overflow:hidden}.v-field--variant-outlined .v-field__loader{top:calc(100% - 3px);width:calc(100% - 2px);left:1px}.v-field__overlay{border-radius:inherit;pointer-events:none;position:absolute;top:0;left:0;width:100%;height:100%}.v-field--variant-filled .v-field__overlay{background-color:currentColor;opacity:.04;transition:opacity .25s cubic-bezier(.4,0,.2,1)}.v-field--variant-filled.v-field--has-background .v-field__overlay{opacity:0}@media (hover: hover){.v-field--variant-filled:hover .v-field__overlay{opacity:calc((.04 + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}}.v-field--variant-filled.v-field--focused .v-field__overlay{opacity:calc((.04 + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}.v-field--variant-solo-filled .v-field__overlay{background-color:currentColor;opacity:.04;transition:opacity .25s cubic-bezier(.4,0,.2,1)}@media (hover: hover){.v-field--variant-solo-filled:hover .v-field__overlay{opacity:calc((.04 + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}}.v-field--variant-solo-filled.v-field--focused .v-field__overlay{opacity:calc((.04 + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}.v-field--variant-solo-inverted .v-field__overlay{transition:opacity .25s cubic-bezier(.4,0,.2,1)}.v-field--variant-solo-inverted.v-field--has-background .v-field__overlay{opacity:0}@media (hover: hover){.v-field--variant-solo-inverted:hover .v-field__overlay{opacity:calc((.04 + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}}.v-field--variant-solo-inverted.v-field--focused .v-field__overlay{background-color:rgb(var(--v-theme-surface-variant));opacity:1}.v-field--reverse .v-field__field,.v-field--reverse .v-field__input,.v-field--reverse .v-field__outline{flex-direction:row-reverse}.v-field--reverse .v-field__input,.v-field--reverse input{text-align:end}.v-input--disabled .v-field--variant-filled .v-field__outline:before,.v-input--disabled .v-field--variant-underlined .v-field__outline:before{border-image:repeating-linear-gradient(to right,rgba(var(--v-theme-on-surface),var(--v-disabled-opacity)) 0px,rgba(var(--v-theme-on-surface),var(--v-disabled-opacity)) 2px,transparent 2px,transparent 4px) 1 repeat}.v-field--loading .v-field__outline:after,.v-field--loading .v-field__outline:before{opacity:0}.v-virtual-scroll{display:block;flex:1 1 auto;max-width:100%;overflow:auto;position:relative}.v-virtual-scroll__container{display:block}.v-badge{display:inline-block;line-height:1}.v-badge__badge{align-items:center;display:inline-flex;border-radius:10px;font-size:.75rem;font-weight:500;height:1.25rem;justify-content:center;min-width:20px;padding:4px 6px;pointer-events:auto;position:absolute;text-align:center;text-indent:0;transition:.225s cubic-bezier(.4,0,.2,1);white-space:nowrap;background:rgb(var(--v-theme-surface-variant));color:rgba(var(--v-theme-on-surface-variant),var(--v-high-emphasis-opacity))}.v-badge--bordered .v-badge__badge:after{border-radius:inherit;border-style:solid;border-width:2px;bottom:0;color:rgb(var(--v-theme-background));content:"";left:0;position:absolute;right:0;top:0;transform:scale(1.05)}.v-badge--dot .v-badge__badge{border-radius:4.5px;height:9px;min-width:0;padding:0;width:9px}.v-badge--dot .v-badge__badge:after{border-width:1.5px}.v-badge--inline .v-badge__badge{position:relative;vertical-align:middle}.v-badge__badge .v-icon{color:inherit;font-size:.75rem;margin:0 -2px}.v-badge__badge img,.v-badge__badge .v-img{height:100%;width:100%}.v-badge__wrapper{display:flex;position:relative}.v-badge--inline .v-badge__wrapper{align-items:center;display:inline-flex;justify-content:center;margin:0 4px}.v-banner{display:grid;flex:1 1;font-size:.875rem;grid-template-areas:"prepend content actions";grid-template-columns:max-content auto max-content;grid-template-rows:max-content max-content;line-height:1.375rem;overflow:hidden;padding-inline:16px 8px;padding-top:16px;padding-bottom:16px;position:relative;width:100%;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0 0 thin 0;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:0;background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-banner--border{border-width:thin;box-shadow:none}.v-banner--absolute{position:absolute}.v-banner--fixed{position:fixed}.v-banner--sticky{position:sticky}.v-banner--rounded{border-radius:4px}.v-banner--stacked:not(.v-banner--one-line){grid-template-areas:"prepend content" ". actions"}.v-banner--stacked .v-banner-text{padding-inline-end:36px}.v-banner--density-default .v-banner-actions{margin-bottom:-8px}.v-banner--density-default.v-banner--one-line{padding-top:8px;padding-bottom:8px}.v-banner--density-default.v-banner--one-line .v-banner-actions{margin-bottom:0}.v-banner--density-default.v-banner--one-line{padding-top:10px}.v-banner--density-default.v-banner--two-line{padding-top:16px;padding-bottom:16px}.v-banner--density-default.v-banner--three-line{padding-top:24px;padding-bottom:16px}.v-banner--density-default:not(.v-banner--one-line) .v-banner-actions,.v-banner--density-default.v-banner--two-line .v-banner-actions,.v-banner--density-default.v-banner--three-line .v-banner-actions{margin-top:20px}.v-banner--density-comfortable .v-banner-actions{margin-bottom:-4px}.v-banner--density-comfortable.v-banner--one-line{padding-top:4px;padding-bottom:4px}.v-banner--density-comfortable.v-banner--one-line .v-banner-actions{margin-bottom:0}.v-banner--density-comfortable.v-banner--two-line{padding-top:12px;padding-bottom:12px}.v-banner--density-comfortable.v-banner--three-line{padding-top:20px;padding-bottom:12px}.v-banner--density-comfortable:not(.v-banner--one-line) .v-banner-actions,.v-banner--density-comfortable.v-banner--two-line .v-banner-actions,.v-banner--density-comfortable.v-banner--three-line .v-banner-actions{margin-top:16px}.v-banner--density-compact .v-banner-actions{margin-bottom:0}.v-banner--density-compact.v-banner--one-line{padding-top:0;padding-bottom:0}.v-banner--density-compact.v-banner--one-line .v-banner-actions{margin-bottom:0}.v-banner--density-compact.v-banner--two-line{padding-top:8px;padding-bottom:8px}.v-banner--density-compact.v-banner--three-line{padding-top:16px;padding-bottom:8px}.v-banner--density-compact:not(.v-banner--one-line) .v-banner-actions,.v-banner--density-compact.v-banner--two-line .v-banner-actions,.v-banner--density-compact.v-banner--three-line .v-banner-actions{margin-top:12px}.v-banner--sticky{top:0}.v-banner__content{align-items:center;display:flex;grid-area:content}.v-banner__prepend{align-self:flex-start;grid-area:prepend;margin-inline-end:24px}.v-banner-actions{align-self:flex-end;display:flex;flex:0 1;grid-area:actions;justify-content:flex-end}.v-banner--two-line .v-banner-actions,.v-banner--three-line .v-banner-actions{margin-top:20px}.v-banner-text{-webkit-box-orient:vertical;display:-webkit-box;padding-inline-end:90px;overflow:hidden}.v-banner--one-line .v-banner-text{-webkit-line-clamp:1}.v-banner--two-line .v-banner-text{-webkit-line-clamp:2}.v-banner--three-line .v-banner-text{-webkit-line-clamp:3}.v-banner--two-line .v-banner-text,.v-banner--three-line .v-banner-text{align-self:flex-start}.v-bottom-navigation{display:flex;max-width:100%;overflow:hidden;position:absolute;transition:transform,color .2s,.2s cubic-bezier(.4,0,.2,1);border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;border-radius:0;background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-bottom-navigation--border{border-width:thin;box-shadow:none}.v-bottom-navigation--active{box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-bottom-navigation__content{display:flex;flex:none;font-size:.75rem;justify-content:center;transition:inherit;width:100%}.v-bottom-navigation .v-bottom-navigation__content>.v-btn{font-size:inherit;height:100%;max-width:168px;min-width:80px;text-transform:none;transition:inherit;width:auto;border-radius:0}.v-bottom-navigation .v-bottom-navigation__content>.v-btn .v-btn__content,.v-bottom-navigation .v-bottom-navigation__content>.v-btn .v-btn__icon{transition:inherit}.v-bottom-navigation .v-bottom-navigation__content>.v-btn .v-btn__icon{font-size:1.5rem}.v-bottom-navigation--grow .v-bottom-navigation__content>.v-btn{flex-grow:1}.v-bottom-navigation--shift .v-bottom-navigation__content .v-btn:not(.v-btn--selected) .v-btn__content>span{transition:inherit;opacity:0}.v-bottom-navigation--shift .v-bottom-navigation__content .v-btn:not(.v-btn--selected) .v-btn__content{transform:translateY(.5rem)}.bottom-sheet-transition-enter-from,.bottom-sheet-transition-leave-to{transform:translateY(100%)}.v-bottom-sheet>.v-bottom-sheet__content.v-overlay__content{align-self:flex-end;border-radius:0;flex:0 1 auto;left:0;right:0;margin-inline:0;margin-bottom:0;transition-duration:.2s;width:100%;max-width:100%;overflow:visible;box-shadow:0 7px 8px -4px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 12px 17px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 5px 22px 4px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-bottom-sheet>.v-bottom-sheet__content.v-overlay__content>.v-card,.v-bottom-sheet>.v-bottom-sheet__content.v-overlay__content>.v-sheet{border-radius:0}.v-bottom-sheet.v-bottom-sheet--inset{max-width:none}@media (min-width: 600px){.v-bottom-sheet.v-bottom-sheet--inset{max-width:70%}}.v-dialog{align-items:center;justify-content:center;margin:auto}.v-dialog>.v-overlay__content{max-height:calc(100% - 48px);width:calc(100% - 48px);max-width:calc(100% - 48px);margin:24px}.v-dialog>.v-overlay__content,.v-dialog>.v-overlay__content>form{display:flex;flex-direction:column;min-height:0}.v-dialog>.v-overlay__content>.v-card,.v-dialog>.v-overlay__content>.v-sheet,.v-dialog>.v-overlay__content>form>.v-card,.v-dialog>.v-overlay__content>form>.v-sheet{--v-scrollbar-offset: 0px;border-radius:4px;overflow-y:auto;box-shadow:0 11px 15px -7px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 24px 38px 3px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 9px 46px 8px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-dialog>.v-overlay__content>.v-card,.v-dialog>.v-overlay__content>form>.v-card{display:flex;flex-direction:column}.v-dialog>.v-overlay__content>.v-card>.v-card-item,.v-dialog>.v-overlay__content>form>.v-card>.v-card-item{padding:14px 24px 0}.v-dialog>.v-overlay__content>.v-card>.v-card-item+.v-card-text,.v-dialog>.v-overlay__content>form>.v-card>.v-card-item+.v-card-text{padding-top:10px}.v-dialog>.v-overlay__content>.v-card>.v-card-text,.v-dialog>.v-overlay__content>form>.v-card>.v-card-text{font-size:inherit;letter-spacing:.03125em;line-height:inherit;padding:16px 24px 10px}.v-dialog--fullscreen{--v-scrollbar-offset: 0px}.v-dialog--fullscreen>.v-overlay__content{border-radius:0;margin:0;padding:0;width:100%;height:100%;max-width:100%;max-height:100%;overflow-y:auto;top:0;left:0}.v-dialog--fullscreen>.v-overlay__content>.v-card,.v-dialog--fullscreen>.v-overlay__content>.v-sheet,.v-dialog--fullscreen>.v-overlay__content>form>.v-card,.v-dialog--fullscreen>.v-overlay__content>form>.v-sheet{min-height:100%;min-width:100%;border-radius:0}.v-dialog--scrollable>.v-overlay__content,.v-dialog--scrollable>.v-overlay__content>form{display:flex}.v-dialog--scrollable>.v-overlay__content>.v-card,.v-dialog--scrollable>.v-overlay__content>form>.v-card{display:flex;flex:1 1 100%;flex-direction:column;max-height:100%;max-width:100%}.v-dialog--scrollable>.v-overlay__content>.v-card>.v-card-text,.v-dialog--scrollable>.v-overlay__content>form>.v-card>.v-card-text{backface-visibility:hidden;overflow-y:auto}.v-breadcrumbs{display:flex;align-items:center;line-height:1.375rem;padding:16px 12px}.v-breadcrumbs--rounded{border-radius:4px}.v-breadcrumbs--density-default{padding-top:16px;padding-bottom:16px}.v-breadcrumbs--density-comfortable{padding-top:12px;padding-bottom:12px}.v-breadcrumbs--density-compact{padding-top:8px;padding-bottom:8px}.v-breadcrumbs__prepend{align-items:center;display:inline-flex}.v-breadcrumbs-item{align-items:center;color:inherit;display:inline-flex;padding:0 4px;text-decoration:none;vertical-align:middle}.v-breadcrumbs-item--disabled{opacity:var(--v-disabled-opacity);pointer-events:none}.v-breadcrumbs-item--link{color:inherit;text-decoration:none}.v-breadcrumbs-item--link:hover{text-decoration:underline}.v-breadcrumbs-item .v-icon{font-size:1rem;margin-inline:-4px 2px}.v-breadcrumbs-divider{display:inline-block;padding:0 8px;vertical-align:middle}.v-card{display:block;overflow:hidden;overflow-wrap:break-word;position:relative;padding:0;text-decoration:none;transition-duration:.28s;transition-property:box-shadow,opacity,background;transition-timing-function:cubic-bezier(.4,0,.2,1);z-index:0;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;border-radius:4px}.v-card--border{border-width:thin;box-shadow:none}.v-card--absolute{position:absolute}.v-card--fixed{position:fixed}.v-card:hover>.v-card__overlay{opacity:calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier))}.v-card:focus-visible>.v-card__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-card:focus>.v-card__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}}.v-card--active>.v-card__overlay,.v-card[aria-haspopup=menu][aria-expanded=true]>.v-card__overlay{opacity:calc(var(--v-activated-opacity) * var(--v-theme-overlay-multiplier))}.v-card--active:hover>.v-card__overlay,.v-card[aria-haspopup=menu][aria-expanded=true]:hover>.v-card__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}.v-card--active:focus-visible>.v-card__overlay,.v-card[aria-haspopup=menu][aria-expanded=true]:focus-visible>.v-card__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-card--active:focus>.v-card__overlay,.v-card[aria-haspopup=menu][aria-expanded=true]:focus>.v-card__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}}.v-card--variant-plain,.v-card--variant-outlined,.v-card--variant-text,.v-card--variant-tonal{background:transparent;color:inherit}.v-card--variant-plain{opacity:.62}.v-card--variant-plain:focus,.v-card--variant-plain:hover{opacity:1}.v-card--variant-plain .v-card__overlay{display:none}.v-card--variant-elevated,.v-card--variant-flat{background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-card--variant-elevated{box-shadow:0 2px 1px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 1px 1px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 3px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-card--variant-flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-card--variant-outlined{border:thin solid currentColor}.v-card--variant-text .v-card__overlay{background:currentColor}.v-card--variant-tonal .v-card__underlay{background:currentColor;opacity:var(--v-activated-opacity);border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.v-card--disabled{pointer-events:none;-webkit-user-select:none;user-select:none}.v-card--disabled>:not(.v-card__loader){opacity:.6}.v-card--flat{box-shadow:none}.v-card--hover{cursor:pointer}.v-card--hover:before,.v-card--hover:after{border-radius:inherit;bottom:0;content:"";display:block;left:0;pointer-events:none;position:absolute;right:0;top:0;transition:inherit}.v-card--hover:before{opacity:1;z-index:-1;box-shadow:0 2px 1px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 1px 1px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 3px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-card--hover:after{z-index:1;opacity:0;box-shadow:0 5px 5px -3px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 8px 10px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 3px 14px 2px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-card--hover:hover:after{opacity:1}.v-card--hover:hover:before{opacity:0}.v-card--hover:hover{box-shadow:0 5px 5px -3px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 8px 10px 1px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 3px 14px 2px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-card--link{cursor:pointer}.v-card-actions{align-items:center;display:flex;flex:none;min-height:52px;padding:.5rem}.v-card-item{align-items:center;display:grid;flex:none;grid-template-areas:"prepend content append";grid-template-columns:max-content auto max-content;padding:.625rem 1rem}.v-card-item+.v-card-text{padding-top:0}.v-card-item__prepend,.v-card-item__append{align-items:center;display:flex}.v-card-item__prepend{grid-area:prepend;padding-inline-end:.5rem}.v-card-item__append{grid-area:append;padding-inline-start:.5rem}.v-card-item__content{align-self:center;grid-area:content;overflow:hidden}.v-card-title{display:block;flex:none;font-size:1.25rem;font-weight:500;-webkit-hyphens:auto;hyphens:auto;letter-spacing:.0125em;min-width:0;overflow-wrap:normal;overflow:hidden;padding:.5rem 1rem;text-overflow:ellipsis;text-transform:none;white-space:nowrap;word-break:normal;word-wrap:break-word}.v-card .v-card-title{line-height:2rem}.v-card--density-comfortable .v-card-title{line-height:1.75rem}.v-card--density-compact .v-card-title{line-height:1.55rem}.v-card-item .v-card-title{padding:0}.v-card-title+.v-card-text,.v-card-title+.v-card-actions{padding-top:0}.v-card-subtitle{display:block;flex:none;font-size:.875rem;font-weight:400;letter-spacing:.0178571429em;opacity:var(--v-medium-emphasis-opacity);overflow:hidden;padding:0 1rem;text-overflow:ellipsis;text-transform:none;white-space:nowrap}.v-card .v-card-subtitle{line-height:1.25rem}.v-card--density-comfortable .v-card-subtitle{line-height:1.125rem}.v-card--density-compact .v-card-subtitle{line-height:1rem}.v-card-item .v-card-subtitle{padding:0 0 .25rem}.v-card-text{flex:1 1 auto;font-size:.875rem;font-weight:400;letter-spacing:.0178571429em;padding:1rem;text-transform:none}.v-card .v-card-text{line-height:1.25rem}.v-card--density-comfortable .v-card-text{line-height:1.2rem}.v-card--density-compact .v-card-text{line-height:1.15rem}.v-card__image{display:flex;height:100%;flex:1 1 auto;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:-1}.v-card__content{border-radius:inherit;overflow:hidden;position:relative}.v-card__loader{bottom:auto;top:0;left:0;position:absolute;right:0;width:100%;z-index:1}.v-card__overlay{background-color:currentColor;border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;opacity:0;transition:opacity .2s ease-in-out}.v-carousel{overflow:hidden;position:relative;width:100%}.v-carousel__controls{align-items:center;bottom:0;display:flex;height:50px;justify-content:center;list-style-type:none;position:absolute;width:100%;z-index:1;background:rgba(var(--v-theme-surface-variant),.3);color:rgb(var(--v-theme-on-surface-variant))}.v-carousel__controls>.v-item-group{flex:0 1 auto}.v-carousel__controls__item{margin:0 8px}.v-carousel__controls__item .v-icon{opacity:.5}.v-carousel__controls__item--active .v-icon{opacity:1;vertical-align:middle}.v-carousel__controls__item:hover{background:none}.v-carousel__controls__item:hover .v-icon{opacity:.8}.v-carousel__progress{margin:0;position:absolute;bottom:0;left:0;right:0}.v-carousel-item{display:block;height:inherit;text-decoration:none}.v-carousel-item>.v-img{height:inherit}.v-carousel--hide-delimiter-background .v-carousel__controls{background:transparent}.v-carousel--vertical-delimiters .v-carousel__controls{flex-direction:column;height:100%!important;width:50px}.v-window{overflow:hidden}.v-window__container{display:flex;flex-direction:column;height:inherit;position:relative;transition:.3s cubic-bezier(.25,.8,.5,1)}.v-window__controls{position:absolute;left:0;top:0;width:100%;height:100%;display:flex;align-items:center;justify-content:space-between;padding:0 16px;pointer-events:none}.v-window__controls>*{pointer-events:auto}.v-window--show-arrows-on-hover{overflow:hidden}.v-window--show-arrows-on-hover .v-window__left{transform:translate(-200%)}.v-window--show-arrows-on-hover .v-window__right{transform:translate(200%)}.v-window--show-arrows-on-hover:hover .v-window__left,.v-window--show-arrows-on-hover:hover .v-window__right{transform:translate(0)}.v-window-x-transition-enter-active,.v-window-x-transition-leave-active,.v-window-x-reverse-transition-enter-active,.v-window-x-reverse-transition-leave-active,.v-window-y-transition-enter-active,.v-window-y-transition-leave-active,.v-window-y-reverse-transition-enter-active,.v-window-y-reverse-transition-leave-active{transition:.3s cubic-bezier(.25,.8,.5,1)}.v-window-x-transition-leave-from,.v-window-x-transition-leave-to,.v-window-x-reverse-transition-leave-from,.v-window-x-reverse-transition-leave-to,.v-window-y-transition-leave-from,.v-window-y-transition-leave-to,.v-window-y-reverse-transition-leave-from,.v-window-y-reverse-transition-leave-to{position:absolute!important;top:0;width:100%}.v-window-x-transition-enter-from{transform:translate(100%)}.v-window-x-transition-leave-to,.v-window-x-reverse-transition-enter-from{transform:translate(-100%)}.v-window-x-reverse-transition-leave-to{transform:translate(100%)}.v-window-y-transition-enter-from{transform:translateY(100%)}.v-window-y-transition-leave-to,.v-window-y-reverse-transition-enter-from{transform:translateY(-100%)}.v-window-y-reverse-transition-leave-to{transform:translateY(100%)}.v-code{background-color:rgb(var(--v-theme-code));color:rgb(var(--v-theme-on-code));border-radius:4px;line-height:1.8;font-size:.9em;font-weight:400;padding:.2em .4em}.v-color-picker{align-self:flex-start;contain:content}.v-color-picker.v-sheet{box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:4px}.v-color-picker__controls{display:flex;flex-direction:column;padding:16px}.v-color-picker--flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-color-picker--flat .v-color-picker__track:not(.v-input--is-disabled) .v-slider__thumb{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-color-picker-canvas{display:flex;position:relative;overflow:hidden;contain:content;touch-action:none}.v-color-picker-canvas__dot{position:absolute;top:0;left:0;width:15px;height:15px;background:transparent;border-radius:50%;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1.5px #0000004d}.v-color-picker-canvas__dot--disabled{box-shadow:0 0 0 1.5px #ffffffb3,inset 0 0 1px 1.5px #0000004d}.v-color-picker-canvas:hover .v-color-picker-canvas__dot{will-change:transform}.v-color-picker-edit{display:flex;margin-top:24px}.v-color-picker-edit__input{width:100%;display:flex;flex-wrap:wrap;justify-content:center;text-align:center}.v-color-picker-edit__input:not(:last-child){margin-inline-end:8px}.v-color-picker-edit__input input{border-radius:4px;margin-bottom:8px;min-width:0;outline:none;text-align:center;width:100%;height:32px;background:rgba(var(--v-theme-surface-variant),.2);color:rgba(var(--v-theme-on-surface))}.v-color-picker-edit__input span{font-size:.75rem}.v-color-picker-preview__alpha .v-slider-track__background{background-color:transparent!important}.v-locale--is-ltr.v-color-picker-preview__alpha .v-slider-track__background,.v-locale--is-ltr .v-color-picker-preview__alpha .v-slider-track__background{background-image:linear-gradient(to right,transparent,var(--v-color-picker-color-hsv))}.v-locale--is-rtl.v-color-picker-preview__alpha .v-slider-track__background,.v-locale--is-rtl .v-color-picker-preview__alpha .v-slider-track__background{background-image:linear-gradient(to left,transparent,var(--v-color-picker-color-hsv))}.v-color-picker-preview__alpha .v-slider-track__background:after{content:"";z-index:-1;left:0;top:0;width:100%;height:100%;position:absolute;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAACRJREFUKFNjPHTo0H8GJGBnZ8eIzGekgwJk+0BsdCtRHEQbBQBbbh0dIGKknQAAAABJRU5ErkJggg==) repeat;border-radius:inherit}.v-color-picker-preview__sliders{display:flex;flex:1 0 auto;flex-direction:column;padding-inline-end:16px}.v-color-picker-preview__dot{position:relative;height:30px;width:30px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAACRJREFUKFNjPHTo0H8GJGBnZ8eIzGekgwJk+0BsdCtRHEQbBQBbbh0dIGKknQAAAABJRU5ErkJggg==) repeat;border-radius:50%;overflow:hidden;margin-inline-end:24px}.v-color-picker-preview__dot>div{width:100%;height:100%}.v-locale--is-ltr.v-color-picker-preview__hue:not(.v-input--is-disabled) .v-slider-track__background,.v-locale--is-ltr .v-color-picker-preview__hue:not(.v-input--is-disabled) .v-slider-track__background{background:linear-gradient(to right,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.v-locale--is-rtl.v-color-picker-preview__hue:not(.v-input--is-disabled) .v-slider-track__background,.v-locale--is-rtl .v-color-picker-preview__hue:not(.v-input--is-disabled) .v-slider-track__background{background:linear-gradient(to left,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.v-color-picker-preview__track{position:relative;width:100%;margin:0!important}.v-color-picker-preview__track .v-slider-track__fill{display:none}.v-color-picker-preview{align-items:center;display:flex;margin-bottom:0}.v-color-picker-preview__eye-dropper{position:relative;margin-right:12px}.v-slider .v-slider__container input{cursor:default;padding:0;width:100%;display:none}.v-slider>.v-input__append,.v-slider>.v-input__prepend{padding:0}.v-slider__container{position:relative;min-height:inherit;width:100%;height:100%;display:flex;justify-content:center;align-items:center;cursor:pointer}.v-input--disabled .v-slider__container{opacity:var(--v-disabled-opacity)}.v-input--error:not(.v-input--disabled) .v-slider__container{color:rgb(var(--v-theme-error))}.v-slider.v-input--horizontal{align-items:center;margin-inline:8px 8px}.v-slider.v-input--horizontal>.v-input__control{min-height:32px;display:flex;align-items:center}.v-slider.v-input--vertical{justify-content:center;margin-top:12px;margin-bottom:12px}.v-slider.v-input--vertical>.v-input__control{min-height:300px}.v-slider.v-input--disabled{pointer-events:none}.v-slider--has-labels>.v-input__control{margin-bottom:4px}.v-slider__label{margin-inline-end:12px}.v-slider-thumb{touch-action:none;color:rgb(var(--v-theme-surface-variant))}.v-input--error:not(.v-input--disabled) .v-slider-thumb{color:inherit}.v-slider-thumb__label{background:rgba(var(--v-theme-surface-variant),.7);color:rgb(var(--v-theme-on-surface-variant))}.v-slider-thumb__label:before{color:rgba(var(--v-theme-surface-variant),.7)}.v-slider-thumb{outline:none;position:absolute;transition:.3s cubic-bezier(.25,.8,.5,1)}.v-slider-thumb__surface{cursor:pointer;width:var(--v-slider-thumb-size);height:var(--v-slider-thumb-size);border-radius:50%;-webkit-user-select:none;user-select:none;background-color:currentColor}.v-slider-thumb__surface:before{transition:.3s cubic-bezier(.4,0,.2,1);content:"";color:inherit;top:0;left:0;width:100%;height:100%;border-radius:50%;background:currentColor;position:absolute;pointer-events:none;opacity:0}.v-slider-thumb__surface:after{content:"";width:42px;height:42px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.v-slider-thumb__label-container{position:absolute;transition:.2s cubic-bezier(.4,0,1,1)}.v-slider-thumb__label{display:flex;align-items:center;justify-content:center;font-size:.75rem;min-width:35px;height:25px;border-radius:4px;padding:6px;position:absolute;-webkit-user-select:none;user-select:none;transition:.2s cubic-bezier(.4,0,1,1)}.v-slider-thumb__label:before{content:"";width:0;height:0;position:absolute}.v-slider-thumb__ripple{position:absolute;left:calc(var(--v-slider-thumb-size) / -2);top:calc(var(--v-slider-thumb-size) / -2);width:calc(var(--v-slider-thumb-size) * 2);height:calc(var(--v-slider-thumb-size) * 2);background:inherit}.v-slider.v-input--horizontal .v-slider-thumb{top:50%;transform:translateY(-50%);inset-inline-start:calc(var(--v-slider-thumb-position) - var(--v-slider-thumb-size) / 2)}.v-slider.v-input--horizontal .v-slider-thumb__label-container{left:calc(var(--v-slider-thumb-size) / 2);top:0}.v-slider.v-input--horizontal .v-slider-thumb__label{bottom:calc(var(--v-slider-thumb-size) / 2)}.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-thumb__label,.v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-thumb__label{transform:translate(-50%)}.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-thumb__label,.v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-thumb__label{transform:translate(50%)}.v-slider.v-input--horizontal .v-slider-thumb__label:before{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid currentColor;bottom:-6px}.v-slider.v-input--vertical .v-slider-thumb{top:calc(var(--v-slider-thumb-position) - var(--v-slider-thumb-size) / 2)}.v-slider.v-input--vertical .v-slider-thumb__label-container{top:calc(var(--v-slider-thumb-size) / 2);right:0}.v-slider.v-input--vertical .v-slider-thumb__label{top:-12.5px;left:calc(var(--v-slider-thumb-size) / 2)}.v-slider.v-input--vertical .v-slider-thumb__label:before{border-right:6px solid currentColor;border-top:6px solid transparent;border-bottom:6px solid transparent;left:-6px}.v-slider-thumb--focused .v-slider-thumb__surface:before{transform:scale(2);opacity:var(--v-focus-opacity)}.v-slider-thumb--pressed{transition:none}.v-slider-thumb--pressed .v-slider-thumb__surface:before{opacity:var(--v-pressed-opacity)}@media (hover: hover){.v-slider-thumb:hover .v-slider-thumb__surface:before{transform:scale(2)}.v-slider-thumb:hover:not(.v-slider-thumb--focused) .v-slider-thumb__surface:before{opacity:var(--v-hover-opacity)}}.v-slider-track__background,.v-slider-track__fill,.v-slider-track__tick{background-color:rgb(var(--v-theme-surface-variant))}.v-slider-track__tick--filled{background-color:rgb(var(--v-theme-surface-light))}.v-slider-track{border-radius:6px}.v-slider-track__background,.v-slider-track__fill{position:absolute;transition:.3s cubic-bezier(.25,.8,.5,1);border-radius:inherit}.v-slider--pressed .v-slider-track__background,.v-slider--pressed .v-slider-track__fill{transition:none}.v-input--error:not(.v-input--disabled) .v-slider-track__background,.v-input--error:not(.v-input--disabled) .v-slider-track__fill{background-color:currentColor}.v-slider-track__ticks{height:100%;width:100%;position:relative}.v-slider-track__tick{position:absolute;opacity:0;transition:.2s opacity cubic-bezier(.4,0,.2,1);border-radius:2px;width:var(--v-slider-tick-size);height:var(--v-slider-tick-size);transform:translate(calc(var(--v-slider-tick-size) / -2),calc(var(--v-slider-tick-size) / -2))}.v-locale--is-ltr.v-slider-track__tick--first .v-slider-track__tick-label,.v-locale--is-ltr .v-slider-track__tick--first .v-slider-track__tick-label{transform:none}.v-locale--is-rtl.v-slider-track__tick--first .v-slider-track__tick-label,.v-locale--is-rtl .v-slider-track__tick--first .v-slider-track__tick-label{transform:translate(100%)}.v-locale--is-ltr.v-slider-track__tick--last .v-slider-track__tick-label,.v-locale--is-ltr .v-slider-track__tick--last .v-slider-track__tick-label{transform:translate(-100%)}.v-locale--is-rtl.v-slider-track__tick--last .v-slider-track__tick-label,.v-locale--is-rtl .v-slider-track__tick--last .v-slider-track__tick-label{transform:none}.v-slider-track__tick-label{position:absolute;-webkit-user-select:none;user-select:none;white-space:nowrap}.v-slider.v-input--horizontal .v-slider-track{display:flex;align-items:center;width:100%;height:calc(var(--v-slider-track-size) + 2px);touch-action:pan-y}.v-slider.v-input--horizontal .v-slider-track__background{height:var(--v-slider-track-size)}.v-slider.v-input--horizontal .v-slider-track__fill{height:inherit}.v-slider.v-input--horizontal .v-slider-track__tick{margin-top:calc(calc(var(--v-slider-track-size) + 2px) / 2)}.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick,.v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick{transform:translate(calc(var(--v-slider-tick-size) / 2),calc(var(--v-slider-tick-size) / -2))}.v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label{margin-top:calc(var(--v-slider-track-size) / 2 + 8px)}.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label,.v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label{transform:translate(-50%)}.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label,.v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick .v-slider-track__tick-label{transform:translate(50%)}.v-slider.v-input--horizontal .v-slider-track__tick--first{margin-inline-start:calc(var(--v-slider-tick-size) + 1px)}.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label,.v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label,.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label,.v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick--first .v-slider-track__tick-label{transform:translate(0)}.v-slider.v-input--horizontal .v-slider-track__tick--last{margin-inline-start:calc(100% - var(--v-slider-tick-size) - 1px)}.v-locale--is-ltr.v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label,.v-locale--is-ltr .v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label{transform:translate(-100%)}.v-locale--is-rtl.v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label,.v-locale--is-rtl .v-slider.v-input--horizontal .v-slider-track__tick--last .v-slider-track__tick-label{transform:translate(100%)}.v-slider.v-input--vertical .v-slider-track{height:100%;display:flex;justify-content:center;width:calc(var(--v-slider-track-size) + 2px);touch-action:pan-x}.v-slider.v-input--vertical .v-slider-track__background{width:var(--v-slider-track-size)}.v-slider.v-input--vertical .v-slider-track__fill{width:inherit}.v-slider.v-input--vertical .v-slider-track__ticks{height:100%}.v-slider.v-input--vertical .v-slider-track__tick{margin-inline-start:calc(calc(var(--v-slider-track-size) + 2px) / 2);transform:translate(calc(var(--v-slider-tick-size) / -2),calc(var(--v-slider-tick-size) / 2))}.v-locale--is-rtl.v-slider.v-input--vertical .v-slider-track__tick,.v-locale--is-rtl .v-slider.v-input--vertical .v-slider-track__tick{transform:translate(calc(var(--v-slider-tick-size) / 2),calc(var(--v-slider-tick-size) / 2))}.v-slider.v-input--vertical .v-slider-track__tick--first{bottom:calc(0% + var(--v-slider-tick-size) + 1px)}.v-slider.v-input--vertical .v-slider-track__tick--last{bottom:calc(100% - var(--v-slider-tick-size) - 1px)}.v-slider.v-input--vertical .v-slider-track__tick .v-slider-track__tick-label{margin-inline-start:calc(var(--v-slider-track-size) / 2 + 12px);transform:translateY(-50%)}.v-slider-track__ticks--always-show .v-slider-track__tick,.v-slider--focused .v-slider-track__tick{opacity:1}.v-slider-track__background--opacity{opacity:.38}.v-color-picker-swatches{overflow-y:auto}.v-color-picker-swatches>div{display:flex;flex-wrap:wrap;justify-content:center;padding:8px}.v-color-picker-swatches__swatch{display:flex;flex-direction:column;margin-bottom:10px}.v-color-picker-swatches__color{position:relative;height:18px;max-height:18px;width:45px;margin:2px 4px;border-radius:2px;-webkit-user-select:none;user-select:none;overflow:hidden;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAACRJREFUKFNjPHTo0H8GJGBnZ8eIzGekgwJk+0BsdCtRHEQbBQBbbh0dIGKknQAAAABJRU5ErkJggg==) repeat;cursor:pointer}.v-color-picker-swatches__color>div{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.v-sheet{display:block;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:0;background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-background),var(--v-high-emphasis-opacity))}.v-sheet--border{border-width:thin;box-shadow:none}.v-sheet--absolute{position:absolute}.v-sheet--fixed{position:fixed}.v-sheet--relative{position:relative}.v-sheet--sticky{position:sticky}.v-sheet--rounded{border-radius:4px}.v-combobox .v-field .v-text-field__prefix,.v-combobox .v-field .v-text-field__suffix,.v-combobox .v-field .v-field__input,.v-combobox .v-field.v-field{cursor:text}.v-combobox .v-field .v-field__input>input{flex:1 1}.v-combobox .v-field input{min-width:64px}.v-combobox .v-field:not(.v-field--focused) input{min-width:0}.v-combobox .v-field--dirty .v-combobox__selection{margin-inline-end:2px}.v-combobox .v-combobox__selection-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.v-combobox__content{overflow:hidden;box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:4px}.v-combobox__mask{background:rgb(var(--v-theme-surface-light))}.v-combobox__selection{display:inline-flex;align-items:center;height:1.5rem;letter-spacing:inherit;line-height:inherit;max-width:calc(100% - 4px)}.v-combobox__selection:first-child{margin-inline-start:0}.v-combobox--chips.v-input--density-compact .v-field--variant-solo .v-label.v-field-label--floating,.v-combobox--chips.v-input--density-compact .v-field--variant-solo-inverted .v-label.v-field-label--floating,.v-combobox--chips.v-input--density-compact .v-field--variant-filled .v-label.v-field-label--floating,.v-combobox--chips.v-input--density-compact .v-field--variant-solo-filled .v-label.v-field-label--floating{top:0}.v-combobox--selecting-index .v-combobox__selection{opacity:var(--v-medium-emphasis-opacity)}.v-combobox--selecting-index .v-combobox__selection--selected{opacity:1}.v-combobox--selecting-index .v-field__input>input{caret-color:transparent}.v-combobox--single:not(.v-combobox--selection-slot).v-text-field input{flex:1 1;position:absolute;left:0;right:0;width:100%;padding-inline:inherit}.v-combobox--single:not(.v-combobox--selection-slot) .v-field--active input{transition:none}.v-combobox--single:not(.v-combobox--selection-slot) .v-field--dirty:not(.v-field--focused) input{opacity:0}.v-combobox--single:not(.v-combobox--selection-slot) .v-field--focused .v-combobox__selection{opacity:0}.v-combobox__menu-icon{margin-inline-start:4px;transition:.2s cubic-bezier(.4,0,.2,1)}.v-combobox--active-menu .v-combobox__menu-icon{opacity:var(--v-high-emphasis-opacity);transform:rotate(180deg)}.v-data-table{width:100%}.v-data-table__table{width:100%;border-collapse:separate;border-spacing:0}.v-data-table__tr--focus{border:1px dotted black}.v-data-table__tr--clickable{cursor:pointer}.v-data-table .v-table__wrapper>table>thead>tr>td.v-data-table-column--align-end,.v-data-table .v-table__wrapper>table>thead>tr th.v-data-table-column--align-end,.v-data-table .v-table__wrapper>table tbody>tr>td.v-data-table-column--align-end,.v-data-table .v-table__wrapper>table tbody>tr th.v-data-table-column--align-end{text-align:end}.v-data-table .v-table__wrapper>table>thead>tr>td.v-data-table-column--align-end .v-data-table-header__content,.v-data-table .v-table__wrapper>table>thead>tr th.v-data-table-column--align-end .v-data-table-header__content,.v-data-table .v-table__wrapper>table tbody>tr>td.v-data-table-column--align-end .v-data-table-header__content,.v-data-table .v-table__wrapper>table tbody>tr th.v-data-table-column--align-end .v-data-table-header__content{flex-direction:row-reverse}.v-data-table .v-table__wrapper>table>thead>tr>td.v-data-table-column--align-center,.v-data-table .v-table__wrapper>table>thead>tr th.v-data-table-column--align-center,.v-data-table .v-table__wrapper>table tbody>tr>td.v-data-table-column--align-center,.v-data-table .v-table__wrapper>table tbody>tr th.v-data-table-column--align-center{text-align:center}.v-data-table .v-table__wrapper>table>thead>tr>td.v-data-table-column--align-center .v-data-table-header__content,.v-data-table .v-table__wrapper>table>thead>tr th.v-data-table-column--align-center .v-data-table-header__content,.v-data-table .v-table__wrapper>table tbody>tr>td.v-data-table-column--align-center .v-data-table-header__content,.v-data-table .v-table__wrapper>table tbody>tr th.v-data-table-column--align-center .v-data-table-header__content{justify-content:center}.v-data-table .v-table__wrapper>table>thead>tr>td.v-data-table-column--no-padding,.v-data-table .v-table__wrapper>table>thead>tr th.v-data-table-column--no-padding,.v-data-table .v-table__wrapper>table tbody>tr>td.v-data-table-column--no-padding,.v-data-table .v-table__wrapper>table tbody>tr th.v-data-table-column--no-padding{padding:0 8px}.v-data-table .v-table__wrapper>table>thead>tr>th,.v-data-table .v-table__wrapper>table tbody>tr>th{align-items:center}.v-data-table .v-table__wrapper>table>thead>tr>th.v-data-table__th--fixed,.v-data-table .v-table__wrapper>table tbody>tr>th.v-data-table__th--fixed{position:sticky}.v-data-table .v-table__wrapper>table>thead>tr>th.v-data-table__th--sortable:hover,.v-data-table .v-table__wrapper>table tbody>tr>th.v-data-table__th--sortable:hover{cursor:pointer;color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-data-table .v-table__wrapper>table>thead>tr>th:not(.v-data-table__th--sorted) .v-data-table-header__sort-icon,.v-data-table .v-table__wrapper>table tbody>tr>th:not(.v-data-table__th--sorted) .v-data-table-header__sort-icon{opacity:0}.v-data-table .v-table__wrapper>table>thead>tr>th:not(.v-data-table__th--sorted):hover .v-data-table-header__sort-icon,.v-data-table .v-table__wrapper>table tbody>tr>th:not(.v-data-table__th--sorted):hover .v-data-table-header__sort-icon{opacity:.5}.v-data-table-column--fixed,.v-data-table__th--sticky{background:rgb(var(--v-theme-surface));position:sticky!important;left:0;z-index:1}.v-data-table-column--last-fixed{border-right:1px solid rgba(var(--v-border-color),var(--v-border-opacity))}.v-data-table.v-table--fixed-header>.v-table__wrapper>table>thead>tr>th.v-data-table-column--fixed{z-index:2}.v-data-table-group-header-row td{background:rgba(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface))}.v-data-table-group-header-row td>span{padding-left:5px}.v-data-table--loading .v-data-table__td{opacity:.3}.v-data-table-group-header-row__column{padding-left:calc(var(--v-data-table-group-header-row-depth) * 16px)!important}.v-data-table-header__content{display:flex;align-items:center}.v-data-table-header__sort-badge{display:inline-flex;justify-content:center;align-items:center;font-size:.875rem;padding:4px;border-radius:50%;background:rgba(var(--v-border-color),var(--v-border-opacity));min-width:20px;min-height:20px;width:20px;height:20px}.v-data-table-progress>th{border:none!important;height:auto!important;padding:0!important}.v-data-table-progress__loader{position:relative}.v-data-table-rows-loading,.v-data-table-rows-no-data{text-align:center}.v-data-table-footer{display:flex;align-items:center;flex-wrap:wrap;padding:4px;justify-content:flex-end}.v-data-table-footer__items-per-page{display:flex;align-items:center;justify-content:center}.v-data-table-footer__items-per-page>span{padding-inline-end:8px}.v-data-table-footer__items-per-page>.v-select{width:90px}.v-data-table-footer__info{display:flex;justify-content:flex-end;min-width:116px;padding:0 16px}.v-data-table-footer__pagination{display:flex;align-items:center;margin-inline-start:16px}.v-data-table-footer__page{padding:0 8px}.v-pagination__list{display:inline-flex;list-style-type:none;justify-content:center;width:100%}.v-pagination__item,.v-pagination__first,.v-pagination__prev,.v-pagination__next,.v-pagination__last{margin:.3rem}.v-table{background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity));font-size:.875rem;transition-duration:.28s;transition-property:box-shadow,opacity,background,height;transition-timing-function:cubic-bezier(.4,0,.2,1)}.v-table .v-table-divider{border-right:thin solid rgba(var(--v-border-color),var(--v-border-opacity))}.v-table .v-table__wrapper>table>thead>tr>th{border-bottom:thin solid rgba(var(--v-border-color),var(--v-border-opacity))}.v-table .v-table__wrapper>table>tbody>tr:not(:last-child)>td,.v-table .v-table__wrapper>table>tbody>tr:not(:last-child)>th{border-bottom:thin solid rgba(var(--v-border-color),var(--v-border-opacity))}.v-table .v-table__wrapper>table>tfoot>tr>td,.v-table .v-table__wrapper>table>tfoot>tr>th{border-top:thin solid rgba(var(--v-border-color),var(--v-border-opacity))}.v-table.v-table--hover>.v-table__wrapper>table>tbody>tr>td{position:relative}.v-table.v-table--hover>.v-table__wrapper>table>tbody>tr:hover>td:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(var(--v-border-color),var(--v-hover-opacity));pointer-events:none}.v-table.v-table--fixed-header>.v-table__wrapper>table>thead>tr>th{background:rgb(var(--v-theme-surface));box-shadow:inset 0 -1px rgba(var(--v-border-color),var(--v-border-opacity));z-index:1}.v-table.v-table--fixed-footer>tfoot>tr>th,.v-table.v-table--fixed-footer>tfoot>tr>td{background:rgb(var(--v-theme-surface));box-shadow:inset 0 1px rgba(var(--v-border-color),var(--v-border-opacity))}.v-table{border-radius:inherit;line-height:1.5;max-width:100%;display:flex;flex-direction:column}.v-table>.v-table__wrapper>table{width:100%;border-spacing:0}.v-table>.v-table__wrapper>table>tbody>tr>td,.v-table>.v-table__wrapper>table>tbody>tr>th,.v-table>.v-table__wrapper>table>thead>tr>td,.v-table>.v-table__wrapper>table>thead>tr>th,.v-table>.v-table__wrapper>table>tfoot>tr>td,.v-table>.v-table__wrapper>table>tfoot>tr>th{padding:0 16px;transition-duration:.28s;transition-property:box-shadow,opacity,background,height;transition-timing-function:cubic-bezier(.4,0,.2,1)}.v-table>.v-table__wrapper>table>tbody>tr>td,.v-table>.v-table__wrapper>table>thead>tr>td,.v-table>.v-table__wrapper>table>tfoot>tr>td{height:var(--v-table-row-height)}.v-table>.v-table__wrapper>table>tbody>tr>th,.v-table>.v-table__wrapper>table>thead>tr>th,.v-table>.v-table__wrapper>table>tfoot>tr>th{height:var(--v-table-header-height);font-weight:500;-webkit-user-select:none;user-select:none;text-align:start}.v-table--density-default{--v-table-header-height: 56px;--v-table-row-height: 52px}.v-table--density-comfortable{--v-table-header-height: 48px;--v-table-row-height: 44px}.v-table--density-compact{--v-table-header-height: 40px;--v-table-row-height: 36px}.v-table__wrapper{border-radius:inherit;overflow:auto;flex:1 1 auto}.v-table--has-top>.v-table__wrapper>table>tbody>tr:first-child:hover>td:first-child{border-top-left-radius:0}.v-table--has-top>.v-table__wrapper>table>tbody>tr:first-child:hover>td:last-child{border-top-right-radius:0}.v-table--has-bottom>.v-table__wrapper>table>tbody>tr:last-child:hover>td:first-child{border-bottom-left-radius:0}.v-table--has-bottom>.v-table__wrapper>table>tbody>tr:last-child:hover>td:last-child{border-bottom-right-radius:0}.v-table--fixed-height>.v-table__wrapper{overflow-y:auto}.v-table--fixed-header>.v-table__wrapper>table>thead{position:sticky;top:0;z-index:2}.v-table--fixed-header>.v-table__wrapper>table>thead>tr>th{border-bottom:0px!important}.v-table--fixed-footer>.v-table__wrapper>table>tfoot>tr{position:sticky;bottom:0;z-index:1}.v-table--fixed-footer>.v-table__wrapper>table>tfoot>tr>td,.v-table--fixed-footer>.v-table__wrapper>table>tfoot>tr>th{border-top:0px!important}.v-date-picker{overflow:hidden;width:328px}.v-date-picker--show-week{width:368px}.v-date-picker-controls{display:flex;align-items:center;justify-content:space-between;font-size:.875rem;padding-top:4px;padding-bottom:4px;padding-inline-start:6px;padding-inline-end:12px}.v-date-picker-controls>.v-btn:first-child{text-transform:none;font-weight:400;line-height:initial;letter-spacing:initial}.v-date-picker-controls--variant-classic{padding-inline-start:12px}.v-date-picker-controls--variant-modern .v-date-picker__title:not(:hover){opacity:.7}.v-date-picker--month .v-date-picker-controls--variant-modern .v-date-picker__title{cursor:pointer}.v-date-picker--year .v-date-picker-controls--variant-modern .v-date-picker__title{opacity:1}.v-date-picker-controls .v-btn:last-child{margin-inline-start:4px}.v-date-picker--year .v-date-picker-controls .v-date-picker-controls__mode-btn{transform:rotate(180deg)}.v-date-picker-controls__date{margin-inline-end:4px}.v-date-picker-controls--variant-classic .v-date-picker-controls__date{margin:auto;text-align:center}.v-date-picker-controls__month{display:flex}.v-locale--is-rtl.v-date-picker-controls__month,.v-locale--is-rtl .v-date-picker-controls__month{flex-direction:row-reverse}.v-date-picker-controls--variant-classic .v-date-picker-controls__month{flex:1 0 auto}.v-date-picker__title{display:inline-block}.v-date-picker-header{align-items:flex-end;height:70px;display:grid;grid-template-areas:"prepend content append";grid-template-columns:min-content minmax(0,1fr) min-content;overflow:hidden;padding-inline:24px 12px;padding-bottom:12px}.v-date-picker-header__append{grid-area:append}.v-date-picker-header__prepend{grid-area:prepend;padding-inline-start:8px}.v-date-picker-header__content{align-items:center;display:inline-flex;font-size:32px;line-height:40px;grid-area:content;justify-content:space-between}.v-date-picker-header--clickable .v-date-picker-header__content{cursor:pointer}.v-date-picker-header--clickable .v-date-picker-header__content:not(:hover){opacity:.7}.date-picker-header-transition-enter-active,.date-picker-header-reverse-transition-enter-active,.date-picker-header-transition-leave-active,.date-picker-header-reverse-transition-leave-active{transition-duration:.3s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.date-picker-header-transition-enter-from{transform:translateY(100%)}.date-picker-header-transition-leave-to{opacity:0;transform:translateY(-100%)}.date-picker-header-reverse-transition-enter-from{transform:translateY(-100%)}.date-picker-header-reverse-transition-leave-to{opacity:0;transform:translateY(100%)}.v-date-picker-month{display:flex;justify-content:center;padding:0 12px 8px;--v-date-picker-month-day-diff: 4px}.v-date-picker-month__weeks{display:grid;grid-template-rows:min-content min-content min-content min-content min-content min-content min-content;column-gap:4px;font-size:.85rem}.v-date-picker-month__weeks+.v-date-picker-month__days{grid-row-gap:0}.v-date-picker-month__weekday{font-size:.85rem}.v-date-picker-month__days{display:grid;grid-template-columns:min-content min-content min-content min-content min-content min-content min-content;column-gap:4px;flex:1 1;justify-content:space-around}.v-date-picker-month__day{align-items:center;display:flex;justify-content:center;position:relative;height:40px;width:40px}.v-date-picker-month__day--selected .v-btn{background-color:rgb(var(--v-theme-surface-variant));color:rgb(var(--v-theme-on-surface-variant))}.v-date-picker-month__day .v-btn.v-date-picker-month__day-btn{--v-btn-height: 24px;--v-btn-size: .85rem}.v-date-picker-month__day--week{font-size:var(--v-btn-size)}.v-date-picker-month__day--adjacent{opacity:.5}.v-date-picker-month__day--hide-adjacent{opacity:0}.v-date-picker-months{height:288px}.v-date-picker-months__content{align-items:center;display:grid;flex:1 1;height:inherit;justify-content:space-around;grid-template-columns:repeat(2,1fr);grid-gap:0px 24px;padding-inline-start:36px;padding-inline-end:36px}.v-date-picker-months__content .v-btn{text-transform:none;padding-inline-start:8px;padding-inline-end:8px}.v-date-picker-years{height:288px;overflow-y:scroll}.v-date-picker-years__content{display:grid;flex:1 1;justify-content:space-around;grid-template-columns:repeat(3,1fr);gap:8px 24px;padding-inline:32px}.v-date-picker-years__content .v-btn{padding-inline:8px}.v-picker.v-sheet{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:4px;display:grid;grid-auto-rows:min-content;grid-template-areas:"title" "header" "body";overflow:hidden}.v-picker.v-sheet.v-picker--with-actions{grid-template-areas:"title" "header" "body" "actions"}.v-picker__body{grid-area:body}.v-picker__header{grid-area:header}.v-picker__actions{grid-area:actions;padding:0 12px 12px;display:flex;align-items:center;justify-content:flex-end}.v-picker__actions .v-btn{min-width:48px}.v-picker__actions .v-btn:not(:last-child){margin-inline-end:8px}.v-picker--landscape{grid-template-areas:"title" "header body" "header body"}.v-picker--landscape.v-picker--with-actions{grid-template-areas:"title" "header body" "header actions"}.v-picker-title{text-transform:uppercase;font-size:.75rem;grid-area:title;padding-inline:24px 12px;padding-top:16px;padding-bottom:16px;font-weight:400;letter-spacing:.1666666667em}.v-expansion-panel{background-color:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-expansion-panel:not(:first-child):after{border-color:rgba(var(--v-border-color),var(--v-border-opacity))}.v-expansion-panel--disabled .v-expansion-panel-title{color:rgba(var(--v-theme-on-surface),.26)}.v-expansion-panel--disabled .v-expansion-panel-title .v-expansion-panel-title__overlay{opacity:.4615384615}.v-expansion-panels{display:flex;flex-wrap:wrap;justify-content:center;list-style-type:none;padding:0;width:100%;position:relative;z-index:1}.v-expansion-panels:not(.v-expansion-panels--variant-accordion)>:not(:first-child):not(:last-child):not(.v-expansion-panel--active):not(.v-expansion-panel--before-active){border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}.v-expansion-panels:not(.v-expansion-panels--variant-accordion)>:not(:first-child):not(:last-child):not(.v-expansion-panel--active):not(.v-expansion-panel--after-active){border-top-left-radius:0!important;border-top-right-radius:0!important}.v-expansion-panels:not(.v-expansion-panels--variant-accordion)>:first-child:not(:last-child):not(.v-expansion-panel--active):not(.v-expansion-panel--before-active){border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}.v-expansion-panels:not(.v-expansion-panels--variant-accordion)>:last-child:not(:first-child):not(.v-expansion-panel--active):not(.v-expansion-panel--after-active){border-top-left-radius:0!important;border-top-right-radius:0!important}.v-expansion-panels--variant-accordion>:first-child:not(:last-child){border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}.v-expansion-panels--variant-accordion>:last-child:not(:first-child){border-top-left-radius:0!important;border-top-right-radius:0!important}.v-expansion-panels--variant-accordion>:last-child:not(:first-child) .v-expansion-panel-title--active{border-bottom-left-radius:initial;border-bottom-right-radius:initial}.v-expansion-panels--variant-accordion>:not(:first-child):not(:last-child){border-radius:0!important}.v-expansion-panels--variant-accordion .v-expansion-panel-title__overlay{transition:.3s border-radius cubic-bezier(.4,0,.2,1)}.v-expansion-panel{flex:1 0 100%;max-width:100%;position:relative;transition:.3s all cubic-bezier(.4,0,.2,1);transition-property:margin-top,border-radius,border,max-width;border-radius:4px}.v-expansion-panel:not(:first-child):after{border-top-style:solid;border-top-width:thin;content:"";left:0;position:absolute;right:0;top:0;transition:.3s opacity cubic-bezier(.4,0,.2,1)}.v-expansion-panel--disabled .v-expansion-panel-title{pointer-events:none}.v-expansion-panel--active:not(:first-child),.v-expansion-panel--active+.v-expansion-panel{margin-top:16px}.v-expansion-panel--active:not(:first-child):after,.v-expansion-panel--active+.v-expansion-panel:after{opacity:0}.v-expansion-panel--active>.v-expansion-panel-title{border-bottom-left-radius:0;border-bottom-right-radius:0}.v-expansion-panel--active>.v-expansion-panel-title:not(.v-expansion-panel-title--static){min-height:64px}.v-expansion-panel__shadow{position:absolute;top:0;left:0;width:100%;height:100%;box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:inherit;z-index:-1}.v-expansion-panel-title{align-items:center;text-align:start;border-radius:inherit;display:flex;font-size:.9375rem;line-height:1;min-height:48px;outline:none;padding:16px 24px;position:relative;transition:.3s min-height cubic-bezier(.4,0,.2,1);width:100%;justify-content:space-between}.v-expansion-panel-title:hover>.v-expansion-panel-title__overlay{opacity:calc(var(--v-hover-opacity) * var(--v-theme-overlay-multiplier))}.v-expansion-panel-title:focus-visible>.v-expansion-panel-title__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-expansion-panel-title:focus>.v-expansion-panel-title__overlay{opacity:calc(var(--v-focus-opacity) * var(--v-theme-overlay-multiplier))}}.v-expansion-panel-title--focusable.v-expansion-panel-title--active .v-expansion-panel-title__overlay{opacity:calc(var(--v-activated-opacity) * var(--v-theme-overlay-multiplier))}.v-expansion-panel-title--focusable.v-expansion-panel-title--active:hover .v-expansion-panel-title__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-hover-opacity)) * var(--v-theme-overlay-multiplier))}.v-expansion-panel-title--focusable.v-expansion-panel-title--active:focus-visible .v-expansion-panel-title__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}@supports not selector(:focus-visible){.v-expansion-panel-title--focusable.v-expansion-panel-title--active:focus .v-expansion-panel-title__overlay{opacity:calc((var(--v-activated-opacity) + var(--v-focus-opacity)) * var(--v-theme-overlay-multiplier))}}.v-expansion-panel-title__overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:currentColor;border-radius:inherit;opacity:0}.v-expansion-panel-title__icon{display:inline-flex;margin-bottom:-4px;margin-top:-4px;-webkit-user-select:none;user-select:none;margin-inline-start:auto}.v-expansion-panel-text{display:flex}.v-expansion-panel-text__wrapper{padding:8px 24px 16px;flex:1 1 auto;max-width:100%}.v-expansion-panels--variant-accordion>.v-expansion-panel{margin-top:0}.v-expansion-panels--variant-accordion>.v-expansion-panel:after{opacity:1}.v-expansion-panels--variant-popout>.v-expansion-panel{max-width:calc(100% - 32px)}.v-expansion-panels--variant-popout>.v-expansion-panel--active{max-width:calc(100% + 16px)}.v-expansion-panels--variant-inset>.v-expansion-panel{max-width:100%}.v-expansion-panels--variant-inset>.v-expansion-panel--active{max-width:calc(100% - 32px)}.v-expansion-panels--flat>.v-expansion-panel:after{border-top:none}.v-expansion-panels--flat>.v-expansion-panel .v-expansion-panel__shadow{display:none}.v-expansion-panels--tile{border-radius:0}.v-expansion-panels--tile>.v-expansion-panel{border-radius:0}.v-file-input--chips.v-input--density-compact .v-field--variant-solo .v-label.v-field-label--floating,.v-file-input--chips.v-input--density-compact .v-field--variant-solo-inverted .v-label.v-field-label--floating,.v-file-input--chips.v-input--density-compact .v-field--variant-filled .v-label.v-field-label--floating,.v-file-input--chips.v-input--density-compact .v-field--variant-solo-filled .v-label.v-field-label--floating{top:0}.v-file-input input[type=file]{height:100%;left:0;opacity:0;position:absolute;top:0;width:100%;z-index:1}.v-file-input .v-input__details{padding-inline:16px}.v-input--plain-underlined.v-file-input .v-input__details{padding-inline:0}.v-infinite-scroll--horizontal{display:flex;flex-direction:row;overflow-x:auto}.v-infinite-scroll--horizontal .v-infinite-scroll-intersect{height:100%;width:1px}.v-infinite-scroll--vertical{display:flex;flex-direction:column;overflow-y:auto}.v-infinite-scroll--vertical .v-infinite-scroll-intersect{height:1px;width:100%}.v-infinite-scroll__side{align-items:center;display:flex;justify-content:center;padding:8px}.v-item-group{flex:0 1 auto;max-width:100%;position:relative;transition:.2s cubic-bezier(.4,0,.2,1)}.v-kbd{background:rgb(var(--v-theme-kbd));color:rgb(var(--v-theme-on-kbd));border-radius:3px;display:inline;font-size:85%;font-weight:400;padding:.2em .4rem;box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-locale-provider{display:contents}.v-navigation-drawer{-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;height:100%;max-width:100%;pointer-events:auto;transition-duration:.2s;transition-property:box-shadow,transform,visibility,width,height,left,right,top,bottom;transition-timing-function:cubic-bezier(.4,0,.2,1);position:absolute;border-color:rgba(var(--v-border-color),var(--v-border-opacity));border-style:solid;border-width:0;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));background:rgb(var(--v-theme-surface));color:rgba(var(--v-theme-on-surface),var(--v-high-emphasis-opacity))}.v-navigation-drawer--border{border-width:thin;box-shadow:none}.v-navigation-drawer--rounded{border-radius:4px}.v-navigation-drawer--top{top:0;border-bottom-width:thin}.v-navigation-drawer--bottom{left:0;border-top-width:thin}.v-navigation-drawer--left{top:0;left:0;right:auto;border-right-width:thin}.v-navigation-drawer--right{top:0;left:auto;right:0;border-left-width:thin}.v-navigation-drawer--floating{border:none}.v-navigation-drawer--temporary{box-shadow:0 8px 10px -5px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 16px 24px 2px var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 6px 30px 5px var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-navigation-drawer--sticky{height:auto;transition:box-shadow,transform,visibility,width,height,left,right}.v-navigation-drawer .v-list{overflow:hidden}.v-navigation-drawer__content{flex:0 1 auto;height:100%;max-width:100%;overflow-x:hidden;overflow-y:auto}.v-navigation-drawer__img{height:100%;left:0;position:absolute;top:0;width:100%;z-index:-1}.v-navigation-drawer__img img:not(.v-img__img){height:inherit;object-fit:cover;width:inherit}.v-navigation-drawer__scrim{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;opacity:.2;transition:opacity .2s cubic-bezier(.4,0,.2,1);z-index:1}.v-navigation-drawer__prepend,.v-navigation-drawer__append{flex:none;overflow:hidden}.v-otp-input{border-radius:4px;align-items:center;display:flex;justify-content:center;padding:.5rem 0;position:relative}.v-otp-input .v-field{height:100%}.v-otp-input__divider{margin:0 8px}.v-otp-input__content{align-items:center;display:flex;gap:.5rem;height:64px;padding:.5rem;justify-content:center;max-width:320px;position:relative;border-radius:inherit}.v-otp-input--divided .v-otp-input__content{max-width:360px}.v-otp-input__field{color:inherit;font-size:1.25rem;height:100%;outline:none;text-align:center;width:100%}.v-otp-input__field[type=number]::-webkit-outer-spin-button,.v-otp-input__field[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.v-otp-input__field[type=number]{-moz-appearance:textfield}.v-otp-input__loader{align-items:center;display:flex;height:100%;justify-content:center;width:100%}.v-otp-input__loader .v-progress-linear{position:absolute}.v-parallax{position:relative;overflow:hidden}.v-parallax--active>.v-img__img{will-change:transform}.v-radio-group>.v-input__control{flex-direction:column}.v-radio-group>.v-input__control>.v-label{margin-inline-start:16px}.v-radio-group>.v-input__control>.v-label+.v-selection-control-group{padding-inline-start:6px;margin-top:8px}.v-radio-group .v-input__details{padding-inline:16px}.v-rating{max-width:100%;display:inline-flex;white-space:nowrap}.v-rating--readonly{pointer-events:none}.v-rating__wrapper{align-items:center;display:inline-flex;flex-direction:column}.v-rating__wrapper--bottom{flex-direction:column-reverse}.v-rating__item{display:inline-flex;position:relative}.v-rating__item label{cursor:pointer}.v-rating__item .v-btn--variant-plain{opacity:1}.v-rating__item .v-btn{transition-property:transform}.v-rating__item .v-btn .v-icon{transition:inherit;transition-timing-function:cubic-bezier(0,0,.2,1)}.v-rating--hover .v-rating__item:hover:not(.v-rating__item--focused) .v-btn{transform:scale(1.25)}.v-rating__item--half{overflow:hidden;position:absolute;clip-path:polygon(0 0,50% 0,50% 100%,0 100%);z-index:1}.v-rating__item--half .v-btn__overlay,.v-rating__item--half:hover .v-btn__overlay{opacity:0}.v-rating__hidden{height:0;opacity:0;position:absolute;width:0}.v-skeleton-loader{align-items:center;background:rgb(var(--v-theme-surface));border-radius:4px;display:flex;flex-wrap:wrap;position:relative;vertical-align:top}.v-skeleton-loader__actions{justify-content:end}.v-skeleton-loader .v-skeleton-loader__ossein{height:100%}.v-skeleton-loader .v-skeleton-loader__avatar,.v-skeleton-loader .v-skeleton-loader__button,.v-skeleton-loader .v-skeleton-loader__chip,.v-skeleton-loader .v-skeleton-loader__divider,.v-skeleton-loader .v-skeleton-loader__heading,.v-skeleton-loader .v-skeleton-loader__image,.v-skeleton-loader .v-skeleton-loader__ossein,.v-skeleton-loader .v-skeleton-loader__text{background:rgba(var(--v-theme-on-surface),var(--v-border-opacity))}.v-skeleton-loader .v-skeleton-loader__list-item,.v-skeleton-loader .v-skeleton-loader__list-item-avatar,.v-skeleton-loader .v-skeleton-loader__list-item-text,.v-skeleton-loader .v-skeleton-loader__list-item-two-line,.v-skeleton-loader .v-skeleton-loader__list-item-avatar-two-line,.v-skeleton-loader .v-skeleton-loader__list-item-three-line,.v-skeleton-loader .v-skeleton-loader__list-item-avatar-three-line{border-radius:4px}.v-skeleton-loader__bone{align-items:center;border-radius:inherit;display:flex;flex:1 1 100%;flex-wrap:wrap;overflow:hidden;position:relative}.v-skeleton-loader__bone:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;animation:loading 1.5s infinite;background:linear-gradient(90deg,rgba(var(--v-theme-surface),0),rgba(var(--v-theme-surface),.3),rgba(var(--v-theme-surface),0));transform:translate(-100%);z-index:1}.v-skeleton-loader__avatar{border-radius:50%;flex:0 1 auto;margin:8px 16px;max-height:48px;min-height:48px;height:48px;max-width:48px;min-width:48px;width:48px}.v-skeleton-loader__avatar+.v-skeleton-loader__bone{flex:1 1 auto;margin-inline-start:0}.v-skeleton-loader__avatar+.v-skeleton-loader__sentences>.v-skeleton-loader__text,.v-skeleton-loader__avatar+.v-skeleton-loader__paragraph>.v-skeleton-loader__text{margin-inline-start:0}.v-skeleton-loader__button{border-radius:4px;height:36px;margin:16px;max-width:64px}.v-skeleton-loader__button+.v-skeleton-loader__bone{flex:1 1 auto;margin-inline-start:0}.v-skeleton-loader__button+.v-skeleton-loader__sentences>.v-skeleton-loader__text,.v-skeleton-loader__button+.v-skeleton-loader__paragraph>.v-skeleton-loader__text{margin-inline-start:0}.v-skeleton-loader__chip{border-radius:16px;margin:16px;height:32px;max-width:96px}.v-skeleton-loader__chip+.v-skeleton-loader__bone{flex:1 1 auto;margin-inline-start:0}.v-skeleton-loader__chip+.v-skeleton-loader__sentences>.v-skeleton-loader__text,.v-skeleton-loader__chip+.v-skeleton-loader__paragraph>.v-skeleton-loader__text{margin-inline-start:0}.v-skeleton-loader__date-picker{border-radius:inherit}.v-skeleton-loader__date-picker .v-skeleton-loader__list-item:first-child .v-skeleton-loader__text{max-width:88px;width:20%}.v-skeleton-loader__date-picker .v-skeleton-loader__heading{max-width:256px;width:40%}.v-skeleton-loader__date-picker-days{flex-wrap:wrap;margin:16px}.v-skeleton-loader__date-picker-days .v-skeleton-loader__avatar{border-radius:4px;margin:4px;max-width:100%}.v-skeleton-loader__date-picker-options{flex-wrap:nowrap}.v-skeleton-loader__date-picker-options .v-skeleton-loader__text{flex:1 1 auto}.v-skeleton-loader__divider{border-radius:1px;height:2px}.v-skeleton-loader__heading{border-radius:12px;margin:16px;height:24px}.v-skeleton-loader__heading+.v-skeleton-loader__subtitle{margin-top:-16px}.v-skeleton-loader__image{height:150px;border-radius:0}.v-skeleton-loader__card .v-skeleton-loader__image{border-radius:0}.v-skeleton-loader__list-item{margin:16px}.v-skeleton-loader__list-item .v-skeleton-loader__text{margin:0}.v-skeleton-loader__table-thead{justify-content:space-between}.v-skeleton-loader__table-thead .v-skeleton-loader__heading{margin-top:16px;max-width:16px}.v-skeleton-loader__table-tfoot{flex-wrap:nowrap}.v-skeleton-loader__table-tfoot>.v-skeleton-loader__text.v-skeleton-loader__bone{margin-top:16px}.v-skeleton-loader__table-row{align-items:baseline;margin:0 8px;justify-content:space-evenly;flex-wrap:nowrap}.v-skeleton-loader__table-row>.v-skeleton-loader__text.v-skeleton-loader__bone{margin-inline:8px}.v-skeleton-loader__table-row+.v-skeleton-loader__divider{margin:0 16px}.v-skeleton-loader__table-cell{align-items:center;display:flex;height:48px;width:88px}.v-skeleton-loader__table-cell .v-skeleton-loader__text{margin-bottom:0}.v-skeleton-loader__subtitle{max-width:70%}.v-skeleton-loader__subtitle>.v-skeleton-loader__text{height:16px;border-radius:8px}.v-skeleton-loader__text{border-radius:6px;margin:16px;height:12px}.v-skeleton-loader__text+.v-skeleton-loader__text{margin-top:-8px;max-width:50%}.v-skeleton-loader__text+.v-skeleton-loader__text+.v-skeleton-loader__text{max-width:70%}.v-skeleton-loader--boilerplate .v-skeleton-loader__bone:after{display:none}.v-skeleton-loader--is-loading{overflow:hidden}.v-skeleton-loader--tile,.v-skeleton-loader--tile .v-skeleton-loader__bone{border-radius:0}@keyframes loading{to{transform:translate(100%)}}.v-snackbar{justify-content:center;z-index:10000;margin:8px;margin-inline-end:calc(8px + var(--v-scrollbar-offset))}.v-snackbar:not(.v-snackbar--centered):not(.v-snackbar--top){align-items:flex-end}.v-snackbar__wrapper{align-items:center;display:flex;max-width:672px;min-height:48px;min-width:344px;overflow:hidden;padding:0;border-radius:4px}.v-snackbar--variant-plain,.v-snackbar--variant-outlined,.v-snackbar--variant-text,.v-snackbar--variant-tonal{background:transparent;color:inherit}.v-snackbar--variant-plain{opacity:.62}.v-snackbar--variant-plain:focus,.v-snackbar--variant-plain:hover{opacity:1}.v-snackbar--variant-plain .v-snackbar__overlay{display:none}.v-snackbar--variant-elevated,.v-snackbar--variant-flat{background:rgb(var(--v-theme-surface-variant));color:rgb(var(--v-theme-on-surface-variant))}.v-snackbar--variant-elevated{box-shadow:0 3px 5px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 6px 10px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 18px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-snackbar--variant-flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-snackbar--variant-outlined{border:thin solid currentColor}.v-snackbar--variant-text .v-snackbar__overlay{background:currentColor}.v-snackbar--variant-tonal .v-snackbar__underlay{background:currentColor;opacity:var(--v-activated-opacity);border-radius:inherit;position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.v-snackbar__content{flex-grow:1;font-size:.875rem;font-weight:400;letter-spacing:.0178571429em;line-height:1.25rem;margin-right:auto;padding:14px 16px;text-align:initial}.v-snackbar__actions{align-items:center;align-self:center;display:flex;margin-inline-end:8px}.v-snackbar__actions>.v-btn{padding:0 8px;min-width:auto}.v-snackbar__timer{width:100%;position:absolute;top:0}.v-snackbar__timer .v-progress-linear{transition:.2s linear}.v-snackbar--absolute{position:absolute;z-index:1}.v-snackbar--multi-line .v-snackbar__wrapper{min-height:68px}.v-snackbar--vertical .v-snackbar__wrapper{flex-direction:column}.v-snackbar--vertical .v-snackbar__wrapper .v-snackbar__actions{align-self:flex-end;margin-bottom:8px}.v-snackbar-transition-enter-active,.v-snackbar-transition-leave-active{transition-duration:.15s;transition-timing-function:cubic-bezier(0,0,.2,1)}.v-snackbar-transition-enter-active{transition-property:opacity,transform}.v-snackbar-transition-enter-from{opacity:0;transform:scale(.8)}.v-snackbar-transition-leave-active{transition-property:opacity}.v-snackbar-transition-leave-to{opacity:0}.v-stepper.v-sheet{box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));border-radius:4px;overflow:hidden}.v-stepper.v-sheet.v-stepper--flat{box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-stepper-header{box-shadow:0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));align-items:center;display:flex;position:relative;overflow-x:auto;justify-content:space-between;z-index:1}.v-stepper-header .v-divider{margin:0 -16px}.v-stepper-header .v-divider:last-child{margin-inline-end:0}.v-stepper-header .v-divider:first-child{margin-inline-start:0}.v-stepper--alt-labels .v-stepper-header{height:auto}.v-stepper--alt-labels .v-stepper-header .v-divider{align-self:flex-start;margin:35px -67px 0}.v-stepper-window{margin:1.5rem}.v-stepper-actions{display:flex;align-items:center;justify-content:space-between;padding:1rem}.v-stepper .v-stepper-actions{padding:0 1.5rem 1rem}.v-stepper-window-item .v-stepper-actions{padding:1.5rem 0 0}.v-stepper-item{align-items:center;align-self:stretch;display:inline-flex;flex:none;opacity:var(--v-medium-emphasis-opacity);padding:1.5rem;transition-duration:.2s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.v-stepper-item--selected{opacity:1}.v-stepper-item--error{color:rgb(var(--v-theme-error))}.v-stepper-item--disabled{opacity:var(--v-medium-emphasis-opacity);pointer-events:none}.v-stepper--alt-labels .v-stepper-item{flex-direction:column;justify-content:flex-start;align-items:center;flex-basis:175px}.v-stepper-item__avatar.v-avatar{background:rgba(var(--v-theme-surface-variant),var(--v-medium-emphasis-opacity));color:rgb(var(--v-theme-on-surface-variant));font-size:.75rem;margin-inline-end:8px}.v-stepper-item__avatar.v-avatar .v-icon{font-size:.875rem}.v-stepper-item--selected .v-stepper-item__avatar.v-avatar,.v-stepper-item--complete .v-stepper-item__avatar.v-avatar{background:rgb(var(--v-theme-surface-variant))}.v-stepper-item--error .v-stepper-item__avatar.v-avatar{background:rgb(var(--v-theme-error))}.v-stepper--alt-labels .v-stepper-item__avatar.v-avatar{margin-bottom:16px;margin-inline-end:0}.v-stepper-item__title{line-height:1}.v-stepper--mobile .v-stepper-item__title{display:none}.v-stepper-item__subtitle{font-size:.75rem;text-align:left;line-height:1;opacity:var(--v-medium-emphasis-opacity)}.v-stepper--alt-labels .v-stepper-item__subtitle{text-align:center}.v-stepper--mobile .v-stepper-item__subtitle{display:none}.v-switch .v-label{padding-inline-start:10px}.v-switch__loader{display:flex}.v-switch__loader .v-progress-circular{color:rgb(var(--v-theme-surface))}.v-switch__track,.v-switch__thumb{transition:none}.v-selection-control--error:not(.v-selection-control--disabled) .v-switch__track,.v-selection-control--error:not(.v-selection-control--disabled) .v-switch__thumb{background-color:rgb(var(--v-theme-error));color:rgb(var(--v-theme-on-error))}.v-switch__track-true{margin-inline-end:auto}.v-selection-control:not(.v-selection-control--dirty) .v-switch__track-true{opacity:0}.v-switch__track-false{margin-inline-start:auto}.v-selection-control--dirty .v-switch__track-false{opacity:0}.v-switch__track{display:inline-flex;align-items:center;font-size:.5rem;padding:0 5px;background-color:rgb(var(--v-theme-surface-variant));border-radius:9999px;height:14px;opacity:.6;min-width:36px;cursor:pointer;transition:.2s background-color cubic-bezier(.4,0,.2,1)}.v-switch--inset .v-switch__track{border-radius:9999px;font-size:.75rem;height:32px;min-width:52px}.v-switch__thumb{align-items:center;background-color:rgb(var(--v-theme-surface-bright));color:rgb(var(--v-theme-on-surface-bright));border-radius:50%;display:flex;font-size:.75rem;height:20px;justify-content:center;width:20px;pointer-events:none;transition:.15s .05s transform cubic-bezier(0,0,.2,1),.2s color cubic-bezier(.4,0,.2,1),.2s background-color cubic-bezier(.4,0,.2,1);position:relative;overflow:hidden}.v-switch:not(.v-switch--inset) .v-switch__thumb{box-shadow:0 2px 4px -1px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 4px 5px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 1px 10px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-switch.v-switch--flat:not(.v-switch--inset) .v-switch__thumb{background:rgb(var(--v-theme-surface-variant));color:rgb(var(--v-theme-on-surface-variant));box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-switch--inset .v-switch__thumb{height:24px;width:24px;transform:scale(.6666666667)}.v-switch--inset .v-switch__thumb--filled{transform:none}.v-switch--inset .v-selection-control--dirty .v-switch__thumb{transform:none;transition:.15s .05s transform cubic-bezier(0,0,.2,1)}.v-switch.v-input{flex:0 1 auto}.v-switch .v-selection-control{min-height:var(--v-input-control-height)}.v-switch .v-selection-control__input{border-radius:50%;transition:.2s transform cubic-bezier(.4,0,.2,1);transform:translate(-10px);position:absolute}.v-switch .v-selection-control__input .v-icon{position:absolute}.v-switch .v-selection-control--dirty .v-selection-control__input{transform:translate(10px)}.v-switch.v-switch--indeterminate .v-selection-control__input{transform:scale(.8)}.v-switch.v-switch--indeterminate .v-switch__thumb{transform:scale(.75);box-shadow:none}.v-switch.v-switch--inset .v-selection-control__wrapper{width:auto}.v-switch.v-input--vertical .v-label{min-width:max-content}.v-switch.v-input--vertical .v-selection-control__wrapper{transform:rotate(-90deg)}.v-system-bar{align-items:center;display:flex;flex:1 1 auto;height:24px;justify-content:flex-end;max-width:100%;padding-inline:8px;position:relative;text-align:end;width:100%;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12));background:rgba(var(--v-theme-surface-light));color:rgba(var(--v-theme-on-surface-light),var(--v-high-emphasis-opacity));font-size:.75rem;font-weight:400;letter-spacing:.0333333333em;line-height:1.25rem;text-transform:none}.v-system-bar .v-icon{opacity:var(--v-medium-emphasis-opacity)}.v-system-bar--absolute{position:absolute}.v-system-bar--fixed{position:fixed}.v-system-bar--rounded{border-radius:0}.v-system-bar--window{height:32px}.v-system-bar:not(.v-system-bar--absolute){padding-inline-end:calc(var(--v-scrollbar-offset) + 8px)}.v-tabs{display:flex;height:var(--v-tabs-height)}.v-tabs--density-default{--v-tabs-height: 48px}.v-tabs--density-default.v-tabs--stacked{--v-tabs-height: 72px}.v-tabs--density-comfortable{--v-tabs-height: 44px}.v-tabs--density-comfortable.v-tabs--stacked{--v-tabs-height: 68px}.v-tabs--density-compact{--v-tabs-height: 36px}.v-tabs--density-compact.v-tabs--stacked{--v-tabs-height: 60px}.v-tabs.v-slide-group--vertical{height:auto;flex:none;--v-tabs-height: 48px}.v-tabs--align-tabs-title:not(.v-slide-group--has-affixes) .v-tab:first-child{margin-inline-start:42px}.v-tabs--fixed-tabs .v-slide-group__content>*:last-child,.v-tabs--align-tabs-center .v-slide-group__content>*:last-child{margin-inline-end:auto}.v-tabs--fixed-tabs .v-slide-group__content>*:first-child,.v-tabs--align-tabs-center .v-slide-group__content>*:first-child{margin-inline-start:auto}.v-tabs--grow{flex-grow:1}.v-tabs--grow .v-tab{flex:1 0 auto;max-width:none}.v-tabs--align-tabs-end .v-tab:first-child{margin-inline-start:auto}.v-tabs--align-tabs-end .v-tab:last-child{margin-inline-end:0}@media (max-width: 1279.98px){.v-tabs.v-slide-group--is-overflowing.v-slide-group--horizontal:not(.v-slide-group--has-affixes) .v-tab:first-child{margin-inline-start:52px}.v-tabs.v-slide-group--is-overflowing.v-slide-group--horizontal:not(.v-slide-group--has-affixes) .v-tab:last-child{margin-inline-end:52px}}.v-tab.v-tab.v-btn{height:var(--v-tabs-height);border-radius:0;min-width:90px}.v-slide-group--horizontal .v-tab{max-width:360px}.v-slide-group--vertical .v-tab{justify-content:start}.v-tab__slider{position:absolute;bottom:0;left:0;height:2px;width:100%;background:currentColor;pointer-events:none;opacity:0}.v-tab--selected .v-tab__slider{opacity:1}.v-slide-group--vertical .v-tab__slider{top:0;height:100%;width:2px}.v-textarea .v-field{--v-textarea-control-height: var(--v-input-control-height)}.v-textarea .v-field__field{--v-input-control-height: var(--v-textarea-control-height)}.v-textarea .v-field__input{flex:1 1 auto;outline:none;-webkit-mask-image:linear-gradient(to bottom,transparent,transparent calc(var(--v-field-padding-top, 0) + var(--v-input-padding-top, 0) - 6px),black calc(var(--v-field-padding-top, 0) + var(--v-input-padding-top, 0) + 4px));mask-image:linear-gradient(to bottom,transparent,transparent calc(var(--v-field-padding-top, 0) + var(--v-input-padding-top, 0) - 6px),black calc(var(--v-field-padding-top, 0) + var(--v-input-padding-top, 0) + 4px))}.v-textarea .v-field__input.v-textarea__sizer{visibility:hidden;position:absolute;top:0;left:0;height:0!important;min-height:0!important;pointer-events:none}.v-textarea--no-resize .v-field__input{resize:none}.v-textarea .v-field--no-label textarea,.v-textarea .v-field--active textarea{opacity:1}.v-textarea textarea{opacity:0;flex:1;min-width:0;transition:.15s opacity cubic-bezier(.4,0,.2,1)}.v-textarea textarea:focus,.v-textarea textarea:active{outline:none}.v-textarea textarea:invalid{box-shadow:none}.v-theme-provider{background:rgb(var(--v-theme-background));color:rgb(var(--v-theme-on-background))}.v-timeline .v-timeline-divider__dot{background:rgb(var(--v-theme-surface-light))}.v-timeline .v-timeline-divider__inner-dot{background:rgb(var(--v-theme-on-surface))}.v-timeline{display:grid;grid-auto-flow:dense;position:relative}.v-timeline--horizontal.v-timeline{grid-column-gap:24px;width:100%}.v-timeline--horizontal.v-timeline .v-timeline-item:nth-child(2n) .v-timeline-item__body{grid-row:3;padding-block-start:24px}.v-timeline--horizontal.v-timeline .v-timeline-item:nth-child(2n) .v-timeline-item__opposite{grid-row:1;padding-block-end:24px;align-self:flex-end}.v-timeline--horizontal.v-timeline .v-timeline-item:nth-child(odd) .v-timeline-item__body{grid-row:1;padding-block-end:24px;align-self:flex-end}.v-timeline--horizontal.v-timeline .v-timeline-item:nth-child(odd) .v-timeline-item__opposite{grid-row:3;padding-block-start:24px}.v-timeline--vertical.v-timeline{row-gap:24px;height:100%}.v-timeline--vertical.v-timeline .v-timeline-item:first-child .v-timeline-divider,.v-timeline--vertical.v-timeline .v-timeline-item:first-child .v-timeline-item__body,.v-timeline--vertical.v-timeline .v-timeline-item:first-child .v-timeline-item__opposite{padding-block-start:24px}.v-timeline--vertical.v-timeline .v-timeline-item:last-child .v-timeline-divider,.v-timeline--vertical.v-timeline .v-timeline-item:last-child .v-timeline-item__body,.v-timeline--vertical.v-timeline .v-timeline-item:last-child .v-timeline-item__opposite{padding-block-end:24px}.v-timeline--vertical.v-timeline .v-timeline-item:nth-child(2n) .v-timeline-item__body{grid-column:1;padding-inline-end:24px}.v-timeline--vertical.v-timeline .v-timeline-item:nth-child(2n) .v-timeline-item__opposite{grid-column:3;padding-inline-start:24px}.v-timeline--vertical.v-timeline .v-timeline-item:nth-child(odd) .v-timeline-item__body{grid-column:3;padding-inline-start:24px}.v-timeline--vertical.v-timeline .v-timeline-item:nth-child(odd) .v-timeline-item__opposite{grid-column:1;justify-self:flex-end;padding-inline-end:24px}.v-timeline-item{display:contents}.v-timeline-divider{position:relative;display:flex;align-items:center}.v-timeline--horizontal .v-timeline-divider{flex-direction:row;grid-row:2;width:100%}.v-timeline--vertical .v-timeline-divider{height:100%;flex-direction:column;grid-column:2}.v-timeline-divider__before{background:rgba(var(--v-border-color),var(--v-border-opacity));position:absolute}.v-timeline--horizontal .v-timeline-divider__before{height:var(--v-timeline-line-thickness);width:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));inset-inline-start:-12px;inset-inline-end:initial}.v-timeline--vertical .v-timeline-divider__before{height:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));width:var(--v-timeline-line-thickness);top:-12px}.v-timeline-divider__after{background:rgba(var(--v-border-color),var(--v-border-opacity));position:absolute}.v-timeline--horizontal .v-timeline-divider__after{height:var(--v-timeline-line-thickness);width:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));inset-inline-end:-12px;inset-inline-start:initial}.v-timeline--vertical .v-timeline-divider__after{height:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));width:var(--v-timeline-line-thickness);bottom:-12px}.v-timeline--vertical .v-timeline-item:first-child .v-timeline-divider__before{height:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));top:0}.v-timeline--horizontal .v-timeline-item:first-child .v-timeline-divider__before{width:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));inset-inline-start:0;inset-inline-end:initial}.v-timeline--vertical .v-timeline-item:first-child .v-timeline-divider__after{height:calc(var(--v-timeline-line-size-base) - var(--v-timeline-line-inset) + var(--v-timeline-line-size-offset))}.v-timeline--horizontal .v-timeline-item:first-child .v-timeline-divider__after{width:calc(var(--v-timeline-line-size-base) - var(--v-timeline-line-inset) + var(--v-timeline-line-size-offset));inset-inline-end:-12px;inset-inline-start:initial}.v-timeline--vertical .v-timeline-item:last-child .v-timeline-divider__before{height:calc(var(--v-timeline-line-size-base) - var(--v-timeline-line-inset) + var(--v-timeline-line-size-offset))}.v-timeline--horizontal .v-timeline-item:last-child .v-timeline-divider__before{width:calc(var(--v-timeline-line-size-base) - var(--v-timeline-line-inset) + var(--v-timeline-line-size-offset))}.v-timeline--vertical .v-timeline-item:last-child .v-timeline-divider__after{height:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));bottom:0}.v-timeline--horizontal .v-timeline-item:last-child .v-timeline-divider__after{width:calc(var(--v-timeline-line-size-base) + 12px - var(--v-timeline-line-inset));inset-inline-end:0;inset-inline-start:initial}.v-timeline--vertical .v-timeline-item:only-child .v-timeline-divider__after{height:calc(var(--v-timeline-line-size-base) - var(--v-timeline-line-inset))}.v-timeline-divider__dot{z-index:1;flex-shrink:0;border-radius:50%;display:flex;justify-content:center;align-items:center;box-shadow:0 0 0 0 var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, .2)),0 0 0 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, .14)),0 0 0 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, .12))}.v-timeline-divider__dot--size-x-small{height:22px;width:22px}.v-timeline-divider__dot--size-x-small .v-timeline-divider__inner-dot{height:calc(100% - 6px);width:calc(100% - 6px)}.v-timeline-divider__dot--size-small{height:30px;width:30px}.v-timeline-divider__dot--size-small .v-timeline-divider__inner-dot{height:calc(100% - 8px);width:calc(100% - 8px)}.v-timeline-divider__dot--size-default{height:38px;width:38px}.v-timeline-divider__dot--size-default .v-timeline-divider__inner-dot{height:calc(100% - 8px);width:calc(100% - 8px)}.v-timeline-divider__dot--size-large{height:46px;width:46px}.v-timeline-divider__dot--size-large .v-timeline-divider__inner-dot{height:calc(100% - 8px);width:calc(100% - 8px)}.v-timeline-divider__dot--size-x-large{height:54px;width:54px}.v-timeline-divider__dot--size-x-large .v-timeline-divider__inner-dot{height:calc(100% - 10px);width:calc(100% - 10px)}.v-timeline-divider__inner-dot{align-items:center;border-radius:50%;display:flex;justify-content:center}.v-timeline--horizontal.v-timeline--justify-center{grid-template-rows:minmax(auto,50%) min-content minmax(auto,50%)}.v-timeline--vertical.v-timeline--justify-center{grid-template-columns:minmax(auto,50%) min-content minmax(auto,50%)}.v-timeline--horizontal.v-timeline--justify-auto{grid-template-rows:auto min-content auto}.v-timeline--vertical.v-timeline--justify-auto{grid-template-columns:auto min-content auto}.v-timeline--horizontal.v-timeline--density-comfortable{height:100%}.v-timeline--horizontal.v-timeline--density-comfortable.v-timeline--side-end{grid-template-rows:min-content min-content auto}.v-timeline--horizontal.v-timeline--density-comfortable.v-timeline--side-start{grid-template-rows:auto min-content min-content}.v-timeline--vertical.v-timeline--density-comfortable{width:100%}.v-timeline--vertical.v-timeline--density-comfortable.v-timeline--side-end{grid-template-columns:min-content min-content auto}.v-timeline--vertical.v-timeline--density-comfortable.v-timeline--side-start{grid-template-columns:auto min-content min-content}.v-timeline--horizontal.v-timeline--density-compact.v-timeline--side-end{grid-template-rows:0 min-content auto}.v-timeline--horizontal.v-timeline--density-compact.v-timeline--side-start{grid-template-rows:auto min-content 0}.v-timeline--horizontal.v-timeline--density-compact .v-timeline-item__body{grid-row:1}.v-timeline--vertical.v-timeline--density-compact.v-timeline--side-end{grid-template-columns:0 min-content auto}.v-timeline--vertical.v-timeline--density-compact.v-timeline--side-start{grid-template-columns:auto min-content 0}.v-timeline--vertical.v-timeline--density-compact .v-timeline-item__body{grid-column:3}.v-timeline--horizontal.v-timeline.v-timeline--side-end .v-timeline-item .v-timeline-item__body{grid-row:3;padding-block-end:initial;padding-block-start:24px}.v-timeline--horizontal.v-timeline.v-timeline--side-end .v-timeline-item .v-timeline-item__opposite{grid-row:1;padding-block-end:24px;padding-block-start:initial}.v-timeline--vertical.v-timeline.v-timeline--side-end .v-timeline-item .v-timeline-item__body{grid-column:3;padding-inline-start:24px;padding-inline-end:initial;justify-self:flex-start}.v-timeline--vertical.v-timeline.v-timeline--side-end .v-timeline-item .v-timeline-item__opposite{grid-column:1;justify-self:flex-end;padding-inline-end:24px;padding-inline-start:initial}.v-timeline--horizontal.v-timeline.v-timeline--side-start .v-timeline-item .v-timeline-item__body{grid-row:1;padding-block-end:24px;padding-block-start:initial}.v-timeline--horizontal.v-timeline.v-timeline--side-start .v-timeline-item .v-timeline-item__opposite{grid-row:3;padding-block-end:initial;padding-block-start:24px}.v-timeline--vertical.v-timeline.v-timeline--side-start .v-timeline-item .v-timeline-item__body{grid-column:1;justify-self:flex-end;padding-inline-end:24px}.v-timeline--vertical.v-timeline.v-timeline--side-start .v-timeline-item .v-timeline-item__opposite{grid-column:3;padding-inline-start:24px;justify-self:flex-start}.v-timeline-divider--fill-dot .v-timeline-divider__inner-dot{height:inherit;width:inherit}.v-timeline--align-center{--v-timeline-line-size-base: 50%;--v-timeline-line-size-offset: 0px}.v-timeline--horizontal.v-timeline--align-center{justify-items:center}.v-timeline--horizontal.v-timeline--align-center .v-timeline-item__body,.v-timeline--horizontal.v-timeline--align-center .v-timeline-item__opposite{padding-inline:12px}.v-timeline--horizontal.v-timeline--align-center .v-timeline-divider{justify-content:center}.v-timeline--vertical.v-timeline--align-center{align-items:center}.v-timeline--vertical.v-timeline--align-center .v-timeline-divider{justify-content:center}.v-timeline--align-start{--v-timeline-line-size-base: 100%;--v-timeline-line-size-offset: 12px}.v-timeline--align-start .v-timeline-item:first-child .v-timeline-divider__before{--v-timeline-line-size-offset: 24px}.v-timeline--align-start .v-timeline-item:first-child .v-timeline-divider__after{--v-timeline-line-size-offset: -12px}.v-timeline--align-start .v-timeline-item:last-child .v-timeline-divider__after{--v-timeline-line-size-offset: 0px}.v-timeline--horizontal.v-timeline--align-start{justify-items:flex-start}.v-timeline--horizontal.v-timeline--align-start .v-timeline-divider{justify-content:flex-start}.v-timeline--horizontal.v-timeline--align-start .v-timeline-divider .v-timeline-divider__before{width:calc(var(--v-timeline-line-size-offset) + var(--v-timeline-dot-size) / 2 - var(--v-timeline-line-inset))}.v-timeline--horizontal.v-timeline--align-start .v-timeline-divider .v-timeline-divider__after{width:calc(var(--v-timeline-line-size-base) - var(--v-timeline-dot-size) / 2 + var(--v-timeline-line-size-offset) - var(--v-timeline-line-inset))}.v-timeline--vertical.v-timeline--align-start{align-items:flex-start}.v-timeline--vertical.v-timeline--align-start .v-timeline-divider{justify-content:flex-start}.v-timeline--vertical.v-timeline--align-start .v-timeline-divider .v-timeline-divider__before{height:calc(var(--v-timeline-line-size-offset) + var(--v-timeline-dot-size) / 2 - var(--v-timeline-line-inset))}.v-timeline--vertical.v-timeline--align-start .v-timeline-divider .v-timeline-divider__after{height:calc(var(--v-timeline-line-size-base) - var(--v-timeline-dot-size) / 2 + var(--v-timeline-line-size-offset) - var(--v-timeline-line-inset))}.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-divider__before{display:none}.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-divider__after{--v-timeline-line-size-offset: 12px}.v-timeline--vertical.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-divider,.v-timeline--vertical.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-item__body,.v-timeline--vertical.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-item__opposite{padding-block-start:0}.v-timeline--horizontal.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-divider,.v-timeline--horizontal.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-item__body,.v-timeline--horizontal.v-timeline--truncate-line-start .v-timeline-item:first-child .v-timeline-item__opposite{padding-inline-start:0}.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-divider__after{display:none}.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-divider__before{--v-timeline-line-size-offset: 12px}.v-timeline--vertical.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-divider,.v-timeline--vertical.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-item__body,.v-timeline--vertical.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-item__opposite{padding-block-end:0}.v-timeline--horizontal.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-divider,.v-timeline--horizontal.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-item__body,.v-timeline--horizontal.v-timeline--truncate-line-end .v-timeline-item:last-child .v-timeline-item__opposite{padding-inline-end:0}.v-tooltip>.v-overlay__content{background:rgb(var(--v-theme-surface-variant));color:rgb(var(--v-theme-on-surface-variant));border-radius:4px;font-size:.875rem;line-height:1.6;display:inline-block;padding:5px 16px;text-transform:initial;width:auto;opacity:1;pointer-events:none;transition-property:opacity,transform;overflow-wrap:break-word}.v-tooltip>.v-overlay__content[class*=enter-active]{transition-timing-function:cubic-bezier(0,0,.2,1);transition-duration:.15s}.v-tooltip>.v-overlay__content[class*=leave-active]{transition-timing-function:cubic-bezier(.4,0,1,1);transition-duration:75ms}.leaflet-pane,.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile-container,.leaflet-pane>svg,.leaflet-pane>canvas,.leaflet-zoom-box,.leaflet-image-layer,.leaflet-layer{position:absolute;left:0;top:0}.leaflet-container{overflow:hidden}.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-tile::selection{background:transparent}.leaflet-safari .leaflet-tile{image-rendering:-webkit-optimize-contrast}.leaflet-safari .leaflet-tile-container{width:1600px;height:1600px;-webkit-transform-origin:0 0}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container .leaflet-overlay-pane svg{max-width:none!important;max-height:none!important}.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-shadow-pane img,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer,.leaflet-container .leaflet-tile{max-width:none!important;max-height:none!important;width:auto;padding:0}.leaflet-container img.leaflet-tile{mix-blend-mode:plus-lighter}.leaflet-container.leaflet-touch-zoom{-ms-touch-action:pan-x pan-y;touch-action:pan-x pan-y}.leaflet-container.leaflet-touch-drag{-ms-touch-action:pinch-zoom;touch-action:none;touch-action:pinch-zoom}.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{-ms-touch-action:none;touch-action:none}.leaflet-container{-webkit-tap-highlight-color:transparent}.leaflet-container a{-webkit-tap-highlight-color:rgba(51,181,229,.4)}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0;-moz-box-sizing:border-box;box-sizing:border-box;z-index:800}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-pane{z-index:400}.leaflet-tile-pane{z-index:200}.leaflet-overlay-pane{z-index:400}.leaflet-shadow-pane{z-index:500}.leaflet-marker-pane{z-index:600}.leaflet-tooltip-pane{z-index:650}.leaflet-popup-pane{z-index:700}.leaflet-map-pane canvas{z-index:100}.leaflet-map-pane svg{z-index:200}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{position:relative;z-index:800;pointer-events:visiblePainted;pointer-events:auto}.leaflet-top,.leaflet-bottom{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-control{float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-fade-anim .leaflet-popup{opacity:0;-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-animated{-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0}svg.leaflet-zoom-animated{will-change:transform}.leaflet-zoom-anim .leaflet-zoom-animated{-webkit-transition:-webkit-transform .25s cubic-bezier(0,0,.25,1);-moz-transition:-moz-transform .25s cubic-bezier(0,0,.25,1);transition:transform .25s cubic-bezier(0,0,.25,1)}.leaflet-zoom-anim .leaflet-tile,.leaflet-pan-anim .leaflet-tile{-webkit-transition:none;-moz-transition:none;transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive{cursor:crosshair}.leaflet-popup-pane,.leaflet-control{cursor:auto}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable{cursor:move;cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-image-layer,.leaflet-pane>svg path,.leaflet-tile-container{pointer-events:none}.leaflet-marker-icon.leaflet-interactive,.leaflet-image-layer.leaflet-interactive,.leaflet-pane>svg path.leaflet-interactive,svg.leaflet-image-layer.leaflet-interactive path{pointer-events:visiblePainted;pointer-events:auto}.leaflet-container{background:#ddd;outline-offset:1px}.leaflet-container a{color:#0078a8}.leaflet-zoom-box{border:2px dotted #38f;background:#ffffff80}.leaflet-container{font-family:Helvetica Neue,Arial,Helvetica,sans-serif;font-size:12px;font-size:.75rem;line-height:1.5}.leaflet-bar{box-shadow:0 1px 5px #000000a6;border-radius:4px}.leaflet-bar a{background-color:#fff;border-bottom:1px solid #ccc;width:26px;height:26px;line-height:26px;display:block;text-align:center;text-decoration:none;color:#000}.leaflet-bar a,.leaflet-control-layers-toggle{background-position:50% 50%;background-repeat:no-repeat;display:block}.leaflet-bar a:hover,.leaflet-bar a:focus{background-color:#f4f4f4}.leaflet-bar a:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.leaflet-bar a:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom:none}.leaflet-bar a.leaflet-disabled{cursor:default;background-color:#f4f4f4;color:#bbb}.leaflet-touch .leaflet-bar a{width:30px;height:30px;line-height:30px}.leaflet-touch .leaflet-bar a:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.leaflet-touch .leaflet-bar a:last-child{border-bottom-left-radius:2px;border-bottom-right-radius:2px}.leaflet-control-zoom-in,.leaflet-control-zoom-out{font:700 18px Lucida Console,Monaco,monospace;text-indent:1px}.leaflet-touch .leaflet-control-zoom-in,.leaflet-touch .leaflet-control-zoom-out{font-size:22px}.leaflet-control-layers{box-shadow:0 1px 5px #0006;background:#fff;border-radius:5px}.leaflet-control-layers-toggle{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAQAAAADQ4RFAAACf0lEQVR4AY1UM3gkARTePdvdoTxXKc+qTl3aU5U6b2Kbkz3Gtq3Zw6ziLGNPzrYx7946Tr6/ee/XeCQ4D3ykPtL5tHno4n0d/h3+xfuWHGLX81cn7r0iTNzjr7LrlxCqPtkbTQEHeqOrTy4Yyt3VCi/IOB0v7rVC7q45Q3Gr5K6jt+3Gl5nCoDD4MtO+j96Wu8atmhGqcNGHObuf8OM/x3AMx38+4Z2sPqzCxRFK2aF2e5Jol56XTLyggAMTL56XOMoS1W4pOyjUcGGQdZxU6qRh7B9Zp+PfpOFlqt0zyDZckPi1ttmIp03jX8gyJ8a/PG2yutpS/Vol7peZIbZcKBAEEheEIAgFbDkz5H6Zrkm2hVWGiXKiF4Ycw0RWKdtC16Q7qe3X4iOMxruonzegJzWaXFrU9utOSsLUmrc0YjeWYjCW4PDMADElpJSSQ0vQvA1Tm6/JlKnqFs1EGyZiFCqnRZTEJJJiKRYzVYzJck2Rm6P4iH+cmSY0YzimYa8l0EtTODFWhcMIMVqdsI2uiTvKmTisIDHJ3od5GILVhBCarCfVRmo4uTjkhrhzkiBV7SsaqS+TzrzM1qpGGUFt28pIySQHR6h7F6KSwGWm97ay+Z+ZqMcEjEWebE7wxCSQwpkhJqoZA5ivCdZDjJepuJ9IQjGGUmuXJdBFUygxVqVsxFsLMbDe8ZbDYVCGKxs+W080max1hFCarCfV+C1KATwcnvE9gRRuMP2prdbWGowm1KB1y+zwMMENkM755cJ2yPDtqhTI6ED1M/82yIDtC/4j4BijjeObflpO9I9MwXTCsSX8jWAFeHr05WoLTJ5G8IQVS/7vwR6ohirYM7f6HzYpogfS3R2OAAAAAElFTkSuQmCC);width:36px;height:36px}.leaflet-retina .leaflet-control-layers-toggle{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAQAAABvcdNgAAAEsklEQVR4AWL4TydIhpZK1kpWOlg0w3ZXP6D2soBtG42jeI6ZmQTHzAxiTbSJsYLjO9HhP+WOmcuhciVnmHVQcJnp7DFvScowZorad/+V/fVzMdMT2g9Cv9guXGv/7pYOrXh2U+RRR3dSd9JRx6bIFc/ekqHI29JC6pJ5ZEh1yWkhkbcFeSjxgx3L2m1cb1C7bceyxA+CNjT/Ifff+/kDk2u/w/33/IeCMOSaWZ4glosqT3DNnNZQ7Cs58/3Ce5HL78iZH/vKVIaYlqzfdLu8Vi7dnvUbEza5Idt36tquZFldl6N5Z/POLof0XLK61mZCmJSWjVF9tEjUluu74IUXvgttuVIHE7YxSkaYhJZam7yiM9Pv82JYfl9nptxZaxMJE4YSPty+vF0+Y2up9d3wwijfjZbabqm/3bZ9ecKHsiGmRflnn1MW4pjHf9oLufyn2z3y1D6n8g8TZhxyzipLNPnAUpsOiuWimg52psrTZYnOWYNDTMuWBWa0tJb4rgq1UvmutpaYEbZlwU3CLJm/ayYjHW5/h7xWLn9Hh1vepDkyf7dE7MtT5LR4e7yYpHrkhOUpEfssBLq2pPhAqoSWKUkk7EDqkmK6RrCEzqDjhNDWNE+XSMvkJRDWlZTmCW0l0PHQGRZY5t1L83kT0Y3l2SItk5JAWHl2dCOBm+fPu3fo5/3v61RMCO9Jx2EEYYhb0rmNQMX/vm7gqOEJLcXTGw3CAuRNeyaPWwjR8PRqKQ1PDA/dpv+on9Shox52WFnx0KY8onHayrJzm87i5h9xGw/tfkev0jGsQizqezUKjk12hBMKJ4kbCqGPVNXudyyrShovGw5CgxsRICxF6aRmSjlBnHRzg7Gx8fKqEubI2rahQYdR1YgDIRQO7JvQyD52hoIQx0mxa0ODtW2Iozn1le2iIRdzwWewedyZzewidueOGqlsn1MvcnQpuVwLGG3/IR1hIKxCjelIDZ8ldqWz25jWAsnldEnK0Zxro19TGVb2ffIZEsIO89EIEDvKMPrzmBOQcKQ+rroye6NgRRxqR4U8EAkz0CL6uSGOm6KQCdWjvjRiSP1BPalCRS5iQYiEIvxuBMJEWgzSoHADcVMuN7IuqqTeyUPq22qFimFtxDyBBJEwNyt6TM88blFHao/6tWWhuuOM4SAK4EI4QmFHA+SEyWlp4EQoJ13cYGzMu7yszEIBOm2rVmHUNqwAIQabISNMRstmdhNWcFLsSm+0tjJH1MdRxO5Nx0WDMhCtgD6OKgZeljJqJKc9po8juskR9XN0Y1lZ3mWjLR9JCO1jRDMd0fpYC2VnvjBSEFg7wBENc0R9HFlb0xvF1+TBEpF68d+DHR6IOWVv2BECtxo46hOFUBd/APU57WIoEwJhIi2CdpyZX0m93BZicktMj1AS9dClteUFAUNUIEygRZCtik5zSxI9MubTBH1GOiHsiLJ3OCoSZkILa9PxiN0EbvhsAo8tdAf9Seepd36lGWHmtNANTv5Jd0z4QYyeo/UEJqxKRpg5LZx6btLPsOaEmdMyxYdlc8LMaJnikDlhclqmPiQnTEpLUIZEwkRagjYkEibQErwhkTAKCLQEbUgkzJQWc/0PstHHcfEdQ+UAAAAASUVORK5CYII=);background-size:26px 26px}.leaflet-touch .leaflet-control-layers-toggle{width:44px;height:44px}.leaflet-control-layers .leaflet-control-layers-list,.leaflet-control-layers-expanded .leaflet-control-layers-toggle{display:none}.leaflet-control-layers-expanded .leaflet-control-layers-list{display:block;position:relative}.leaflet-control-layers-expanded{padding:6px 10px 6px 6px;color:#333;background:#fff}.leaflet-control-layers-scrollbar{overflow-y:scroll;overflow-x:hidden;padding-right:5px}.leaflet-control-layers-selector{margin-top:2px;position:relative;top:1px}.leaflet-control-layers label{display:block;font-size:13px;font-size:1.08333em}.leaflet-control-layers-separator{height:0;border-top:1px solid #ddd;margin:5px -10px 5px -6px}.leaflet-default-icon-path{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII=)}.leaflet-container .leaflet-control-attribution{background:#fff;background:#fffc;margin:0}.leaflet-control-attribution,.leaflet-control-scale-line{padding:0 5px;color:#333;line-height:1.4}.leaflet-control-attribution a{text-decoration:none}.leaflet-control-attribution a:hover,.leaflet-control-attribution a:focus{text-decoration:underline}.leaflet-attribution-flag{display:inline!important;vertical-align:baseline!important;width:1em;height:.6669em}.leaflet-left .leaflet-control-scale{margin-left:5px}.leaflet-bottom .leaflet-control-scale{margin-bottom:5px}.leaflet-control-scale-line{border:2px solid #777;border-top:none;line-height:1.1;padding:2px 5px 1px;white-space:nowrap;-moz-box-sizing:border-box;box-sizing:border-box;background:#fffc;text-shadow:1px 1px #fff}.leaflet-control-scale-line:not(:first-child){border-top:2px solid #777;border-bottom:none;margin-top:-2px}.leaflet-control-scale-line:not(:first-child):not(:last-child){border-bottom:2px solid #777}.leaflet-touch .leaflet-control-attribution,.leaflet-touch .leaflet-control-layers,.leaflet-touch .leaflet-bar{box-shadow:none}.leaflet-touch .leaflet-control-layers,.leaflet-touch .leaflet-bar{border:2px solid rgba(0,0,0,.2);background-clip:padding-box}.leaflet-popup{position:absolute;text-align:center;margin-bottom:20px}.leaflet-popup-content-wrapper{padding:1px;text-align:left;border-radius:12px}.leaflet-popup-content{margin:13px 24px 13px 20px;line-height:1.3;font-size:13px;font-size:1.08333em;min-height:1px}.leaflet-popup-content p{margin:1.3em 0}.leaflet-popup-tip-container{width:40px;height:20px;position:absolute;left:50%;margin-top:-1px;margin-left:-20px;overflow:hidden;pointer-events:none}.leaflet-popup-tip{width:17px;height:17px;padding:1px;margin:-10px auto 0;pointer-events:auto;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.leaflet-popup-content-wrapper,.leaflet-popup-tip{background:#fff;color:#333;box-shadow:0 3px 14px #0006}.leaflet-container a.leaflet-popup-close-button{position:absolute;top:0;right:0;border:none;text-align:center;width:24px;height:24px;font:16px/24px Tahoma,Verdana,sans-serif;color:#757575;text-decoration:none;background:transparent}.leaflet-container a.leaflet-popup-close-button:hover,.leaflet-container a.leaflet-popup-close-button:focus{color:#585858}.leaflet-popup-scrolled{overflow:auto}.leaflet-oldie .leaflet-popup-content-wrapper{-ms-zoom:1}.leaflet-oldie .leaflet-popup-tip{width:24px;margin:0 auto;-ms-filter:"progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";filter:progid:DXImageTransform.Microsoft.Matrix(M11=.70710678,M12=.70710678,M21=-.70710678,M22=.70710678)}.leaflet-oldie .leaflet-control-zoom,.leaflet-oldie .leaflet-control-layers,.leaflet-oldie .leaflet-popup-content-wrapper,.leaflet-oldie .leaflet-popup-tip{border:1px solid #999}.leaflet-div-icon{background:#fff;border:1px solid #666}.leaflet-tooltip{position:absolute;padding:6px;background-color:#fff;border:1px solid #fff;border-radius:3px;color:#222;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;box-shadow:0 1px 3px #0006}.leaflet-tooltip.leaflet-interactive{cursor:pointer;pointer-events:auto}.leaflet-tooltip-top:before,.leaflet-tooltip-bottom:before,.leaflet-tooltip-left:before,.leaflet-tooltip-right:before{position:absolute;pointer-events:none;border:6px solid transparent;background:transparent;content:""}.leaflet-tooltip-bottom{margin-top:6px}.leaflet-tooltip-top{margin-top:-6px}.leaflet-tooltip-bottom:before,.leaflet-tooltip-top:before{left:50%;margin-left:-6px}.leaflet-tooltip-top:before{bottom:0;margin-bottom:-12px;border-top-color:#fff}.leaflet-tooltip-bottom:before{top:0;margin-top:-12px;margin-left:-6px;border-bottom-color:#fff}.leaflet-tooltip-left{margin-left:-6px}.leaflet-tooltip-right{margin-left:6px}.leaflet-tooltip-left:before,.leaflet-tooltip-right:before{top:50%;margin-top:-6px}.leaflet-tooltip-left:before{right:0;margin-right:-12px;border-left-color:#fff}.leaflet-tooltip-right:before{left:0;margin-left:-12px;border-right-color:#fff}@media print{.leaflet-control{-webkit-print-color-adjust:exact;print-color-adjust:exact}}.leaflet-draw-section{position:relative}.leaflet-draw-toolbar{margin-top:12px}.leaflet-draw-toolbar-top{margin-top:0}.leaflet-draw-toolbar-notop a:first-child{border-top-right-radius:0}.leaflet-draw-toolbar-nobottom a:last-child{border-bottom-right-radius:0}.leaflet-draw-toolbar a{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAAeCAYAAACWuCNnAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAG7AAABuwBHnU4NQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAbvSURBVHic7dtdbBxXFQfw/9nZ3SRKwAP7UFFUQOoHqGnUoEAoNghX9tyxVcpD1X0J+WgiUQmpfUB5ACSgG1qJIKASqBIUIauqAbWseIlqb+bOWHVR6y0FKZBEqdIUQROIREGRx3FFvR/38ODZst3a3nE8Ywfv+T2t7hzdM3fle/bOnWtACCGEEEIIIYQQQgghhBBCCCGEEEIIIcRa0EbfgBDdFItFKwzDAa3175LuWylVAvBIR/MxrXUp6Vxx9dp4VyObVEdKKW591lonXgiVUg6AHzPzk9ls9meVSmUh6RzXkz179uQKhcIgM+8CACI6U6vVnp+enm6knXt4ePiuTCbzWQAwxlSDIHg57ZwroDAMnwKwz3XdBzzPG08hxzsTNprQG2lTjtd13WFmfghAP4A+AJcATFiW9YNKpfL3uP0kUliiX4SG1pqUUpx0wXJd9/PMXAGwPWq6yMyPz8/P/7xarf4nyVwt7QV4JWkU52i8YwBu6bh0wRhzJAiCF5POCQCDg4N2Pp//NYDRjkuTxph9QRCESeYrFov5ubm5R5n5AIAPtV1aYOb7BgYGTpZKJeO67lFmPsbM9/i+/8Ja8y6zylhOYquPXhsvAJRKpczMzMwTAIaJ6LFGo+HNzs5eKRQKNxPRAWb+CoAjWuvn4vS35skWFasxAAdbbUlOYqVUPwAPwI4lLr8J4KeWZT1eqVTmksoZ5d2QghUVKx/AlmVCFph5yPf9l5LMCwBKqUksFqszRHQcAJj5GwB2MfOE7/tfTDKf4zjHiejrAE4CuNhqZ+bf2rY9FYbhGBH92/O8o47j3Oj7/uUk86+3XhsvACilHmPmgW3btn3pxIkTVzuvj4yMfNoY85wxZiQIglPd+lvTZIuq5xiAQwCe6evr218ul5tr6bNd9GiiAbyvS+hFrfVHk8oLbEzBih4Dz+G9K6t3IaLXFhYWdib5eBh911UA8wBu1lq/CQBDQ0M3WJb1OoAdRPQZz/NeSSqnUuofAKpa6/vb26MfwacA7AdwFcCdWuu/JpU3yl1C91VHoquNXhvvyMjIx4wxr1iWtbNSqfxruTjHcR4AcMj3/bu79XnNe1hpFyvHcXYT0QS6FysASHR1tVEKhcIguhQrAGDm23K53BcATCWV27KsAWYGgPOtYgUAU1NT/1RKnQewxxjzOQCJFSwANwI4297QtmLfD+AtZr43m83OJ5iz3bGU+l1OT43XGFNk5mdXKlYAYNv2eBiG31dK3aS1vrRSbOZabqRYLFppFisAIKJxAB+MGf56krk30O64gZlMJnZsHMxsoo8fHxoauqHVHn3+BAAQUaxV57Xq2F54i5nvIaJXm81mYoX5etID491JRH/sFlQul5tEdMoYc3u32FUXrLYvObViBQDM/MQqwi8knX8jEJHpHrXIGJNo8WDm1spph2VZgeu6+5RSX7YsK8D/Xnb8Psmcnebm5h7G4uS9ysxutOH8VQC70sy7UTb7eImImTnWlgkzUyaT6fr3v6qC1fGL8EytVjuQRrECANu2fwHg1TixzPyXNO5hvTHz6VWE/znJ3L7vzxBRa9PzDmb+FYBfArgjajvd39+f9vGGKwACZh5te6mwmc8KburxMvO5TCbzqW5xxWLRArDbsqyu8z32HtZSxSrNM0Hlcrnpum6JmZ+NEb4pHglrtdrz+Xz+AoBbu4Ser9fra37d3YEBfBvAkq+XmfmbpVIp9grwWnie9zSAp9PMcT3Z7OPNZrO/aTQaf1BKfbd9X7RTGIaHmPlcnPNYsVZYSikOw7AB4CAzj/f19e1fjwOMnueVEeMxJJfLbYqCNT093TDGHAGw0qHYBQBH0vj+Pc+bYOb3HFRk5nHf9yeTzgfgMhF9uEvMTQD+71/vR3pqvJOTk28AeBJAeXR09P1LxbiuuxfA9wB8LU6fsVdYrUOhtm0fTusxcAlMRN+KziUt5SqAM3v37r00OZnGfFp/QRC86DjOUCaTGWPm2zoun8fiIbuZtPLX6/UH8/n8rQDuippertfrD6aRKyqOR5VS81ji8Z+IbmfmgwB+mEb+9dZr4wWA/v7+R6rV6k+azeYpx3EezeVyJ7dv335lfn7+lkajcZCZDzPzYd/3/xSnv9gFq3UuaR2LFQDA87xAKVUB8BEAZ6N9nrNEdEZr/TcArLVOPG8aJ9jj8n3/pcHBwZ1btmx5519zmPl0vV5/Ie2V7fT09Nujo6Nus9kcA4CtW7ce1lq/nUYu27a/Mzs7CyI6gMVX/u/CzJeZ+Ue2bcc9pb1aXc8lJZms18YLANE2wkOu694N4OFGo3E8DMMPAHiDiCaY+ZOb4YCsEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhEjYfwGO+b5dFNs4OgAAAABJRU5ErkJggg==);background-image:linear-gradient(transparent,transparent),url(/app/assets/spritesheet-DpIxuf5L.svg);background-repeat:no-repeat;background-size:300px 30px;background-clip:padding-box}.leaflet-retina .leaflet-draw-toolbar a{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlgAAAA8CAYAAAC6nMS5AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA16SURBVHic7d1/jBxneQfw7zNzvotdn+9sVQkxoRKoammBqqpbk6uT5mLfvHPn42yn1VFRVCEhoFH5IYpoSaUCKi1NcGkcfrbCVRFKEwG2aHLn83pmLvY2CTqT1AmCOBE0EOT4B0nBPw/snb2dp3/sLr6s77i923dud/a+H8ny7tzMo8f3eud99p133gGIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiFYGaXYCRETUPMYYrWe/MAzZX2QQ27d5OpqdABFROxgZGVlz5cqVrzuOc18QBJPNzofsYvvSYrVcgTVftZ2l6npgYODXHMc5oKoHHcfZHQTB2WbnRETpGRkZWVMoFA6IyO2qutX3/R1Z64TnO8fWOwLSzti+mSKDg4M3l0qlnSJyG4CbAFwP4ByAlwE8paoPX3fddcH4+PjP00yk5QqsrDPGvAZAHsBrReRNqvpeY8x/iMg9QRCcaXJ6ZIHv+xtUdReAHQBej/IHGABOAnhORMY6OjoempiYONe0JC3zPM84jjOqqrfi6r/3RQCPAdgXhmHUvOyaa3R01L1w4cJBALdVNq1W1THP87woir7ZzNyocWzf7PA8b4uI7E6S5A9Frqknb6j8eZOIvKNQKPzU9/1/dhznvlwuV0gjn5YbFapW09Vqu/Z9K9u2bdsNruvmUe50axUAfMV13X/I5XInlzcze2x/28lCu1b19fWt7u7u/hCAvwGwboHdL6jq7unp6T1TU1OXlyG9VAwODv5mkiR7Ady6wK6Plkqldz/yyCPfX468bBkaGuqamZm5E8DbReQNANYscMiLIrI1CILnZ280xrwHwL+hck4VkacBDLTS6HVaIxWt/Blm+zauldu3atOmTas2bNjwWRG5s7LplKp+VUQOuq77/bVr17589uzZ9SKy0XGcAVUdFZE/qOx7zHXdXWn0yy31i6sMw/4MyF6BZYy5XlWPiMhvL7BrrKpfcxznE7Uf4ixYqQWW53kbATw060NZr28nSbJzcnLyRBp5pcnzvNtE5CEAvXUecg7ArjAMH00xLWuGhoZuKpVKEwB+p85DXnRd9/ZcLvcDAOjv778un88XAChwtRMWkW+jxTpfYOV1wGxfO1q1fav6+vpWr1u3blxVtwH4uar+/fT09OcW+mJrjBkBcC+AXwdwBoAJw/AZm7m1zC+uUlyNA9g6189buZH7+/t/tbOz8wiANy7isKKqftV13U8eOnToe2nlZttKLLAqJ+qjAF69xBAnZ2Zmbj58+PApm3mlqTJydRTXFldHAUxVXvcBuLnm5+dU9c1RFP1v2jk2YmhoqKtUKj2B+jvfE0mS3D45OflD4OqcHADPh2H4F6h0wp7nva1YLOby+fz5dDKnerB9Vwzxff8BVX0bgFMAdoZheKzeg4eHh9cXi8WvAfAAvOC67ptzudz/WUvOVqBGVO7OmBCR/vn2adWOuL+/v7ezs3MSwKYlhkgAHBSRjwdB8JTF1FKx0gqsymXBxwH8XoOh/ieO41vz+fwVG3mlzRjzKF55WfA8gD8LwzA3ez/P87aLyIMAeqrbVDUfRdHty5Pp0hhjPgDgM9X3qnq/iNwPYM5RCdd1T1RPvLM63+q/ce/sTpiaj+27Mvi+f6eq/iuAi67r9uVyuWcXG6NSjB8B0KeqE1EUvcVWfk3v3OYZuXosjuPt+Xx+ull51WNgYKBHRKIlXDaaS6Kq+6Mo+lMLsVKz0gosz/M+KiKfsBTub8MwvMdSrNQYYzwAYc3m7bXFVZXv+8OqemD2NlUdiKLokbRybJQx5lsANlfefi4Mww/UedyvADgI4I9mbxeRDwdB8C92s0yHrc9wK3922b6Na+X2BYD+/v61nZ2dz6M8cX00DMP9S421ffv2V83MzDwHoNfmucuxEWSpslxcjYyMrHEcZ8xScQUAjoj8vqVYZIHv+xtE5MMWQ941PDy83mK8VIjIW2s2HZ2vuAKAIAgmADyxQIxWM3uu5J56DhgZGVkDYBw1nS+ApwB82VJeZAfbt82tWrXqPSgXV481UlwBwMGDB3+sqncDgIh81EZ+QBMLrKwXV5Uh5NoPYqMyN+m9nanqHVj4bsHF6InjeKfFeKmoLMUw+/2Ct6KLyOM1m2x/NmxbW30RhuGPFtp5jstGVU+JiNdqE57rEYahzB6lWOz7Fsf2be/2hYj8SeXlvTbiFYvFLwK4DOAWY8z1NmI2pcDKcnE1OjraWSgU9uPaD2LDRKSlJwavQCO2A4rIDtsxU7BxsQeoau2Jeak3BDTDL72kUm/n63neaFoJUkPYvm3G9/0NKN9gc7mrq6t2OsOSVGqPSQCuiAzaiLnsBVaWiysAuHDhwn4AQ2nEVtUfpBGXluwNKcRcaBmPVpDMfiMiW+o4pnafZM69MmYxnW9lsj9lCNs3m1T1tSjXL89aXo39WCX+62wEW9YCK+vFVcXLKcbmJcLW8qoUYmZhZOfFmvc3e563fb6djTFvwdUJxfPFyJx6O1/f999a6Xz5ZIwMYftm2o2Vv60+HUVETldeLnoUfy7LVmC1SXEFVf0YgFSeX5QkCQus9tfyIzsicnSObQ/6vj9cu71SXP1nPTGyplAo5FDT+arqk3Ecb5s9J0dV2flmENs3u0REgTmnJjRkVjwrd2Iuy3+adimuACCKotPGmC8A+GvLoZOZmZkXLMekBojIaVX9DcthTy+8S3MlSTIuIu+q2dyjqgeMMU8A+CYAUdUtAOa8izZJkvG081wG19xN5jjO4ByLTLrLlRBZxfbNrjMAICI3LrTjIlVHrqyMjKU+gtVOxVVVHMf/hHkWrGvAiawsQrlSqOqiF61rRkzbOjo6AsxfCG4G8FcAPvhLlih5qVgsWpl42kIyezcZ1YXtmy0/QvlqwG9V1i6zZRMAiIiV+dCpFljtWFwBQOUbzqcth+XlwdZjfRRGRMZsx7St8mT5zzcQ4r52+LKgqp9S1U8B+GTtZSPKPrZvdlXaagrAalU1NmJWCrVtAEqO4xyyETO1S4TtWlxVXbp06b7u7u6/BHCTjXiqygKrxYjIQ6p6L2Y9BqZB51etWtXyBRYAuK77hVKp9H5cnUxarzOu634xjZyWWxRFdzU7B0oP2zfbVPUbIrLFcZwPAfivRuOJyPtUdbWq5m09jzCVEax2L64AYGpq6rKq/qOteI7jsMBqMUEQnFXV3bbiqerdExMT52zFS1Mul7soIovugETkI7lc7mIaORERVRWLxS8BeElVb/F9v6EnR/i+f6Oq3gUAjuPYejSavQLLGKPVP4VC4Wd4ZXF1pKura7Bdiquq3t7efwfwnKVwLLBa0PT09B5U1kZp0BPFYvGzFuIsmyAI7kf5uWz1OhgEwTV3FLaoX5yLKosWLknNsZcayohsYvu2uUo98TEAUNW9vu8vad3CoaGhLlX9BoBeAONBEByxleNyLNPwWBzHOywvBtYS9u3bV1LVj1sKxwKrBU1NTV12XXcXgFMNhDmpqndkcF6SisifAzhRx76n4jh+Byzd3rwMjldfqOqSV+xPkmT2yvzH592RlhvbdwUIw3AvgAcArFPVcHBwcFHPBvZ9f0OpVDqA8qrwL8Rx/E6b+VkvsGqfZ9ROlwXnEkXRfgDfajCMXrx48Yc28iH7crncSVXdrKpPLvZYEXk6SZItURS1/PIMcwmC4KzjOCMAam9dn+0SgJ35fP4ny5SWDQ/Mer3HGLPoTtgYMyIiv3gOmqpmZfRuJWD7rgwax/G7UH7EzcYkSf7bGHNXX1/f6oUO9H1/Z+WcPoDysgw7bJ/DUl8Hq52LqwoVkb9T1WiRx8UoX158RlWfnJqaupxCbmRJFEWn+/r6buvu7v4ggI9g4Ynv50XknkKh8JkMjly9wqFDh77j+/6oqo4BqD1xXRaRPw6CwMZl1GXjuu6XSqXSOwH8LoD1AMaMMecA1PtF53WV4wCUC+menp699jOlpWD7rhz5fP5Kf3//UFdX132q+l4Ad3d3d7/fGPN1EZlQ1e/19PS8dPbs2fWu694kIgOqOqqqm4Dy4rKlUumOw4cPN3KVYk7WVkE1xsx5aSBLT+duhDEmQrkSnssZlIeXnxWRY6p6PI7j41nveFeq4eHh9XEc7xSRnQBej6t3kp5EuWh+OI7jh+dYsDDTfN/frKrjAKpPmv9pkiS7JicnH29mXku1devWV3d0dBxAuRNeMhF5ulgsjqRxgk7DfOfqxWr1czvbtzGt3r5zGRwc7FPV3ap6y0L7ishPAHx63bp1e/bt2xenkQ8LLEuMMZtE5JCqfhfAMwCeSZLkO2vWrDk+NjbGyZHUFjzP2yginwcAVX1fVi99Vo2OjnaeP3/+3SLydgBvBNBd56GXAHxXVR/s7e3dm9YJOg0rqQNm+y5dFtp3HmKM2QxgF8qr9b8GwA0AzgH4MYBjIjJ28eLFkFeOiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIhWgv8Hnffz4dmwY9cAAAAASUVORK5CYII=);background-image:linear-gradient(transparent,transparent),url(/app/assets/spritesheet-DpIxuf5L.svg)}.leaflet-draw a{display:block;text-align:center;text-decoration:none}.leaflet-draw a .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.leaflet-draw-actions{display:none;list-style:none;margin:0;padding:0;position:absolute;left:26px;top:0;white-space:nowrap}.leaflet-touch .leaflet-draw-actions{left:32px}.leaflet-right .leaflet-draw-actions{right:26px;left:auto}.leaflet-touch .leaflet-right .leaflet-draw-actions{right:32px;left:auto}.leaflet-draw-actions li{display:inline-block}.leaflet-draw-actions li:first-child a{border-left:none}.leaflet-draw-actions li:last-child a{-webkit-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.leaflet-right .leaflet-draw-actions li:last-child a{-webkit-border-radius:0;border-radius:0}.leaflet-right .leaflet-draw-actions li:first-child a{-webkit-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.leaflet-draw-actions a{background-color:#919187;border-left:1px solid #AAA;color:#fff;font:11px/19px Helvetica Neue,Arial,Helvetica,sans-serif;line-height:28px;text-decoration:none;padding-left:10px;padding-right:10px;height:28px}.leaflet-touch .leaflet-draw-actions a{font-size:12px;line-height:30px;height:30px}.leaflet-draw-actions-bottom{margin-top:0}.leaflet-draw-actions-top{margin-top:1px}.leaflet-draw-actions-top a,.leaflet-draw-actions-bottom a{height:27px;line-height:27px}.leaflet-draw-actions a:hover{background-color:#a0a098}.leaflet-draw-actions-top.leaflet-draw-actions-bottom a{height:26px;line-height:26px}.leaflet-draw-toolbar .leaflet-draw-draw-polyline{background-position:-2px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-polyline{background-position:0 -1px}.leaflet-draw-toolbar .leaflet-draw-draw-polygon{background-position:-31px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-polygon{background-position:-29px -1px}.leaflet-draw-toolbar .leaflet-draw-draw-rectangle{background-position:-62px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-rectangle{background-position:-60px -1px}.leaflet-draw-toolbar .leaflet-draw-draw-circle{background-position:-92px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-circle{background-position:-90px -1px}.leaflet-draw-toolbar .leaflet-draw-draw-marker{background-position:-122px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-marker{background-position:-120px -1px}.leaflet-draw-toolbar .leaflet-draw-draw-circlemarker{background-position:-273px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-draw-circlemarker{background-position:-271px -1px}.leaflet-draw-toolbar .leaflet-draw-edit-edit{background-position:-152px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-edit{background-position:-150px -1px}.leaflet-draw-toolbar .leaflet-draw-edit-remove{background-position:-182px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-remove{background-position:-180px -1px}.leaflet-draw-toolbar .leaflet-draw-edit-edit.leaflet-disabled{background-position:-212px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-edit.leaflet-disabled{background-position:-210px -1px}.leaflet-draw-toolbar .leaflet-draw-edit-remove.leaflet-disabled{background-position:-242px -2px}.leaflet-touch .leaflet-draw-toolbar .leaflet-draw-edit-remove.leaflet-disabled{background-position:-240px -2px}.leaflet-mouse-marker{background-color:#fff;cursor:crosshair}.leaflet-draw-tooltip{background:#363636;background:#00000080;border:1px solid transparent;-webkit-border-radius:4px;border-radius:4px;color:#fff;font:12px/18px Helvetica Neue,Arial,Helvetica,sans-serif;margin-left:20px;margin-top:-21px;padding:4px 8px;position:absolute;visibility:hidden;white-space:nowrap;z-index:6}.leaflet-draw-tooltip:before{border-right:6px solid black;border-right-color:#00000080;border-top:6px solid transparent;border-bottom:6px solid transparent;content:"";position:absolute;top:7px;left:-7px}.leaflet-error-draw-tooltip{background-color:#f2dede;border:1px solid #E6B6BD;color:#b94a48}.leaflet-error-draw-tooltip:before{border-right-color:#e6b6bd}.leaflet-draw-tooltip-single{margin-top:-12px}.leaflet-draw-tooltip-subtext{color:#f8d5e4}.leaflet-draw-guide-dash{font-size:1%;opacity:.6;position:absolute;width:5px;height:5px}.leaflet-edit-marker-selected{background-color:#fe57a11a;border:4px dashed rgba(254,87,161,.6);-webkit-border-radius:4px;border-radius:4px;box-sizing:content-box}.leaflet-edit-move{cursor:move}.leaflet-edit-resize{cursor:pointer}.leaflet-oldie .leaflet-draw-toolbar{border:1px solid #999}.leaflet-control-geosearch *,.leaflet-control-geosearch *:before,.leaflet-control-geosearch *:after{box-sizing:border-box}.leaflet-control-geosearch .leaflet-bar-part{border-radius:4px;border-bottom:none}.leaflet-control-geosearch a.leaflet-bar-part:before,.leaflet-control-geosearch a.leaflet-bar-part:after{position:absolute;display:block;content:""}.leaflet-control-geosearch a.leaflet-bar-part:before{top:17px;left:15px;width:6px;border-top:2px solid #555;transform:rotate(45deg)}.leaflet-control-geosearch a.leaflet-bar-part:after{top:10px;left:10px;height:8px;width:8px;border-radius:50%;border:2px solid #555}.leaflet-control-geosearch.error a.leaflet-bar-part:before,.leaflet-control-geosearch.pending a.leaflet-bar-part:before{display:none}.leaflet-control-geosearch.pending a.leaflet-bar-part:after,.leaflet-control-geosearch.error a.leaflet-bar-part:after{left:50%;top:50%;width:18px;height:18px;margin:-9px 0 0 -9px;border-radius:50%}.leaflet-control-geosearch.pending a.leaflet-bar-part:after{content:"";border:2px solid #555;border-top:2px solid #f3f3f3;animation:spin 1s linear infinite}.leaflet-control-geosearch.error a.leaflet-bar-part:after{content:"!";line-height:initial;font-weight:600;font-size:18px;border:none}.leaflet-control-geosearch form{display:none;position:absolute;top:0;left:30px;border-radius:0 4px 4px 0;background-color:#fff;background-clip:padding-box;z-index:-1;height:auto;margin:0;padding:0 8px;box-shadow:0 1px 5px #000000a6}.leaflet-geosearch-button form.open{border-radius:0 4px 4px}.leaflet-control-geosearch.active form{display:block}.leaflet-geosearch-button.active .leaflet-bar-part{border-radius:4px 0 0 4px;width:30px}.leaflet-geosearch-button form{max-width:350px}.leaflet-control-geosearch form input{min-width:200px;width:100%;outline:none;margin:0;padding:0;font-size:12px;height:30px;border:none;border-radius:0 4px 4px 0;text-indent:8px}.leaflet-touch .leaflet-geosearch-bar form{border:2px solid rgba(0,0,0,.2);box-shadow:none}.leaflet-touch .leaflet-geosearch-bar form input{height:30px}.leaflet-control-geosearch .results{background:#fff}.leaflet-control-geosearch .results>*{line-height:24px;padding:0 8px;border:1px solid transparent;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.leaflet-control-geosearch .results.active{padding:8px 0;border-top:1px solid #c6c6c6}.leaflet-control-geosearch .results>.active,.leaflet-control-geosearch .results>:hover{background-color:#f8f8f8;border-color:#c6c6c6;cursor:pointer}.leaflet-control-geosearch .results.active:after{content:"";display:block;width:0;position:absolute;left:-2px;bottom:-2px;top:30px}.leaflet-touch .leaflet-control-geosearch .results.active:after{border-left:2px solid rgba(0,0,0,.2)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.leaflet-top .leaflet-geosearch-bar,.leaflet-bottom .leaflet-geosearch-bar{display:none}.leaflet-geosearch-bar{position:relative;display:block;height:auto;width:400px;max-width:calc(100% - 120px);margin:10px auto 0;cursor:auto;z-index:1000}.leaflet-geosearch-bar form{position:relative;top:0;left:0;display:block;border-radius:4px}.leaflet-geosearch-bar form input{min-width:100%;width:100%}.leaflet-geosearch-bar .results.active:after{opacity:.2}.leaflet-right .leaflet-control-geosearch form{right:28px;left:initial;border-radius:4px 0 0 4px;border-left:inherit;border-right:none}.leaflet-bar-notfound{font-style:italic}.leaflet-control-geosearch button.reset{color:#000;font-weight:700;position:absolute;line-height:26px;padding:0 8px;right:0;top:0;cursor:pointer;border:none;text-decoration:none;background-color:#fff;border-radius:0 4px 4px 0}.leaflet-touch .leaflet-control-geosearch button.reset{line-height:30px}.leaflet-control-geosearch button.reset:hover{background:#f5f5f5}.mixin-top-margin{margin-top:1rem}.v-btn[data-v-0f977e61]{height:40px}.v-card-text[data-v-89abb022]{display:flex!important;padding:1.5rem}.dialog-icon[data-v-89abb022]{margin-right:1rem;object-fit:contain;align-self:flex-start}.dialog-text[data-v-89abb022]{flex:1 1 auto;width:90%}.subTitleWrapper[data-v-02c74e6d]{font-style:normal!important;font-size:18px!important;font-variant:normal!important;font-family:BCSans!important;font-weight:400!important;color:#707070c1!important;gap:10px!important;padding-bottom:0!important;margin-bottom:0!important}.titleWrapper[data-v-02c74e6d]{font-style:normal!important;font-size:22px!important;font-weight:700!important;font-variant:normal!important;font-family:BCSans!important;color:#000!important}.hr[data-v-02c74e6d]{height:1px;border:none;background-color:#707070c1;margin-bottom:0}.thumbnail[data-v-99b127ff]:hover{cursor:pointer}.v-card[data-v-71cc4af6]{border-left:15px solid #38598a;border-radius:0;background-color:#f2f2f2;padding:1.5rem}.v-card .v-icon[data-v-71cc4af6]{color:#38598a;margin-right:.5em}.v-card .v-card-text[data-v-71cc4af6]:not(.under-title){color:#494949!important;font-size:16px;padding:0}.v-card .under-title[data-v-71cc4af6]{padding-left:4em}[data-v-63447c0e] .v-icon{opacity:1}[data-v-63447c0e] .v-field__input{opacity:1!important}.target-notification[data-v-7bd898ba] .v-alert__icon.v-icon:after{display:none}.v-alert[data-v-7bd898ba]{color:#fff!important}.v-alert-title[data-v-7bd898ba]{font-weight:700!important}.v-card[data-v-23dd6b4d]{border-radius:.5em}.v-card .v-card-title[data-v-23dd6b4d]{background-color:#efefef;border-bottom:1px solid lightgray;font-weight:800;padding:.5em 1em}.v-card .v-card-text[data-v-23dd6b4d]{padding:1.5em}.v-card--variant-outlined[data-v-23dd6b4d]{border:thin solid rgba(0,0,0,.12)!important} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-vuetify-bs-bridge.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-vuetify-bs-bridge.css new file mode 100644 index 0000000000..7946ba7880 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/GrantApplications/chefs-vuetify-bs-bridge.css @@ -0,0 +1,16 @@ +/* + * chefs-vuetify-bs-bridge.css + * Overrides Bootstrap bg-* utility classes with CHEFS BC Government theme colors. + * Color values are sourced from the CHEFS Vuetify chefsTheme (vuetify-theme-stylesheet). + + * + * Formio panel themes are a fixed set (primary, secondary, info, success, warning, danger) + * so all cases are covered here without needing dynamic CSS variable resolution. + * Below values are extracted from inline