├── Dockerfile ├── README.md ├── azure-pipelines.yml ├── infra ├── bicep │ ├── main.bicep │ └── webapp.bicep ├── infradeploy.yml └── terraform │ ├── .gitignore │ ├── README.md │ ├── main.tf │ ├── modules │ ├── app-service │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── application-insights │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── cosmosdb-mongodb │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── key-vault │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── sql-server │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── storage-blob │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ └── virtual-network │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf │ ├── outputs.tf │ └── variables.tf ├── scripts └── ImageScanSummaryAssessmentGate.ps1 └── src ├── css ├── font-awesome.min.css ├── ie │ ├── PIE.htc │ ├── backgroundsize.min.htc │ ├── html5shiv.js │ ├── v8.css │ └── v9.css ├── images │ └── overlay.png ├── skel.css ├── style-large.css ├── style-medium.css ├── style-small.css ├── style-xlarge.css ├── style-xsmall.css └── style.css ├── elements.html ├── fonts ├── FontAwesome.otf ├── fontawesome-webfont.eot ├── fontawesome-webfont.svg ├── fontawesome-webfont.ttf └── fontawesome-webfont.woff ├── images ├── banner.jpg ├── pic01.jpg ├── pic02.jpg ├── pic03.jpg ├── pic04.jpg ├── pic05.jpg ├── pic06.jpg ├── pic07.jpg ├── pic08.jpg ├── pic09.jpg ├── slide01.jpg ├── slide02.jpg └── slide03.jpg ├── index.html ├── js ├── init.js ├── jquery.dropotron.min.js ├── jquery.min.js ├── jquery.scrollgress.min.js ├── jquery.scrolly.min.js ├── jquery.slidertron.min.js ├── skel-layers.min.js └── skel.min.js ├── left-sidebar.html ├── no-sidebar.html ├── readme.md ├── right-sidebar.html ├── sass ├── _mixins.scss ├── _vars.scss ├── ie │ ├── v8.scss │ └── v9.scss ├── style-large.scss ├── style-medium.scss ├── style-small.scss ├── style-xlarge.scss ├── style-xsmall.scss └── style.scss └── styles.css /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | COPY src/. /usr/share/nginx/html/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | This project is setup to demo the features of Azure DevOps. Each element is configured for demo purposes only. This repo is meant to be used for reference for the Azure DevOps: Zero to Hero Course - Available [here.](https://aka.ms/AzureDevOps/ZeroToHero) 3 | 4 | # Getting Started 5 | 1. Follow along with the video: https://aka.ms/AzureDevOps/ZeroToHero 6 | 2. Clone the repository 7 | 3. Configure the Build pipeline with connectors to your preferred cloud service and Docker Registry. Azure Container Registry is the registry of choice that was used in this demo. A login and subscription to Azure is required. 8 | 4. Build out your tasks using Azure Boards. 9 | 5. Create and configure your Build and Release Pipelines. Feel free to use the sample 'Azure-Pipelines.yml' 10 | 6. Go forth and code! 11 | 12 | # Build and Test 13 | All testing is done via the pipelines. The Pipeline is defined into stages using Build and Deploy. 14 | 15 | # Contribute 16 | Feedback is welcome. Please create a branch and open a PR with any suggestions. 17 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - main 3 | 4 | pool: 5 | vmImage: 'ubuntu-latest' 6 | 7 | variables: 8 | IMAGE_REGISTRY_CONNECTION: 'ACR Demo' 9 | IMAGE_REGISTRY: 'ADODemo' 10 | IMAGE_REPOSITORY: 'adodemo.azurecr.io' 11 | TAG: '$(Build.BuildId)' 12 | 13 | stages: 14 | - stage: BuildApp 15 | jobs: 16 | - job: BuildPushImage 17 | steps: 18 | - task: Docker@2 19 | inputs: 20 | containerRegistry: '$(IMAGE_REGISTRY_CONNECTION)' 21 | repository: '$(IMAGE_REPOSITORY)' 22 | command: 'buildAndPush' 23 | Dockerfile: '**/Dockerfile' 24 | tags: '$(TAG)' 25 | 26 | - stage: DeployDev 27 | jobs: 28 | - job: DeployDev 29 | steps: 30 | - task: AzureRmWebAppDeployment@4 31 | inputs: 32 | ConnectionType: 'AzureRM' 33 | azureSubscription: 'Azure' 34 | appType: 'webAppContainer' 35 | WebAppName: 'ADODemo-Dev' 36 | DockerNamespace: '$(IMAGE_REGISTRY)' 37 | DockerRepository: '$(IMAGE_REPOSITORY)' 38 | DockerImageTag: '$(TAG)' 39 | 40 | - stage: DeployProdAzure 41 | jobs: 42 | - job: ApproveRelease 43 | timeoutInMinutes: 4320 # job times out in 3 days 44 | pool: server 45 | steps: 46 | - task: ManualValidation@0 47 | timeoutInMinutes: 1440 # task times out in 1 day 48 | inputs: 49 | notifyUsers: 'nana.janashia@nnsoftware.at' 50 | instructions: 'Please validate and approve deployment to prod' 51 | - job: DeployProd 52 | steps: 53 | - task: AzureRmWebAppDeployment@4 54 | inputs: 55 | ConnectionType: 'AzureRM' 56 | azureSubscription: 'Azure' 57 | appType: 'webAppContainer' 58 | WebAppName: 'ADODemo-prod' 59 | DockerNamespace: '$(IMAGE_REGISTRY)' 60 | DockerRepository: '$(IMAGE_REPOSITORY)' 61 | DockerImageTag: '$(TAG)' 62 | 63 | - stage: DeployProdAWS 64 | jobs: 65 | - job: ApproveRelease 66 | timeoutInMinutes: 4320 # job times out in 3 days 67 | pool: server 68 | steps: 69 | - task: ManualValidation@0 70 | timeoutInMinutes: 1440 # task times out in 1 day 71 | inputs: 72 | notifyUsers: 'nana.janashia@nnsoftware.at' 73 | instructions: 'Please validate and approve deployment to prod' 74 | - job: DeployProd 75 | steps: 76 | - task: DownloadSecureFile@1 77 | name: sshKey 78 | inputs: 79 | secureFile: 'adodemo-key.pem' 80 | - script: | 81 | sudo chmod 400 $(sshKey.secureFilePath) 82 | ssh -o StrictHostKeyChecking=no -i $(sshKey.secureFilePath) ubuntu@35.180.100.164 " 83 | docker ps -aq | xargs docker stop | xargs docker rm && 84 | docker run -d -p 8080:80 $(IMAGE_REPOSITORY)/$(IMAGE_REPOSITORY):$(TAG)" -------------------------------------------------------------------------------- /infra/bicep/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param location string = 'westeurope' 4 | param rgName string = 'RG-Example' 5 | param webAppName string = 'mywebapp' 6 | param appServicePlanTier string = 'Standard' 7 | param appServicePlanSku string = 'S1' 8 | param dockerRegistryHost string = 'yourregistry.azurecr.io' 9 | param dockerRegistryServerUsername string = 'yourregistry' 10 | param dockerRegistryServerPassword string = 'somepassword' 11 | param dockerImage string = 'imagename' 12 | 13 | resource rg 'Microsoft.Resources/resourceGroups@2020-06-01' = { 14 | name: rgName 15 | location: location 16 | } 17 | 18 | module WebApp './webapp.bicep' = { 19 | name: webAppName 20 | scope: resourceGroup(rg.name) 21 | params: { 22 | location: location 23 | webAppName: webAppName 24 | appServicePlanTier: appServicePlanTier 25 | appServicePlanSku: appServicePlanSku 26 | dockerRegistryHost: dockerRegistryHost 27 | dockerRegistryServerUsername: dockerRegistryServerUsername 28 | dockerRegistryServerPassword: dockerRegistryServerPassword 29 | dockerImage: dockerImage 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /infra/bicep/webapp.bicep: -------------------------------------------------------------------------------- 1 | param webAppName string = 'mywebapp' 2 | param location string = 'westeurope' 3 | param appServicePlanTier string = 'Standard' 4 | param appServicePlanSku string = 'S1' 5 | param dockerRegistryHost string = 'yourregistry.azurecr.io' 6 | param dockerRegistryServerUsername string = 'yourregistry' 7 | param dockerRegistryServerPassword string = 'somepassword' 8 | param dockerImage string = 'imagename' 9 | 10 | var appServicePlanName = toLower('appsvc-${webAppName}') 11 | var webSiteName = toLower('${webAppName}') 12 | 13 | resource appServicePlan 'Microsoft.Web/serverfarms@2020-06-01' = { 14 | name: appServicePlanName 15 | location: location 16 | properties: { 17 | reserved: true 18 | } 19 | sku: { 20 | tier: appServicePlanTier 21 | name: appServicePlanSku 22 | } 23 | kind: 'linux' 24 | } 25 | 26 | resource appService 'Microsoft.Web/sites@2020-06-01' = { 27 | name: webSiteName 28 | location: location 29 | properties: { 30 | serverFarmId: appServicePlan.id 31 | siteConfig: { 32 | appSettings: [ 33 | { 34 | name: 'WEBSITES_ENABLE_APP_SERVICE_STORAGE' 35 | value: 'false' 36 | } 37 | { 38 | name: 'DOCKER_REGISTRY_SERVER_URL' 39 | value: 'https://${dockerRegistryHost}' 40 | } 41 | { 42 | name: 'DOCKER_REGISTRY_SERVER_USERNAME' 43 | value: dockerRegistryServerUsername 44 | } 45 | { 46 | name: 'DOCKER_REGISTRY_SERVER_PASSWORD' 47 | value: dockerRegistryServerPassword 48 | } 49 | ] 50 | linuxFxVersion: 'DOCKER|${dockerRegistryHost}/${dockerImage}' 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /infra/infradeploy.yml: -------------------------------------------------------------------------------- 1 | name: Infrastructure Deployment 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'env-*' 7 | 8 | env: 9 | DOTNET_VERSION: '6.0' 10 | # APP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root 11 | 12 | jobs: 13 | manage-infrastructure: 14 | runs-on: ubuntu-20.04 15 | outputs: 16 | application_name: ${{ steps.infrastructure-deployment.outputs.application_name }} 17 | application_url: ${{ steps.infrastructure-deployment.outputs.application_url }} 18 | resource_group: ${{ steps.infrastructure-deployment.outputs.resource_group }} 19 | steps: 20 | - name: Apply Terraform configuration 21 | id: infrastructure-deployment 22 | uses: microsoft/nubesgen-actions/gitops-apply-terraform@v0.8.0 23 | with: 24 | azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} 25 | tf_storage_account: ${{ secrets.TF_STORAGE_ACCOUNT }} 26 | build: 27 | runs-on: ubuntu-20.04 28 | steps: 29 | - name: Build a .NET application 30 | uses: microsoft/nubesgen-actions/gitops-build-dotnet@v0.8.0 31 | with: 32 | dotnet_version: ${{ env.DOTNET_VERSION }} 33 | application_package_path: ${{ env.APP_PACKAGE_PATH }} 34 | deploy: 35 | needs: [manage-infrastructure, build] 36 | runs-on: ubuntu-20.04 37 | steps: 38 | - name: Deploy a .NET application to Azure App Service 39 | uses: microsoft/nubesgen-actions/gitops-deploy-to-app-service-dotnet@v0.8.0 40 | with: 41 | azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} 42 | application_name: ${{ needs.manage-infrastructure.outputs.application_name }} 43 | display-information: 44 | needs: [manage-infrastructure] 45 | runs-on: ubuntu-20.04 46 | steps: 47 | - name: Display Azure infrastructure information 48 | uses: microsoft/nubesgen-actions/gitops-display-information@v0.8.0 49 | with: 50 | application_name: ${{ needs.manage-infrastructure.outputs.application_name }} 51 | application_url: ${{ needs.manage-infrastructure.outputs.application_url }} 52 | resource_group: ${{ needs.manage-infrastructure.outputs.resource_group }} 53 | 54 | -------------------------------------------------------------------------------- /infra/terraform/.gitignore: -------------------------------------------------------------------------------- 1 | ### Terraform ### 2 | *.tfstate 3 | *.tfstate.backup 4 | *.tfstate.lock.info 5 | .terraform/ 6 | -------------------------------------------------------------------------------- /infra/terraform/README.md: -------------------------------------------------------------------------------- 1 | # Terraform configuration 2 | 3 | This configuration has been generated by [https://nubesgen.com/](https://nubesgen.com/). 4 | 5 | You can regenerate it by running: 6 | 7 | ``` 8 | curl "https://nubesgen.com/cosmosusergroup.zip?iactool=TERRAFORM®ion=westeurope&application=APP_SERVICE.standard&runtime=DOTNET&database=SQL_SERVER.general_purpose&addons=application_insights,key_vault,storage_blob,cosmosdb_mongodb&gitops=true&network=VIRTUAL_NETWORK" | tar -xzvf - 9 | ``` 10 | 11 | Resources: 12 | - [NubesGen documentation](https://docs.nubesgen.com) 13 | - [What is NubesGen?](https://docs.nubesgen.com/what-is-nubesgen/overview/) 14 | - [NubesGen source code on GitHub](https://github.com/microsoft/NubesGen) 15 | 16 | ## Running Terraform 17 | 18 | [Terraform](https://www.terraform.io/) is used to automate infrastructure configuration. 19 | 20 | As you selected the [NubesGen GitOps option](https://docs.nubesgen.com/gitops/gitops-quick-start/), 21 | Terraform should be run by a generated GitHub Action called `gitops.yml`. 22 | 23 | Once your Terraform configuration has been applied, you can go to the [Azure Portal](https://aka.ms/nubesgen-portal) to check your resources. 24 | 25 | ## Resources 26 | 27 | ### Terraform documentation 28 | 29 | - [Terraform Azure provider documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs) 30 | 31 | ### Azure naming conventions 32 | 33 | - [Recommended abbreviations for Azure resource types](https://aka.ms/nubesgen-recommended-abbreviations) 34 | - [Naming rules and restrictions for Azure resources](https://aka.ms/nubesgen-naming-rules) 35 | - [Example names for common Azure resource types](https://aka.ms/nubesgen-caf-example-names) 36 | -------------------------------------------------------------------------------- /infra/terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurerm = { 4 | source = "hashicorp/azurerm" 5 | version = "3.11.0" 6 | } 7 | azurecaf = { 8 | source = "aztfmod/azurecaf" 9 | version = "1.2.16" 10 | } 11 | } 12 | backend "azurerm" {} 13 | } 14 | 15 | provider "azurerm" { 16 | features {} 17 | } 18 | 19 | locals { 20 | // If an environment is set up (dev, test, prod...), it is used in the application name 21 | environment = var.environment == "" ? "dev" : var.environment 22 | } 23 | 24 | data "http" "myip" { 25 | url = "http://whatismyip.akamai.com" 26 | } 27 | 28 | locals { 29 | myip = chomp(data.http.myip.body) 30 | } 31 | 32 | resource "azurecaf_name" "resource_group" { 33 | name = var.application_name 34 | resource_type = "azurerm_resource_group" 35 | suffixes = [local.environment] 36 | } 37 | 38 | resource "azurerm_resource_group" "main" { 39 | name = azurecaf_name.resource_group.result 40 | location = var.location 41 | 42 | tags = { 43 | "terraform" = "true" 44 | "environment" = local.environment 45 | "application-name" = var.application_name 46 | "nubesgen-version" = "0.13.0" 47 | 48 | // Name of the Azure Storage Account that stores the Terraform state 49 | "terraform_storage_account" = var.terraform_storage_account 50 | } 51 | } 52 | 53 | module "application" { 54 | source = "./modules/app-service" 55 | resource_group = azurerm_resource_group.main.name 56 | application_name = var.application_name 57 | environment = local.environment 58 | location = var.location 59 | 60 | database_url = module.database.database_url 61 | database_username = "@Microsoft.KeyVault(SecretUri=${module.key-vault.vault_uri}secrets/database-username)" 62 | database_password = "@Microsoft.KeyVault(SecretUri=${module.key-vault.vault_uri}secrets/database-password)" 63 | 64 | azure_application_insights_instrumentation_key = module.application-insights.azure_application_insights_instrumentation_key 65 | 66 | vault_id = module.key-vault.vault_id 67 | 68 | azure_storage_account_name = module.storage-blob.azurerm_storage_account_name 69 | azure_storage_blob_endpoint = module.storage-blob.azurerm_storage_blob_endpoint 70 | azure_storage_account_key = "@Microsoft.KeyVault(SecretUri=${module.key-vault.vault_uri}secrets/storage-account-key)" 71 | 72 | azure_cosmosdb_mongodb_database = module.cosmosdb-mongodb.azure_cosmosdb_mongodb_database 73 | azure_cosmosdb_mongodb_uri = "@Microsoft.KeyVault(SecretUri=${module.key-vault.vault_uri}secrets/cosmosdb-mongodb-uri)" 74 | 75 | subnet_id = module.network.app_subnet_id 76 | } 77 | 78 | module "database" { 79 | source = "./modules/sql-server" 80 | resource_group = azurerm_resource_group.main.name 81 | application_name = var.application_name 82 | environment = local.environment 83 | location = var.location 84 | 85 | subnet_id = module.network.app_subnet_id 86 | } 87 | 88 | module "application-insights" { 89 | source = "./modules/application-insights" 90 | resource_group = azurerm_resource_group.main.name 91 | application_name = var.application_name 92 | environment = local.environment 93 | location = var.location 94 | } 95 | 96 | module "key-vault" { 97 | source = "./modules/key-vault" 98 | resource_group = azurerm_resource_group.main.name 99 | application_name = var.application_name 100 | environment = local.environment 101 | location = var.location 102 | 103 | database_username = module.database.database_username 104 | database_password = module.database.database_password 105 | 106 | storage_account_key = module.storage-blob.azurerm_storage_account_key 107 | 108 | cosmosdb_mongodb_uri = module.cosmosdb-mongodb.azure_cosmosdb_mongodb_uri 109 | 110 | subnet_id = module.network.app_subnet_id 111 | myip = local.myip 112 | } 113 | 114 | module "storage-blob" { 115 | source = "./modules/storage-blob" 116 | resource_group = azurerm_resource_group.main.name 117 | application_name = var.application_name 118 | environment = local.environment 119 | location = var.location 120 | subnet_id = module.network.app_subnet_id 121 | myip = local.myip 122 | } 123 | 124 | module "cosmosdb-mongodb" { 125 | source = "./modules/cosmosdb-mongodb" 126 | resource_group = azurerm_resource_group.main.name 127 | application_name = var.application_name 128 | environment = local.environment 129 | location = var.location 130 | subnet_id = module.network.app_subnet_id 131 | } 132 | 133 | module "network" { 134 | source = "./modules/virtual-network" 135 | resource_group = azurerm_resource_group.main.name 136 | application_name = var.application_name 137 | environment = local.environment 138 | location = var.location 139 | 140 | service_endpoints = ["Microsoft.Sql", "Microsoft.AzureCosmosDB", "Microsoft.KeyVault", "Microsoft.Storage"] 141 | 142 | address_space = var.address_space 143 | app_subnet_prefix = var.app_subnet_prefix 144 | } 145 | -------------------------------------------------------------------------------- /infra/terraform/modules/app-service/README.md: -------------------------------------------------------------------------------- 1 | # Terraform module for Azure App Service configuration 2 | 3 | This module configures a Azure App Service instance with Terraform. 4 | 5 | ## Resources 6 | 7 | [Azure App Service pricing](https://aka.ms/nubesgen-app-service-pricing) 8 | [Terraform Azure App Service reference](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service) 9 | -------------------------------------------------------------------------------- /infra/terraform/modules/app-service/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurecaf = { 4 | source = "aztfmod/azurecaf" 5 | version = "1.2.16" 6 | } 7 | } 8 | } 9 | 10 | resource "azurecaf_name" "app_service_plan" { 11 | name = var.application_name 12 | resource_type = "azurerm_app_service_plan" 13 | suffixes = [var.environment] 14 | } 15 | 16 | # This creates the plan that the service use 17 | resource "azurerm_service_plan" "application" { 18 | name = azurecaf_name.app_service_plan.result 19 | resource_group_name = var.resource_group 20 | location = var.location 21 | 22 | sku_name = "S1" 23 | os_type = "Linux" 24 | 25 | tags = { 26 | "environment" = var.environment 27 | "application-name" = var.application_name 28 | } 29 | } 30 | 31 | resource "azurecaf_name" "app_service" { 32 | name = var.application_name 33 | resource_type = "azurerm_app_service" 34 | suffixes = [var.environment] 35 | } 36 | 37 | # This creates the service definition 38 | resource "azurerm_linux_web_app" "application" { 39 | name = azurecaf_name.app_service.result 40 | resource_group_name = var.resource_group 41 | location = var.location 42 | service_plan_id = azurerm_service_plan.application.id 43 | https_only = true 44 | 45 | tags = { 46 | "environment" = var.environment 47 | "application-name" = var.application_name 48 | } 49 | 50 | site_config { 51 | application_stack { 52 | dotnet_version = "6.0" 53 | } 54 | always_on = true 55 | ftps_state = "FtpsOnly" 56 | } 57 | 58 | identity { 59 | type = "SystemAssigned" 60 | } 61 | 62 | app_settings = { 63 | "WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false" 64 | 65 | // Monitoring with Azure Application Insights 66 | "APPINSIGHTS_INSTRUMENTATIONKEY" = var.azure_application_insights_instrumentation_key 67 | 68 | # These are app specific environment variables 69 | 70 | "DATABASE_URL" = var.database_url 71 | "DATABASE_USERNAME" = var.database_username 72 | "DATABASE_PASSWORD" = var.database_password 73 | 74 | "AZURE_STORAGE_ACCOUNT_NAME" = var.azure_storage_account_name 75 | "AZURE_STORAGE_BLOB_ENDPOINT" = var.azure_storage_blob_endpoint 76 | "AZURE_STORAGE_ACCOUNT_KEY" = var.azure_storage_account_key 77 | 78 | "MONGODB_DATABASE" = var.azure_cosmosdb_mongodb_database 79 | "MONGODB_URI" = var.azure_cosmosdb_mongodb_uri 80 | } 81 | } 82 | 83 | data "azurerm_client_config" "current" {} 84 | 85 | resource "azurerm_key_vault_access_policy" "application" { 86 | key_vault_id = var.vault_id 87 | tenant_id = data.azurerm_client_config.current.tenant_id 88 | object_id = azurerm_linux_web_app.application.identity[0].principal_id 89 | 90 | secret_permissions = [ 91 | "Get", 92 | "List" 93 | ] 94 | } 95 | 96 | resource "azurerm_app_service_virtual_network_swift_connection" "swift_connection" { 97 | app_service_id = azurerm_linux_web_app.application.id 98 | subnet_id = var.subnet_id 99 | } 100 | -------------------------------------------------------------------------------- /infra/terraform/modules/app-service/outputs.tf: -------------------------------------------------------------------------------- 1 | output "application_url" { 2 | value = "https://${azurerm_linux_web_app.application.default_hostname}" 3 | description = "The Web application URL." 4 | } 5 | 6 | output "application_fqdn" { 7 | value = azurerm_linux_web_app.application.default_hostname 8 | description = "The Web application fully qualified domain name (FQDN)." 9 | } 10 | 11 | output "application_caf_name" { 12 | value = azurecaf_name.app_service.result 13 | description = "The application name generated by the Azure Cloud Adoption Framework." 14 | } 15 | -------------------------------------------------------------------------------- /infra/terraform/modules/app-service/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group" { 2 | type = string 3 | description = "The resource group" 4 | } 5 | 6 | variable "application_name" { 7 | type = string 8 | description = "The name of your application" 9 | } 10 | 11 | variable "environment" { 12 | type = string 13 | description = "The environment (dev, test, prod...)" 14 | default = "dev" 15 | } 16 | 17 | variable "location" { 18 | type = string 19 | description = "The Azure region where all resources in this example should be created" 20 | } 21 | 22 | variable "database_url" { 23 | type = string 24 | description = "The URL to the database" 25 | } 26 | 27 | variable "database_username" { 28 | type = string 29 | description = "The database username" 30 | } 31 | 32 | variable "database_password" { 33 | type = string 34 | description = "The database password" 35 | } 36 | 37 | variable "azure_application_insights_instrumentation_key" { 38 | type = string 39 | description = "The Azure Application Insights instrumentation key" 40 | } 41 | 42 | variable "vault_id" { 43 | type = string 44 | description = "The Azure Key Vault ID" 45 | } 46 | 47 | variable "azure_storage_account_name" { 48 | type = string 49 | description = "The name of the Azure Storage account" 50 | } 51 | 52 | variable "azure_storage_account_key" { 53 | type = string 54 | description = "The access key of the Azure Storage account" 55 | } 56 | 57 | variable "azure_storage_blob_endpoint" { 58 | type = string 59 | description = "The blob endpoint URL of the Azure Storage account" 60 | } 61 | 62 | variable "azure_cosmosdb_mongodb_database" { 63 | type = string 64 | description = "The Cosmos DB with MongoDB API database name" 65 | } 66 | 67 | variable "azure_cosmosdb_mongodb_uri" { 68 | type = string 69 | description = "The Cosmos DB with MongoDB API database URI" 70 | } 71 | 72 | variable "subnet_id" { 73 | type = string 74 | description = "The subnet the app can use" 75 | } 76 | -------------------------------------------------------------------------------- /infra/terraform/modules/application-insights/README.md: -------------------------------------------------------------------------------- 1 | # Terraform module for Azure Application Insights configuration 2 | 3 | This module configures an Azure Application Insights instance with Terraform. 4 | 5 | ## Resources 6 | 7 | [What is Azure Application Insights](https://aka.ms/nubesgen-app-insights) 8 | [Terraform Azure Application Insights reference](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/application_insights) 9 | -------------------------------------------------------------------------------- /infra/terraform/modules/application-insights/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurecaf = { 4 | source = "aztfmod/azurecaf" 5 | version = "1.2.16" 6 | } 7 | } 8 | } 9 | 10 | resource "azurecaf_name" "application_insights" { 11 | name = var.application_name 12 | resource_type = "azurerm_application_insights" 13 | suffixes = [var.environment] 14 | } 15 | 16 | resource "azurerm_application_insights" "application_insights" { 17 | name = azurecaf_name.application_insights.result 18 | location = var.location 19 | resource_group_name = var.resource_group 20 | application_type = "web" 21 | 22 | tags = { 23 | "environment" = var.environment 24 | "application-name" = var.application_name 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /infra/terraform/modules/application-insights/outputs.tf: -------------------------------------------------------------------------------- 1 | output "azure_application_insights_instrumentation_key" { 2 | value = azurerm_application_insights.application_insights.instrumentation_key 3 | description = "The Azure Application Insights instrumentation key" 4 | } 5 | 6 | output "azure_application_insights_connection_string" { 7 | value = azurerm_application_insights.application_insights.connection_string 8 | description = "The Azure Application Insights connection string" 9 | } -------------------------------------------------------------------------------- /infra/terraform/modules/application-insights/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group" { 2 | type = string 3 | description = "The resource group" 4 | default = "" 5 | } 6 | 7 | variable "application_name" { 8 | type = string 9 | description = "The name of your application" 10 | default = "" 11 | } 12 | 13 | variable "environment" { 14 | type = string 15 | description = "The environment (dev, test, prod...)" 16 | default = "dev" 17 | } 18 | 19 | variable "location" { 20 | type = string 21 | description = "The Azure region where all resources in this example should be created" 22 | default = "" 23 | } 24 | -------------------------------------------------------------------------------- /infra/terraform/modules/cosmosdb-mongodb/README.md: -------------------------------------------------------------------------------- 1 | # Terraform module for Cosmos DB with MongoDB configuration 2 | 3 | This module configures Cosmos DB with MongoDB with Terraform. 4 | -------------------------------------------------------------------------------- /infra/terraform/modules/cosmosdb-mongodb/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurecaf = { 4 | source = "aztfmod/azurecaf" 5 | version = "1.2.16" 6 | } 7 | } 8 | } 9 | 10 | resource "azurecaf_name" "cosmosdb_account" { 11 | name = var.application_name 12 | resource_type = "azurerm_cosmosdb_account" 13 | suffixes = [var.environment] 14 | } 15 | 16 | resource "azurerm_cosmosdb_account" "cosmosdb" { 17 | name = azurecaf_name.cosmosdb_account.result 18 | resource_group_name = var.resource_group 19 | location = var.location 20 | offer_type = "Standard" 21 | kind = "MongoDB" 22 | enable_free_tier = true 23 | 24 | tags = { 25 | "environment" = var.environment 26 | "application-name" = var.application_name 27 | } 28 | 29 | consistency_policy { 30 | consistency_level = "Session" 31 | } 32 | 33 | geo_location { 34 | failover_priority = 0 35 | location = var.location 36 | } 37 | 38 | is_virtual_network_filter_enabled = true 39 | 40 | virtual_network_rule { 41 | id = var.subnet_id 42 | } 43 | } 44 | 45 | # azurerm_cosmosdb_mongo_database isn't implemented yet in azurecaf_name 46 | resource "azurerm_cosmosdb_mongo_database" "cosmosdb" { 47 | name = "cosmos-${var.application_name}-001" 48 | resource_group_name = azurerm_cosmosdb_account.cosmosdb.resource_group_name 49 | account_name = azurerm_cosmosdb_account.cosmosdb.name 50 | throughput = var.throughput 51 | } 52 | -------------------------------------------------------------------------------- /infra/terraform/modules/cosmosdb-mongodb/outputs.tf: -------------------------------------------------------------------------------- 1 | output "azure_cosmosdb_mongodb_database" { 2 | value = azurerm_cosmosdb_mongo_database.cosmosdb.name 3 | description = "The Cosmos DB database name." 4 | } 5 | 6 | output "azure_cosmosdb_mongodb_uri" { 7 | value = azurerm_cosmosdb_account.cosmosdb.connection_strings[0] 8 | sensitive = true 9 | description = "The Cosmos DB connection string." 10 | } 11 | -------------------------------------------------------------------------------- /infra/terraform/modules/cosmosdb-mongodb/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group" { 2 | type = string 3 | description = "The resource group" 4 | default = "" 5 | } 6 | 7 | variable "application_name" { 8 | type = string 9 | description = "The name of your application" 10 | default = "" 11 | } 12 | 13 | variable "environment" { 14 | type = string 15 | description = "The environment (dev, test, prod...)" 16 | default = "dev" 17 | } 18 | 19 | variable "location" { 20 | type = string 21 | description = "The Azure region where all resources in this example should be created" 22 | default = "" 23 | } 24 | 25 | variable "throughput" { 26 | type = number 27 | description = "The throughput of the MongoDB database (RU/s)" 28 | default = 400 29 | } 30 | 31 | variable "subnet_id" { 32 | type = string 33 | description = "The subnet from which the access is allowed" 34 | } 35 | -------------------------------------------------------------------------------- /infra/terraform/modules/key-vault/README.md: -------------------------------------------------------------------------------- 1 | # Terraform module for Azure Key Vault configuration 2 | 3 | This module configures a Azure Key Vault instance with Terraform. 4 | 5 | ## Resources 6 | 7 | [Terraform Azure Key Vault reference](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) 8 | -------------------------------------------------------------------------------- /infra/terraform/modules/key-vault/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurecaf = { 4 | source = "aztfmod/azurecaf" 5 | version = "1.2.16" 6 | } 7 | } 8 | } 9 | 10 | resource "azurecaf_name" "key_vault" { 11 | random_length = "15" 12 | resource_type = "azurerm_key_vault" 13 | suffixes = [var.environment] 14 | } 15 | 16 | data "azurerm_client_config" "current" {} 17 | 18 | resource "azurerm_key_vault" "application" { 19 | name = azurecaf_name.key_vault.result 20 | resource_group_name = var.resource_group 21 | location = var.location 22 | 23 | tenant_id = data.azurerm_client_config.current.tenant_id 24 | soft_delete_retention_days = 90 25 | 26 | sku_name = "standard" 27 | 28 | network_acls { 29 | default_action = "Deny" 30 | bypass = "None" 31 | virtual_network_subnet_ids = [var.subnet_id] 32 | ip_rules = [var.myip] 33 | } 34 | 35 | tags = { 36 | "environment" = var.environment 37 | "application-name" = var.application_name 38 | } 39 | } 40 | 41 | resource "azurerm_key_vault_access_policy" "client" { 42 | key_vault_id = azurerm_key_vault.application.id 43 | tenant_id = data.azurerm_client_config.current.tenant_id 44 | object_id = data.azurerm_client_config.current.object_id 45 | 46 | secret_permissions = [ 47 | "Set", 48 | "Get", 49 | "List", 50 | "Delete" 51 | ] 52 | } 53 | 54 | resource "azurerm_key_vault_secret" "database_username" { 55 | name = "database-username" 56 | value = var.database_username 57 | key_vault_id = azurerm_key_vault.application.id 58 | 59 | depends_on = [ azurerm_key_vault_access_policy.client ] 60 | } 61 | 62 | resource "azurerm_key_vault_secret" "database_password" { 63 | name = "database-password" 64 | value = var.database_password 65 | key_vault_id = azurerm_key_vault.application.id 66 | 67 | depends_on = [ azurerm_key_vault_access_policy.client ] 68 | } 69 | 70 | resource "azurerm_key_vault_secret" "storage_account_key" { 71 | name = "storage-account-key" 72 | value = var.storage_account_key 73 | key_vault_id = azurerm_key_vault.application.id 74 | 75 | depends_on = [ azurerm_key_vault_access_policy.client ] 76 | } 77 | 78 | resource "azurerm_key_vault_secret" "cosmosdb_mongodb_uri" { 79 | name = "cosmosdb-mongodb-uri" 80 | value = var.cosmosdb_mongodb_uri 81 | key_vault_id = azurerm_key_vault.application.id 82 | 83 | depends_on = [ azurerm_key_vault_access_policy.client ] 84 | } 85 | -------------------------------------------------------------------------------- /infra/terraform/modules/key-vault/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vault_id" { 2 | value = azurerm_key_vault.application.id 3 | description = "The Azure Key Vault ID" 4 | } 5 | 6 | output "vault_uri" { 7 | value = azurerm_key_vault.application.vault_uri 8 | description = "The Azure Key Vault URI" 9 | } 10 | -------------------------------------------------------------------------------- /infra/terraform/modules/key-vault/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group" { 2 | type = string 3 | description = "The resource group" 4 | } 5 | 6 | variable "application_name" { 7 | type = string 8 | description = "The name of your application" 9 | } 10 | 11 | variable "environment" { 12 | type = string 13 | description = "The environment (dev, test, prod...)" 14 | default = "dev" 15 | } 16 | 17 | variable "location" { 18 | type = string 19 | description = "The Azure region where all resources in this example should be created" 20 | } 21 | 22 | variable "database_username" { 23 | type = string 24 | description = "The database username" 25 | } 26 | 27 | variable "database_password" { 28 | type = string 29 | description = "The database password" 30 | } 31 | 32 | variable "storage_account_key" { 33 | type = string 34 | description = "The Azure Storage Account key" 35 | } 36 | 37 | variable "cosmosdb_mongodb_uri" { 38 | type = string 39 | description = "The Cosmos DB connection string" 40 | } 41 | 42 | variable "subnet_id" { 43 | type = string 44 | description = "The subnet from which the access is allowed" 45 | } 46 | 47 | variable "myip" { 48 | type = string 49 | description = "The IP address of the current client. It is required to provide access to this client to be able to create the secrets" 50 | } 51 | -------------------------------------------------------------------------------- /infra/terraform/modules/sql-server/README.md: -------------------------------------------------------------------------------- 1 | # Terraform module for SQL Server database configuration 2 | 3 | This module configures a SQL Server database with Terraform. 4 | 5 | ## Resources 6 | 7 | - [Azure SQL pricing](https://aka.ms/nubesgen-azure-sql-pricing) 8 | - [SKU list for Azure SQL database](https://aka.ms/nubesgen-azure-sql-sku) 9 | - [Terraform Azure SQL reference](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/mssql_database) 10 | -------------------------------------------------------------------------------- /infra/terraform/modules/sql-server/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurecaf = { 4 | source = "aztfmod/azurecaf" 5 | version = "1.2.16" 6 | } 7 | } 8 | } 9 | 10 | resource "azurecaf_name" "mssql_server" { 11 | name = var.application_name 12 | resource_type = "azurerm_mssql_server" 13 | suffixes = [var.environment] 14 | } 15 | 16 | resource "random_password" "password" { 17 | length = 32 18 | special = true 19 | override_special = "_%@" 20 | } 21 | 22 | resource "azurerm_mssql_server" "database" { 23 | name = azurecaf_name.mssql_server.result 24 | resource_group_name = var.resource_group 25 | location = var.location 26 | version = "12.0" 27 | 28 | administrator_login = var.administrator_login 29 | administrator_login_password = random_password.password.result 30 | 31 | tags = { 32 | "environment" = var.environment 33 | "application-name" = var.application_name 34 | } 35 | } 36 | 37 | resource "azurecaf_name" "mssql_database" { 38 | name = var.application_name 39 | resource_type = "azurerm_mssql_database" 40 | suffixes = [var.environment] 41 | } 42 | 43 | resource "azurerm_mssql_database" "database" { 44 | name = azurecaf_name.mssql_database.result 45 | server_id = azurerm_mssql_server.database.id 46 | collation = "SQL_Latin1_General_CP1_CI_AS" 47 | 48 | sku_name = "GP_Gen5_2" 49 | } 50 | 51 | resource "azurecaf_name" "sql_network_rule" { 52 | name = var.application_name 53 | resource_type = "azurerm_network_security_rule" 54 | suffixes = [var.environment] 55 | } 56 | 57 | # This rule only allows traffic from the apps VNet 58 | resource "azurerm_mssql_virtual_network_rule" "network_rule" { 59 | name = azurecaf_name.sql_network_rule.result 60 | server_id = azurerm_mssql_server.database.id 61 | subnet_id = var.subnet_id 62 | } 63 | -------------------------------------------------------------------------------- /infra/terraform/modules/sql-server/outputs.tf: -------------------------------------------------------------------------------- 1 | output "database_url" { 2 | value = "${azurerm_mssql_server.database.name}.database.windows.net:1433;database=${azurerm_mssql_database.database.name};encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;" 3 | description = "The Azure SQL server URL." 4 | } 5 | 6 | output "database_username" { 7 | value = "${var.administrator_login}@${azurerm_mssql_server.database.name}" 8 | description = "The Azure SQL server user name." 9 | } 10 | 11 | output "database_password" { 12 | value = random_password.password.result 13 | sensitive = true 14 | description = "The Azure SQL server password." 15 | } 16 | -------------------------------------------------------------------------------- /infra/terraform/modules/sql-server/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group" { 2 | type = string 3 | description = "The resource group" 4 | default = "" 5 | } 6 | 7 | variable "application_name" { 8 | type = string 9 | description = "The name of your application" 10 | default = "" 11 | } 12 | 13 | variable "environment" { 14 | type = string 15 | description = "The environment (dev, test, prod...)" 16 | default = "dev" 17 | } 18 | 19 | variable "location" { 20 | type = string 21 | description = "The Azure region where all resources in this example should be created" 22 | default = "" 23 | } 24 | 25 | variable "administrator_login" { 26 | type = string 27 | description = "The SQL Server administrator login" 28 | default = "sqladmin" 29 | } 30 | 31 | variable "subnet_id" { 32 | type = string 33 | description = "The subnet from which the access is allowed" 34 | } 35 | -------------------------------------------------------------------------------- /infra/terraform/modules/storage-blob/README.md: -------------------------------------------------------------------------------- 1 | # Terraform module for Blob storage configuration 2 | 3 | This module configures a Blob storage with Terraform. 4 | -------------------------------------------------------------------------------- /infra/terraform/modules/storage-blob/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurecaf = { 4 | source = "aztfmod/azurecaf" 5 | version = "1.2.16" 6 | } 7 | } 8 | } 9 | 10 | resource "azurecaf_name" "storage_account" { 11 | name = var.application_name 12 | resource_type = "azurerm_storage_account" 13 | suffixes = [var.environment] 14 | } 15 | 16 | resource "azurerm_storage_account" "storage-blob" { 17 | name = azurecaf_name.storage_account.result 18 | resource_group_name = var.resource_group 19 | location = var.location 20 | account_tier = "Standard" 21 | account_replication_type = "LRS" 22 | 23 | tags = { 24 | "environment" = var.environment 25 | "application-name" = var.application_name 26 | } 27 | } 28 | 29 | resource "azurerm_storage_account_network_rules" "storage_only_app_traffic" { 30 | storage_account_id = azurerm_storage_account.storage-blob.id 31 | 32 | default_action = "Deny" 33 | virtual_network_subnet_ids = [var.subnet_id] 34 | ip_rules = [var.myip] 35 | } 36 | 37 | resource "azurecaf_name" "storage_container" { 38 | name = var.application_name 39 | resource_type = "azurerm_storage_container" 40 | suffixes = [var.environment] 41 | } 42 | 43 | resource "azurerm_storage_container" "storage-blob" { 44 | name = azurecaf_name.storage_container.result 45 | storage_account_name = azurerm_storage_account.storage-blob.name 46 | container_access_type = "private" 47 | } 48 | -------------------------------------------------------------------------------- /infra/terraform/modules/storage-blob/outputs.tf: -------------------------------------------------------------------------------- 1 | output "azurerm_storage_account_name" { 2 | value = azurerm_storage_account.storage-blob.name 3 | description = "The Azure Blob storage account name." 4 | } 5 | 6 | output "azurerm_storage_account_key" { 7 | value = azurerm_storage_account.storage-blob.primary_access_key 8 | sensitive = true 9 | description = "The Azure Blob storage access key." 10 | } 11 | 12 | output "azurerm_storage_blob_endpoint" { 13 | value = azurerm_storage_account.storage-blob.primary_blob_endpoint 14 | description = "The Azure Blob storage endpoint." 15 | } 16 | -------------------------------------------------------------------------------- /infra/terraform/modules/storage-blob/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group" { 2 | type = string 3 | description = "The resource group" 4 | default = "" 5 | } 6 | 7 | variable "application_name" { 8 | type = string 9 | description = "The name of your application" 10 | default = "" 11 | } 12 | 13 | variable "environment" { 14 | type = string 15 | description = "The environment (dev, test, prod...)" 16 | default = "dev" 17 | } 18 | 19 | variable "location" { 20 | type = string 21 | description = "The Azure region where all resources in this example should be created" 22 | default = "" 23 | } 24 | 25 | variable "subnet_id" { 26 | type = string 27 | description = "The subnet from which the access is allowed" 28 | } 29 | 30 | variable "myip" { 31 | type = string 32 | description = "The IP address of the current client. It is required to provide access to this client to be able to create containers" 33 | } 34 | -------------------------------------------------------------------------------- /infra/terraform/modules/virtual-network/README.md: -------------------------------------------------------------------------------- 1 | # Terraform module for Networking configuration 2 | 3 | This module configures the service networking with Terraform. 4 | 5 | ## Resources 6 | 7 | [Azure Virtual Network service pricing](https://azure.microsoft.com/en-us/pricing/details/virtual-network/) 8 | [Terraform Azure Virtual Network reference](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network) 9 | -------------------------------------------------------------------------------- /infra/terraform/modules/virtual-network/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | azurecaf = { 4 | source = "aztfmod/azurecaf" 5 | version = "1.2.16" 6 | } 7 | } 8 | } 9 | 10 | resource "azurecaf_name" "virtual_network" { 11 | name = var.application_name 12 | resource_type = "azurerm_virtual_network" 13 | suffixes = [var.environment] 14 | } 15 | 16 | resource "azurerm_virtual_network" "virtual_network" { 17 | name = azurecaf_name.virtual_network.result 18 | address_space = [var.address_space] 19 | location = var.location 20 | resource_group_name = var.resource_group 21 | 22 | tags = { 23 | "environment" = var.environment 24 | "application-name" = var.application_name 25 | } 26 | } 27 | 28 | resource "azurecaf_name" "app_subnet" { 29 | name = var.application_name 30 | resource_type = "azurerm_subnet" 31 | suffixes = [var.environment, "app"] 32 | } 33 | 34 | resource "azurerm_subnet" "app_subnet" { 35 | name = azurecaf_name.app_subnet.result 36 | resource_group_name = var.resource_group 37 | virtual_network_name = azurerm_virtual_network.virtual_network.name 38 | address_prefixes = [var.app_subnet_prefix] 39 | service_endpoints = var.service_endpoints 40 | delegation { 41 | name = "${var.application_name}-delegation" 42 | 43 | service_delegation { 44 | name = "Microsoft.Web/serverFarms" 45 | actions = ["Microsoft.Network/virtualNetworks/subnets/action"] 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /infra/terraform/modules/virtual-network/outputs.tf: -------------------------------------------------------------------------------- 1 | output "virtual_network_id" { 2 | value = azurerm_virtual_network.virtual_network.id 3 | description = "Application Virtual Network" 4 | } 5 | 6 | output "app_subnet_id" { 7 | value = azurerm_subnet.app_subnet.id 8 | description = "Application Subnet" 9 | } 10 | -------------------------------------------------------------------------------- /infra/terraform/modules/virtual-network/variables.tf: -------------------------------------------------------------------------------- 1 | variable "resource_group" { 2 | type = string 3 | description = "The resource group" 4 | } 5 | 6 | variable "application_name" { 7 | type = string 8 | description = "The name of your application" 9 | } 10 | 11 | variable "environment" { 12 | type = string 13 | description = "The environment (dev, test, prod...)" 14 | default = "dev" 15 | } 16 | 17 | variable "location" { 18 | type = string 19 | description = "The Azure region where all resources in this example should be created" 20 | } 21 | 22 | variable "address_space" { 23 | type = string 24 | description = "VNet address space" 25 | } 26 | 27 | variable "app_subnet_prefix" { 28 | type = string 29 | description = "Application subnet prefix" 30 | } 31 | 32 | variable "service_endpoints" { 33 | type = list(string) 34 | description = "Service endpoints used by the solution" 35 | } 36 | -------------------------------------------------------------------------------- /infra/terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "application_url" { 2 | value = module.application.application_url 3 | description = "The Web application URL." 4 | } 5 | 6 | output "resource_group" { 7 | value = azurerm_resource_group.main.name 8 | description = "The resource group." 9 | } 10 | 11 | output "application_name" { 12 | value = module.application.application_caf_name 13 | description = "The application name generated by the Azure Cloud Adoption Framework." 14 | } 15 | -------------------------------------------------------------------------------- /infra/terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "application_name" { 2 | type = string 3 | description = "The name of your application" 4 | default = "cosmosusergroup" 5 | } 6 | 7 | variable "terraform_storage_account" { 8 | type = string 9 | description = "When using an Azure back-end, the name of the Azure Storage Account that stores the Terraform state" 10 | default = "" 11 | } 12 | 13 | variable "environment" { 14 | type = string 15 | description = "The environment (dev, test, prod...)" 16 | default = "" 17 | } 18 | 19 | variable "location" { 20 | type = string 21 | description = "The Azure region where all resources in this example should be created" 22 | default = "westeurope" 23 | } 24 | 25 | variable "address_space" { 26 | type = string 27 | description = "Virtual Network address space" 28 | default = "10.11.0.0/16" 29 | } 30 | 31 | variable "app_subnet_prefix" { 32 | type = string 33 | description = "Application subnet prefix" 34 | default = "10.11.0.0/24" 35 | } 36 | -------------------------------------------------------------------------------- /scripts/ImageScanSummaryAssessmentGate.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Automation script to include ASC vulnerability assessment scan summary for provided image as a gate. 4 | Check result and assess whether to pass security gate by findings severity. 5 | 6 | .DESCRIPTION 7 | Azure secuirty center (ASC) scan Azure container registry (ACR) images for known vulnerabilities on multiple scenarios including image push. 8 | (https://docs.microsoft.com/en-us/azure/security-center/defender-for-container-registries-introduction#when-are-images-scanned) 9 | Using this tool you can have a security gate as part of image release(push) or 10 | deployment to cluster to check if for image there is existent scan in ASC (for example part following push) - retry , 11 | And assess it's findings by configurable thresholds to decide whether to fail the gate - i.e the release/deployment. 12 | Script extracts provided ACR image digest, try to extract ASC scan summary using Azure resource graph AZ CLI module and check if result is healthy or not. 13 | If Healthy, will exit gate successfully, otherwise if unhealthy, 14 | Check for any high findings or medium findings count suppress their thresholds to fail the gate, otherwise will set gate in warning mode. 15 | In case there's a major vulnerability in image, gate(script) will fail to allow exit in CI/CD pipelines. 16 | 17 | 18 | .PARAMETER registryName 19 | [mandatory] 20 | Azure container registry resource name image is stored. 21 | .PARAMETER repository 22 | [mandatory] 23 | It can be any EXISTING resource group, using the ASC default "DefaultResourceGroup-XXX" is one option. 24 | Note: Since the ASC VA solution is not an Azure resource it will not be listed under the resource group, but still it is attached to it. 25 | .PARAMETER tag 26 | [mandatory] 27 | The name of the new solution 28 | .PARAMETER scanExtractionRetryCount 29 | [optional] 30 | Max retries to get image scan summary from ASC. (Useful for waiting for scan result to finish following image push). 31 | .PARAMETER mediumFindingsCountFailThreshold 32 | [optional] 33 | Threshold to fail gate on Medium severity findings count in scan (default is 5) 34 | ** In the case of High servirty finging gate will always fail.** 35 | .PARAMETER lowFindingsCountFailThreshold 36 | [optional] 37 | Threshold to fail gate on Low severity findings count in scan (default is 15) 38 | ** In the case of High servirty finging gate will always fail.** 39 | .PARAMETER ignoreNonPatchable 40 | [optional] 41 | Flag to set whether to fileter out non patchble findings from report (default is $false) 42 | 43 | 44 | .EXAMPLE 45 | .\ImageScanSummaryAssessmentGate.ps1 -registryName -repository -tag 46 | .EXAMPLE 47 | .\ImageScanSummaryAssessmentGate.ps1 -registryName tomerregistry -repository build -tag latest 48 | 49 | .NOTES 50 | AUTHOR: Tomer Weinberger - Software Engineer at Microsoft Azure Security Center 51 | #> 52 | 53 | # Prerequisites 54 | # Azure CLI installed 55 | # Optional: Azure CLI Resource Grpah extension installed (installed as part of script) 56 | Param( 57 | # Image registry name 58 | [Parameter(Mandatory=$true)] 59 | $registryName, 60 | 61 | # Image repository name in registry 62 | [Parameter(Mandatory=$true)] 63 | $repository, 64 | 65 | # Image tag 66 | [Parameter(Mandatory=$true)] 67 | $tag, 68 | 69 | # Max retries to get image scan summary from ASC. 70 | $scanExtractionRetryCount = 3, 71 | 72 | # Medium servrity findings failure threshold 73 | $mediumFindingsCountFailThreshold = 5, 74 | 75 | # Low servrity findings failure threshold 76 | $lowFindingsCountFailThreshold = 15, 77 | 78 | # Image tag 79 | $ignoreNonPatchable = $false 80 | ) 81 | 82 | 83 | 84 | az extension add --name resource-graph -y 85 | 86 | 87 | $imageDigest = az acr repository show -n $registryName --image "$($repository):$($tag)" -o tsv --query digest 88 | if(!$imageDigest) 89 | { 90 | Write-Error "Image '$($repository):$($tag)' was not found! (Registry: $registryName)" 91 | exit 1 92 | } 93 | 94 | Write-Host "Image Digest: $imageDigest" 95 | 96 | # All images scan summary ARG query. 97 | $query = "securityresources 98 | | where type == 'microsoft.security/assessments/subassessments' 99 | | where id matches regex '(.+?)/providers/Microsoft.ContainerRegistry/registries/(.+)/providers/Microsoft.Security/assessments/dbd0cb49-b563-45e7-9724-889e799fa648/' 100 | | extend registryResourceId = tostring(split(id, '/providers/Microsoft.Security/assessments/')[0]) 101 | | extend registryResourceName = tostring(split(registryResourceId, '/providers/Microsoft.ContainerRegistry/registries/')[1]) 102 | | extend imageDigest = tostring(properties.additionalData.imageDigest) 103 | | extend repository = tostring(properties.additionalData.repositoryName) 104 | | extend patchable = tobool(properties.additionalData.patchable) 105 | | extend scanFindingSeverity = tostring(properties.status.severity), scanStatus = tostring(properties.status.code) 106 | | summarize findingsCountOverAll = count(), scanFindingSeverityCount = countif(patchable or not(tobool($ignoreNonPatchable))) by scanFindingSeverity, scanStatus, registryResourceId, registryResourceName, repository, imageDigest 107 | | summarize findingsCountOverAll = sum(findingsCountOverAll), severitySummary = make_bag(pack(scanFindingSeverity, scanFindingSeverityCount)) by registryResourceId, registryResourceName, repository, imageDigest, scanStatus 108 | | summarize findingsCountOverAll = sum(findingsCountOverAll) , scanReport = make_bag_if(pack('scanStatus', scanStatus, 'scanSummary', severitySummary), scanStatus != 'NotApplicable')by registryResourceId, registryResourceName, repository, imageDigest 109 | | extend IsScanned = iif(findingsCountOverAll > 0, true, false)" 110 | 111 | # Add filter to get scan summary for specific provided image 112 | $filter = "| where imageDigest =~ '$imagedigest' and repository =~ '$repository' and registryResourceName =~ '$registryname'" 113 | $query = @($query, $filter) | out-string 114 | 115 | Write-Host "Query: $query" 116 | 117 | # Remove query's new line to use ARG CLI 118 | $query = $query -replace [Environment]::NewLine,"" -replace "`r`n","" -replace "`n","" 119 | 120 | # Get result wit retry policy 121 | $i = 0 122 | while(($result = az graph query -q $query -o json | ConvertFrom-Json).count -eq 0 -and ($i = $i + 1) -lt $scanExtractionRetryCount) 123 | { 124 | Write-Host "No results for image $($repository):$($tag) yet ..." 125 | Start-Sleep -s 20 126 | } 127 | 128 | if(!$result -or $result.count -eq 0) 129 | { 130 | Write-Error "No results were found for digest: $imageDigest after $scanExtractionRetryCount retries!" 131 | exit 1 132 | } 133 | 134 | if(!$result -or $result.count -gt 1) 135 | { 136 | Write-Error "Too many rows returnes, unknown issue $imageDigest, investigate retunres result on top ARG" 137 | exit 1 138 | } 139 | 140 | # Extract scan summary from result 141 | $scanReportRow = $result.data[0] 142 | Write-Host "Scan report row: $($scanReportRow | out-string)" 143 | 144 | if($scanReportRow.IsScanned -ne 1){ 145 | Write-Error "Image not scanned, image: $imageDigest" 146 | exit 1 147 | } 148 | 149 | if ($ignoreNonPatchable) 150 | { 151 | Write-Host "Notice: Filtering non patchble findings Flag is on! this will be cleared from $($scanReportRow.findingsCountOverAll) findinds overall" 152 | Write-Host "" 153 | } 154 | 155 | 156 | $scanReport = $scanReportRow.scanReport 157 | Write-Host "Scan report $($scanReport | out-string)" 158 | 159 | if($scanReport.scanstatus -eq "unhealthy") 160 | { 161 | $scansummary = $scanReport.scanSummary 162 | # Check if there are major vulnerabilities found - customize by parameters 163 | if($scansummary.high -gt 0 ` 164 | -or $scansummary.medium -gt $mediumFindingsCountFailThreshold ` 165 | -or $scansummary.low -gt $lowFindingsCountFailThreshold) 166 | { 167 | Write-Error "Unhealthy scan result, major vulnerabilities found in image summary" 168 | exit 1 169 | } 170 | else 171 | { 172 | Write-Warning "Helathy scan result, as vulnerabilities found in image did not surpass thresholds" 173 | exit 0 174 | } 175 | } 176 | elseif($scanReport.scanstatus -eq "healthy"){ 177 | Write-Host "Healthy Scan found for image!" 178 | exit 0 179 | } 180 | else{ 181 | Write-Host "All non Applicable reuslts Scan -> default as all findings non applicable" 182 | exit 0 183 | } 184 | -------------------------------------------------------------------------------- /src/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 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}.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}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -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:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"} -------------------------------------------------------------------------------- /src/css/ie/backgroundsize.min.htc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/css/ie/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); 8 | for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d img, 11 | .box, 12 | .slider .viewer, 13 | .slider .nav-next, 14 | .slider .nav-previous, 15 | #main > .container { 16 | -ms-behavior: url("css/ie/PIE.htc"); 17 | } 18 | 19 | code, 20 | table td, 21 | ul.icons li .icon, 22 | .feature:before, 23 | input[type="submit"], 24 | input[type="reset"], 25 | input[type="button"], 26 | .button, 27 | input[type="text"], 28 | input[type="password"], 29 | input[type="email"], 30 | select, 31 | textarea { 32 | border: solid 1px #ccc; 33 | } 34 | 35 | /* Box */ 36 | 37 | .box { 38 | position: relative; 39 | } 40 | 41 | .box.post .image:first-child { 42 | margin: 0 0 2em; 43 | width: 100%; 44 | } 45 | 46 | /* Header */ 47 | 48 | #header { 49 | border-bottom: solid 1px #ccc; 50 | } 51 | 52 | #header.alt { 53 | border-bottom: 0; 54 | } 55 | 56 | .dropotron { 57 | border: solid 1px #ccc; 58 | } 59 | 60 | .dropotron.level-0 { 61 | margin-top: -4px; 62 | border-top: 0; 63 | } 64 | 65 | .dropotron.level-0:before { 66 | display: none; 67 | } 68 | 69 | /* Banner */ 70 | 71 | #banner { 72 | background-image: url("../../images/banner.jpg"); 73 | background-repeat: no-repeat; 74 | background-size: cover; 75 | -ms-behavior: url("css/ie/backgroundsize.min.htc"); 76 | } -------------------------------------------------------------------------------- /src/css/ie/v9.css: -------------------------------------------------------------------------------- 1 | /* 2 | Drift by Pixelarity 3 | pixelarity.com @pixelarity 4 | License: pixelarity.com/license 5 | */ 6 | 7 | /* Banner */ 8 | 9 | #banner:after { 10 | display: none; 11 | } -------------------------------------------------------------------------------- /src/css/images/overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/css/images/overlay.png -------------------------------------------------------------------------------- /src/css/skel.css: -------------------------------------------------------------------------------- 1 | /* Resets (http://meyerweb.com/eric/tools/css/reset/ | v2.0 | 20110126 | License: none (public domain)) */ 2 | 3 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block;}body{line-height:1;}ol,ul{list-style:none;}blockquote,q{quotes:none;}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}table{border-collapse:collapse;border-spacing:0;}body{-webkit-text-size-adjust:none} 4 | 5 | /* Box Model */ 6 | 7 | *, *:before, *:after { 8 | -moz-box-sizing: border-box; 9 | -webkit-box-sizing: border-box; 10 | box-sizing: border-box; 11 | } 12 | 13 | /* Container */ 14 | 15 | body { 16 | /* min-width: (containers) */ 17 | min-width: 1200px; 18 | } 19 | 20 | .container { 21 | margin-left: auto; 22 | margin-right: auto; 23 | 24 | /* width: (containers) */ 25 | width: 1200px; 26 | } 27 | 28 | /* Modifiers */ 29 | 30 | /* 125% */ 31 | .container.\31 25\25 { 32 | width: 100%; 33 | 34 | /* max-width: (containers * 1.25) */ 35 | max-width: 1500px; 36 | 37 | /* min-width: (containers) */ 38 | min-width: 1200px; 39 | } 40 | 41 | /* 75% */ 42 | .container.\37 5\25 { 43 | 44 | /* width: (containers * 0.75) */ 45 | width: 900px; 46 | 47 | } 48 | 49 | /* 50% */ 50 | .container.\35 0\25 { 51 | 52 | /* width: (containers * 0.50) */ 53 | width: 600px; 54 | 55 | } 56 | 57 | /* 25% */ 58 | .container.\32 5\25 { 59 | 60 | /* width: (containers * 0.25) */ 61 | width: 300px; 62 | 63 | } 64 | 65 | /* Grid */ 66 | 67 | .row { 68 | border-bottom: solid 1px transparent; 69 | } 70 | 71 | .row > * { 72 | float: left; 73 | } 74 | 75 | .row:after, .row:before { 76 | content: ''; 77 | display: block; 78 | clear: both; 79 | height: 0; 80 | } 81 | 82 | .row.uniform > * > :first-child { 83 | margin-top: 0; 84 | } 85 | 86 | .row.uniform > * > :last-child { 87 | margin-bottom: 0; 88 | } 89 | 90 | /* Gutters */ 91 | 92 | /* Normal */ 93 | 94 | .row > * { 95 | /* padding: (gutters.horizontal) 0 0 (gutters.vertical) */ 96 | padding: 0 0 0 2em; 97 | } 98 | 99 | .row { 100 | /* margin: -(gutters.horizontal) 0 0 -(gutters.vertical) */ 101 | margin: 0 0 0 -2em; 102 | } 103 | 104 | .row.uniform > * { 105 | /* padding: (gutters.vertical) 0 0 (gutters.vertical) */ 106 | padding: 2em 0 0 2em; 107 | } 108 | 109 | .row.uniform { 110 | /* margin: -(gutters.vertical) 0 0 -(gutters.vertical) */ 111 | margin: -2em 0 0 -2em; 112 | } 113 | 114 | /* 200% */ 115 | 116 | .row.\32 00\25 > * { 117 | /* padding: (gutters.horizontal) 0 0 (gutters.vertical) */ 118 | padding: 0 0 0 4em; 119 | } 120 | 121 | .row.\32 00\25 { 122 | /* margin: -(gutters.horizontal) 0 0 -(gutters.vertical) */ 123 | margin: 0 0 0 -4em; 124 | } 125 | 126 | .row.uniform.\32 00\25 > * { 127 | /* padding: (gutters.vertical) 0 0 (gutters.vertical) */ 128 | padding: 4em 0 0 4em; 129 | } 130 | 131 | .row.uniform.\32 00\25 { 132 | /* margin: -(gutters.vertical) 0 0 -(gutters.vertical) */ 133 | margin: -4em 0 0 -4em; 134 | } 135 | 136 | /* 150% */ 137 | 138 | .row.\31 50\25 > * { 139 | /* padding: (gutters.horizontal) 0 0 (gutters.vertical) */ 140 | padding: 0 0 0 1.5em; 141 | } 142 | 143 | .row.\31 50\25 { 144 | /* margin: -(gutters.horizontal) 0 0 -(gutters.vertical) */ 145 | margin: 0 0 0 -1.5em; 146 | } 147 | 148 | .row.uniform.\31 50\25 > * { 149 | /* padding: (gutters.vertical) 0 0 (gutters.vertical) */ 150 | padding: 1.5em 0 0 1.5em; 151 | } 152 | 153 | .row.uniform.\31 50\25 { 154 | /* margin: -(gutters.vertical) 0 0 -(gutters.vertical) */ 155 | margin: -1.5em 0 0 -1.5em; 156 | } 157 | 158 | /* 50% */ 159 | 160 | .row.\35 0\25 > * { 161 | /* padding: (gutters.horizontal) 0 0 (gutters.vertical) */ 162 | padding: 0 0 0 1em; 163 | } 164 | 165 | .row.\35 0\25 { 166 | /* margin: -(gutters.horizontal) 0 0 -(gutters.vertical) */ 167 | margin: 0 0 0 -1em; 168 | } 169 | 170 | .row.uniform.\35 0\25 > * { 171 | /* padding: (gutters.vertical) 0 0 (gutters.vertical) */ 172 | padding: 1em 0 0 1em; 173 | } 174 | 175 | .row.uniform.\35 0\25 { 176 | /* margin: -(gutters.vertical) 0 0 -(gutters.vertical) */ 177 | margin: -1em 0 0 -1em; 178 | } 179 | 180 | /* 25% */ 181 | 182 | .row.\32 5\25 > * { 183 | /* padding: (gutters.horizontal) 0 0 (gutters.vertical) */ 184 | padding: 0 0 0 0.5em; 185 | } 186 | 187 | .row.\32 5\25 { 188 | /* margin: -(gutters.horizontal) 0 0 -(gutters.vertical) */ 189 | margin: 0 0 0 -0.5em; 190 | } 191 | 192 | .row.uniform.\32 5\25 > * { 193 | /* padding: (gutters.vertical) 0 0 (gutters.vertical) */ 194 | padding: 0.5em 0 0 0.5em; 195 | } 196 | 197 | .row.uniform.\32 5\25 { 198 | /* margin: -(gutters.vertical) 0 0 -(gutters.vertical) */ 199 | margin: -0.5em 0 0 -0.5em; 200 | } 201 | 202 | /* 0% */ 203 | 204 | .row.\30 \25 > * { 205 | /* padding: (gutters.horizontal) 0 0 (gutters.vertical) */ 206 | padding: 0; 207 | } 208 | 209 | .row.\30 \25 { 210 | /* margin: -(gutters.horizontal) 0 0 -(gutters.vertical) */ 211 | margin: 0; 212 | } 213 | 214 | /* Cells */ 215 | 216 | .\31 2u, .\31 2u\24, .\31 2u\28 1\29, .\31 2u\24\28 1\29 { width: 100%; clear: none; } 217 | .\31 1u, .\31 1u\24, .\31 1u\28 1\29, .\31 1u\24\28 1\29 { width: 91.6666666667%; clear: none; } 218 | .\31 0u, .\31 0u\24, .\31 0u\28 1\29, .\31 0u\24\28 1\29 { width: 83.3333333333%; clear: none; } 219 | .\39 u, .\39 u\24, .\39 u\28 1\29, .\39 u\24\28 1\29 { width: 75%; clear: none; } 220 | .\38 u, .\38 u\24, .\38 u\28 1\29, .\38 u\24\28 1\29 { width: 66.6666666667%; clear: none; } 221 | .\37 u, .\37 u\24, .\37 u\28 1\29, .\37 u\24\28 1\29 { width: 58.3333333333%; clear: none; } 222 | .\36 u, .\36 u\24, .\36 u\28 1\29, .\36 u\24\28 1\29 { width: 50%; clear: none; } 223 | .\35 u, .\35 u\24, .\35 u\28 1\29, .\35 u\24\28 1\29 { width: 41.6666666667%; clear: none; } 224 | .\34 u, .\34 u\24, .\34 u\28 1\29, .\34 u\24\28 1\29 { width: 33.3333333333%; clear: none; } 225 | .\33 u, .\33 u\24, .\33 u\28 1\29, .\33 u\24\28 1\29 { width: 25%; clear: none; } 226 | .\32 u, .\32 u\24, .\32 u\28 1\29, .\32 u\24\28 1\29 { width: 16.6666666667%; clear: none; } 227 | .\31 u, .\31 u\24, .\31 u\28 1\29, .\31 u\24\28 1\29 { width: 8.3333333333%; clear: none; } 228 | 229 | .\31 2u\24 + *, .\31 2u\24\28 1\29 + *, 230 | .\31 1u\24 + *, .\31 1u\24\28 1\29 + *, 231 | .\31 0u\24 + *, .\31 0u\24\28 1\29 + *, 232 | .\39 u\24 + *, .\39 u\24\28 1\29 + *, 233 | .\38 u\24 + *, .\38 u\24\28 1\29 + *, 234 | .\37 u\24 + *, .\37 u\24\28 1\29 + *, 235 | .\36 u\24 + *, .\36 u\24\28 1\29 + *, 236 | .\35 u\24 + *, .\35 u\24\28 1\29 + *, 237 | .\34 u\24 + *, .\34 u\24\28 1\29 + *, 238 | .\33 u\24 + *, .\33 u\24\28 1\29 + *, 239 | .\32 u\24 + *, .\32 u\24\28 1\29 + *, 240 | .\31 u\24 + *, .\31 u\24\28 1\29 + * { 241 | clear: left; 242 | } 243 | 244 | .\-11u { margin-left: 91.6666666667% } 245 | .\-10u { margin-left: 83.3333333333% } 246 | .\-9u { margin-left: 75% } 247 | .\-8u { margin-left: 66.6666666667% } 248 | .\-7u { margin-left: 58.3333333333% } 249 | .\-6u { margin-left: 50% } 250 | .\-5u { margin-left: 41.6666666667% } 251 | .\-4u { margin-left: 33.3333333333% } 252 | .\-3u { margin-left: 25% } 253 | .\-2u { margin-left: 16.6666666667% } 254 | .\-1u { margin-left: 8.3333333333% } -------------------------------------------------------------------------------- /src/css/style-large.css: -------------------------------------------------------------------------------- 1 | /* 2 | Drift by Pixelarity 3 | pixelarity.com @pixelarity 4 | License: pixelarity.com/license 5 | */ 6 | 7 | /* Basic */ 8 | 9 | body, input, select, textarea { 10 | font-size: 11pt; 11 | } 12 | 13 | /* Header */ 14 | 15 | .dropotron.level-0 { 16 | font-size: 1em; 17 | } 18 | 19 | /* Banner */ 20 | 21 | #banner { 22 | background-attachment: scroll; 23 | padding: 10em 0; 24 | } -------------------------------------------------------------------------------- /src/css/style-medium.css: -------------------------------------------------------------------------------- 1 | /* 2 | Drift by Pixelarity 3 | pixelarity.com @pixelarity 4 | License: pixelarity.com/license 5 | */ 6 | 7 | /* Basic */ 8 | 9 | body, input, select, textarea { 10 | font-size: 12pt; 11 | } 12 | 13 | h2 br, h3 br, h4 br, h5 br, h6 br { 14 | display: none; 15 | } 16 | 17 | /* Section/Article */ 18 | 19 | header br { 20 | display: none; 21 | } 22 | 23 | /* Feature */ 24 | 25 | .feature { 26 | padding-left: 0; 27 | text-align: center; 28 | } 29 | 30 | .feature:before { 31 | margin: 0 0 0.7em 0; 32 | position: relative; 33 | } 34 | 35 | .feature p { 36 | padding: 0 2em; 37 | } 38 | 39 | /* Slider */ 40 | 41 | .slider .viewer { 42 | border-width: 1em; 43 | width: 100%; 44 | } 45 | 46 | .slider .slide img { 47 | border-radius: 0.375em; 48 | display: block; 49 | width: 100%; 50 | } 51 | 52 | .slider .nav-next, 53 | .slider .nav-previous { 54 | background: none; 55 | border-radius: 0; 56 | color: #fff; 57 | height: 100%; 58 | margin-top: 0; 59 | top: 0; 60 | vertical-align: bottom; 61 | width: 50%; 62 | z-index: 1; 63 | } 64 | 65 | .slider .nav-next:before, 66 | .slider .nav-previous:before { 67 | display: block; 68 | height: 2em; 69 | line-height: 2em; 70 | margin-top: -1em; 71 | padding: 0 1em; 72 | top: 50%; 73 | width: 100%; 74 | } 75 | 76 | .slider .nav-next { 77 | right: 0; 78 | text-align: right; 79 | } 80 | 81 | .slider .nav-previous { 82 | left: 0; 83 | text-align: left; 84 | } 85 | 86 | /* Header */ 87 | 88 | #skel-layers-wrapper { 89 | padding-top: 0; 90 | } 91 | 92 | #header { 93 | display: none; 94 | } 95 | 96 | /* Banner */ 97 | 98 | #banner { 99 | padding: 12em 2em; 100 | } 101 | 102 | /* Layers */ 103 | 104 | #navButton .toggle { 105 | text-decoration: none; 106 | height: 100%; 107 | left: 0; 108 | position: absolute; 109 | top: 0; 110 | width: 100%; 111 | } 112 | 113 | #navButton .toggle:before { 114 | -moz-osx-font-smoothing: grayscale; 115 | -webkit-font-smoothing: antialiased; 116 | font-family: FontAwesome; 117 | font-style: normal; 118 | font-weight: normal; 119 | text-transform: none !important; 120 | } 121 | 122 | #navButton .toggle:before { 123 | background: rgba(103, 107, 113, 0.75); 124 | border-radius: 0.5em; 125 | color: #fff; 126 | content: '\f0c9'; 127 | display: block; 128 | font-size: 16px; 129 | height: 2.25em; 130 | left: 0.5em; 131 | line-height: 2.25em; 132 | position: absolute; 133 | text-align: center; 134 | top: 0.5em; 135 | width: 3.5em; 136 | } 137 | 138 | #navPanel { 139 | background-color: #fff; 140 | box-shadow: 0.5em 0 2em 0 rgba(0, 0, 0, 0.1); 141 | padding: 0.5em 1.5em; 142 | } 143 | 144 | #navPanel .link { 145 | border: 0; 146 | border-top: solid 1px rgba(144, 144, 144, 0.2); 147 | color: #646464 !important; 148 | display: block; 149 | height: 3em; 150 | line-height: 3em; 151 | text-decoration: none; 152 | } 153 | 154 | #navPanel .link:first-child { 155 | border-top: 0; 156 | } 157 | 158 | #navPanel .link.depth-0 { 159 | font-weight: 700; 160 | color: #545454 !important; 161 | } 162 | 163 | #navPanel .link .indent-1 { 164 | display: inline-block; 165 | width: 1.25em; 166 | } 167 | 168 | #navPanel .link .indent-2 { 169 | display: inline-block; 170 | width: 2.5em; 171 | } 172 | 173 | #navPanel .link .indent-3 { 174 | display: inline-block; 175 | width: 3.75em; 176 | } 177 | 178 | #navPanel .link .indent-4 { 179 | display: inline-block; 180 | width: 5em; 181 | } 182 | 183 | #navPanel .link .indent-5 { 184 | display: inline-block; 185 | width: 6.25em; 186 | } -------------------------------------------------------------------------------- /src/css/style-small.css: -------------------------------------------------------------------------------- 1 | /* 2 | Drift by Pixelarity 3 | pixelarity.com @pixelarity 4 | License: pixelarity.com/license 5 | */ 6 | 7 | /* Basic */ 8 | 9 | body, input, select, textarea { 10 | font-size: 12pt; 11 | } 12 | 13 | h2 { 14 | font-size: 1.25em; 15 | line-height: 1.5em; 16 | } 17 | 18 | h3 { 19 | font-size: 1.1em; 20 | line-height: 1.5em; 21 | } 22 | 23 | h4 { 24 | font-size: 1em; 25 | line-height: 1.5em; 26 | } 27 | 28 | /* Section/Article */ 29 | 30 | header h2 + p { 31 | font-size: 1em; 32 | margin-top: -0.85em; 33 | line-height: 1.5em; 34 | } 35 | 36 | header h3 + p { 37 | font-size: 1em; 38 | margin-top: -0.85em; 39 | line-height: 1.5em; 40 | } 41 | 42 | header.major h2 { 43 | font-size: 1.5em; 44 | } 45 | 46 | header.major p { 47 | margin: -1em 0 2.5em 0; 48 | } 49 | 50 | /* List */ 51 | 52 | ul.icons li { 53 | padding: 0 0.75em 0 0; 54 | } 55 | 56 | ul.icons li .icon { 57 | font-size: 0.9em; 58 | } 59 | 60 | /* Button */ 61 | 62 | input[type="submit"], 63 | input[type="reset"], 64 | input[type="button"], 65 | .button { 66 | font-size: 0.8em !important; 67 | } 68 | 69 | /* Box */ 70 | 71 | .box.post { 72 | max-width: 23em; 73 | } 74 | 75 | /* Slider */ 76 | 77 | .slider .viewer { 78 | border-width: 0.5em; 79 | } 80 | 81 | /* Wrapper */ 82 | 83 | .wrapper { 84 | padding: 3em 0 1em 0; 85 | } 86 | 87 | /* Banner */ 88 | 89 | #banner { 90 | padding: 5em 2em 4em 2em; 91 | } 92 | 93 | #banner h2 { 94 | font-size: 2em; 95 | } 96 | 97 | #banner p { 98 | font-size: 1.1em; 99 | } 100 | 101 | /* Main */ 102 | 103 | #main > header { 104 | padding: 0 2em; 105 | } 106 | 107 | #main > .container { 108 | padding: 2em 1em; 109 | } 110 | 111 | #content > .image.fit:first-child { 112 | margin: -2em 0 2em -1em; 113 | width: calc(100% + 2em); 114 | } 115 | 116 | #content > .image.fit:first-child img { 117 | border-bottom-left-radius: 0; 118 | border-bottom-right-radius: 0; 119 | } 120 | 121 | /* CTA */ 122 | 123 | #cta { 124 | padding: 2em 0; 125 | } 126 | 127 | /* Footer */ 128 | 129 | #footer { 130 | padding: 2em 0; 131 | } 132 | 133 | #footer .icons { 134 | margin: 0 0 2em 0; 135 | } -------------------------------------------------------------------------------- /src/css/style-xlarge.css: -------------------------------------------------------------------------------- 1 | /* 2 | Drift by Pixelarity 3 | pixelarity.com @pixelarity 4 | License: pixelarity.com/license 5 | */ 6 | 7 | /* Basic */ 8 | 9 | body, input, select, textarea { 10 | font-size: 12pt; 11 | } 12 | 13 | /* Banner */ 14 | 15 | #banner { 16 | padding: 12em 0; 17 | } -------------------------------------------------------------------------------- /src/css/style-xsmall.css: -------------------------------------------------------------------------------- 1 | /* 2 | Drift by Pixelarity 3 | pixelarity.com @pixelarity 4 | License: pixelarity.com/license 5 | */ 6 | 7 | /* Basic */ 8 | 9 | html, body { 10 | min-width: 320px; 11 | } 12 | 13 | body, input, select, textarea { 14 | font-size: 12pt; 15 | } 16 | 17 | /* List */ 18 | 19 | ul.actions { 20 | margin: 0 0 2em 0; 21 | } 22 | 23 | ul.actions li { 24 | display: block; 25 | padding: 1em 0 0 0; 26 | text-align: center; 27 | width: 100%; 28 | } 29 | 30 | ul.actions li:first-child { 31 | padding-top: 0; 32 | } 33 | 34 | ul.actions li > * { 35 | margin: 0 !important; 36 | width: 100%; 37 | } 38 | 39 | ul.actions li > *.icon:before { 40 | margin-left: -2em; 41 | } 42 | 43 | ul.actions.small li { 44 | padding: 0.5em 0 0 0; 45 | } 46 | 47 | ul.actions.small li:first-child { 48 | padding-top: 0; 49 | } 50 | 51 | ul.menu { 52 | font-size: 0.8em; 53 | line-height: 2em; 54 | } 55 | 56 | ul.menu li { 57 | border: 0; 58 | margin: 0; 59 | padding: 0 0.5em !important; 60 | } 61 | 62 | /* Button */ 63 | 64 | input[type="submit"], 65 | input[type="reset"], 66 | input[type="button"], 67 | .button { 68 | padding: 0; 69 | } 70 | 71 | /* Slider */ 72 | 73 | .slider { 74 | position: relative; 75 | } 76 | 77 | .slider .viewer { 78 | border-radius: 0 !important; 79 | border-width: 0em; 80 | margin-left: -5vw; 81 | width: 100vw; 82 | } 83 | 84 | .slider .slide img { 85 | border-radius: 0 !important; 86 | } 87 | 88 | .slider .nav-next:before, 89 | .slider .nav-previous:before { 90 | font-size: 0.8em; 91 | } 92 | 93 | /* Banner */ 94 | 95 | #banner { 96 | padding: 5em 2em 4em 2em; 97 | } 98 | 99 | /* CTA */ 100 | 101 | #cta { 102 | padding: 2em; 103 | } 104 | 105 | #cta h2 { 106 | display: block; 107 | margin: 0 0 1em 0; 108 | } 109 | 110 | #cta .actions { 111 | display: block; 112 | } -------------------------------------------------------------------------------- /src/elements.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 55 | 56 | 57 |
58 |
59 |

Elements

60 |

Faucibus neque adipiscing mi lorem semper blandit

61 |
62 |
63 | 64 | 65 |
66 | 67 | 68 |
69 |

Text

70 |

This is bold and this is strong. This is italic and this is emphasized. 71 | This is superscript text and this is subscript text. 72 | This is underlined and this is code: for (;;) { ... }. Finally, this is a link.

73 | 74 |
75 | 76 |
77 |

Heading with a Subtitle

78 |

Lorem ipsum dolor sit amet nullam id egestas urna aliquam

79 |
80 |

Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan varius montes viverra nibh in adipiscing blandit tempus accumsan.

81 |
82 |

Heading with a Subtitle

83 |

Lorem ipsum dolor sit amet nullam id egestas urna aliquam

84 |
85 |

Nunc lacinia ante nunc ac lobortis. Interdum adipiscing gravida odio porttitor sem non mi integer non faucibus ornare mi ut ante amet placerat aliquet. Volutpat eu sed ante lacinia sapien lorem accumsan varius montes viverra nibh in adipiscing blandit tempus accumsan.

86 | 87 |
88 | 89 |

Heading Level 2

90 |

Heading Level 3

91 |

Heading Level 4

92 |
Heading Level 5
93 |
Heading Level 6
94 | 95 |
96 | 97 |

Blockquote

98 |
Fringilla nisl. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan faucibus. Vestibulum ante ipsum primis in faucibus lorem ipsum dolor sit amet nullam adipiscing eu felis.
99 | 100 |

Preformatted

101 |
i = 0;
102 | 
103 | while (!deck.isInOrder()) {
104 |     print 'Iteration ' + i;
105 |     deck.shuffle();
106 |     i++;
107 | }
108 | 
109 | print 'It took ' + i + ' iterations to sort the deck.';
110 | 
111 |
112 | 113 | 114 |
115 |

Lists

116 |
117 |
118 | 119 |

Unordered

120 |
    121 |
  • Dolor pulvinar etiam magna etiam.
  • 122 |
  • Sagittis adipiscing lorem eleifend.
  • 123 |
  • Felis enim feugiat dolore viverra.
  • 124 |
125 | 126 |

Alternate

127 |
    128 |
  • Dolor pulvinar etiam magna etiam.
  • 129 |
  • Sagittis adipiscing lorem eleifend.
  • 130 |
  • Felis enim feugiat dolore viverra.
  • 131 |
132 | 133 |
134 |
135 | 136 |

Ordered

137 |
    138 |
  1. Dolor pulvinar etiam magna etiam.
  2. 139 |
  3. Etiam vel felis at lorem sed viverra.
  4. 140 |
  5. Felis enim feugiat dolore viverra.
  6. 141 |
  7. Dolor pulvinar etiam magna etiam.
  8. 142 |
  9. Etiam vel felis at lorem sed viverra.
  10. 143 |
  11. Felis enim feugiat dolore viverra.
  12. 144 |
145 | 146 |

Icons

147 | 155 | 156 |
157 |
158 | 159 |

Actions

160 | 164 | 168 |
169 |
170 | 174 |
175 |
176 | 180 |
181 |
182 | 186 |
187 |
188 | 192 |
193 |
194 |
195 | 196 | 197 |
198 |

Table

199 | 200 |

Default

201 |
202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 |
NameDescriptionPrice
SomethingAnte turpis integer aliquet porttitor.29.99
NothingVis ac commodo adipiscing arcu aliquet.19.99
Something Morbi faucibus arcu accumsan lorem.29.99
NothingVitae integer tempus condimentum.19.99
SomethingAnte turpis integer aliquet porttitor.29.99
100.00
244 |
245 | 246 |

Alternate

247 |
248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 |
NameDescriptionPrice
SomethingAnte turpis integer aliquet porttitor.29.99
NothingVis ac commodo adipiscing arcu aliquet.19.99
Something Morbi faucibus arcu accumsan lorem.29.99
NothingVitae integer tempus condimentum.19.99
SomethingAnte turpis integer aliquet porttitor.29.99
100.00
290 |
291 |
292 | 293 | 294 |
295 |

Buttons

296 | 300 | 305 | 309 | 313 | 317 |
    318 |
  • Special
  • 319 |
  • Default
  • 320 |
321 |
322 | 323 | 324 |
325 |

Form

326 |
327 |
328 |
329 | 330 |
331 |
332 | 333 |
334 |
335 |
336 |
337 |
338 | 345 |
346 |
347 |
348 |
349 |
350 | 351 | 352 |
353 |
354 | 355 | 356 |
357 |
358 | 359 | 360 |
361 |
362 |
363 |
364 | 365 | 366 |
367 |
368 | 369 | 370 |
371 |
372 |
373 |
374 | 375 |
376 |
377 |
378 |
379 |
    380 |
  • 381 |
  • 382 |
383 |
384 |
385 |
386 |
387 | 388 | 389 |
390 |

Image

391 |

Fit

392 | 393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 | 407 |

Left & Right

408 |

Fringilla nisl. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent tincidunt praesent. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent.

409 |

Fringilla nisl. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent tincidunt praesent. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus felis sagittis eget. tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan eu faucibus. Integer ac pellentesque praesent.

410 |
411 | 412 |
413 | 414 |
415 |
416 | 417 | 418 | 436 | 437 | 438 | -------------------------------------------------------------------------------- /src/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/images/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/banner.jpg -------------------------------------------------------------------------------- /src/images/pic01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic01.jpg -------------------------------------------------------------------------------- /src/images/pic02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic02.jpg -------------------------------------------------------------------------------- /src/images/pic03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic03.jpg -------------------------------------------------------------------------------- /src/images/pic04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic04.jpg -------------------------------------------------------------------------------- /src/images/pic05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic05.jpg -------------------------------------------------------------------------------- /src/images/pic06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic06.jpg -------------------------------------------------------------------------------- /src/images/pic07.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic07.jpg -------------------------------------------------------------------------------- /src/images/pic08.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic08.jpg -------------------------------------------------------------------------------- /src/images/pic09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/pic09.jpg -------------------------------------------------------------------------------- /src/images/slide01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/slide01.jpg -------------------------------------------------------------------------------- /src/images/slide02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/slide02.jpg -------------------------------------------------------------------------------- /src/images/slide03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scubaninja/AzureDevOps-Demo/ab9379c48628137f0927d69de49b7c022a891e3c/src/images/slide03.jpg -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 55 | 56 | 57 | 66 | 67 | 68 |
69 |
70 |
71 |

Follow me @TheAprilEdwards

72 |

I can haz a cheeseburger.

73 |
74 |
75 | 76 |
77 |
78 |
79 | 80 |
81 |
82 | 83 |
84 |
85 | 86 |
87 |
88 |
89 | 90 |
91 |
92 |
93 | 94 | 95 |
96 |
97 |
98 |
99 |
100 |

Natoque phasellus

101 |

Ipsum dolor tempus commodo amet sed accumsan et adipiscing blandit porttitor sed faucibus.

102 |
103 |
104 |
105 |
106 |

Ultricies dolore

107 |

Ipsum dolor tempus commodo amet sed accumsan et adipiscing blandit porttitor sed faucibus.

108 |
109 |
110 |
111 |
112 |

Magna lacinia

113 |

Ipsum dolor tempus commodo amet sed accumsan et adipiscing blandit porttitor sed faucibus.

114 |
115 |
116 |
117 |
118 |

Praesent lacinia

119 |

Ipsum dolor tempus commodo amet sed accumsan et adipiscing blandit porttitor sed faucibus.

120 |
121 |
122 |
123 |
124 |

Morbi semper

125 |

Ipsum dolor tempus commodo amet sed accumsan et adipiscing blandit porttitor sed faucibus.

126 |
127 |
128 |
129 |
130 |

Arcu consequat

131 |

Ipsum dolor tempus commodo amet sed accumsan et adipiscing blandit porttitor sed faucibus.

132 |
133 |
134 |
135 |
136 |
137 | 138 | 139 |
140 |
141 |
142 |

Amet nisl consequat

143 |

Ipsum dolor tempus commodo turpis adipiscing adipiscing in tempor placerat
144 | sed amet accumsan enim lorem sem turpis ut. Massa amet erat accumsan curae
145 | blandit porttitor faucibus in nisl nisi volutpat massa mi non nascetur.

146 |
147 |
148 |
149 |
150 | 151 |

Sed amet lorem

152 |

Ipsum dolor tempus et commodo lorem accumsan et adipiscing blandit porttitor feugiat tempus lorem faucibus.

153 | 156 |
157 |
158 |
159 |
160 | 161 |

Massa accumsan

162 |

Ipsum dolor tempus et commodo lorem accumsan et adipiscing blandit porttitor feugiat tempus lorem faucibus.

163 | 166 |
167 |
168 |
169 |
170 | 171 |

Faucibus portitor

172 |

Ipsum dolor tempus et commodo lorem accumsan et adipiscing blandit porttitor feugiat tempus lorem faucibus.

173 | 176 |
177 |
178 |
179 |
180 | 181 |

Non placerat

182 |

Ipsum dolor tempus et commodo lorem accumsan et adipiscing blandit porttitor feugiat tempus lorem faucibus.

183 | 186 |
187 |
188 |
189 |
190 | 191 |

Adipiscing dolor

192 |

Ipsum dolor tempus et commodo lorem accumsan et adipiscing blandit porttitor feugiat tempus lorem faucibus.

193 | 196 |
197 |
198 |
199 |
200 | 201 |

Feugiat tempus

202 |

Ipsum dolor tempus et commodo lorem accumsan et adipiscing blandit porttitor feugiat tempus lorem faucibus.

203 | 206 |
207 |
208 |
209 |
210 |
211 | 212 | 213 |
214 |

Sed faucibus et consequat

215 | 218 |
219 | 220 | 221 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /src/js/init.js: -------------------------------------------------------------------------------- 1 | /* 2 | Drift by Pixelarity 3 | pixelarity.com @pixelarity 4 | License: pixelarity.com/license 5 | */ 6 | 7 | (function($) { 8 | 9 | skel.init({ 10 | reset: 'full', 11 | breakpoints: { 12 | global: { href: 'css/style.css', containers: 1400, grid: { gutters: ['2em', 0] } }, 13 | xlarge: { media: '(max-width: 1680px)', href: 'css/style-xlarge.css', containers: 1200 }, 14 | large: { media: '(max-width: 1280px)', href: 'css/style-large.css', containers: 960, grid: { gutters: ['1.5em', 0] }, viewport: { scalable: false } }, 15 | medium: { media: '(max-width: 980px)', href: 'css/style-medium.css', containers: '90%', grid: { zoom: 2 } }, 16 | small: { media: '(max-width: 736px)', href: 'css/style-small.css', containers: '90%!', grid: { gutters: ['1.25em', 0], zoom: 3 } }, 17 | xsmall: { media: '(max-width: 480px)', href: 'css/style-xsmall.css' } 18 | }, 19 | plugins: { 20 | layers: { 21 | 22 | // Config. 23 | config: { 24 | transformTest: function() { return skel.vars.isMobile; } 25 | }, 26 | 27 | // Navigation Button. 28 | navButton: { 29 | breakpoints: 'medium', 30 | height: '4em', 31 | html: '', 32 | position: 'top-left', 33 | side: 'top', 34 | width: '6em' 35 | }, 36 | 37 | // Navigation Panel. 38 | navPanel: { 39 | animation: 'overlayX', 40 | breakpoints: 'medium', 41 | clickToHide: true, 42 | height: '100%', 43 | hidden: true, 44 | html: '
', 45 | orientation: 'vertical', 46 | position: 'top-left', 47 | side: 'left', 48 | width: 250 49 | } 50 | 51 | } 52 | } 53 | }); 54 | 55 | $(function() { 56 | 57 | var $window = $(window), 58 | $body = $('body'), 59 | $banner = $('#banner'), 60 | $header = $('#header'); 61 | 62 | // Disable animations/transitions until the page has loaded. 63 | $body.addClass('is-loading'); 64 | 65 | $window.on('load', function() { 66 | window.setTimeout(function() { 67 | $body.removeClass('is-loading'); 68 | }, 500); 69 | }); 70 | 71 | // Forms (IE<10). 72 | var $form = $('form'); 73 | if ($form.length > 0) { 74 | 75 | $form.find('.form-button-submit') 76 | .on('click', function() { 77 | $(this).parents('form').submit(); 78 | return false; 79 | }); 80 | 81 | if (skel.vars.IEVersion < 10) { 82 | $.fn.n33_formerize=function(){var _fakes=new Array(),_form = $(this);_form.find('input[type=text],textarea').each(function() { var e = $(this); if (e.val() == '' || e.val() == e.attr('placeholder')) { e.addClass('formerize-placeholder'); e.val(e.attr('placeholder')); } }).blur(function() { var e = $(this); if (e.attr('name').match(/_fakeformerizefield$/)) return; if (e.val() == '') { e.addClass('formerize-placeholder'); e.val(e.attr('placeholder')); } }).focus(function() { var e = $(this); if (e.attr('name').match(/_fakeformerizefield$/)) return; if (e.val() == e.attr('placeholder')) { e.removeClass('formerize-placeholder'); e.val(''); } }); _form.find('input[type=password]').each(function() { var e = $(this); var x = $($('
').append(e.clone()).remove().html().replace(/type="password"/i, 'type="text"').replace(/type=password/i, 'type=text')); if (e.attr('id') != '') x.attr('id', e.attr('id') + '_fakeformerizefield'); if (e.attr('name') != '') x.attr('name', e.attr('name') + '_fakeformerizefield'); x.addClass('formerize-placeholder').val(x.attr('placeholder')).insertAfter(e); if (e.val() == '') e.hide(); else x.hide(); e.blur(function(event) { event.preventDefault(); var e = $(this); var x = e.parent().find('input[name=' + e.attr('name') + '_fakeformerizefield]'); if (e.val() == '') { e.hide(); x.show(); } }); x.focus(function(event) { event.preventDefault(); var x = $(this); var e = x.parent().find('input[name=' + x.attr('name').replace('_fakeformerizefield', '') + ']'); x.hide(); e.show().focus(); }); x.keypress(function(event) { event.preventDefault(); x.val(''); }); }); _form.submit(function() { $(this).find('input[type=text],input[type=password],textarea').each(function(event) { var e = $(this); if (e.attr('name').match(/_fakeformerizefield$/)) e.attr('name', ''); if (e.val() == e.attr('placeholder')) { e.removeClass('formerize-placeholder'); e.val(''); } }); }).bind("reset", function(event) { event.preventDefault(); $(this).find('select').val($('option:first').val()); $(this).find('input,textarea').each(function() { var e = $(this); var x; e.removeClass('formerize-placeholder'); switch (this.type) { case 'submit': case 'reset': break; case 'password': e.val(e.attr('defaultValue')); x = e.parent().find('input[name=' + e.attr('name') + '_fakeformerizefield]'); if (e.val() == '') { e.hide(); x.show(); } else { e.show(); x.hide(); } break; case 'checkbox': case 'radio': e.attr('checked', e.attr('defaultValue')); break; case 'text': case 'textarea': e.val(e.attr('defaultValue')); if (e.val() == '') { e.addClass('formerize-placeholder'); e.val(e.attr('placeholder')); } break; default: e.val(e.attr('defaultValue')); break; } }); window.setTimeout(function() { for (x in _fakes) _fakes[x].trigger('formerize_sync'); }, 10); }); return _form; }; 83 | $form.n33_formerize(); 84 | } 85 | 86 | } 87 | 88 | // Scrolly links. 89 | $('.scrolly').scrolly(); 90 | 91 | // Header. 92 | // If the header is using "alt" styling and #banner is present, use scrollwatch 93 | // to revert it back to normal styling once the user scrolls past the banner. 94 | if ($header.hasClass('alt') 95 | && $banner.length > 0) { 96 | 97 | $window.on('load', function() { 98 | 99 | $banner.scrollwatch({ 100 | delay: 0, 101 | range: 0.98, 102 | anchor: 'top', 103 | on: function() { $header.addClass('alt reveal'); }, 104 | off: function() { $header.removeClass('alt'); } 105 | }); 106 | 107 | skel.change(function() { 108 | 109 | if (skel.isActive('medium')) 110 | $banner.scrollwatchSuspend(); 111 | else 112 | $banner.scrollwatchResume(); 113 | 114 | }); 115 | 116 | }); 117 | 118 | } 119 | 120 | // Dropdowns. 121 | $('#nav > ul').dropotron({ 122 | alignment: 'right' 123 | }); 124 | 125 | // Slider. 126 | var $sliders = $('.slider'); 127 | 128 | if ($sliders.length > 0) { 129 | 130 | $sliders.slidertron({ 131 | mode: 'fadeIn', 132 | seamlessWrap: true, 133 | viewerSelector: '.viewer', 134 | reelSelector: '.viewer .reel', 135 | slidesSelector: '.viewer .reel .slide', 136 | advanceDelay: 0, 137 | speed: 400, 138 | fadeInSpeed: 1000, 139 | autoFit: true, 140 | autoFitAspectRatio: (840 / 344), 141 | navPreviousSelector: '.nav-previous', 142 | navNextSelector: '.nav-next', 143 | indicatorSelector: '.indicator ul li', 144 | slideLinkSelector: '.link' 145 | }); 146 | 147 | $window 148 | .on('resize load', function() { 149 | $sliders.trigger('slidertron_reFit'); 150 | }) 151 | .trigger('resize'); 152 | 153 | } 154 | 155 | }); 156 | 157 | })(jQuery); -------------------------------------------------------------------------------- /src/js/jquery.dropotron.min.js: -------------------------------------------------------------------------------- 1 | /* jquery.dropotron.js v1.4.3 | (c) n33 | n33.co | MIT licensed */ 2 | (function(e){var t="openerActiveClass",n="click touchend",r="left",i="doCollapseAll",s="position",o="trigger",u="disableSelection_dropotron",a="addClass",f="doCollapse",l=!1,c="outerWidth",h="removeClass",p="preventDefault",d="length",v="dropotron",m="clearTimeout",g="right",y="parent",b=!0,w="speed",E="none",S="stopPropagation",x="doExpand",T=":visible",N="absolute",C="css",k="center",L="toggle",A="baseZIndex",O="offsetX",M="alignment",_="submenuClassPrefix",D="children",P="hover",H="relative",B="doToggle",j="ul",F="z-index",I="opacity",q="find",R="opener",U="px",z=null,W="hide",X="offset",V="detach",$="fast";e.fn[u]=function(){return e(this)[C]("user-select",E)[C]("-khtml-user-select",E)[C]("-moz-user-select",E)[C]("-o-user-select",E)[C]("-webkit-user-select",E)},e.fn[v]=function(t){var n;if(this[d]==0)return e(this);if(this[d]>1)for(n=0;n0&&i.add(d).on("mouseleave",function(){window[m](at),at=window.setTimeout(function(){i[o](f)},et.hideDelay)}),i[u]()[W]()[a](et.menuClass)[C](s,N).on("mouseenter",function(){window[m](at)}).on(x,function(){var n,u,p,v,E,S,x,_,D,P,B;if(i.is(T))return l;window[m](at),nt.each(function(){var t=e(this);e.contains(t.get(0),d.get(0))||t[o](f)}),n=d[X](),u=d[s](),p=d[y]()[s](),v=d[c](),E=i[c](),S=i[C](F)==et[A];if(S){et[V]?x=n:x=u,P=x.top+d.outerHeight()+et.globalOffsetY,_=et[M],i[h](r)[h](g)[h](k);switch(et[M]){case g:D=x[r]-E+v,D<0&&(D=x[r],_=r);break;case k:D=x[r]-Math.floor((E-v)/2),D<0?(D=x[r],_=r):D+E>st.width()&&(D=x[r]-E+v,_=g);break;case r:default:D=x[r],D+E>st.width()&&(D=x[r]-E+v,_=g)}i[a](_)}else{d[C](s)==H||d[C](s)==N?(P=et.offsetY,D=-1*u[r]):(P=u.top+et.offsetY,D=0);switch(et[M]){case g:D+=-1*d[y]()[c]()+et[O];break;case k:case r:default:D+=d[y]()[c]()+et[O]}}navigator.userAgent.match(/MSIE ([0-9]+)\./)&&RegExp.$1<8&&(D+=et.IEOffsetX,P+=et.IEOffsetY),i[C](r,D+U)[C]("top",P+U)[C](I,"0.01").show(),B=l,d[C](s)==H||d[C](s)==N?D=-1*u[r]:D=0,i[X]()[r]<0?(D+=d[y]()[c]()-et[O],B=b):i[X]()[r]+E>st.width()&&(D+=-1*d[y]()[c]()-et[O],B=b),B&&i[C](r,D+U),i[W]()[C](I,"1");switch(et.mode){case"zoom":ot=b,d[a](et[t]),i.animate({width:L,height:L},et[w],et.easing,function(){ot=l});break;case"slide":ot=b,d[a](et[t]),i.animate({height:L},et[w],et.easing,function(){ot=l});break;case"fade":ot=b,S&&!et.noOpenerFade?(et[w]=="slow"?B=80:et[w]==$?B=40:B=Math.floor(et[w]/2),d.fadeTo(B,.01,function(){d[a](et[t]),d.fadeTo(et[w],1),i.fadeIn(et[w],function(){ot=l})})):(d[a](et[t]),d.fadeTo(et[w],1),i.fadeIn(et[w],function(){ot=l}));break;case"instant":default:d[a](et[t]),i.show()}return l}).on(f,function(){return i.is(T)?(i[W](),d[h](et[t]),i[q]("."+et[t])[h](et[t]),i[q](j)[W](),l):l}).on(B,function(){return i.is(T)?i[o](f):i[o](x),l}),d[u]()[a](R)[C]("cursor","pointer").on(n,function(e){if(ot)return;e[p](),e[S](),i[o](B)}),et.expandMode==P&&d[P](function(){if(ot)return;ut=window.setTimeout(function(){i[o](x)},et.hoverDelay)},function(){window[m](ut)})}),nt[q]("a")[C]("display","block").on(n,function(t){if(ot)return;e(this).attr("href")[d]<1&&t[p]()}),tt[q]("li")[C]("white-space","nowrap").each(function(){var t=e(this),r=t[D]("a"),s=t[D](j),u=r.attr("href");r.on(n,function(e){u[d]==0||u=="#"?e[p]():e[S]()}),r[d]>0&&s[d]==0&&t.on(n,function(e){if(ot)return;tt[o](i),e[S]()})}),tt[D]("li").each(function(){var t,n,r,i,s=e(this),o=s[D](j);if(o[d]>0){et[V]&&(et.cloneOnDetach&&(t=o.clone(),t.attr("class","")[W]().appendTo(o[y]())),o[V]().appendTo(rt));for(n=et[A],r=1,i=o;i[d]>0;r++)i[C](F,n++),et[_]&&i[a](et[_]+(n-1-et[A])),i=i[q]("> li > ul")}}),st.on("scroll",function(){tt[o](i)}).on("keypress",function(e){!ot&&e.keyCode==27&&(e[p](),tt[o](i))}),it.on(n,function(){ot||tt[o](i)})}})(jQuery); -------------------------------------------------------------------------------- /src/js/jquery.scrollgress.min.js: -------------------------------------------------------------------------------- 1 | /* jquery.scrollgress vx.x | (c) n33 | n33.co @n33co | MIT */ 2 | (function(){var e="scrollwatchResume",t="length",n="removeData",r="data",i="scrollwatch-state",s="scrollwatch-suspended",o="scrollgress-suspended",u="setTimeout",a="trigger",f="scroll",l="scrollwatchSuspend",c=!0,h="scrollwatch",p=null,d="top",v="rangeMin",m="rangeMax",g="scrollgress",y=!1,b="anchor",w="unscrollwatch",E="unscrollgress",S="element",x="-id",T="scroll.",N="height",C="scrollTop",k="center",L="bottom",A=$(window),O=$(document),M=1e3;jQuery.fn[e]=function(){var l,c;if(this[t]==0)return $(this);if(this[t]>1){for(l=0;l1){for(e=0;e1){for(n=0;n=a[v],n=a[m]===y||e<=a[m];if(t&&n){f[r](i,1),a.on&&a.on(f),w&&(w(f,c),w=p);return}}if(s==1||s==-1){t=a[v]!==y&&ea[m];if(t||n){f[r](i,0),a.off&&a.off(f),w&&(w(f,y),w=p);return}}},w?0:a.delay)},{anchor:a[b]},h),f},jQuery.fn[w]=function(){var e,r;if(this[t]==0)return $(this);if(this[t]>1){for(e=0;e1){for(s=0;s0?s=Math.max(0,s-u.easing/100):s<0&&(s=Math.min(0,s+u.easing/100)),e(s,l)})[a](f),l},jQuery.fn[E]=function(e){var i,s,o,u;if(this[t]==0)return $(this);if(this[t]>1){for(i=0;i1&&(n=e(a)).length>0&&(s=n.offset().top,u.hasClass("scrolly-centered")?o=s-(e(window).height()-n.outerHeight())/2:(o=Math.max(s,0),i&&(typeof i=="function"?o-=i():o-=i)),t.preventDefault(),e("body,html").stop().animate({scrollTop:o},r,"swing"))}),s}})(jQuery); -------------------------------------------------------------------------------- /src/js/jquery.slidertron.min.js: -------------------------------------------------------------------------------- 1 | /* jquery.slidertron.js v1.4 | (c) n33 | n33.co @n33co | MIT */ 2 | (function(e){var t=!1,n="preventDefault",r="activeSlideClass",s="advanceNavActiveClass",o="click",u="onSlideSwitch",a="object",f="removeClass",l="cursor",c="realIndex",h="initialSlide",p=null,d="advanceDelay",v="addClass",m=!0,g="length",y="left",b="clickToNav",w="active",E="setTimeout",S="selectorParent",T="default",N="pointer",C="activeJumpLinkClass",k="viewerOffset",L="captionLines",A="css",O="location",M="seamlessWrap",_="disabledNavClass",D="disableSelection_slidertron",P="slidertron",H="none",B="push",j="id",F="captions",I="random",q="position",R="navWrap",U="slide",z="navSize",W="autoFitAspectRatio",X="width",V="jumpLink",J="bind",K="forward",Q="height",G="slidesSelector",Y="viewerSelector",Z="absolute";e.fn[D]=function(){return e(this)[A]("user-select",H)[A]("-khtml-user-select",H)[A]("-moz-user-select",H)[A]("-o-user-select",H)[A]("-webkit-user-select",H)},e.fn[P]=function(t){var n,r;if(this[g]==0)return $(this);if(this[g]>1){for(n=0;nat?e=at:e<0&&(e=0)}e!==t&&Vt(e)}function Ut(){var e=t;Ct?e=parseInt(Lt)-St[z]:(Lt>$?e=parseInt(Lt)-St[z]:St[R]&&(e=at),e>at?e=at:e<0&&(e=0)),e!==t&&Vt(e)}function zt(e){if(!wt||!kt[e][V])return;wt[f](St[C]),kt[e][V][v](St[C])}function Wt(){if(!St.hashJump||!kt[Lt][j])return;Lt!=$?window[O].replace("#"+kt[Lt][j]):window[O].replace("#")}function Xt(){var e;if(St[_]===t||St[R]===m)return;for(x in Mt)Mt[x]&&Mt[x][f](St[_])[A](l,N);e=new Array,Lt==$&&(e[B](pt),e[B](mt)),Lt==at&&(e[B](dt),e[B](vt));for(x in e)e[x]&&e[x][v](St[_])[A](l,T)}function Vt(n){var i,s,o,h,p;if(Tt||Lt===n)return t;wt&&wt[f](St[C]),St.blurOnChange&&e("input, textarea, select").blur(),Tt=m;if(Lt===t){Lt=n,ct[A](y,-1*kt[Lt].x),Tt=t,ht&&(ht[f](w),e(ht.get(Lt-$))[v](w)),St[r]&&kt[Lt][a][v](St[r]),St[b]&&!kt[Lt].link&&kt[Lt][a][A](l,T);if(bt)if(kt[Lt][F])for(i in bt)bt[i].html(kt[Lt][F][i]);else for(i in bt)bt[i].html("");Xt(),zt(Lt),St[u]&&window[E](function(){St[u](kt[Lt][a])},500)}else{St[r]&&kt[Lt][a][f](St[r]),St[b]&&kt[Lt][a][A](l,N),o=kt[Lt].x,h=kt[n].x,s=o-h,kt[n][c]!==t?p=kt[n][c]:p=n,ht&&(ht[f](w),e(ht.get(p-$))[v](w));if(bt)if(kt[p][F])for(i in bt)bt[i].html(kt[p][F][i]);else for(i in bt)bt[i].html("");zt(p);switch(St.mode){case"fadeIn":i=kt[Lt][a].clone(),i.appendTo(lt)[A](y,0)[A]("top",0),Lt=n,ct[A](y,-1*kt[Lt].x),kt[Lt][c]!==t&&(Lt=kt[Lt][c],ct[A](y,-1*kt[Lt].x)),St[r]&&kt[Lt][a][v](St[r]),St[b]&&!kt[Lt].link&&kt[Lt][a][A](l,T),Xt(),Wt(),St[u]&&St[u](kt[Lt][a]),i.fadeOut(St.speed,function(){Tt=t,i.remove()});break;case"fade":ct.fadeTo(St.speed,.001,function(){Lt=n,ct[A](y,-1*kt[Lt].x),kt[Lt][c]!==t&&(Lt=kt[Lt][c],ct[A](y,-1*kt[Lt].x)),ct.fadeTo(St.speed,1,function(){St[r]&&kt[Lt][a][v](St[r]),St[b]&&!kt[Lt].link&&kt[Lt][a][A](l,T),Xt(),Wt(),St[u]&&St[u](kt[Lt][a]),Tt=t})});break;case U:default:ct.animate({left:"+="+s},St.speed,"swing",function(){Lt=n,kt[Lt][c]!==t&&(Lt=kt[Lt][c],ct[A](y,-1*kt[Lt].x)),St[r]&&kt[Lt][a][v](St[r]),St[b]&&!kt[Lt].link&&kt[Lt][a][A](l,T),Xt(),Wt(),St[u]&&St[u](kt[Lt][a]),Tt=t})}}}function $t(){var r,s,u,a,f,d,v,w,E,S,T,C,_,D,P;kt=new Array,lt=_t(St[Y],m),ct=_t(St.reelSelector,m),ft=_t(St[G],m),ht=_t(St.indicatorSelector,t),wt=_t(St.jumpLinksSelector,t,m),St.autoFit&&(lt[Q](Math.floor(lt[X]()/St[W])),ft[X](lt[X]())[Q](lt[Q]())),s=new Array;for(i=1;i<=St[L];i++){u=St.captionLineSelector,St[L]>1&&(u+=i),r=_t(u,t);if(r==p){s=p;break}s[B](r)}bt=s,pt=_t(St.navFirstSelector),dt=_t(St.navLastSelector),vt=_t(St.navNextSelector),mt=_t(St.navPreviousSelector),gt=_t(St.navStopAdvanceSelector),yt=_t(St.navPlayAdvanceSelector),pt&&Mt[B](pt),dt&&Mt[B](dt),vt&&Mt[B](vt),mt&&Mt[B](mt);if(St.autoHideNav&&ft[g]<2)for(x in Mt)Mt[x].remove();if(St[k]===t&&St[b])return alert("Error: clickToNav only works when viewerOffset is in use."),t;if(ht&&ht[g]!=ft[g])return alert("Error: Indicator needs to have as many items as there are slides."),t;St[R]||(St[M]=t);if(xt==t)return alert("Error: One or more configuration errors detected. Aborting."),t;St[k]==t&&(St[k]=0);if(St[h]==I)St[h]=Math.ceil(Math[I]()*ft[g]);else if(isNaN(parseInt(St[h]))==m||St[h]<1||St[h]>ft[g])St[h]=1;return lt[A](q,"relative"),lt[A]("overflow","hidden"),ct[A](q,Z),ct[A](y,0),ct[A]("top",0),ct.hide(),a=0,f=ft[g],St[M]?(Ct=m,d=ft.eq(0),v=ft.eq(Math.min(f-1,1)),w=ft.eq(Math.max(f-2,0)),E=ft.eq(Math.max(f-1,0)),S=d,T=E,C=d.clone(),_=v.clone(),D=E.clone(),P=w.clone(),C.attr(j,""),_.attr(j,""),D.attr(j,""),P.attr(j,""),P.insertBefore(S),D.insertBefore(S),_.insertAfter(T),C.insertAfter(T),ft=_t(St[G],m),$=2,at=ft[g]-3):($=0,at=f-1),ft.each(function(n){var r,i,s,u,f,c=e(this),h=t,d=new Array;St[b]&&c[A](l,N)[o](function(e){Lt!=n&&(e.stopPropagation(),Nt&&Ht(),Vt(n))}),r=c.find(St.slideLinkSelector),r[g]>0&&(h=r.attr("href"),r.remove(),c[A](l,N)[o](function(){Lt==n&&(window[O]=h)}));for(i=1;i<=St[L];i++)u=St.slideCaptionSelector,St[L]>1&&(u+=i),s=c.find(u),s[g]>0&&(d[B](s.html()),s.remove());d[g]!=St[L]&&(d=t),f=c.attr(j),f||(f=p),c.attr(j,""),kt[n]={object:c,x:a-St[k],realIndex:t,link:h,captions:d,id:f,jumpLink:t},c[A](q,Z),c[A](y,a),c[A]("top",0),a+=c[X]()}),Ct&&(kt[$-1][c]=at,kt[at+1][c]=$),ht&&ht.each(function(){var r=e(this);r[A](l,N)[J](Ot,function(e){e[n]();if(Tt)return t;Nt&&Ht(),Vt(r.index()+$)}),Ot!=o&&r[o](function(e){e[n]()})}),wt&&wt.each(function(){var r,i=e(this),s=i.attr("href").split("#")[1];(r=Ft(s))!==t?(i.hasClass("primary")&&(kt[r][V]=i),i[o](function(e){e[n](),Nt&&Ht(),Vt(r)})):i[o](function(e){e[n]()})}),pt&&(pt[J](Ot,function(e){e[n]();if(Tt)return t;Nt&&Ht(),It()}),Ot!=o&&pt[o](function(e){e[n]()})),dt&&(dt[J](Ot,function(e){e[n]();if(Tt)return t;Nt&&Ht(),qt()}),Ot!=o&&dt[o](function(e){e[n]()})),vt&&(vt[J](Ot,function(e){e[n]();if(Tt)return t;Nt&&Ht(),Rt()}),Ot!=o&&vt[o](function(e){e[n]()})),mt&&(mt[J](Ot,function(e){e[n]();if(Tt)return t;Nt&&Ht(),Ut()}),Ot!=o&&mt[o](function(e){e[n]()})),gt&&(gt[J](Ot,function(e){e[n]();if(Tt)return t;if(!Nt)return t;Bt()}),Ot!=o&>[o](function(e){e[n]()})),yt&&(yt[J](Ot,function(e){e[n]();if(Tt)return t;if(Nt)return t;jt()}),Ot!=o&&yt[o](function(e){e[n]()})),St.arrowsToNav&&e(document).keydown(function(e){switch(e.keyCode){case 37:if(Tt)return t;Nt&&Ht(),Ut();break;case 39:if(Tt)return t;Nt&&Ht(),Rt();break;default:}}),ct.fadeIn(St.fadeInSpeed),m}var H,$,at,ft,lt,ct,ht,pt,dt,vt,mt,gt,yt,bt,wt,Et,St=e.extend({selectorParent:p,viewerSelector:p,reelSelector:p,slidesSelector:p,indicatorSelector:p,jumpLinksSelector:p,navNextSelector:p,navPreviousSelector:p,navFirstSelector:p,navLastSelector:p,navStopAdvanceSelector:p,navPlayAdvanceSelector:p,captionLineSelector:p,slideLinkSelector:p,slideCaptionSelector:p,mode:U,speed:"fast",fadeInSpeed:"slow",navWrap:m,seamlessWrap:m,advanceDelay:0,advanceWait:0,advanceNavActiveClass:w,advanceDirection:K,viewerOffset:t,activeSlideClass:w,disabledNavClass:"disabled",clickToNav:t,captionLines:0,autoHideNav:t,autoFit:t,autoFitAspectRatio:.5,initialSlide:1,hashJump:t,hashJumpStopAdvance:m,activeJumpLinkClass:w,arrowsToNav:t,blurOnChange:t,navSize:1,disableSelection:m,onSlideSwitch:t},P),xt=m,Tt=t,Nt=t,Ct=t,kt=new Array,Lt=t,At="ontouchstart"in window,Ot=At?"touchend":o,Mt=new Array;Et=St[S]?St[S]:St[Y],Et&&Et[J]("previousSlide",function(){Nt&&Ht(),Ut()})[J]("nextSlide",function(){Nt&&Ht(),Rt()})[J]("firstSlide",function(){Nt&&Ht(),It()})[J]("lastSlide",function(){Nt&&Ht(),qt()})[J]("slidertron_onSwitchSlide",function(){})[J]("slidertron_reFit",function(e,t){var n=0;t||(t=St[W]),window[E](function(){var e=Math.floor(lt[X]()/t);for(x in kt)kt[x][a][X](lt[X]()),kt[x][a][Q](e),kt[x].x=n-St[k],kt[x][a][A](y,n),n+=kt[x][a][X]();ct[A](y,-1*kt[Lt].x),lt[Q](e)},100)})[J]("slidertron_stopAdvance",function(){Nt&&Bt()}),e().ready(function(){var e,n=window[O].hash.split("#")[1],r=m;n&&(window[O].hash=""),$t()&&(St.hashJump&&n&&(e=Ft(n))!==t?(setTimeout(function(){window.scrollTo(0,0)},0),Vt(e),e!=$&&(window[O].hash="#"+n),St.hashJumpStopAdvance&&(r=t)):St[M]?Vt(St[h]+1):Vt(St[h]-1),r&&(H=window[E](function(){Pt()},St.advanceWait)))})}})(jQuery); -------------------------------------------------------------------------------- /src/js/skel-layers.min.js: -------------------------------------------------------------------------------- 1 | /* skel-layers.js v1.0.3 | (c) n33 | getskel.com | MIT licensed */ 2 | skel.registerPlugin("layers",function(e){function cn(e,r,i){var o,u;this.id=e,this.index=i,this[n]={breakpoints:x,states:x,position:x,side:x,animation:mt,orientation:mt,width:0,height:0,zIndex:this.index,html:"",hidden:H,exclusive:V,resetScroll:V,resetForms:V,swipeToHide:V,clickToHide:H},t._.extend(this[n],r),this[j]=t._.newDiv(this[n][jt]),this[j].id=e,this[j]._layer=this,this[s]=x,this[bt]=x,this[St]=x,this[z]=H,u=t._.newElement(this.id,this[j],ut,1),u.onAttach=function(){var e=this[$t]._layer;e[Z]()||e.init(),e.resume()},u.onDetach=function(){var e=this[$t]._layer;e.suspend()},this[n].states&&this[n].states!=t._.sd?(t._.cacheElement(u),o=t._[un](this[n].states),t._[Ht](o,function(e){t._.addCachedElementToState(o[e],u)})):this[n].breakpoints?(t._.cacheElement(u),o=t._[un](this[n].breakpoints),t._[Ht](o,function(e){t._.addCachedElementToBreakpoint(o[e],u)})):t._.attachElement(u)}var t,n="config",r="_skel_layers_translateOrigin",i="cache",s="$element",o="_skel_layers_translate",u="visibleWrapper",f="_skel_layers_resetForms",l="_skel_layers_resume",c="_skel_layers_promote",h="exclusiveLayer",p="_skel_layers_demote",d="moveToVisibleWrapper",v="setTimeout",m="moveToHiddenWrapper",g="right",y="bottom",b="position",w="useActive",E="width",S="css",x=null,T="center",N="_skel_layers_suspend",C="prototype",k="left",L="wrapper",A="skel-layers-layer-z-index",O="children",M="_skel_layers_init",_="skel-layers-moved",D="overflow-x",P="hiddenWrapper",H=!1,B="scrollTop",j="element",F=".skel-layers-fixed:not(.skel-layers-moved)",I="transform",q="top",R="height",U="length",z="visible",W="touchstart.lock click.lock scroll.lock",X='
1){for(t=0;t0&&(t[lt](),t[S](E,(t.data(Jt)+r)/12*100+"%"))},e.fn[Lt]=function(){return e(this).parents()[U]>0},e.fn[lt]=function(){var t=e(this);t[At]("class").match(/(\s+|^)([0-9]+)u(\s+|$)/)&&t.data(Jt,parseInt(RegExp.$2))},e.fn[c]=function(r){var i,s,o;if(this[U]>1){for(i=0;i-1*f&&t>l;break;case g:a=n-1*f&&t<-1*l;break;case q:a=t-1*f&&n>l;break;case y:a=t-1*f&&n<-1*l}if(a)return o[bt]=x,o[St]=x,o[It](),H}if(i[B]()==0&&n<0||u>s-2&&u0)return H}),this[s]=i},cn[C][Z]=function(){return this[s]!==x},cn[C][tn]=function(){return this[s].is(":visible")},cn[C][d]=function(){t[i][u][ht](this[s])},cn[C][m]=function(){if(!this[s][Lt]())return;t[i][P][ht](this[s])},cn[C].resume=function(r){if(!this[Z]())return;this[s][Ot](on).each(function(){t.parseResume(e(this))}),this[n][nt]||this[rn](r)},cn[C].suspend=function(){if(!this[Z]())return;this[s][r](),this[s][Ot](on).each(function(){t.parseSuspend(e(this))}),this[z]&&this[It]()},t={cache:{visibleWrapper:x,body:x,exclusiveLayer:x,html:x,htmlbody:x,hiddenWrapper:x,layers:{},window:x,wrapper:x},config:{baseZIndex:1e4,layers:{},speed:250,transform:V,transformBreakpoints:x,transformTest:x},eventType:"click touchend",show:function(e){t._[Pt](function(){t[i][ct][e][rn]()})},hide:function(e){t._[Pt](function(){t[i][ct][e][It]()})},toggle:function(e){t._[Pt](function(){var n=t[i][ct][e];n[tn]()?n[It]():n[rn]()})},getBaseFontSize:function(){return t._.vars.IEVersion<9?16.5:parseFloat(getComputedStyle(t[i][Qt].get(0)).fontSize)},getHalf:function(e){var t=parseInt(e);return typeof e=="string"&&e.charAt(e[U]-1)=="%"?Math.floor(t/2)+"%":Math.floor(t/2)+Gt},lockView:function(e){t[i][wt]._skel_layers_scrollPos=t[i][wt][B](),e==fn&&t[i][ln][S](D,nt),t[i][L].on(W,function(e){e[kt](),e[Et](),t[i][h]&&t[i][h][It]()}),t[i][wt].on(yt,function(e){t[i][h]&&t[i][h][It]()}),t._.vars.isMobile||window[v](function(){t[i][wt].on(pt,function(e){t[i][h]&&t[i][h][It]()})},t[n][dt]+50)},parseInit:function(n){var r,s,o=n.get(0),u=n[At]("data-action"),a=n[At]("data-args"),f,c;u&&a&&(a=a.split(","));switch(u){case"toggleLayer":case"layerToggle":n[S](Y,zt)[S]("cursor","pointer"),r=function(n){n[kt](),n[Et]();if(t[i][h])return t[i][h][It](),H;var r=e(this),s=t[i][ct][a[0]];s[tn]()?s[It]():s[rn]()},n.on(t.eventType,r);break;case"navList":f=e(an+a[0]),r=f[Ot]("a"),s=[],r.each(function(){var t=e(this),n,r;n=Math.max(0,t.parents("li")[U]-1),r=t[At]("href"),s.push(''+t.text()+"")}),s[U]>0&&n[jt]("");break;case"copyText":f=e(an+a[0]),n[jt](f.text());break;case"copyHTML":f=e(an+a[0]),n[jt](f[jt]());break;case"moveElementContents":f=e(an+a[0]),o[l]=function(){f[O]().each(function(){var t=e(this);n[ht](t),t[Dt](_)})},o[N]=function(){n[O]().each(function(){var n=e(this);f[ht](n),n[Xt](_),t.refresh(n)})},o[l]();break;case"moveElement":f=e(an+a[0]),o[l]=function(){e(X+f[At]("id")+'" />').insertBefore(f),n[ht](f),f[Dt](_)},o[N]=function(){e(at+f[At]("id")).replaceWith(f),f[Xt](_),t.refresh(f)},o[l]();break;case"moveCell":f=e(an+a[0]),c=e(an+a[1]),o[l]=function(){e(X+f[At]("id")+'" />').insertBefore(f),n[ht](f),f[S](E,Ft),c&&c[Ct]()},o[N]=function(){e(at+f[At]("id")).replaceWith(f),f[S](E,""),c&&c[S](E,"")},o[l]();break;default:}},parseResume:function(e){var t=e.get(0);t[l]&&t[l]()},parseSuspend:function(e){var t=e.get(0);t[N]&&t[N]()},recalc:function(e,n){var r=t._.parseMeasurement(e),i;switch(r[1]){case"%":i=Math.floor(n*(r[0]/100));break;case"em":i=t.getBaseFontSize()*r[0];break;default:case Gt:i=r[0]}return i},recalcH:function(n){return t.recalc(n,e(window)[R]())},recalcW:function(n){return t.recalc(n,e(window)[E]())},refresh:function(r){var s;t[n][I]&&(r?s=r.filter(F):s=e(F),s[M]()[Vt](t[i][u]))},unlockView:function(e){e==fn&&t[i][ln][S](D,z),t[i][L].off(W),t[i][wt].off(yt),t._.vars.isMobile||t[i][wt].off(pt)},init:function(){n in t[n]&&(t._.extend(t[n],t[n][n]),delete t[n][n]),t._[Ht](t[n],function(e){t[n][e]&&typeof t[n][e]==$t&&b in t[n][e]&&(t[n][ct][e]=t[n][e],delete t[n][e])}),t[n][sn]&&(t[n][I]=t[n][sn]());if(t[n][I]){if(t._.vars[Mt]=="android"&&t._.vars.deviceVersion<4||t._.vars[Mt]=="wp")t[n][I]=H;t._.vars.IEVersion<10&&(t[n][I]=H),t[n][Rt]&&!t._.hasActive(t._[un](t[n][Rt]))&&(t[n][I]=H)}t.initObjects(),t.initTransforms(),t._[Pt](function(){t.initLayers(),t.initIncludes(),t._.updateState(),t.refresh()})},initIncludes:function(){e(".skel-layers-include").each(function(){t.parseInit(e(this))})},initLayers:function(){var r,s,o,u=1;t._[Ht](t[n][ct],function(r){var s;if(!(b in t[n][ct][r]))return;if(!t[n][ct][r][jt]&&(s=e(an+r))[U]==0)return;o=new cn(r,t[n][ct][r],u++),t[i][ct][r]=o,s&&(s[O]()[Vt](o[j]),s.remove())})},initObjects:function(){t[i][wt]=e(window),t._[Pt](function(){t[i][jt]=e(jt),t[i][Qt]=e(Qt),t[i][ln]=e("html,body"),t[i][Qt].wrapInner('
'),t[i][L]=e("#skel-layers-wrapper"),t[i][L][S](b,nn)[S](k,"0")[S](g,"0")[S](q,"0")[M](),t[i][P]=e('
')[Vt](t[i][Qt]),t[i][P][S](R,"100%"),t[i][u]=e('
')[Vt](t[i][Qt]),t[i][u][S](b,nn),t._[vt](ut,t[i][P][0]),t._[vt]("skel_layers_visibleWrapper",t[i][u][0]),t._[vt]("skel_layers_wrapper",t[i][L][0]),e("[autofocus]").focus()})},initTransforms:function(){if(t[n][I])e.fn[r]=function(){return e(this)[o](0,0)},e.fn[o]=function(t,n){return e(this)[S](I,"translate("+t+"px, "+n+"px)")},e.fn[M]=function(){return e(this)[S]("backface-visibility",nt)[S]("perspective","500")[qt]("transition","transform "+t[n][dt]/1e3+"s ease-in-out")};else{var s,u=[];t[i][wt].resize(function(){if(t[n][dt]!=0){var e=t[n][dt];t[n][dt]=0,window[v](function(){t[n][dt]=e,u=[]},e)}}),e.fn[r]=function(){for(var r=0;r0&&Qt[J](function(){Qt[n](r,function(e){Qt[ut](r[e])})})},cacheElement:function(e){return Qt[_][s][e.id]=e,e},cacheNewElement:function(e,t,n,r){var i;return t[S]&&t[S].removeChild(t),i=Qt[H](e,t,n,r),Qt.cacheElement(i)},detachAllElements:function(e){var t,r,i={};Qt[n](e,function(t){i[e[t].id]=E}),Qt[n](Qt[_][s],function(e){if(e in i)return;Qt.detachElement(e)})},detachElement:function(e){var t=Qt[_][s][e],n;if(!t[yt])return;n=t[A];if(!n[S]||n[S]&&!n[S].tagName)return;n[S].removeChild(n),t[yt]=a,t.onDetach&&t.onDetach()},getCachedElement:function(e){return Qt[_][s][e]?Qt[_][s][e]:c},newElement:function(e,t,n,r){return{id:e,object:t,location:n,priority:r,attached:a}},changeState:function(i){var u,c,g,S,x,T,N,C,k;Qt[y].lastStateId=Qt[r],Qt[r]=i;if(!Qt[_][ct][Qt[r]]){Qt[_][ct][Qt[r]]={config:{},elements:[],values:{}},g=Qt[_][ct][Qt[r]],Qt[r]===Qt.sd?u=[]:u=Qt[r][L](1)[Ct](Qt.sd),Qt[I](g[e],Qt[$][v]),Qt[n](u,function(n){Qt[I](g[e],Qt[t][u[n]][e])}),N="mV"+Qt[r],g[e][h].content?C=g[e][h].content:Qt.isLocked()?(S=[],S[q]("user-scalable=yes"),Qt[y][V][0]&&S[q]("width="+Qt[y][V][0]),Qt[y][V][1]&&S[q](zt+Qt[y][V][1]),C=S.join(","),window.setTimeout(function(){Qt.poll()},0)):(S=[],S[q]("user-scalable="+(g[e][h].scalable?"yes":"no")),g[e][h].width&&S[q]("width="+g[e][h].width),g[e][h].height&&S[q](zt+g[e][h].height),g[e][h].width==ht&&g[e][h].height==lt&&S[q](pt),C=S.join(",")),(x=Qt[p](N))||(x=Qt[d](N,Qt.newMeta(h,C),G,4)),g[s][q](x);var A,O,M=a;S=Qt[et](g[e][z]),A=S[0],O=S[1],g.values[z]=A+O,N="iC"+g.values[z],O.substr(-1)=="!"&&(M=E,O=O.substr(0,O[f]-1)),(x=Qt[p](N))||(x=Qt[d](N,Qt[w]("body{min-width:"+A*1+O+b+".container{margin-left:auto;margin-right:auto;width:"+A*1+O+(M?"!important;max-width:none!important;min-width:0!important"+b:b+".container.\\31 25\\25{width:100%;max-width:"+A*1.25+O+";min-width:"+A+b+".container.\\37 5\\25{width:"+A*.75+O+b+".container.\\35 0\\25{width:"+A*.5+O+b+".container.\\32 5\\25{width:"+A*.25+O+b)),P,3)),g[s][q](x),N="iGG"+g[e][U][m][0]+"_"+g[e][U][m][1];if(!(x=Qt[p](N))){var H,j;S=Qt[et](g[e][U][m][0]),H=S[0],j=S[1];var F,R;S=Qt[et](g[e][U][m][1]),F=S[0],R=S[1],x=Qt[d]("iGG"+g[e][U][m][0]+"_"+g[e][U][m][1],Qt[w](".row>*{padding:"+F*1+R+l+H*1+j+b+".row{margin:"+F*-1+R+l+H*-1+j+b+".row.uniform>*{padding:"+H*1+j+l+H*1+j+b+".row.uniform{margin:"+H*-1+j+l+H*-1+j+b+".row.\\32 00\\25>*{padding:"+F*2+R+l+H*2+j+b+".row.\\32 00\\25{margin:"+F*-2+R+l+H*-2+j+b+".row.uniform.\\32 00\\25>*{padding:"+H*2+j+l+H*2+j+b+".row.uniform.\\32 00\\25{margin:"+H*-2+j+l+H*-2+j+b+".row.\\31 50\\25>*{padding:"+F*1.5+R+l+H*1.5+j+b+".row.\\31 50\\25{margin:"+F*-1.5+R+l+H*-1.5+j+b+".row.uniform.\\31 50\\25>*{padding:"+H*1.5+j+l+H*1.5+j+b+".row.uniform.\\31 50\\25{margin:"+H*-1.5+j+l+H*-1.5+j+b+".row.\\35 0\\25>*{padding:"+F*.5+R+l+H*.5+j+b+".row.\\35 0\\25{margin:"+F*-0.5+R+l+H*-0.5+j+b+".row.uniform.\\35 0\\25>*{padding:"+H*.5+j+l+H*.5+j+b+".row.uniform.\\35 0\\25{margin:"+H*-0.5+j+l+H*-0.5+j+b+".row.\\32 5\\25>*{padding:"+F*.25+R+l+H*.25+j+b+".row.\\32 5\\25{margin:"+F*-0.25+R+l+H*-0.25+j+b+".row.uniform.\\32 5\\25>*{padding:"+H*.25+j+l+H*.25+j+b+".row.uniform.\\32 5\\25{margin:"+H*-0.25+j+l+H*-0.25+j+b+".row.\\30 \\25>*{padding:0}"+".row.\\30 \\25{margin:0}"),P,3)}g[s][q](x),N="igZ"+g[e][U][$t];if(!(x=Qt[p](N))){C="";for(T=1;T<=g[e][U][$t];T++)C+=Qt.css.gc("\\28 "+T+"\\29");x=Qt[d](N,Qt[w](C),P,3)}g[s][q](x),g[e][U][bt]&&(N="igC"+g[e][z],(x=Qt[p](N))||(x=Qt[d](N,Qt[w](".row:not(.no-collapse)>*{width:100%!important;margin-left:0!important"+b),P,3)),g[s][q](x)),N="iCd"+Qt[r];if(!(x=Qt[p](N))){C=[],k=[],Qt[n](Qt[t],function(e){Qt[B](u,e)!==-1?C[q](".not-"+e):k[q](".only-"+e)});var W=(C[f]>0?C.join(",")+Y:"")+(k[f]>0?k.join(",")+Y:"");x=Qt[d](N,Qt[w](W[D](/\.([0-9])/,Wt)),P,3),g[s][q](x)}Qt[n](u,function(r){Qt[t][u[r]][e][Ut]&&(N="ss"+u[r],(x=Qt[p](N))||(x=Qt[d](N,Qt.newStyleSheet(Qt[t][u[r]][e][Ut]),P,5)),g[s][q](x)),Qt[t][u[r]][s][f]>0&&Qt[n](Qt[t][u[r]][s],function(e){g[s][q](Qt[t][u[r]][s][e])})}),Qt[_][o][Qt[r]]&&(Qt[n](Qt[_][o][Qt[r]],function(e){g[s][q](Qt[_][o][Qt[r]][e])}),Qt[_][o][Qt[r]]=[])}else g=Qt[_][ct][Qt[r]];Qt.detachAllElements(g[s]),Qt[st](g[s]),Qt[J](function(){Qt[Nt](g)}),Qt[y].state=Qt[_][ct][Qt[r]],Qt[y][r]=Qt[r],Qt.trigger(Tt)},getStateId:function(){if(Qt[Lt]&&Qt[e].defaultState)return Qt[e].defaultState;var r="";return Qt[n](Qt[t],function(e){Qt[t][e].test()&&(r+=Qt.sd+e)}),r},poll:function(){var e="";e=Qt.getStateId(),e===""&&(e=Qt.sd),e!==Qt[r]&&(Qt[Vt]?Qt.changeState(e):(Qt[x][kt][k]=Qt[x][kt][k][D](Qt[r][L](1)[D](new RegExp(Qt.sd,"g")," "),""),Qt.changeState(e),Qt[x][kt][k]=Qt[x][kt][k]+" "+Qt[r][L](1)[D](new RegExp(Qt.sd,"g")," "),Qt[x][kt][k].charAt(0)==" "&&(Qt[x][kt][k]=Qt[x][kt][k][L](1))))},updateState:function(){var e,i,u,a,l=[];if(Qt[r]==Qt.sd)return;e=Qt[r][L](1)[Ct](Qt.sd),Qt[n](e,function(o){i=Qt[t][e[o]];if(i[s][f]==0)return;Qt[n](i[s],function(e){Qt[_][ct][Qt[r]][s][q](i[s][e]),l[q](i[s][e])})}),Qt[_][o][Qt[r]]&&(Qt[n](Qt[_][o][Qt[r]],function(e){Qt[_][ct][Qt[r]][s][q](Qt[_][o][Qt[r]][e]),l[q](Qt[_][o][Qt[r]][e])}),Qt[_][o][Qt[r]]=[]),l[f]>0&&Qt[st](l)},newDiv:function(e){var t=document[N]("div");return t[jt]=e,t},newInline:function(e){var t;return t=document[N]("style"),t.type=ft,t[jt]=e,t},newMeta:function(e,t){var n=document[N]("meta");return n.name=e,n.content=t,n},newStyleSheet:function(e){var t=document[N]("link");return t.rel="stylesheet",t.type=ft,t[Ut]=e,t},initPlugin:function(t,n){typeof n==A&&Qt[I](t[e],n),t.init&&t.init()},registerPlugin:function(e,t){if(!t)return a;Qt[ot][e]=t,t._=this,t.register&&t.register()},init:function(t,r){Qt.initConfig(t),Qt.initElements(),Qt.initEvents(),Qt.poll(),r&&typeof r==A&&(Qt[e][ot]=r),Qt[n](Qt[ot],function(t){Qt.initPlugin(Qt[ot][t],t in Qt[e][ot]?Qt[e][ot][t]:c)}),Qt.isInit=E},initAPI:function(){var e,t,r=navigator.userAgent;Qt[y][nt]=99,e="other",r[M](/Firefox/)?e="firefox":r[M](/Chrome/)?e="chrome":r[M](/Safari/)&&!r[M](/Chrome/)?e="safari":r[M](/(OPR|Opera)/)?e="opera":r[M](/MSIE ([0-9]+)/)?(e="ie",Qt[y][nt]=RegExp.$1):r[M](/Trident\/.+rv:([0-9]+)/)&&(e="ie",Qt[y][nt]=RegExp.$1),Qt[y].browser=e,Qt[y][C]="other",t={ios:"(iPad|iPhone|iPod)",android:"Android",mac:"Macintosh",wp:"Windows Phone",windows:"Windows NT"},Qt[n](t,function(e){r[M](new RegExp(t[e],"g"))&&(Qt[y][C]=e)});switch(Qt[y][C]){case"ios":r[M](/([0-9_]+) like Mac OS X/),e=parseFloat(RegExp.$1[D]("_",".")[D]("_",""));break;case Kt:r[M](/Android ([0-9\.]+)/),e=parseFloat(RegExp.$1);break;case"mac":r[M](/Mac OS X ([0-9_]+)/),e=parseFloat(RegExp.$1[D]("_",".")[D]("_",""));break;case"wp":r[M](/IEMobile\/([0-9\.]+)/),e=parseFloat(RegExp.$1);break;case"windows":r[M](/Windows NT ([0-9\.]+)/),e=parseFloat(RegExp.$1);break;default:e=99}Qt[y].deviceVersion=e,Qt[y].isTouch=Qt[y][C]=="wp"?navigator.msMaxTouchPoints>0:"ontouchstart"in window,Qt[y].isMobile=Qt[y][C]=="wp"||Qt[y][C]==Kt||Qt[y][C]=="ios",e=document.cookie[Ct](";"),Qt[n](e,function(t){var n=e[t][Ct]("=");if(n[0][D](/^\s+|\s+$/g,"")==Qt.lcn&&n[1][f]>0){Qt[y][V]=n[1][Ct]("_");return}})},initConfig:function(r){var i=[],o=[];if(!r||!(t in r))Qt[Vt]=E,Qt[e][h].width="",Qt[e][h].height="",Qt[e][h].scalable=E;typeof r==A&&(r[t]&&(Qt[e][t]={}),Qt[I](Qt[e],r)),U in Qt[e]&&m in Qt[e][U]&&!Qt[O](Qt[e][U][m])&&(Qt[e][U][m]=[Qt[e][U][m],Qt[e][U][m]]),Qt[I](Qt[$][v][U],Qt[e][U]),Qt[X]=Math.max(Qt[X],Qt[e][U][$t]),Qt[I](Qt[$][v][h],Qt[e][h]),Qt[$][v][z]=Qt[e][z],Qt[n](Qt[e][t],function(n){var r,i={},u,a;Qt[I](i,Qt[e][t][n]),Ut in i||(i[Ut]=Qt[$][v][Ut]),Et in i||(i[Et]=Qt[$][v][Et]),"range"in i&&(u=i.range,u=="*"?a="":u.charAt(0)=="-"?a="(max-width: "+parseInt(u[L](1))+"px)":u.charAt(u[f]-1)=="-"?a=xt+parseInt(u[L](0,u[f]-1))+"px)":Qt[B](u,"-")!=-1&&(u=u[Ct]("-"),a=xt+parseInt(u[0])+"px) and (max-width: "+parseInt(u[1])+"px)"),i[Et]=a),U in i&&(m in i[U]&&!Qt[O](i[U][m])&&(i[U][m]=[i[U][m],i[U][m]]),$t in i[U]&&(Qt[X]=Math.max(Qt[X],i[U][$t]))),Qt[e][t][n]=i,r={},Qt[I](r,Qt[$].breakpoint),r[e]=Qt[e][t][n],r.test=function(){return Qt[R](i[Et])},r[s]=[],Qt[e].preload&&r[e][Ut]&&o[q](r[e][Ut]),Qt[t][n]=r,Qt.breakpointList[q](n)}),Qt[n](Qt[e][tt],function(t){Qt.bind(t,Qt[e][tt][t])}),o[f]>0&&window[St].protocol!="file:"&&Qt[J](function(){var e,t=document[u](P)[0],r=new XMLHttpRequest;Qt[n](o,function(e){r.open("GET",o[e],a),r.send("")})})},initElements:function(){var t=[];t[q](Qt[H]("mV",Qt.newMeta(h,pt),G,1));switch(Qt[e].reset){case"full":t[q](Qt[H]("iR",Qt[w](Qt.css.r),G,2));break;case wt:t[q](Qt[H]("iN",Qt[w](Qt.css.n),G,2))}t[q](Qt[H]("iBM",Qt[w](Qt.css.bm),G,1)),t[q](Qt[H]("iG",Qt[w]('.row{border-bottom:solid 1px transparent}.row>*{float:left}.row:after,.row:before{content:"";display:block;clear:both;height:0}.row.uniform>*>:first-child{margin-top:0}.row.uniform>*>:last-child{margin-bottom:0}'+Qt.css.gc("")),P,3)),Qt[st](t)},initEvents:function(){var t;!Qt[e].pollOnce&&!Qt[Vt]&&(Qt.bind(gt,function(){Qt.poll()}),Qt.bind(T,function(){Qt.poll()})),Qt[y][C]=="ios"&&Qt[J](function(){Qt.bind(T,function(){var e=document[u]("input");Qt[n](e,function(t){e[t][At]=e[t][rt],e[t][rt]=""}),window.setTimeout(function(){Qt[n](e,function(t){e[t][rt]=e[t][At]})},100)})}),window[Jt]&&Qt.bind(gt,window[Jt]),window[Jt]=function(){Qt.trigger(gt)},window[W]&&Qt.bind(T,window[W]),window[W]=function(){Qt.trigger(T)}},initUtilityMethods:function(){document[Q]?!function(e,t){Qt[J]=t()}(It,function(){function e(e){s=1;while(e=t.shift())e()}var t=[],n,r=document,i=at,s=/^loaded|^c/.test(r[Rt]);return r[Q](i,n=function(){r[vt](i,n),e()}),function(e){s?e():t[q](e)}}):!function(e,t){Qt[J]=t()}(It,function(e){function t(e){p=1;while(e=n.shift())e()}var n=[],r,i=!1,s=document,o=s[it],u=o.doScroll,a=at,f=Q,l="onreadystatechange",c=Rt,h=u?/^loaded|^c/:/^loaded|c/,p=h.test(s[c]);return s[f]&&s[f](a,r=function(){s[vt](a,r,i),t()},i),u&&s.attachEvent(l,r=function(){/^c/.test(s[c])&&(s.detachEvent(l,r),t())}),e=u?function(t){self!=top?p?t():n[q](t):function(){try{o.doScroll("left")}catch(n){return setTimeout(function(){e(t)},50)}t()}()}:function(e){p?e():n[q](e)}}),document[i]?Qt[i]=function(e){return document[i](e)}:Qt[i]=function(e){var t=document;return t[Dt]?t[Dt](("."+e[D](" "," ."))[D](/\.([0-9])/,Wt)):[]},Array[Bt][B]?Qt[B]=function(e,t){return e[B](t)}:Qt[B]=function(e,t){if(typeof e=="string")return e[B](t);var n,r=t?t:0,i;if(!this)throw new TypeError;i=this[f];if(i===0||r>=i)return-1;r<0&&(r=i-Math.abs(r));for(n=r;ns[Pt]||s[_t]!==c&&ls[Mt]?a:E})},preInit:function(){var e=document[u]("script");Qt.me=e[e[f]-1],Qt.initUtilityMethods(),Qt.initAPI(),Qt[Z](kt,document[u](kt)[0]),Qt[Z](P,document[u](P)[0]),Qt[J](function(){Qt[Z]("body",document[u]("body")[0])}),Qt[y][nt]>=10&&Qt[ut](Qt[H]("msie-viewport-fix",Qt[w]("@-ms-viewport{width:device-width;}"),G,1))}};return Qt.preInit(),Qt[y][nt]<9&&(Qt[Nt]=function(e){},Qt[w]=function(e){var t;return t=document[N]("span"),t[jt]=' ",t}),Qt}(); -------------------------------------------------------------------------------- /src/left-sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 55 | 56 | 57 |
58 |
59 |

Left Sidebar

60 |

Faucibus neque adipiscing mi lorem semper blandit

61 |
62 |
63 |
64 |
65 | 66 | 67 | 89 | 90 |
91 |
92 | 93 | 94 |
95 | 96 |

Dolore Amet Consequat

97 |

Aliquam massa urna, imperdiet sit amet mi non, bibendum euismod est. Curabitur mi justo, tincidunt vel eros ullamcorper, porta cursus justo. Cras vel neque eros. Vestibulum diam quam, mollis at magna consectetur non, malesuada quis augue. Morbi tincidunt pretium interdum est. Curabitur mi justo, tincidunt vel eros ullamcorper, porta cursus justo. Cras vel neque eros. Vestibulum diam.

98 |

Sed Magna Ornare

99 |

In vestibulum massa quis arcu lobortis tempus. Nam pretium arcu in odio vulputate luctus. Suspendisse euismod lorem eget lacinia fringilla. Sed sed felis justo. Nunc sodales elit in laoreet aliquam. Nam gravida, nisl sit amet iaculis porttitor, risus nisi rutrum metus.

100 |
    101 |
  • Faucibus orci lobortis ac adipiscing integer.
  • 102 |
  • Col accumsan arcu mi aliquet placerat.
  • 103 |
  • Lobortis vestibulum ut magna tempor massa nascetur.
  • 104 |
  • Blandit massa non blandit tempor interdum.
  • 105 |
  • Lacinia mattis arcu nascetur lobortis.
  • 106 |
107 |
108 | 109 |
110 |
111 |
112 |
113 | 114 | 115 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/no-sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 55 | 56 | 57 |
58 |
59 |

No Sidebar

60 |

Faucibus neque adipiscing mi lorem semper blandit

61 |
62 |
63 | 64 | 65 |
66 | 67 |

Dolore Amet Consequat

68 |

Aliquam massa urna, imperdiet sit amet mi non, bibendum euismod est. Curabitur mi justo, tincidunt vel eros ullamcorper, porta cursus justo. Cras vel neque eros. Vestibulum diam quam, mollis at magna consectetur non, malesuada quis augue. Morbi tincidunt pretium interdum est. Curabitur mi justo, tincidunt vel eros ullamcorper, porta cursus justo. Cras vel neque eros. Vestibulum diam.

69 |

Sed Magna Ornare

70 |

In vestibulum massa quis arcu lobortis tempus. Nam pretium arcu in odio vulputate luctus. Suspendisse euismod lorem eget lacinia fringilla. Sed sed felis justo. Nunc sodales elit in laoreet aliquam. Nam gravida, nisl sit amet iaculis porttitor, risus nisi rutrum metus.

71 |
    72 |
  • Faucibus orci lobortis ac adipiscing integer.
  • 73 |
  • Col accumsan arcu mi aliquet placerat.
  • 74 |
  • Lobortis vestibulum ut magna tempor massa nascetur.
  • 75 |
  • Blandit massa non blandit tempor interdum.
  • 76 |
  • Lacinia mattis arcu nascetur lobortis.
  • 77 |
78 |
79 | 80 |
81 |
82 | 83 | 84 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/readme.md: -------------------------------------------------------------------------------- 1 | # Vanilla JavaScript App 2 | 3 | 4 | [Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/overview) allows you to easily build JavaScript apps in minutes. Use this repo with the [quickstart](https://docs.microsoft.com/azure/static-web-apps/getting-started?tabs=vanilla-javascript) to build and customize a new static site. 5 | 6 | This repo is used as a starter for a _very basic_ HTML web application using no front-end frameworks. 7 | -------------------------------------------------------------------------------- /src/right-sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 55 | 56 | 57 |
58 |
59 |

Right Sidebar

60 |

Faucibus neque adipiscing mi lorem semper blandit

61 |
62 |
63 |
64 |
65 | 66 | 67 |
68 | 69 |

Dolore Amet Consequat

70 |

Aliquam massa urna, imperdiet sit amet mi non, bibendum euismod est. Curabitur mi justo, tincidunt vel eros ullamcorper, porta cursus justo. Cras vel neque eros. Vestibulum diam quam, mollis at magna consectetur non, malesuada quis augue. Morbi tincidunt pretium interdum est. Curabitur mi justo, tincidunt vel eros ullamcorper, porta cursus justo. Cras vel neque eros. Vestibulum diam.

71 |

Sed Magna Ornare

72 |

In vestibulum massa quis arcu lobortis tempus. Nam pretium arcu in odio vulputate luctus. Suspendisse euismod lorem eget lacinia fringilla. Sed sed felis justo. Nunc sodales elit in laoreet aliquam. Nam gravida, nisl sit amet iaculis porttitor, risus nisi rutrum metus.

73 |
    74 |
  • Faucibus orci lobortis ac adipiscing integer.
  • 75 |
  • Col accumsan arcu mi aliquet placerat.
  • 76 |
  • Lobortis vestibulum ut magna tempor massa nascetur.
  • 77 |
  • Blandit massa non blandit tempor interdum.
  • 78 |
  • Lacinia mattis arcu nascetur lobortis.
  • 79 |
80 |
81 | 82 |
83 |
84 | 85 | 86 | 108 | 109 |
110 |
111 |
112 |
113 | 114 | 115 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/sass/_mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin vendor-property($property, $value) { 2 | @each $vendor in ('-moz-', '-webkit-', '-o-', '-ms-', '') { 3 | #{$vendor}#{$property}: #{$value}; 4 | } 5 | } 6 | 7 | @mixin vendor-value($property, $value) { 8 | @each $vendor in ('-moz-', '-webkit-', '-o-', '-ms-', '') { 9 | #{$property}: #{$vendor}#{$value}; 10 | } 11 | } 12 | 13 | @mixin vendor-keyframes($name) { 14 | @-moz-keyframes #{$name} { @content; } 15 | @-webkit-keyframes #{$name} { @content; } 16 | @-o-keyframes #{$name} { @content; } 17 | @-ms-keyframes #{$name} { @content; } 18 | @keyframes #{$name} { @content; } 19 | } 20 | 21 | @mixin icon($content: false) { 22 | text-decoration: none; 23 | 24 | &:before { 25 | @if $content { 26 | content: $content; 27 | } 28 | -moz-osx-font-smoothing: grayscale; 29 | -webkit-font-smoothing: antialiased; 30 | font-family: FontAwesome; 31 | font-style: normal; 32 | font-weight: normal; 33 | text-transform: none !important; 34 | } 35 | } -------------------------------------------------------------------------------- /src/sass/_vars.scss: -------------------------------------------------------------------------------- 1 | // Duration. 2 | $duration-transition: 0.2s; 3 | 4 | // Size. 5 | $size-border-radius: 0.5em; 6 | $size-border-width: 1px; 7 | $size-element-height: 2.75em; 8 | $size-element-margin: 2em; 9 | 10 | // Font. 11 | $font-family: 'Lato', Helvetica, sans-serif; 12 | $font-family-fixed: 'Courier New', monospace; 13 | $font-weight: 300; 14 | $font-weight-bold: 700; 15 | 16 | // Color. 17 | $color-bg: #fff; 18 | $color-fg: #646464; 19 | $color-fg-bold: #545454; 20 | $color-fg-light: #949494; 21 | $color-border: rgba(144,144,144,0.25); 22 | $color-border-bg: rgba(144,144,144,0.075); 23 | $color-border2: rgba(144,144,144,0.5); 24 | $color-border2-bg: rgba(144,144,144,0.2); 25 | 26 | $color-accent-bg: #e0555a; 27 | $color-accent-fg: mix($color-accent-bg, #ffffff, 25%); 28 | $color-accent-fg-bold: #ffffff; 29 | $color-accent-fg-light: mix($color-accent-bg, #ffffff, 40%); 30 | $color-accent-border: rgba(255,255,255,1); 31 | $color-accent-border-bg: rgba(255,255,255,0.075); 32 | $color-accent-border2: rgba(255,255,255,0.5); 33 | $color-accent-border2-bg: rgba(255,255,255,0.2); 34 | 35 | $color-accent2-bg: #494d53; 36 | $color-accent2-fg: mix($color-accent2-bg, #ffffff, 25%); 37 | $color-accent2-fg-bold: #ffffff; 38 | $color-accent2-fg-light: mix($color-accent2-bg, #ffffff, 40%); 39 | $color-accent2-border: rgba(255,255,255,1); 40 | $color-accent2-border-bg: rgba(255,255,255,0.075); 41 | $color-accent2-border2: rgba(255,255,255,0.5); 42 | $color-accent2-border2-bg: rgba(255,255,255,0.2); -------------------------------------------------------------------------------- /src/sass/ie/v8.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'mixins'; 3 | 4 | /* 5 | Drift by Pixelarity 6 | pixelarity.com @pixelarity 7 | License: pixelarity.com/license 8 | */ 9 | 10 | /* Border Fix */ 11 | 12 | .image, 13 | .image > img, 14 | .box, 15 | .slider .viewer, 16 | .slider .nav-next, 17 | .slider .nav-previous, 18 | #main > .container { 19 | -ms-behavior: url('css/ie/PIE.htc'); 20 | } 21 | 22 | code, 23 | table td, 24 | ul.icons li .icon, 25 | .feature:before, 26 | input[type="submit"], 27 | input[type="reset"], 28 | input[type="button"], 29 | .button, 30 | input[type="text"], 31 | input[type="password"], 32 | input[type="email"], 33 | select, 34 | textarea { 35 | border: solid $size-border-width #ccc; 36 | } 37 | 38 | /* Box */ 39 | 40 | .box { 41 | position: relative; 42 | 43 | &.post { 44 | .image { 45 | &:first-child { 46 | margin: 0 0 $size-element-margin; 47 | width: 100%; 48 | } 49 | } 50 | } 51 | } 52 | 53 | /* Header */ 54 | 55 | #header { 56 | border-bottom: solid 1px #ccc; 57 | 58 | &.alt { 59 | border-bottom: 0; 60 | } 61 | } 62 | 63 | .dropotron { 64 | border: solid 1px #ccc; 65 | 66 | &.level-0 { 67 | margin-top: -4px; 68 | border-top: 0; 69 | 70 | &:before { 71 | display: none; 72 | } 73 | } 74 | } 75 | 76 | /* Banner */ 77 | 78 | #banner { 79 | background-image: url('../../images/banner.jpg'); 80 | background-repeat: no-repeat; 81 | background-size: cover; 82 | -ms-behavior: url('css/ie/backgroundsize.min.htc'); 83 | } -------------------------------------------------------------------------------- /src/sass/ie/v9.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'mixins'; 3 | 4 | /* 5 | Drift by Pixelarity 6 | pixelarity.com @pixelarity 7 | License: pixelarity.com/license 8 | */ 9 | 10 | /* Banner */ 11 | 12 | #banner { 13 | &:after { 14 | display: none; 15 | } 16 | } -------------------------------------------------------------------------------- /src/sass/style-large.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'mixins'; 3 | 4 | /* 5 | Drift by Pixelarity 6 | pixelarity.com @pixelarity 7 | License: pixelarity.com/license 8 | */ 9 | 10 | /* Basic */ 11 | 12 | body, input, select, textarea { 13 | font-size: 11pt; 14 | } 15 | 16 | /* Header */ 17 | 18 | .dropotron { 19 | &.level-0 { 20 | font-size: 1em; 21 | } 22 | } 23 | 24 | /* Banner */ 25 | 26 | #banner { 27 | background-attachment: scroll; 28 | padding: 10em 0; 29 | } -------------------------------------------------------------------------------- /src/sass/style-medium.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'mixins'; 3 | 4 | /* 5 | Drift by Pixelarity 6 | pixelarity.com @pixelarity 7 | License: pixelarity.com/license 8 | */ 9 | 10 | /* Basic */ 11 | 12 | body, input, select, textarea { 13 | font-size: 12pt; 14 | } 15 | 16 | h2, h3, h4, h5, h6 { 17 | br { 18 | display: none; 19 | } 20 | } 21 | 22 | /* Section/Article */ 23 | 24 | header { 25 | br { 26 | display: none; 27 | } 28 | } 29 | 30 | /* Feature */ 31 | 32 | .feature { 33 | padding-left: 0; 34 | text-align: center; 35 | 36 | &:before { 37 | margin: 0 0 ($size-element-margin * 0.35) 0; 38 | position: relative; 39 | } 40 | 41 | p { 42 | padding: 0 2em; 43 | } 44 | } 45 | 46 | /* Slider */ 47 | 48 | .slider { 49 | .viewer { 50 | border-width: 1em; 51 | width: 100%; 52 | } 53 | 54 | .slide { 55 | img { 56 | border-radius: $size-border-radius * 0.75; 57 | display: block; 58 | width: 100%; 59 | } 60 | } 61 | 62 | .nav-next, 63 | .nav-previous { 64 | background: none; 65 | border-radius: 0; 66 | color: #fff; 67 | height: 100%; 68 | margin-top: 0; 69 | top: 0; 70 | vertical-align: bottom; 71 | width: 50%; 72 | z-index: 1; 73 | 74 | &:before { 75 | display: block; 76 | height: 2em; 77 | line-height: 2em; 78 | margin-top: -1em; 79 | padding: 0 1em; 80 | top: 50%; 81 | width: 100%; 82 | } 83 | } 84 | 85 | .nav-next { 86 | right: 0; 87 | text-align: right; 88 | } 89 | 90 | .nav-previous { 91 | left: 0; 92 | text-align: left; 93 | } 94 | } 95 | 96 | /* Header */ 97 | 98 | #skel-layers-wrapper { 99 | padding-top: 0; 100 | } 101 | 102 | #header { 103 | display: none; 104 | } 105 | 106 | /* Banner */ 107 | 108 | #banner { 109 | padding: 12em 2em; 110 | } 111 | 112 | /* Layers */ 113 | 114 | #navButton { 115 | .toggle { 116 | @include icon; 117 | height: 100%; 118 | left: 0; 119 | position: absolute; 120 | top: 0; 121 | width: 100%; 122 | 123 | &:before { 124 | background: rgba(103,107,113,0.75); 125 | border-radius: $size-border-radius; 126 | color: #fff; 127 | content: '\f0c9'; 128 | display: block; 129 | font-size: 16px; 130 | height: 2.25em; 131 | left: 0.5em; 132 | line-height: 2.25em; 133 | position: absolute; 134 | text-align: center; 135 | top: 0.5em; 136 | width: 3.5em; 137 | } 138 | } 139 | } 140 | 141 | #navPanel { 142 | background-color: #fff; 143 | box-shadow: 0.5em 0 2em 0 rgba(0,0,0,0.1); 144 | padding: 0.5em 1.5em; 145 | 146 | .link { 147 | border: 0; 148 | border-top: solid 1px $color-border2-bg; 149 | color: $color-fg !important; 150 | display: block; 151 | height: 3em; 152 | line-height: 3em; 153 | text-decoration: none; 154 | 155 | &:first-child { 156 | border-top: 0; 157 | } 158 | 159 | &.depth-0 { 160 | font-weight: $font-weight-bold; 161 | color: $color-fg-bold !important; 162 | } 163 | 164 | .indent-1 { display: inline-block; width: 1.25em; } 165 | .indent-2 { display: inline-block; width: 2.5em; } 166 | .indent-3 { display: inline-block; width: 3.75em; } 167 | .indent-4 { display: inline-block; width: 5em; } 168 | .indent-5 { display: inline-block; width: 6.25em; } 169 | } 170 | } -------------------------------------------------------------------------------- /src/sass/style-small.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'mixins'; 3 | 4 | /* 5 | Drift by Pixelarity 6 | pixelarity.com @pixelarity 7 | License: pixelarity.com/license 8 | */ 9 | 10 | /* Basic */ 11 | 12 | body, input, select, textarea { 13 | font-size: 12pt; 14 | } 15 | 16 | h2 { 17 | font-size: 1.25em; 18 | line-height: 1.5em; 19 | } 20 | 21 | h3 { 22 | font-size: 1.1em; 23 | line-height: 1.5em; 24 | } 25 | 26 | h4 { 27 | font-size: 1em; 28 | line-height: 1.5em; 29 | } 30 | 31 | /* Section/Article */ 32 | 33 | header { 34 | h2 + p { 35 | font-size: 1em; 36 | margin-top: -0.85em; 37 | line-height: 1.5em; 38 | } 39 | 40 | h3 + p { 41 | font-size: 1em; 42 | margin-top: -0.85em; 43 | line-height: 1.5em; 44 | } 45 | 46 | &.major { 47 | h2 { 48 | font-size: 1.5em; 49 | } 50 | 51 | p { 52 | margin: -1em 0 2.5em 0; 53 | } 54 | } 55 | } 56 | 57 | /* List */ 58 | 59 | ul { 60 | &.icons { 61 | li { 62 | padding: 0 0.75em 0 0; 63 | 64 | .icon { 65 | font-size: 0.9em; 66 | } 67 | } 68 | } 69 | } 70 | 71 | /* Button */ 72 | 73 | input[type="submit"], 74 | input[type="reset"], 75 | input[type="button"], 76 | .button { 77 | font-size: 0.8em !important; 78 | } 79 | 80 | /* Box */ 81 | 82 | .box { 83 | &.post { 84 | max-width: 23em; 85 | } 86 | } 87 | 88 | /* Slider */ 89 | 90 | .slider { 91 | .viewer { 92 | border-width: 0.5em; 93 | } 94 | } 95 | 96 | /* Wrapper */ 97 | 98 | .wrapper { 99 | padding: 3em 0 1em 0; 100 | } 101 | 102 | /* Banner */ 103 | 104 | #banner { 105 | padding: 5em 2em 4em 2em; 106 | 107 | h2 { 108 | font-size: 2em; 109 | } 110 | 111 | p { 112 | font-size: 1.1em; 113 | } 114 | } 115 | 116 | /* Main */ 117 | 118 | #main { 119 | > header { 120 | padding: 0 2em; 121 | } 122 | 123 | > .container { 124 | padding: $size-element-margin ($size-element-margin * 0.5); 125 | } 126 | } 127 | 128 | #content { 129 | > .image.fit:first-child { 130 | margin: ($size-element-margin * -1) 0 $size-element-margin ($size-element-margin * -0.5); 131 | width: calc(100% + #{$size-element-margin}); 132 | 133 | img { 134 | border-bottom-left-radius: 0; 135 | border-bottom-right-radius: 0; 136 | } 137 | } 138 | } 139 | 140 | /* CTA */ 141 | 142 | #cta { 143 | padding: 2em 0; 144 | } 145 | 146 | /* Footer */ 147 | 148 | #footer { 149 | padding: 2em 0; 150 | 151 | .icons { 152 | margin: 0 0 $size-element-margin 0; 153 | } 154 | } -------------------------------------------------------------------------------- /src/sass/style-xlarge.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'mixins'; 3 | 4 | /* 5 | Drift by Pixelarity 6 | pixelarity.com @pixelarity 7 | License: pixelarity.com/license 8 | */ 9 | 10 | /* Basic */ 11 | 12 | body, input, select, textarea { 13 | font-size: 12pt; 14 | } 15 | 16 | /* Banner */ 17 | 18 | #banner { 19 | padding: 12em 0; 20 | } -------------------------------------------------------------------------------- /src/sass/style-xsmall.scss: -------------------------------------------------------------------------------- 1 | @import 'vars'; 2 | @import 'mixins'; 3 | 4 | /* 5 | Drift by Pixelarity 6 | pixelarity.com @pixelarity 7 | License: pixelarity.com/license 8 | */ 9 | 10 | /* Basic */ 11 | 12 | html, body { 13 | min-width: 320px; 14 | } 15 | 16 | body, input, select, textarea { 17 | font-size: 12pt; 18 | } 19 | 20 | /* List */ 21 | 22 | ul { 23 | &.actions { 24 | margin: 0 0 $size-element-margin 0; 25 | 26 | li { 27 | display: block; 28 | padding: ($size-element-margin * 0.5) 0 0 0; 29 | text-align: center; 30 | width: 100%; 31 | 32 | &:first-child { 33 | padding-top: 0; 34 | } 35 | 36 | > * { 37 | margin: 0 !important; 38 | width: 100%; 39 | 40 | &.icon { 41 | &:before { 42 | margin-left: -2em; 43 | } 44 | } 45 | } 46 | } 47 | 48 | &.small { 49 | li { 50 | padding: ($size-element-margin * 0.25) 0 0 0; 51 | 52 | &:first-child { 53 | padding-top: 0; 54 | } 55 | } 56 | } 57 | } 58 | 59 | &.menu { 60 | font-size: 0.8em; 61 | line-height: 2em; 62 | 63 | li { 64 | border: 0; 65 | margin: 0; 66 | padding: 0 0.5em !important; 67 | } 68 | } 69 | } 70 | 71 | /* Button */ 72 | 73 | input[type="submit"], 74 | input[type="reset"], 75 | input[type="button"], 76 | .button { 77 | padding: 0; 78 | } 79 | 80 | /* Slider */ 81 | 82 | .slider { 83 | position: relative; 84 | 85 | .viewer { 86 | border-radius: 0 !important; 87 | border-width: 0em; 88 | margin-left: -5vw; 89 | width: 100vw; 90 | } 91 | 92 | .slide { 93 | img { 94 | border-radius: 0 !important; 95 | } 96 | } 97 | 98 | .nav-next, 99 | .nav-previous { 100 | &:before { 101 | font-size: 0.8em; 102 | } 103 | } 104 | } 105 | 106 | /* Banner */ 107 | 108 | #banner { 109 | padding: 5em 2em 4em 2em; 110 | } 111 | 112 | /* CTA */ 113 | 114 | #cta { 115 | padding: 2em; 116 | 117 | h2 { 118 | display: block; 119 | margin: 0 0 1em 0; 120 | } 121 | 122 | .actions { 123 | display: block; 124 | } 125 | } -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: Arial, Helvetica, sans-serif; 3 | } 4 | 5 | html, body { 6 | margin: 0; 7 | border: 0; 8 | padding: 0; 9 | background-color: #fff; 10 | } 11 | 12 | main { 13 | margin: auto; 14 | width: 50%; 15 | padding: 20px; 16 | } 17 | 18 | main > h1 { 19 | text-align: center; 20 | font-size: 3.5em; 21 | } --------------------------------------------------------------------------------