Deve preencher todos os campos obrigatórios.
');
+ redirect(base_url('login/register'));
+ }
+ $id = $this->auth_model->insert('usuarios',
+ array(
+ 'nome' => $nome,
+ 'cpf' => $CPF,
+ 'email' => $email,
+ 'senha' => password_hash($password, PASSWORD_DEFAULT),
+ 'fone' => $telefone,
+ 'ativo' => 1,
+ 'atendente' => 0,
+ 'data_criacao_timestamp' => time()
+ )
+ );
+ if ($id) {
+ $this->auth_model->insert('usuarios_endereco',
+ array(
+ 'usuariosid' => $id,
+ 'logradouro' => $logradouro,
+ 'numero' => $numero,
+ 'bairro' => $bairro,
+ 'complemento' => $complemento,
+ 'cidade' => $cidade,
+ 'uf' => $UF,
+ 'cep' => $CEP
+ )
+ );
+ $this->session->set_flashdata('success', 'Usuário cadastrado com sucesso.
');
+ redirect(base_url('login'));
+ }else{
+ $this->session->set_flashdata('error', 'Erro interno, entre em contato com o administrador.
');
+ redirect(base_url('login/register'));
+ }
+
+}
+
+public function forgotPassword()
+{
+ $this->template->loadContent('auth/forgotPassword.php');
+}
+
+public function forgotPassword_pro()
+{
+ if ($this->auth_model->check_email($this->input->post('email', true))) {
+ $newPassword = bin2hex(random_bytes(3));
+ $this->auth_model->update('usuarios', 'email', $this->input->post('email', true),
+ array(
+ 'senha' => password_hash($newPassword, PASSWORD_DEFAULT)
+ )
+ );
+ $emailFrom = $this->configs->info->email;
+ $nomeSite = $this->configs->info->nome_site;
+ $destino = $this->input->post('email', true);
+ $assunto = "Recueperação de senha";
+ $headers = 'MIME-Version: 1.0' . "\r\n";
+ $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
+ $headers .= 'From: $nome <$emailFrom>';
+ $mensagem = "Olá usuário,E-mail enviado para '.$this->input->post('email', true).', em instantes chegará o e-mail informando sua nova senha.
');
+ redirect(base_url('login'));
+ }else{
+ $this->session->set_flashdata('error', 'Email não encontrado na base de dados.
');
+ redirect(base_url('login'));
+ }
+
+}
+
+public function check_cpf()
+{
+ if (!$this->input->is_ajax_request()) redirect(base_url('login'));
+
+ header('Access-Control-Allow-Origin: ' . base_url());
+ header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
+ header('Content-Type: application/json');
+
+ if ($this->auth_model->check_cpf($this->input->post('cpf'))) {
+ echo json_encode(array('return' => true));
+ }else{
+ echo json_encode(array('return' => false));
+ }
+ exit();
+}
+
+public function check_email()
+{
+ if (!$this->input->is_ajax_request()) redirect(base_url('login'));
+
+ header('Access-Control-Allow-Origin: ' . base_url());
+ header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
+ header('Content-Type: application/json');
+
+ if ($this->auth_model->check_email($this->input->post('email'))) {
+ echo json_encode(array('return' => true));
+ }else{
+ echo json_encode(array('return' => false));
+ }
+ exit();
+}
+
+public function sair()
+{
+ $this->session->sess_destroy();
+ redirect('login');
+}
+
+public function verificarLogin()
+{
+ header('Access-Control-Allow-Origin: ' . base_url());
+ header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
+ header('Content-Type: application/json');
+
+ $this->load->library('form_validation');
+ $this->form_validation->set_rules('usuario', 'Usuário', 'required|trim');
+ $this->form_validation->set_rules('password', 'Senha', 'required|trim');
+ if ($this->form_validation->run() == false) {
+ $json = ['result' => false, 'message' => validation_errors()];
+ echo json_encode($json);
+ } else {
+ $usuario = $this->input->post('usuario');
+ $password = $this->input->post('password');
+ $user = $this->auth_model->Verifica($usuario);
+
+ if ($user) {
+ if (!$user->ativo) {
+ $json = ['result' => false, 'message' => 'O usuário não está ativo no sistema.'];
+ echo json_encode($json);
+ die();
+ }
+
+ if (password_verify($password, $user->senha)) {
+ $session_data = ['nome' => $user->nome, 'email' => $user->email, 'id' => $user->id, 'atendente' => $user->atendente, 'logado' => true];
+ $this->session->set_userdata($session_data);
+ $json = ['result' => true, 'atendente' => $user->atendente];
+ echo json_encode($json);
+ } else {
+ $json = ['result' => false, 'message' => 'Os dados de acesso estão incorretos.'];
+ echo json_encode($json);
+ }
+ } else {
+ $json = ['result' => false, 'message' => 'Email ou CPF não encontrados.'];
+ echo json_encode($json);
+ }
+ }
+ die();
+}
+
+}
\ No newline at end of file
diff --git a/application/controllers/Profile.php b/application/controllers/Profile.php
new file mode 100644
index 0000000..07bd24c
--- /dev/null
+++ b/application/controllers/Profile.php
@@ -0,0 +1,102 @@
+session->userdata('logado')) redirect(base_url('login'));
+ $this->template->set_layout("layout/default.php");
+ $this->load->model('profile_model');
+ $this->template->loadData("activeLink",
+ array("user" => 1));
+ }
+
+ public function index()
+ {
+ $user = $this->profile_model->get_user($this->session->userdata('id'))->row();
+ $user_endereco = $this->profile_model->get_user_endereco($this->session->userdata('id'))->row();
+ $this->template->loadContent("profile/index.php",
+ array(
+ 'user' =>$user,
+ 'user_endereco' =>$user_endereco
+ )
+ );
+ }
+
+ public function user_edit($id)
+ {
+ $user = $this->profile_model->get_user($this->session->userdata('id'))->row();
+ $user_endereco = $this->profile_model->get_user_endereco($this->session->userdata('id'))->row();
+ $this->load->view('profile/user_edit.php',
+ array(
+ 'user' => $user,
+ 'user_endereco' => $user_endereco
+ )
+ );
+ }
+
+ public function user_edit_pro()
+ {
+ $id = $this->session->userdata('id');
+ $nome = $this->input->post('nome', true);
+ $telefone = preg_replace("/[^0-9]/", "", $this->input->post('telefone', true));
+ $logradouro = $this->input->post('logradouro', true);
+ $numero = $this->input->post('numero', true);
+ $bairro = $this->input->post('bairro', true);
+ $complemento = $this->input->post('complemento', true);
+ $cidade = $this->input->post('cidade', true);
+ $UF = $this->input->post('UF', true);
+ $CEP = preg_replace("/[^0-9]/", "", $this->input->post('CEP', true));
+
+ $this->profile_model->update('usuarios', 'id', $id,
+ array(
+ 'nome' => $nome,
+ 'fone' => $telefone
+ )
+ );
+ $this->profile_model->update('usuarios_endereco', 'usuariosid', $id,
+ array(
+ 'logradouro' => $logradouro,
+ 'numero' => $numero,
+ 'bairro' => $bairro,
+ 'complemento' => $complemento,
+ 'cidade' => $cidade,
+ 'uf' => $UF,
+ 'cep' => $CEP
+ )
+ );
+ $this->session->set_flashdata('success', 'Dados alterados com sucesso.');
+ redirect(base_url('profile'));
+ }
+
+ public function edit_password_pro()
+ {
+ $id = $this->session->userdata('id');
+ $senhaAntiga = $this->input->post('senhaAntiga', true);
+ $novaSenha = $this->input->post('novaSenha', true);
+ $novaSenha2 = $this->input->post('novaSenha2', true);
+ $user = $this->profile_model->get_user($id)->row();
+ if ($novaSenha != $novaSenha2) {
+ $this->session->set_flashdata('error', 'As senhas não coincidem.');
+ redirect(base_url('profile'));
+ }
+ if (password_verify($senhaAntiga, $user->senha)) {
+ $this->profile_model->update('usuarios', 'id', $id,
+ array(
+ 'senha' => password_hash($novaSenha, PASSWORD_DEFAULT)
+ )
+ );
+ $this->session->set_flashdata('success', 'Senha alterada com sucesso.');
+ redirect(base_url('profile'));
+ }else{
+ $this->session->set_flashdata('error', 'A senha atual não está correta.');
+ redirect(base_url('profile'));
+ }
+ }
+
+}
+
+/* End of file Profile.php */
+/* Location: ./application/controllers/Profile.php */
\ No newline at end of file
diff --git a/application/controllers/Tickets.php b/application/controllers/Tickets.php
new file mode 100644
index 0000000..70ea4fa
--- /dev/null
+++ b/application/controllers/Tickets.php
@@ -0,0 +1,260 @@
+session->userdata('logado') == true) {
+ if (!$this->session->userdata('atendente')) {
+ redirect(base_url('client'));
+ }
+ }else{
+ redirect(base_url('login'));
+ }
+ $this->load->model("tickets_model");
+ $this->template->set_layout("layout/default.php");
+ }
+ public function index()
+ {
+ $this->template->loadContent("tickets/index.php");
+ }
+
+ public function tickets_page()
+ {
+ $this->load->library("datatables");
+ $this->datatables->set_total_rows($this->tickets_model->get_tickets_total());
+ $tickets = $this->tickets_model->get_tickets($this->datatables);
+ foreach($tickets->result() as $r) {
+ if ($r->usuarios_ult_resp == null || $r->usuarios_ult_resp == $r->usuariosid) {
+ $situacao = "Aguardando resposta";
+ $color = "rgb(249 5 5)";
+ }else{
+ $situacao = "Respondido";
+ $color = "rgb(0 169 29)";
+ }
+ $this->datatables->data[] = array(
+ 'Directory access is forbidden.
+
+
+
diff --git a/application/core/index.html b/application/core/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/core/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/helpers/index.html b/application/helpers/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/helpers/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/hooks/index.html b/application/hooks/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/hooks/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/index.html b/application/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/language/english/index.html b/application/language/english/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/language/english/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/language/index.html b/application/language/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/language/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/language/portuguese-brazilian/calendar_lang.php b/application/language/portuguese-brazilian/calendar_lang.php
new file mode 100644
index 0000000..db2f414
--- /dev/null
+++ b/application/language/portuguese-brazilian/calendar_lang.php
@@ -0,0 +1,56 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/language/portuguese-brazilian/migration_lang.php b/application/language/portuguese-brazilian/migration_lang.php
new file mode 100644
index 0000000..9c0f52e
--- /dev/null
+++ b/application/language/portuguese-brazilian/migration_lang.php
@@ -0,0 +1,19 @@
+ci =& get_instance();
+ }
+
+ public function nohtml($message)
+ {
+ $message = trim($message);
+ $message = strip_tags($message);
+ $message = htmlspecialchars($message, ENT_QUOTES);
+ return $message;
+ }
+
+ public function mask($val, $mask)
+ {
+ $maskared = '';
+ $k = 0;
+ for($i = 0; $i<=strlen($mask)-1; $i++)
+ {
+ if($mask[$i] == '#')
+ {
+ if(isset($val[$k]))
+ $maskared .= $val[$k++];
+ }
+ else
+ {
+ if(isset($mask[$i]))
+ $maskared .= $mask[$i];
+ }
+ }
+ return $maskared;
+ }
+
+}
+
+/* End of file Common.php */
+/* Location: ./application/libraries/Common.php */
diff --git a/application/libraries/Configs.php b/application/libraries/Configs.php
new file mode 100644
index 0000000..34e4cf9
--- /dev/null
+++ b/application/libraries/Configs.php
@@ -0,0 +1,21 @@
+db->select("*")
+ ->limit(1)
+ ->get("configuracoes");
+
+ if($site->num_rows() == 0) {
+ echo "Erro: Falta a linha de configurações no banco de dados.";
+ exit;
+ } else {
+ $this->info = $site->row();
+ }
+ }
+}
+?>
\ No newline at end of file
diff --git a/application/libraries/Datatables.php b/application/libraries/Datatables.php
new file mode 100644
index 0000000..e9f0654
--- /dev/null
+++ b/application/libraries/Datatables.php
@@ -0,0 +1,145 @@
+CI =& get_instance();
+ $this->draw = intval($this->CI->input->post("draw"));
+ $this->start = intval($this->CI->input->post("start"));
+ $this->length = intval($this->CI->input->post("length"));
+
+ if($this->length <= 0 ) $this->length = null;
+ if($this->start <= 0) $this->start = null;
+
+ $this->get_search_data();
+ }
+
+ public function set_default_order($col, $dir)
+ {
+ $this->order = array();
+ $this->order[] = array("field" => $col,"sort" => $dir);
+ return $this;
+ }
+
+ public function set_total_rows($rows)
+ {
+ $this->total_rows = $rows;
+ }
+
+ public function ordering($ordering)
+ {
+
+ if(isset($_GET['order'])) {
+ $order = $this->CI->input->post("order");
+ if(!empty($order)) {
+ foreach($order as $o) {
+ $this->col = $o['column'];
+ $this->dir= $o['dir'];
+ }
+ }
+ }
+
+ if($this->dir != "asc" && $this->dir != "desc") $this->dir = "asc";
+ if(isset($ordering[$this->col])) {
+ $this->order = array();
+ foreach($ordering[$this->col] as $k=>$v) {
+ if(empty($v) || $v === 0 ) {
+ $v = $this->dir;
+ }
+ $this->order[] = array("field" => $k, "sort" => $v);
+ }
+ } else {
+ $this->error = "You tried to search for an invalid section.";
+ }
+ }
+
+ public function get_search_data()
+ {
+ $search = $this->CI->input->post("search");
+ $search_type = intval($this->CI->input->post("search_type"));
+
+ $search_value = "";
+ if(!empty($search['value'])) {
+ $search_value = $this->CI->common->nohtml($search['value']);
+ }
+ $this->search = $search_value;
+ $this->search_type = $search_type;
+ }
+
+ public function process()
+ {
+ $output = array(
+ "draw" => $this->draw,
+ "recordsTotal" => $this->total_rows,
+ "recordsFiltered" => $this->total_rows,
+ "data" => $this->data
+ );
+ if($this->total_rows == 0) {
+ }
+ return $output;
+ }
+
+ public function db_order()
+ {
+ if($this->order != null) {
+ foreach($this->order as $order) {
+ $this->CI->db->order_by($order['field'], $order['sort']);
+ }
+ }
+ }
+
+ public function db_search($columns)
+ {
+ if(!empty($this->search)) {
+ if($this->search_type == 0) {
+
+ $words = explode(" ", $this->search);
+ $this->CI->db->group_start();
+ foreach($words as $word) {
+ foreach($columns as $field) {
+ $this->CI->db->or_like($field, $word);
+ }
+ }
+ $this->CI->db->group_end();
+
+ } elseif($this->search_type == 1) {
+
+ $this->CI->db->group_start();
+ foreach($columns as $field) {
+ $this->CI->db->or_like($field, $this->search);
+ }
+ $this->CI->db->group_end();
+
+ } else {
+
+ if(isset($columns[$this->search_type-2])) {
+ $this->CI->db->group_start();
+ $this->CI->db->or_like($columns[$this->search_type-2],
+ $this->search);
+ $this->CI->db->group_end();
+ }
+ }
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/application/libraries/Template.php b/application/libraries/Template.php
new file mode 100644
index 0000000..d7be9b6
--- /dev/null
+++ b/application/libraries/Template.php
@@ -0,0 +1,41 @@
+layout)) {
+ $this->set_layout($CI->settings->info->layout.'.php');
+ }
+ $site = array();
+ foreach($this->data as $k=>$v) {
+ $site[$k] = $v;
+ }
+ foreach($this->data as $k=>$v) {
+ $data[$k] = $v;
+ }
+ $site['content'] = $CI->load->view($view,$data,true);
+
+
+ $CI->load->view($this->layout, $site);
+ if($die) die($CI->output->get_output());
+ }
+
+ public function loadData($key, $data)
+ {
+ $this->data[$key] = $data;
+ }
+
+ public function set_layout($view)
+ {
+ $this->layout = $view;
+ }
+
+}
+?>
diff --git a/application/libraries/index.html b/application/libraries/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/libraries/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/logs/index.html b/application/logs/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/logs/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/models/Admin_model.php b/application/models/Admin_model.php
new file mode 100644
index 0000000..e47dec6
--- /dev/null
+++ b/application/models/Admin_model.php
@@ -0,0 +1,183 @@
+db->insert($table, $data);
+ $id = $this->db->insert_id();
+ if ($id > 0) {
+ return $id;
+ }else{
+ return false;
+ }
+ }
+
+ function update($table, $columnWhere, $where, $data=array())
+ {
+ $this->db->where($columnWhere, $where)
+ ->set($data)
+ ->update($table);
+ }
+
+ function delete($table, $columnWhere, $where)
+ {
+ $this->db->where($columnWhere, $where)
+ ->delete($table);
+ }
+
+ public function get_status_total()
+ {
+ $s = $this->db->select("COUNT(*) as num")->get("status");
+ $r = $s->row();
+ if(isset($r->num)) return $r->num;
+ return 0;
+ }
+
+ public function get_status($datatable)
+ {
+
+ $datatable->db_search(
+ array(
+ "status.nome"
+ )
+ );
+ if ($this->input->post("order", true)) {
+ $order_column = array(
+ "status.id",
+ "status.nome",
+ null,
+ "status.data_criacao_timestamp"
+ );
+ $this->db->order_by($order_column[$this->input->post("order", true)['0']['column']], $this->input->post("order", true)['0']['dir']);
+ } else {
+ $this->db->order_by("status.nome", "ASC");
+ }
+ return $this->db
+ ->select("*")
+ ->limit($datatable->length, $datatable->start)
+ ->get("status");
+ }
+
+ public function get_departamentos_id($id)
+ {
+ return $this->db->where('id', $id)
+ ->get('departamentos');
+ }
+
+ public function get_departamentos_total()
+ {
+ $s = $this->db->select("COUNT(*) as num")->get("departamentos");
+ $r = $s->row();
+ if(isset($r->num)) return $r->num;
+ return 0;
+ }
+
+ public function get_departamentos($datatable)
+ {
+
+ $datatable->db_search(
+ array(
+ "departamentos.nome"
+ )
+ );
+ if ($this->input->post("order", true)) {
+ $order_column = array(
+ "departamentos.id",
+ "departamentos.nome",
+ "departamentos.data_criacao_timestamp"
+ );
+ $this->db->order_by($order_column[$this->input->post("order", true)['0']['column']], $this->input->post("order", true)['0']['dir']);
+ } else {
+ $this->db->order_by("departamentos.nome", "ASC");
+ }
+ return $this->db
+ ->select("*")
+ ->limit($datatable->length, $datatable->start)
+ ->get("departamentos");
+ }
+
+ public function get_status_id($id)
+ {
+ return $this->db->where('id', $id)
+ ->get('departamentos');
+ }
+
+ public function get_membros_total()
+ {
+ $s = $this->db->select("COUNT(*) as num")->get("usuarios");
+ $r = $s->row();
+ if(isset($r->num)) return $r->num;
+ return 0;
+ }
+
+ public function get_membros($datatable)
+ {
+
+ $datatable->db_search(
+ array(
+ "usuarios.nome"
+ )
+ );
+ if ($this->input->post("order", true)) {
+ $order_column = array(
+ "usuarios.id",
+ "usuarios.nome",
+ "usuarios.email",
+ "usuarios.ativo",
+ "usuarios.atendente",
+ "usuarios.data_criacao_timestamp"
+ );
+ $this->db->order_by($order_column[$this->input->post("order", true)['0']['column']], $this->input->post("order", true)['0']['dir']);
+ } else {
+ $this->db->order_by("usuarios.nome", "ASC");
+ }
+ return $this->db
+ ->select("*")
+ ->limit($datatable->length, $datatable->start)
+ ->get("usuarios");
+ }
+
+ public function get_membros_id($id)
+ {
+ return $this->db->where('id', $id)
+ ->get('usuarios');
+ }
+
+ function get_membros_endereco_id($id)
+ {
+ return $this->db->where('usuariosid', $id)
+ ->get('usuarios_endereco');
+ }
+
+ public function get_status_select()
+ {
+ return $this->db->get('status');
+ }
+
+ public function get_departamentos_select()
+ {
+ return $this->db->get('departamentos');
+ }
+
+ public function get_configuracoes()
+ {
+ return $this->db->limit(1)->get('configuracoes');
+ }
+
+ public function get_usuarios($value)
+ {
+ return $this->db->like("nome", $value)->limit(10)->get("usuarios");
+ }
+
+}
+
+/* End of file Admin_model.php */
+/* Location: ./application/models/Admin_model.php */
\ No newline at end of file
diff --git a/application/models/Auth_model.php b/application/models/Auth_model.php
new file mode 100644
index 0000000..5fdcf0f
--- /dev/null
+++ b/application/models/Auth_model.php
@@ -0,0 +1,65 @@
+db
+ ->where('cpf', $value)
+ ->or_where('email', $value)
+ ->limit(1)
+ ->get('usuarios');
+ if ($r->num_rows() > 0) {
+ return $r->row();
+ }else{
+ return false;
+ }
+ }
+
+ function insert($table, $data=array())
+ {
+ $this->db->insert($table, $data);
+ $id = $this->db->insert_id();
+ if ($id > 0) {
+ return $id;
+ }else{
+ return false;
+ }
+ }
+
+ function update($table, $columnWhere, $where, $data=array())
+ {
+ $this->db->where($columnWhere, $where)
+ ->set($data)
+ ->update($table);
+ }
+
+ function check_cpf($value)
+ {
+ $r = $this->db->where('cpf', $value)
+ ->get('usuarios');
+ if ($r->num_rows() >= 1) {
+ return true;
+ }else{
+ return false;
+ }
+
+ }
+
+ function check_email($value)
+ {
+ $r = $this->db->where('email', $value)
+ ->get('usuarios');
+ if ($r->num_rows() >= 1) {
+ return true;
+ }else{
+ return false;
+ }
+
+ }
+
+}
+
+/* End of file Auth_model.php */
+/* Location: ./application/models/Auth_model.php */
\ No newline at end of file
diff --git a/application/models/Client_model.php b/application/models/Client_model.php
new file mode 100644
index 0000000..3d2fb73
--- /dev/null
+++ b/application/models/Client_model.php
@@ -0,0 +1,64 @@
+db->insert($table, $data);
+ $id = $this->db->insert_id();
+ if ($id > 0) {
+ return $id;
+ }else{
+ return false;
+ }
+ }
+
+ public function get_tickets_total()
+ {
+ $s = $this->db->select("COUNT(*) as num")->get("tickets");
+ $r = $s->row();
+ if(isset($r->num)) return $r->num;
+ return 0;
+ }
+
+ public function get_tickets($datatable)
+ {
+
+ $datatable->db_search(
+ array(
+ "tickets.nome"
+ )
+ );
+ if ($this->input->post("order", true)) {
+ $order_column = array(
+ "tickets.id",
+ "tickets.assunto",
+ "departamentos.nome",
+ "status.nome",
+ "tickets.data_criacao_timestamp"
+ );
+ $this->db->order_by($order_column[$this->input->post("order", true)['0']['column']], $this->input->post("order", true)['0']['dir']);
+ } else {
+ $this->db->order_by("tickets.data_criacao_timestamp", "DESC");
+ }
+ return $this->db
+ ->select(" tickets.id, tickets.assunto, tickets.descricao, tickets.data_criacao_timestamp, departamentos.nome as departamento_nome, status.nome as status_nome, status.escopo, tickets.usuariosid,
+ ( SELECT tickets_respostas.usuariosid
+ FROM tickets_respostas
+ WHERE tickets_respostas.ticketsid = tickets.id
+ ORDER BY tickets_respostas.data_criacao_timestamp DESC
+ LIMIT 1
+ ) AS usuarios_ult_resp
+ ")
+ ->join("status", "tickets.statusid = status.id")
+ ->join("departamentos", "tickets.departamentosid = departamentos.id")
+ ->where("tickets.usuariosid", $this->session->userdata('id'))
+ ->limit($datatable->length, $datatable->start)
+ ->get("tickets");
+ }
+
+}
+
+/* End of file Client_model.php */
+/* Location: ./application/models/Client_model.php */
\ No newline at end of file
diff --git a/application/models/Profile_model.php b/application/models/Profile_model.php
new file mode 100644
index 0000000..c71aafd
--- /dev/null
+++ b/application/models/Profile_model.php
@@ -0,0 +1,34 @@
+db->where('id', $id)
+ ->get('usuarios');
+ }
+
+ function get_user_endereco($id)
+ {
+ return $this->db->where('usuariosid', $id)
+ ->get('usuarios_endereco');
+ }
+
+ function update($table, $columnWhere, $where, $data=array())
+ {
+ $this->db->where($columnWhere, $where)
+ ->set($data)
+ ->update($table);
+ }
+
+}
+
+/* End of file Profile_model.php */
+/* Location: ./application/models/Profile_model.php */
\ No newline at end of file
diff --git a/application/models/Tickets_model.php b/application/models/Tickets_model.php
new file mode 100644
index 0000000..e0dde28
--- /dev/null
+++ b/application/models/Tickets_model.php
@@ -0,0 +1,143 @@
+db->insert($table, $data);
+ $id = $this->db->insert_id();
+ if ($id > 0) {
+ return $id;
+ }else{
+ return false;
+ }
+ }
+
+ function update($table, $columnWhere, $where, $data=array())
+ {
+ $this->db->where($columnWhere, $where)
+ ->set($data)
+ ->update($table);
+ }
+
+ public function get_tickets_total()
+ {
+ $s = $this->db->select("COUNT(*) as num")->get("tickets");
+ $r = $s->row();
+ if(isset($r->num)) return $r->num;
+ return 0;
+ }
+
+ public function get_tickets($datatable)
+ {
+
+ $datatable->db_search(
+ array(
+ "tickets.nome"
+ )
+ );
+ if ($this->input->post("order", true)) {
+ $order_column = array(
+ "tickets.id",
+ "tickets.assunto",
+ "departamentos.nome",
+ "status.nome",
+ "tickets.data_criacao_timestamp"
+ );
+ $this->db->order_by($order_column[$this->input->post("order", true)['0']['column']], $this->input->post("order", true)['0']['dir']);
+ } else {
+ $this->db->order_by("tickets.data_criacao_timestamp", "DESC");
+ }
+ return $this->db
+ ->select(" tickets.id, tickets.assunto, tickets.descricao, tickets.data_criacao_timestamp, departamentos.nome as departamento_nome, status.nome as status_nome, status.escopo, tickets.usuariosid,
+ ( SELECT tickets_respostas.usuariosid
+ FROM tickets_respostas
+ WHERE tickets_respostas.ticketsid = tickets.id
+ ORDER BY tickets_respostas.data_criacao_timestamp DESC
+ LIMIT 1
+ ) AS usuarios_ult_resp
+ ")
+ ->join("status", "tickets.statusid = status.id")
+ ->join("departamentos", "tickets.departamentosid = departamentos.id")
+ ->limit($datatable->length, $datatable->start)
+ ->get("tickets");
+ }
+
+ public function get_ticket($id)
+ {
+ return $this->db->select("tickets.id as ticketid, tickets.assunto, tickets.descricao, tickets.data_criacao_timestamp, usuarios.nome, usuarios.email, usuarios.cpf, usuarios.fone, usuarios_endereco.*, usuarios.id as usuario_id, departamentos.id as departamento_id, status.id as status_id, departamentos.nome as departamento_nome, status.nome as status_nome, status.escopo, case status.escopo
+when 1 then 'Directory access is forbidden.
+
+
+
diff --git a/application/third_party/index.html b/application/third_party/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/third_party/index.html
@@ -0,0 +1,11 @@
+
+
+
+ Directory access is forbidden.
+
+
+
diff --git a/application/views/admin/configuracoes_index.php b/application/views/admin/configuracoes_index.php
new file mode 100644
index 0000000..091bc49
--- /dev/null
+++ b/application/views/admin/configuracoes_index.php
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
Forneça seu email e será enviado uma nova senha para o email.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/login.php b/application/views/auth/login.php
new file mode 100644
index 0000000..c0663a6
--- /dev/null
+++ b/application/views/auth/login.php
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+ = $this->session->flashdata('success'); ?>
+ = $this->session->flashdata('error'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/register.php b/application/views/auth/register.php
new file mode 100644
index 0000000..23f4f2d
--- /dev/null
+++ b/application/views/auth/register.php
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+ = $this->session->flashdata('error'); ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/client/create.php b/application/views/client/create.php
new file mode 100644
index 0000000..76f9d81
--- /dev/null
+++ b/application/views/client/create.php
@@ -0,0 +1,55 @@
+
+ Departamento*:
+
+
+ = $d->nome ?>
+
+
+
+
+ Assunto*:
+
+
+
+ Descrição*:
+
+
+
+ Anexos:
+
+
+
\ No newline at end of file
diff --git a/application/views/client/index.php b/application/views/client/index.php
new file mode 100644
index 0000000..a70d6e7
--- /dev/null
+++ b/application/views/client/index.php
@@ -0,0 +1,151 @@
+
+
+
Tickets
+
+ Área do Cliente
+ Tickets
+
+
+
+
+
+
+
+
+ #
+ Assunto
+ Departamento
+ Status
+ Data criação
+ Ações
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/client/view.php b/application/views/client/view.php
new file mode 100644
index 0000000..3e80a79
--- /dev/null
+++ b/application/views/client/view.php
@@ -0,0 +1,137 @@
+
+
+
Ticket #= $ticket->ticketid ?>
+
+ Área do Cliente
+ Tickets
+ Visualizar
+
+
+
+
+
+
Assunto: = $ticket->assunto ?>
+
Descrição:
= $ticket->descricao ?>
+
Anexos:
+ 0) : ?>
+
+
+
Sem anexos
+
+
+
+
+
+
+
+ = $r->descricao ?>
+ tickets_model->get_ticket_files_responses($ticket->ticketid, $r->id)->result();
+ if(count($ticket_files_responses) > 0) : ?>
+
Anexos:
+
+
+
+
+
Postado em: = date('d/m/Y H:i:s', $r->data_criacao_timestamp) ?>
+
+
+
+ escopo != 3) : ?>
+
+
+
+
+
+
+
Detalhes do ticket
+
+
Data de criação: = date('d/m/Y H:i:s',$ticket->data_criacao_timestamp) ?>
+
Departamento: = $ticket->departamento_nome ?>
+
Status: = $ticket->status_nome ?>
+
+
Dados do cliente
+
+
Cliente: = $ticket->nome ?>
+
CPF: = $this->common->mask($ticket->cpf, "###.###.###-##") ?>
+
E-mail: = $ticket->email ?>
+
Fone: = (strlen($ticket->fone) == 11) ? $this->common->mask($ticket->fone, "## # ####-####") : $this->common->mask($ticket->fone, "## ####-####") ?>
+
Logradouro: = $ticket->logradouro ?>, = $ticket->numero ?>
+
Bairro: = $ticket->bairro ?>
+
Complemento: = $ticket->complemento ?>
+
Cidade / UF: = $ticket->cidade ?> / = $ticket->uf ?>
+
CEP: = $this->common->mask($ticket->cep, "##.###-###") ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/errors/cli/error_404.php b/application/views/errors/cli/error_404.php
new file mode 100644
index 0000000..6984b61
--- /dev/null
+++ b/application/views/errors/cli/error_404.php
@@ -0,0 +1,8 @@
+
+
+An uncaught Exception was encountered
+
+Type:
+Message:
+Filename: getFile(), "\n"; ?>
+Line Number: getLine(); ?>
+
+
+
+Backtrace:
+getTrace() as $error): ?>
+
+ File:
+ Line:
+ Function:
+
+
+
+
diff --git a/application/views/errors/cli/error_general.php b/application/views/errors/cli/error_general.php
new file mode 100644
index 0000000..6984b61
--- /dev/null
+++ b/application/views/errors/cli/error_general.php
@@ -0,0 +1,8 @@
+
+
+A PHP Error was encountered
+
+Severity:
+Message:
+Filename:
+Line Number:
+
+
+
+Backtrace:
+
+
+ File:
+ Line:
+ Function:
+
+
+
+
diff --git a/application/views/errors/cli/index.html b/application/views/errors/cli/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/views/errors/cli/index.html
@@ -0,0 +1,11 @@
+
+
+
+
403 Forbidden
+
+
+
+
Directory access is forbidden.
+
+
+
diff --git a/application/views/errors/html/error_404.php b/application/views/errors/html/error_404.php
new file mode 100644
index 0000000..756ea9d
--- /dev/null
+++ b/application/views/errors/html/error_404.php
@@ -0,0 +1,64 @@
+
+
+
+
+
404 Page Not Found
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/errors/html/error_db.php b/application/views/errors/html/error_db.php
new file mode 100644
index 0000000..f5a43f6
--- /dev/null
+++ b/application/views/errors/html/error_db.php
@@ -0,0 +1,64 @@
+
+
+
+
+
Database Error
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/errors/html/error_exception.php b/application/views/errors/html/error_exception.php
new file mode 100644
index 0000000..8784886
--- /dev/null
+++ b/application/views/errors/html/error_exception.php
@@ -0,0 +1,32 @@
+
+
+
+
+
An uncaught Exception was encountered
+
+
Type:
+
Message:
+
Filename: getFile(); ?>
+
Line Number: getLine(); ?>
+
+
+
+
Backtrace:
+ getTrace() as $error): ?>
+
+
+
+
+ File:
+ Line:
+ Function:
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/errors/html/error_general.php b/application/views/errors/html/error_general.php
new file mode 100644
index 0000000..fc3b2eb
--- /dev/null
+++ b/application/views/errors/html/error_general.php
@@ -0,0 +1,64 @@
+
+
+
+
+
Error
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/errors/html/error_php.php b/application/views/errors/html/error_php.php
new file mode 100644
index 0000000..b146f9c
--- /dev/null
+++ b/application/views/errors/html/error_php.php
@@ -0,0 +1,33 @@
+
+
+
+
+
A PHP Error was encountered
+
+
Severity:
+
Message:
+
Filename:
+
Line Number:
+
+
+
+
Backtrace:
+
+
+
+
+
+ File:
+ Line:
+ Function:
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/errors/html/index.html b/application/views/errors/html/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/views/errors/html/index.html
@@ -0,0 +1,11 @@
+
+
+
+
403 Forbidden
+
+
+
+
Directory access is forbidden.
+
+
+
diff --git a/application/views/errors/index.html b/application/views/errors/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/views/errors/index.html
@@ -0,0 +1,11 @@
+
+
+
+
403 Forbidden
+
+
+
+
Directory access is forbidden.
+
+
+
diff --git a/application/views/index.html b/application/views/index.html
new file mode 100644
index 0000000..b702fbc
--- /dev/null
+++ b/application/views/index.html
@@ -0,0 +1,11 @@
+
+
+
+
403 Forbidden
+
+
+
+
Directory access is forbidden.
+
+
+
diff --git a/application/views/layout/default.php b/application/views/layout/default.php
new file mode 100644
index 0000000..f5caf63
--- /dev/null
+++ b/application/views/layout/default.php
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
= $this->configs->info->nome_site ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ = $this->configs->info->nome_logo ?>
+
+
+
+
+ session->userdata('atendente')) : ?>
+
+
+
+
+
+
+
+ session->flashdata('error')){ ?>
+
+ Erro! = $this->session->flashdata('error') ?>
+
+ ×
+
+
+ session->flashdata('success')){ ?>
+
+ Sucesso! = $this->session->flashdata('success') ?>
+
+ ×
+
+
+
+ = $content ?>
+
+
+
+
HelpDesk - TCC Cesumar 2020
+
+
+
+
+
+
+
+
+
+
diff --git a/application/views/layout/login.php b/application/views/layout/login.php
new file mode 100644
index 0000000..7cec317
--- /dev/null
+++ b/application/views/layout/login.php
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
= $this->configs->info->nome_site ?>
+
+
+
+
+
+
+
+
+
+ = $content; ?>
+
+
\ No newline at end of file
diff --git a/application/views/profile/index.php b/application/views/profile/index.php
new file mode 100644
index 0000000..bf54f82
--- /dev/null
+++ b/application/views/profile/index.php
@@ -0,0 +1,139 @@
+
+
+
Meus dados
+
+ Meus dados
+
+
+
+
+
Dados pessoais
+
Nome: =$user->nome?>
+
CPF: =$this->common->mask($user->cpf, '###.###.###-##')?>
+
E-mail: =$user->email?>
+
Telefone: =(strlen($user->fone) == 11) ? $this->common->mask($user->fone, '## # ####-####') : $this->common->mask($user->fone, '## ####-####') ?>
+
Situação: = ($user->ativo) ? 'Ativo' : 'Desativado'?>
+
Data criação: =date('d/m/Y H:i:s',$user->data_criacao_timestamp)?>
+
+
Endereço
+
Logradouro: =$user_endereco->logradouro?>
+
Número: =$user_endereco->numero?>
+
Bairro: =$user_endereco->bairro?>
+
Complemento: =$user_endereco->complemento?>
+
Cidade / UF: =$user_endereco->cidade . ' / ' . $user_endereco->uf?>
+
CEP: =$this->common->mask($user_endereco->cep, '##.###-###')?>
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/profile/user_edit.php b/application/views/profile/user_edit.php
new file mode 100644
index 0000000..15c667d
--- /dev/null
+++ b/application/views/profile/user_edit.php
@@ -0,0 +1,101 @@
+
Dados pessoais
+
+
+ Nome:
+
+
+
+ CPF:
+
+
+
+ E-mail:
+
+
+
+ Telefone:
+
+
+
+
Endereço
+
+ Logradouro:
+
+
+
+ Número:
+
+
+
+ Bairro:
+
+
+
+ Complemento:
+
+
+
+
\ No newline at end of file
diff --git a/application/views/tickets/create.php b/application/views/tickets/create.php
new file mode 100644
index 0000000..afea728
--- /dev/null
+++ b/application/views/tickets/create.php
@@ -0,0 +1,60 @@
+
+ Usuário*:
+
+
+
+
+ Departamento*:
+
+
+ = $d->nome ?>
+
+
+
+
+ Assunto*:
+
+
+
+ Descrição*:
+
+
+
+ Anexos:
+
+
+
\ No newline at end of file
diff --git a/application/views/tickets/index.php b/application/views/tickets/index.php
new file mode 100644
index 0000000..11827da
--- /dev/null
+++ b/application/views/tickets/index.php
@@ -0,0 +1,151 @@
+
+
+
Tickets
+
+ Admin
+ Tickets
+
+
+
+
+
+
+
+
+ #
+ Assunto
+ Departamento
+ Status
+ Data criação
+ Ações
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/tickets/view.php b/application/views/tickets/view.php
new file mode 100644
index 0000000..81ab445
--- /dev/null
+++ b/application/views/tickets/view.php
@@ -0,0 +1,193 @@
+
+
+
Ticket #= $ticket->ticketid ?>
+
+ Admin
+ Tickets
+ Visualizar
+
+
+
+
+
+
Assunto: = $ticket->assunto ?>
+
Descrição:
= $ticket->descricao ?>
+
Anexos:
+ 0) : ?>
+
+
+
Sem anexos
+
+
+
+
+
+
+
+ = $r->descricao ?>
+ tickets_model->get_ticket_files_responses($ticket->ticketid, $r->id)->result();
+ if(count($ticket_files_responses) > 0) : ?>
+
Anexos:
+
+
+
+
+
Postado em: = date('d/m/Y H:i:s', $r->data_criacao_timestamp) ?>
+
+
+
+ escopo != 3) : ?>
+
+
+
" method="POST" enctype="multipart/form-data">
+
+ Responder Ticket
+
+
+ Responder
+
+
+
+
+
+
+
+
+
Detalhes do ticket
+
+
Data de criação: = date('d/m/Y H:i:s',$ticket->data_criacao_timestamp) ?>
+
Departamento:
+
+
+ departamento_id == $d->id) ? 'selected' : '' ?> value="= $d->id ?>">= $d->nome ?>
+
+
+
Status:
+
+
+ status_id == $s->id) ? 'selected' : '' ?> value="= $s->id ?>">= $s->nome ?>
+
+
+
Situação: = $ticket->escopo_nome ?>
+
+
Dados do cliente
+
+
Cliente: = $ticket->nome ?>
+
CPF: = $this->common->mask($ticket->cpf, "###.###.###-##") ?>
+
E-mail: = $ticket->email ?>
+
Fone: = (strlen($ticket->fone) == 11) ? $this->common->mask($ticket->fone, "## # ####-####") : $this->common->mask($ticket->fone, "## ####-####") ?>
+
Logradouro: = $ticket->logradouro ?>, = $ticket->numero ?>
+
Bairro: = $ticket->bairro ?>
+
Complemento: = $ticket->complemento ?>
+
Cidade / UF: = $ticket->cidade ?> / = $ticket->uf ?>
+
CEP: = $this->common->mask($ticket->cep, "##.###-###") ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/css/styles.css b/assets/css/styles.css
new file mode 100644
index 0000000..22f5473
--- /dev/null
+++ b/assets/css/styles.css
@@ -0,0 +1,10249 @@
+@charset "UTF-8";
+/*!
+* Start Bootstrap - SB Admin v6.0.2 (https://startbootstrap.com/template/sb-admin)
+* Copyright 2013-2020 Start Bootstrap
+* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-sb-admin/blob/master/LICENSE)
+*/
+/*!
+ * Bootstrap v4.5.3 (https://getbootstrap.com/)
+ * Copyright 2011-2020 The Bootstrap Authors
+ * Copyright 2011-2020 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ */
+:root {
+ --blue: #007bff;
+ --indigo: #6610f2;
+ --purple: #6f42c1;
+ --pink: #e83e8c;
+ --red: #dc3545;
+ --orange: #fd7e14;
+ --yellow: #ffc107;
+ --green: #28a745;
+ --teal: #20c997;
+ --cyan: #17a2b8;
+ --white: #fff;
+ --gray: #6c757d;
+ --gray-dark: #343a40;
+ --primary: #007bff;
+ --secondary: #6c757d;
+ --success: #28a745;
+ --info: #17a2b8;
+ --warning: #ffc107;
+ --danger: #dc3545;
+ --light: #f8f9fa;
+ --dark: #343a40;
+ --breakpoint-xs: 0;
+ --breakpoint-sm: 576px;
+ --breakpoint-md: 768px;
+ --breakpoint-lg: 992px;
+ --breakpoint-xl: 1200px;
+ --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+ -webkit-text-size-adjust: 100%;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
+ display: block;
+}
+
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #212529;
+ text-align: left;
+ background-color: #fff;
+}
+
+[tabindex="-1"]:focus:not(:focus-visible) {
+ outline: 0 !important;
+}
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+ overflow: visible;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 0;
+ margin-bottom: 0.5rem;
+}
+
+p {
+ margin-top: 0;
+ margin-bottom: 0.5rem;
+}
+
+abbr[title],
+abbr[data-original-title] {
+ text-decoration: underline;
+ -webkit-text-decoration: underline dotted;
+ text-decoration: underline dotted;
+ cursor: help;
+ border-bottom: 0;
+ -webkit-text-decoration-skip-ink: none;
+ text-decoration-skip-ink: none;
+}
+
+address {
+ margin-bottom: 1rem;
+ font-style: normal;
+ line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+ margin-bottom: 0;
+}
+
+dt {
+ font-weight: 700;
+}
+
+dd {
+ margin-bottom: 0.5rem;
+ margin-left: 0;
+}
+
+blockquote {
+ margin: 0 0 1rem;
+}
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+small {
+ font-size: 80%;
+}
+
+sub,
+sup {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+a {
+ color: #007bff;
+ text-decoration: none;
+ background-color: transparent;
+}
+a:hover {
+ color: #0056b3;
+ text-decoration: underline;
+}
+
+a:not([href]):not([class]) {
+ color: inherit;
+ text-decoration: none;
+}
+a:not([href]):not([class]):hover {
+ color: inherit;
+ text-decoration: none;
+}
+
+pre,
+code,
+kbd,
+samp {
+ font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ font-size: 1em;
+}
+
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto;
+ -ms-overflow-style: scrollbar;
+}
+
+figure {
+ margin: 0 0 1rem;
+}
+
+img {
+ vertical-align: middle;
+ border-style: none;
+}
+
+svg {
+ overflow: hidden;
+ vertical-align: middle;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+caption {
+ padding-top: 0.75rem;
+ padding-bottom: 0.75rem;
+ color: #6c757d;
+ text-align: left;
+ caption-side: bottom;
+}
+
+th {
+ text-align: inherit;
+ text-align: -webkit-match-parent;
+}
+
+label {
+ display: inline-block;
+ margin-bottom: 0.5rem;
+}
+
+button {
+ border-radius: 0;
+}
+
+button:focus {
+ outline: 1px dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+optgroup,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+
+button,
+input {
+ overflow: visible;
+}
+
+button,
+select {
+ text-transform: none;
+}
+
+[role=button] {
+ cursor: pointer;
+}
+
+select {
+ word-wrap: normal;
+}
+
+button,
+[type=button],
+[type=reset],
+[type=submit] {
+ -webkit-appearance: button;
+}
+
+button:not(:disabled),
+[type=button]:not(:disabled),
+[type=reset]:not(:disabled),
+[type=submit]:not(:disabled) {
+ cursor: pointer;
+}
+
+button::-moz-focus-inner,
+[type=button]::-moz-focus-inner,
+[type=reset]::-moz-focus-inner,
+[type=submit]::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+
+input[type=radio],
+input[type=checkbox] {
+ box-sizing: border-box;
+ padding: 0;
+}
+
+textarea {
+ overflow: auto;
+ resize: vertical;
+}
+
+fieldset {
+ min-width: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+
+legend {
+ display: block;
+ width: 100%;
+ max-width: 100%;
+ padding: 0;
+ margin-bottom: 0.5rem;
+ font-size: 1.5rem;
+ line-height: inherit;
+ color: inherit;
+ white-space: normal;
+}
+
+progress {
+ vertical-align: baseline;
+}
+
+[type=number]::-webkit-inner-spin-button,
+[type=number]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+[type=search] {
+ outline-offset: -2px;
+ -webkit-appearance: none;
+}
+
+[type=search]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+::-webkit-file-upload-button {
+ font: inherit;
+ -webkit-appearance: button;
+}
+
+output {
+ display: inline-block;
+}
+
+summary {
+ display: list-item;
+ cursor: pointer;
+}
+
+template {
+ display: none;
+}
+
+[hidden] {
+ display: none !important;
+}
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+ line-height: 1.2;
+}
+
+h1, .h1 {
+ font-size: 2.5rem;
+}
+
+h2, .h2 {
+ font-size: 2rem;
+}
+
+h3, .h3 {
+ font-size: 1.75rem;
+}
+
+h4, .h4 {
+ font-size: 1.5rem;
+}
+
+h5, .h5 {
+ font-size: 1.25rem;
+}
+
+h6, .h6 {
+ font-size: 1rem;
+}
+
+.lead {
+ font-size: 1.25rem;
+ font-weight: 300;
+}
+
+.display-1 {
+ font-size: 6rem;
+ font-weight: 300;
+ line-height: 1.2;
+}
+
+.display-2 {
+ font-size: 5.5rem;
+ font-weight: 300;
+ line-height: 1.2;
+}
+
+.display-3 {
+ font-size: 4.5rem;
+ font-weight: 300;
+ line-height: 1.2;
+}
+
+.display-4 {
+ font-size: 3.5rem;
+ font-weight: 300;
+ line-height: 1.2;
+}
+
+hr {
+ margin-top: 0;
+ margin-bottom: 0;
+ border: 0;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+small,
+.small {
+ font-size: 80%;
+ font-weight: 400;
+}
+
+mark,
+.mark {
+ padding: 0.2em;
+ background-color: #fcf8e3;
+}
+
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+
+.list-inline {
+ padding-left: 0;
+ list-style: none;
+}
+
+.list-inline-item {
+ display: inline-block;
+}
+.list-inline-item:not(:last-child) {
+ margin-right: 0.5rem;
+}
+
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+
+.blockquote {
+ margin-bottom: 1rem;
+ font-size: 1.25rem;
+}
+
+.blockquote-footer {
+ display: block;
+ font-size: 80%;
+ color: #6c757d;
+}
+.blockquote-footer::before {
+ content: "— ";
+}
+
+.img-fluid {
+ max-width: 100%;
+ height: auto;
+}
+
+.img-thumbnail {
+ padding: 0.25rem;
+ background-color: #fff;
+ border: 1px solid #dee2e6;
+ border-radius: 0.25rem;
+ max-width: 100%;
+ height: auto;
+}
+
+.figure {
+ display: inline-block;
+}
+
+.figure-img {
+ margin-bottom: 0.5rem;
+ line-height: 1;
+}
+
+.figure-caption {
+ font-size: 90%;
+ color: #6c757d;
+}
+
+code {
+ font-size: 87.5%;
+ color: #e83e8c;
+ word-wrap: break-word;
+}
+a > code {
+ color: inherit;
+}
+
+kbd {
+ padding: 0.2rem 0.4rem;
+ font-size: 87.5%;
+ color: #fff;
+ background-color: #212529;
+ border-radius: 0.2rem;
+}
+kbd kbd {
+ padding: 0;
+ font-size: 100%;
+ font-weight: 700;
+}
+
+pre {
+ display: block;
+ font-size: 87.5%;
+ color: #212529;
+}
+pre code {
+ font-size: inherit;
+ color: inherit;
+ word-break: normal;
+}
+
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+
+.container,
+.container-fluid,
+.container-xl,
+.container-lg,
+.container-md,
+.container-sm {
+ width: 100%;
+ padding-right: 0.75rem;
+ padding-left: 0.75rem;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container-sm, .container {
+ max-width: 540px;
+ }
+}
+@media (min-width: 768px) {
+ .container-md, .container-sm, .container {
+ max-width: 720px;
+ }
+}
+@media (min-width: 992px) {
+ .container-lg, .container-md, .container-sm, .container {
+ max-width: 960px;
+ }
+}
+@media (min-width: 1200px) {
+ .container-xl, .container-lg, .container-md, .container-sm, .container {
+ max-width: 1140px;
+ }
+}
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -0.75rem;
+ margin-left: -0.75rem;
+}
+
+.no-gutters {
+ margin-right: 0;
+ margin-left: 0;
+}
+.no-gutters > .col,
+.no-gutters > [class*=col-] {
+ padding-right: 0;
+ padding-left: 0;
+}
+
+.col-xl,
+.col-xl-auto, .col-xl-12, .col-xl-11, .col-xl-10, .col-xl-9, .col-xl-8, .col-xl-7, .col-xl-6, .col-xl-5, .col-xl-4, .col-xl-3, .col-xl-2, .col-xl-1, .col-lg,
+.col-lg-auto, .col-lg-12, .col-lg-11, .col-lg-10, .col-lg-9, .col-lg-8, .col-lg-7, .col-lg-6, .col-lg-5, .col-lg-4, .col-lg-3, .col-lg-2, .col-lg-1, .col-md,
+.col-md-auto, .col-md-12, .col-md-11, .col-md-10, .col-md-9, .col-md-8, .col-md-7, .col-md-6, .col-md-5, .col-md-4, .col-md-3, .col-md-2, .col-md-1, .col-sm,
+.col-sm-auto, .col-sm-12, .col-sm-11, .col-sm-10, .col-sm-9, .col-sm-8, .col-sm-7, .col-sm-6, .col-sm-5, .col-sm-4, .col-sm-3, .col-sm-2, .col-sm-1, .col,
+.col-auto, .col-12, .col-11, .col-10, .col-9, .col-8, .col-7, .col-6, .col-5, .col-4, .col-3, .col-2, .col-1 {
+ position: relative;
+ width: 100%;
+ padding-right: 0.75rem;
+ padding-left: 0.75rem;
+}
+
+.col {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%;
+}
+
+.row-cols-1 > * {
+ flex: 0 0 100%;
+ max-width: 100%;
+}
+
+.row-cols-2 > * {
+ flex: 0 0 50%;
+ max-width: 50%;
+}
+
+.row-cols-3 > * {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+}
+
+.row-cols-4 > * {
+ flex: 0 0 25%;
+ max-width: 25%;
+}
+
+.row-cols-5 > * {
+ flex: 0 0 20%;
+ max-width: 20%;
+}
+
+.row-cols-6 > * {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+}
+
+.col-auto {
+ flex: 0 0 auto;
+ width: auto;
+ max-width: 100%;
+}
+
+.col-1 {
+ flex: 0 0 8.3333333333%;
+ max-width: 8.3333333333%;
+}
+
+.col-2 {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+}
+
+.col-3 {
+ flex: 0 0 25%;
+ max-width: 25%;
+}
+
+.col-4 {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+}
+
+.col-5 {
+ flex: 0 0 41.6666666667%;
+ max-width: 41.6666666667%;
+}
+
+.col-6 {
+ flex: 0 0 50%;
+ max-width: 50%;
+}
+
+.col-7 {
+ flex: 0 0 58.3333333333%;
+ max-width: 58.3333333333%;
+}
+
+.col-8 {
+ flex: 0 0 66.6666666667%;
+ max-width: 66.6666666667%;
+}
+
+.col-9 {
+ flex: 0 0 75%;
+ max-width: 75%;
+}
+
+.col-10 {
+ flex: 0 0 83.3333333333%;
+ max-width: 83.3333333333%;
+}
+
+.col-11 {
+ flex: 0 0 91.6666666667%;
+ max-width: 91.6666666667%;
+}
+
+.col-12 {
+ flex: 0 0 100%;
+ max-width: 100%;
+}
+
+.order-first {
+ order: -1;
+}
+
+.order-last {
+ order: 13;
+}
+
+.order-0 {
+ order: 0;
+}
+
+.order-1 {
+ order: 1;
+}
+
+.order-2 {
+ order: 2;
+}
+
+.order-3 {
+ order: 3;
+}
+
+.order-4 {
+ order: 4;
+}
+
+.order-5 {
+ order: 5;
+}
+
+.order-6 {
+ order: 6;
+}
+
+.order-7 {
+ order: 7;
+}
+
+.order-8 {
+ order: 8;
+}
+
+.order-9 {
+ order: 9;
+}
+
+.order-10 {
+ order: 10;
+}
+
+.order-11 {
+ order: 11;
+}
+
+.order-12 {
+ order: 12;
+}
+
+.offset-1 {
+ margin-left: 8.3333333333%;
+}
+
+.offset-2 {
+ margin-left: 16.6666666667%;
+}
+
+.offset-3 {
+ margin-left: 25%;
+}
+
+.offset-4 {
+ margin-left: 33.3333333333%;
+}
+
+.offset-5 {
+ margin-left: 41.6666666667%;
+}
+
+.offset-6 {
+ margin-left: 50%;
+}
+
+.offset-7 {
+ margin-left: 58.3333333333%;
+}
+
+.offset-8 {
+ margin-left: 66.6666666667%;
+}
+
+.offset-9 {
+ margin-left: 75%;
+}
+
+.offset-10 {
+ margin-left: 83.3333333333%;
+}
+
+.offset-11 {
+ margin-left: 91.6666666667%;
+}
+
+@media (min-width: 576px) {
+ .col-sm {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%;
+ }
+
+ .row-cols-sm-1 > * {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .row-cols-sm-2 > * {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .row-cols-sm-3 > * {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .row-cols-sm-4 > * {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .row-cols-sm-5 > * {
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+
+ .row-cols-sm-6 > * {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-sm-auto {
+ flex: 0 0 auto;
+ width: auto;
+ max-width: 100%;
+ }
+
+ .col-sm-1 {
+ flex: 0 0 8.3333333333%;
+ max-width: 8.3333333333%;
+ }
+
+ .col-sm-2 {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-sm-3 {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .col-sm-4 {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .col-sm-5 {
+ flex: 0 0 41.6666666667%;
+ max-width: 41.6666666667%;
+ }
+
+ .col-sm-6 {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .col-sm-7 {
+ flex: 0 0 58.3333333333%;
+ max-width: 58.3333333333%;
+ }
+
+ .col-sm-8 {
+ flex: 0 0 66.6666666667%;
+ max-width: 66.6666666667%;
+ }
+
+ .col-sm-9 {
+ flex: 0 0 75%;
+ max-width: 75%;
+ }
+
+ .col-sm-10 {
+ flex: 0 0 83.3333333333%;
+ max-width: 83.3333333333%;
+ }
+
+ .col-sm-11 {
+ flex: 0 0 91.6666666667%;
+ max-width: 91.6666666667%;
+ }
+
+ .col-sm-12 {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .order-sm-first {
+ order: -1;
+ }
+
+ .order-sm-last {
+ order: 13;
+ }
+
+ .order-sm-0 {
+ order: 0;
+ }
+
+ .order-sm-1 {
+ order: 1;
+ }
+
+ .order-sm-2 {
+ order: 2;
+ }
+
+ .order-sm-3 {
+ order: 3;
+ }
+
+ .order-sm-4 {
+ order: 4;
+ }
+
+ .order-sm-5 {
+ order: 5;
+ }
+
+ .order-sm-6 {
+ order: 6;
+ }
+
+ .order-sm-7 {
+ order: 7;
+ }
+
+ .order-sm-8 {
+ order: 8;
+ }
+
+ .order-sm-9 {
+ order: 9;
+ }
+
+ .order-sm-10 {
+ order: 10;
+ }
+
+ .order-sm-11 {
+ order: 11;
+ }
+
+ .order-sm-12 {
+ order: 12;
+ }
+
+ .offset-sm-0 {
+ margin-left: 0;
+ }
+
+ .offset-sm-1 {
+ margin-left: 8.3333333333%;
+ }
+
+ .offset-sm-2 {
+ margin-left: 16.6666666667%;
+ }
+
+ .offset-sm-3 {
+ margin-left: 25%;
+ }
+
+ .offset-sm-4 {
+ margin-left: 33.3333333333%;
+ }
+
+ .offset-sm-5 {
+ margin-left: 41.6666666667%;
+ }
+
+ .offset-sm-6 {
+ margin-left: 50%;
+ }
+
+ .offset-sm-7 {
+ margin-left: 58.3333333333%;
+ }
+
+ .offset-sm-8 {
+ margin-left: 66.6666666667%;
+ }
+
+ .offset-sm-9 {
+ margin-left: 75%;
+ }
+
+ .offset-sm-10 {
+ margin-left: 83.3333333333%;
+ }
+
+ .offset-sm-11 {
+ margin-left: 91.6666666667%;
+ }
+}
+@media (min-width: 768px) {
+ .col-md {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%;
+ }
+
+ .row-cols-md-1 > * {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .row-cols-md-2 > * {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .row-cols-md-3 > * {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .row-cols-md-4 > * {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .row-cols-md-5 > * {
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+
+ .row-cols-md-6 > * {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-md-auto {
+ flex: 0 0 auto;
+ width: auto;
+ max-width: 100%;
+ }
+
+ .col-md-1 {
+ flex: 0 0 8.3333333333%;
+ max-width: 8.3333333333%;
+ }
+
+ .col-md-2 {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-md-3 {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .col-md-4 {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .col-md-5 {
+ flex: 0 0 41.6666666667%;
+ max-width: 41.6666666667%;
+ }
+
+ .col-md-6 {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .col-md-7 {
+ flex: 0 0 58.3333333333%;
+ max-width: 58.3333333333%;
+ }
+
+ .col-md-8 {
+ flex: 0 0 66.6666666667%;
+ max-width: 66.6666666667%;
+ }
+
+ .col-md-9 {
+ flex: 0 0 75%;
+ max-width: 75%;
+ }
+
+ .col-md-10 {
+ flex: 0 0 83.3333333333%;
+ max-width: 83.3333333333%;
+ }
+
+ .col-md-11 {
+ flex: 0 0 91.6666666667%;
+ max-width: 91.6666666667%;
+ }
+
+ .col-md-12 {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .order-md-first {
+ order: -1;
+ }
+
+ .order-md-last {
+ order: 13;
+ }
+
+ .order-md-0 {
+ order: 0;
+ }
+
+ .order-md-1 {
+ order: 1;
+ }
+
+ .order-md-2 {
+ order: 2;
+ }
+
+ .order-md-3 {
+ order: 3;
+ }
+
+ .order-md-4 {
+ order: 4;
+ }
+
+ .order-md-5 {
+ order: 5;
+ }
+
+ .order-md-6 {
+ order: 6;
+ }
+
+ .order-md-7 {
+ order: 7;
+ }
+
+ .order-md-8 {
+ order: 8;
+ }
+
+ .order-md-9 {
+ order: 9;
+ }
+
+ .order-md-10 {
+ order: 10;
+ }
+
+ .order-md-11 {
+ order: 11;
+ }
+
+ .order-md-12 {
+ order: 12;
+ }
+
+ .offset-md-0 {
+ margin-left: 0;
+ }
+
+ .offset-md-1 {
+ margin-left: 8.3333333333%;
+ }
+
+ .offset-md-2 {
+ margin-left: 16.6666666667%;
+ }
+
+ .offset-md-3 {
+ margin-left: 25%;
+ }
+
+ .offset-md-4 {
+ margin-left: 33.3333333333%;
+ }
+
+ .offset-md-5 {
+ margin-left: 41.6666666667%;
+ }
+
+ .offset-md-6 {
+ margin-left: 50%;
+ }
+
+ .offset-md-7 {
+ margin-left: 58.3333333333%;
+ }
+
+ .offset-md-8 {
+ margin-left: 66.6666666667%;
+ }
+
+ .offset-md-9 {
+ margin-left: 75%;
+ }
+
+ .offset-md-10 {
+ margin-left: 83.3333333333%;
+ }
+
+ .offset-md-11 {
+ margin-left: 91.6666666667%;
+ }
+}
+@media (min-width: 992px) {
+ .col-lg {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%;
+ }
+
+ .row-cols-lg-1 > * {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .row-cols-lg-2 > * {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .row-cols-lg-3 > * {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .row-cols-lg-4 > * {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .row-cols-lg-5 > * {
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+
+ .row-cols-lg-6 > * {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-lg-auto {
+ flex: 0 0 auto;
+ width: auto;
+ max-width: 100%;
+ }
+
+ .col-lg-1 {
+ flex: 0 0 8.3333333333%;
+ max-width: 8.3333333333%;
+ }
+
+ .col-lg-2 {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-lg-3 {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .col-lg-4 {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .col-lg-5 {
+ flex: 0 0 41.6666666667%;
+ max-width: 41.6666666667%;
+ }
+
+ .col-lg-6 {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .col-lg-7 {
+ flex: 0 0 58.3333333333%;
+ max-width: 58.3333333333%;
+ }
+
+ .col-lg-8 {
+ flex: 0 0 66.6666666667%;
+ max-width: 66.6666666667%;
+ }
+
+ .col-lg-9 {
+ flex: 0 0 75%;
+ max-width: 75%;
+ }
+
+ .col-lg-10 {
+ flex: 0 0 83.3333333333%;
+ max-width: 83.3333333333%;
+ }
+
+ .col-lg-11 {
+ flex: 0 0 91.6666666667%;
+ max-width: 91.6666666667%;
+ }
+
+ .col-lg-12 {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .order-lg-first {
+ order: -1;
+ }
+
+ .order-lg-last {
+ order: 13;
+ }
+
+ .order-lg-0 {
+ order: 0;
+ }
+
+ .order-lg-1 {
+ order: 1;
+ }
+
+ .order-lg-2 {
+ order: 2;
+ }
+
+ .order-lg-3 {
+ order: 3;
+ }
+
+ .order-lg-4 {
+ order: 4;
+ }
+
+ .order-lg-5 {
+ order: 5;
+ }
+
+ .order-lg-6 {
+ order: 6;
+ }
+
+ .order-lg-7 {
+ order: 7;
+ }
+
+ .order-lg-8 {
+ order: 8;
+ }
+
+ .order-lg-9 {
+ order: 9;
+ }
+
+ .order-lg-10 {
+ order: 10;
+ }
+
+ .order-lg-11 {
+ order: 11;
+ }
+
+ .order-lg-12 {
+ order: 12;
+ }
+
+ .offset-lg-0 {
+ margin-left: 0;
+ }
+
+ .offset-lg-1 {
+ margin-left: 8.3333333333%;
+ }
+
+ .offset-lg-2 {
+ margin-left: 16.6666666667%;
+ }
+
+ .offset-lg-3 {
+ margin-left: 25%;
+ }
+
+ .offset-lg-4 {
+ margin-left: 33.3333333333%;
+ }
+
+ .offset-lg-5 {
+ margin-left: 41.6666666667%;
+ }
+
+ .offset-lg-6 {
+ margin-left: 50%;
+ }
+
+ .offset-lg-7 {
+ margin-left: 58.3333333333%;
+ }
+
+ .offset-lg-8 {
+ margin-left: 66.6666666667%;
+ }
+
+ .offset-lg-9 {
+ margin-left: 75%;
+ }
+
+ .offset-lg-10 {
+ margin-left: 83.3333333333%;
+ }
+
+ .offset-lg-11 {
+ margin-left: 91.6666666667%;
+ }
+}
+@media (min-width: 1200px) {
+ .col-xl {
+ flex-basis: 0;
+ flex-grow: 1;
+ max-width: 100%;
+ }
+
+ .row-cols-xl-1 > * {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .row-cols-xl-2 > * {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .row-cols-xl-3 > * {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .row-cols-xl-4 > * {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .row-cols-xl-5 > * {
+ flex: 0 0 20%;
+ max-width: 20%;
+ }
+
+ .row-cols-xl-6 > * {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-xl-auto {
+ flex: 0 0 auto;
+ width: auto;
+ max-width: 100%;
+ }
+
+ .col-xl-1 {
+ flex: 0 0 8.3333333333%;
+ max-width: 8.3333333333%;
+ }
+
+ .col-xl-2 {
+ flex: 0 0 16.6666666667%;
+ max-width: 16.6666666667%;
+ }
+
+ .col-xl-3 {
+ flex: 0 0 25%;
+ max-width: 25%;
+ }
+
+ .col-xl-4 {
+ flex: 0 0 33.3333333333%;
+ max-width: 33.3333333333%;
+ }
+
+ .col-xl-5 {
+ flex: 0 0 41.6666666667%;
+ max-width: 41.6666666667%;
+ }
+
+ .col-xl-6 {
+ flex: 0 0 50%;
+ max-width: 50%;
+ }
+
+ .col-xl-7 {
+ flex: 0 0 58.3333333333%;
+ max-width: 58.3333333333%;
+ }
+
+ .col-xl-8 {
+ flex: 0 0 66.6666666667%;
+ max-width: 66.6666666667%;
+ }
+
+ .col-xl-9 {
+ flex: 0 0 75%;
+ max-width: 75%;
+ }
+
+ .col-xl-10 {
+ flex: 0 0 83.3333333333%;
+ max-width: 83.3333333333%;
+ }
+
+ .col-xl-11 {
+ flex: 0 0 91.6666666667%;
+ max-width: 91.6666666667%;
+ }
+
+ .col-xl-12 {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+
+ .order-xl-first {
+ order: -1;
+ }
+
+ .order-xl-last {
+ order: 13;
+ }
+
+ .order-xl-0 {
+ order: 0;
+ }
+
+ .order-xl-1 {
+ order: 1;
+ }
+
+ .order-xl-2 {
+ order: 2;
+ }
+
+ .order-xl-3 {
+ order: 3;
+ }
+
+ .order-xl-4 {
+ order: 4;
+ }
+
+ .order-xl-5 {
+ order: 5;
+ }
+
+ .order-xl-6 {
+ order: 6;
+ }
+
+ .order-xl-7 {
+ order: 7;
+ }
+
+ .order-xl-8 {
+ order: 8;
+ }
+
+ .order-xl-9 {
+ order: 9;
+ }
+
+ .order-xl-10 {
+ order: 10;
+ }
+
+ .order-xl-11 {
+ order: 11;
+ }
+
+ .order-xl-12 {
+ order: 12;
+ }
+
+ .offset-xl-0 {
+ margin-left: 0;
+ }
+
+ .offset-xl-1 {
+ margin-left: 8.3333333333%;
+ }
+
+ .offset-xl-2 {
+ margin-left: 16.6666666667%;
+ }
+
+ .offset-xl-3 {
+ margin-left: 25%;
+ }
+
+ .offset-xl-4 {
+ margin-left: 33.3333333333%;
+ }
+
+ .offset-xl-5 {
+ margin-left: 41.6666666667%;
+ }
+
+ .offset-xl-6 {
+ margin-left: 50%;
+ }
+
+ .offset-xl-7 {
+ margin-left: 58.3333333333%;
+ }
+
+ .offset-xl-8 {
+ margin-left: 66.6666666667%;
+ }
+
+ .offset-xl-9 {
+ margin-left: 75%;
+ }
+
+ .offset-xl-10 {
+ margin-left: 83.3333333333%;
+ }
+
+ .offset-xl-11 {
+ margin-left: 91.6666666667%;
+ }
+}
+.table {
+ width: 100%;
+ margin-bottom: 1rem;
+ color: #212529;
+}
+.table th,
+.table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #dee2e6;
+}
+.table thead th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #dee2e6;
+}
+.table tbody + tbody {
+ border-top: 2px solid #dee2e6;
+}
+
+.table-sm th,
+.table-sm td {
+ padding: 0.3rem;
+}
+
+.table-bordered {
+ border: 1px solid #dee2e6;
+}
+.table-bordered th,
+.table-bordered td {
+ border: 1px solid #dee2e6;
+}
+.table-bordered thead th,
+.table-bordered thead td {
+ border-bottom-width: 2px;
+}
+
+.table-borderless th,
+.table-borderless td,
+.table-borderless thead th,
+.table-borderless tbody + tbody {
+ border: 0;
+}
+
+.table-striped tbody tr:nth-of-type(odd) {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+.table-hover tbody tr:hover {
+ color: #212529;
+ background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-primary,
+.table-primary > th,
+.table-primary > td {
+ background-color: #b8daff;
+}
+.table-primary th,
+.table-primary td,
+.table-primary thead th,
+.table-primary tbody + tbody {
+ border-color: #7abaff;
+}
+
+.table-hover .table-primary:hover {
+ background-color: #9fcdff;
+}
+.table-hover .table-primary:hover > td,
+.table-hover .table-primary:hover > th {
+ background-color: #9fcdff;
+}
+
+.table-secondary,
+.table-secondary > th,
+.table-secondary > td {
+ background-color: #d6d8db;
+}
+.table-secondary th,
+.table-secondary td,
+.table-secondary thead th,
+.table-secondary tbody + tbody {
+ border-color: #b3b7bb;
+}
+
+.table-hover .table-secondary:hover {
+ background-color: #c8cbcf;
+}
+.table-hover .table-secondary:hover > td,
+.table-hover .table-secondary:hover > th {
+ background-color: #c8cbcf;
+}
+
+.table-success,
+.table-success > th,
+.table-success > td {
+ background-color: #c3e6cb;
+}
+.table-success th,
+.table-success td,
+.table-success thead th,
+.table-success tbody + tbody {
+ border-color: #8fd19e;
+}
+
+.table-hover .table-success:hover {
+ background-color: #b1dfbb;
+}
+.table-hover .table-success:hover > td,
+.table-hover .table-success:hover > th {
+ background-color: #b1dfbb;
+}
+
+.table-info,
+.table-info > th,
+.table-info > td {
+ background-color: #bee5eb;
+}
+.table-info th,
+.table-info td,
+.table-info thead th,
+.table-info tbody + tbody {
+ border-color: #86cfda;
+}
+
+.table-hover .table-info:hover {
+ background-color: #abdde5;
+}
+.table-hover .table-info:hover > td,
+.table-hover .table-info:hover > th {
+ background-color: #abdde5;
+}
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+ background-color: #ffeeba;
+}
+.table-warning th,
+.table-warning td,
+.table-warning thead th,
+.table-warning tbody + tbody {
+ border-color: #ffdf7e;
+}
+
+.table-hover .table-warning:hover {
+ background-color: #ffe8a1;
+}
+.table-hover .table-warning:hover > td,
+.table-hover .table-warning:hover > th {
+ background-color: #ffe8a1;
+}
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+ background-color: #f5c6cb;
+}
+.table-danger th,
+.table-danger td,
+.table-danger thead th,
+.table-danger tbody + tbody {
+ border-color: #ed969e;
+}
+
+.table-hover .table-danger:hover {
+ background-color: #f1b0b7;
+}
+.table-hover .table-danger:hover > td,
+.table-hover .table-danger:hover > th {
+ background-color: #f1b0b7;
+}
+
+.table-light,
+.table-light > th,
+.table-light > td {
+ background-color: #fdfdfe;
+}
+.table-light th,
+.table-light td,
+.table-light thead th,
+.table-light tbody + tbody {
+ border-color: #fbfcfc;
+}
+
+.table-hover .table-light:hover {
+ background-color: #ececf6;
+}
+.table-hover .table-light:hover > td,
+.table-hover .table-light:hover > th {
+ background-color: #ececf6;
+}
+
+.table-dark,
+.table-dark > th,
+.table-dark > td {
+ background-color: #c6c8ca;
+}
+.table-dark th,
+.table-dark td,
+.table-dark thead th,
+.table-dark tbody + tbody {
+ border-color: #95999c;
+}
+
+.table-hover .table-dark:hover {
+ background-color: #b9bbbe;
+}
+.table-hover .table-dark:hover > td,
+.table-hover .table-dark:hover > th {
+ background-color: #b9bbbe;
+}
+
+.table-active,
+.table-active > th,
+.table-active > td {
+ background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover {
+ background-color: rgba(0, 0, 0, 0.075);
+}
+.table-hover .table-active:hover > td,
+.table-hover .table-active:hover > th {
+ background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table .thead-dark th {
+ color: #fff;
+ background-color: #343a40;
+ border-color: #454d55;
+}
+.table .thead-light th {
+ color: #495057;
+ background-color: #e9ecef;
+ border-color: #dee2e6;
+}
+
+.table-dark {
+ color: #fff;
+ background-color: #343a40;
+}
+.table-dark th,
+.table-dark td,
+.table-dark thead th {
+ border-color: #454d55;
+}
+.table-dark.table-bordered {
+ border: 0;
+}
+.table-dark.table-striped tbody tr:nth-of-type(odd) {
+ background-color: rgba(255, 255, 255, 0.05);
+}
+.table-dark.table-hover tbody tr:hover {
+ color: #fff;
+ background-color: rgba(255, 255, 255, 0.075);
+}
+
+@media (max-width: 575.98px) {
+ .table-responsive-sm {
+ display: block;
+ width: 100%;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+ .table-responsive-sm > .table-bordered {
+ border: 0;
+ }
+}
+@media (max-width: 767.98px) {
+ .table-responsive-md {
+ display: block;
+ width: 100%;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+ .table-responsive-md > .table-bordered {
+ border: 0;
+ }
+}
+@media (max-width: 991.98px) {
+ .table-responsive-lg {
+ display: block;
+ width: 100%;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+ .table-responsive-lg > .table-bordered {
+ border: 0;
+ }
+}
+@media (max-width: 1199.98px) {
+ .table-responsive-xl {
+ display: block;
+ width: 100%;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+ .table-responsive-xl > .table-bordered {
+ border: 0;
+ }
+}
+.table-responsive {
+ display: block;
+ width: 100%;
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+}
+.table-responsive > .table-bordered {
+ border: 0;
+}
+
+.form-control {
+ display: block;
+ width: 100%;
+ height: calc(1.5em + 0.75rem + 2px);
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #495057;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #ced4da;
+ border-radius: 0.25rem;
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+@media (prefers-reduced-motion: reduce) {
+ .form-control {
+ transition: none;
+ }
+}
+.form-control::-ms-expand {
+ background-color: transparent;
+ border: 0;
+}
+.form-control:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #495057;
+}
+.form-control:focus {
+ color: #495057;
+ background-color: #fff;
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.form-control::-webkit-input-placeholder {
+ color: #6c757d;
+ opacity: 1;
+}
+.form-control::-moz-placeholder {
+ color: #6c757d;
+ opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+ color: #6c757d;
+ opacity: 1;
+}
+.form-control::-ms-input-placeholder {
+ color: #6c757d;
+ opacity: 1;
+}
+.form-control::placeholder {
+ color: #6c757d;
+ opacity: 1;
+}
+.form-control:disabled, .form-control[readonly] {
+ background-color: #e9ecef;
+ opacity: 1;
+}
+
+input[type=date].form-control,
+input[type=time].form-control,
+input[type=datetime-local].form-control,
+input[type=month].form-control {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+}
+
+select.form-control:focus::-ms-value {
+ color: #495057;
+ background-color: #fff;
+}
+
+.form-control-file,
+.form-control-range {
+ display: block;
+ width: 100%;
+}
+
+.col-form-label {
+ padding-top: calc(0.375rem + 1px);
+ padding-bottom: calc(0.375rem + 1px);
+ margin-bottom: 0;
+ font-size: inherit;
+ line-height: 1.5;
+}
+
+.col-form-label-lg {
+ padding-top: calc(0.5rem + 1px);
+ padding-bottom: calc(0.5rem + 1px);
+ font-size: 1.25rem;
+ line-height: 1.5;
+}
+
+.col-form-label-sm {
+ padding-top: calc(0.25rem + 1px);
+ padding-bottom: calc(0.25rem + 1px);
+ font-size: 0.875rem;
+ line-height: 1.5;
+}
+
+.form-control-plaintext {
+ display: block;
+ width: 100%;
+ padding: 0.375rem 0;
+ margin-bottom: 0;
+ font-size: 1rem;
+ line-height: 1.5;
+ color: #212529;
+ background-color: transparent;
+ border: solid transparent;
+ border-width: 1px 0;
+}
+.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {
+ padding-right: 0;
+ padding-left: 0;
+}
+
+.form-control-sm {
+ height: calc(1.5em + 0.5rem + 2px);
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.5;
+ border-radius: 0.2rem;
+}
+
+.form-control-lg {
+ height: calc(1.5em + 1rem + 2px);
+ padding: 0.5rem 1rem;
+ font-size: 1.25rem;
+ line-height: 1.5;
+ border-radius: 0.3rem;
+}
+
+select.form-control[size], select.form-control[multiple] {
+ height: auto;
+}
+
+textarea.form-control {
+ height: auto;
+}
+
+.form-group {
+ margin-bottom: 1rem;
+}
+
+.form-text {
+ display: block;
+ margin-top: 0.25rem;
+}
+
+.form-row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -5px;
+ margin-left: -5px;
+}
+.form-row > .col,
+.form-row > [class*=col-] {
+ padding-right: 5px;
+ padding-left: 5px;
+}
+
+.form-check {
+ position: relative;
+ display: block;
+ padding-left: 1.25rem;
+}
+
+.form-check-input {
+ position: absolute;
+ margin-top: 0.3rem;
+ margin-left: -1.25rem;
+}
+.form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label {
+ color: #6c757d;
+}
+
+.form-check-label {
+ margin-bottom: 0;
+}
+
+.form-check-inline {
+ display: inline-flex;
+ align-items: center;
+ padding-left: 0;
+ margin-right: 0.75rem;
+}
+.form-check-inline .form-check-input {
+ position: static;
+ margin-top: 0;
+ margin-right: 0.3125rem;
+ margin-left: 0;
+}
+
+.valid-feedback {
+ display: none;
+ width: 100%;
+ margin-top: 0.25rem;
+ font-size: 80%;
+ color: #28a745;
+}
+
+.valid-tooltip {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 5;
+ display: none;
+ max-width: 100%;
+ padding: 0.25rem 0.5rem;
+ margin-top: 0.1rem;
+ font-size: 0.875rem;
+ line-height: 1.5;
+ color: #fff;
+ background-color: rgba(40, 167, 69, 0.9);
+ border-radius: 0.25rem;
+}
+
+.was-validated :valid ~ .valid-feedback,
+.was-validated :valid ~ .valid-tooltip,
+.is-valid ~ .valid-feedback,
+.is-valid ~ .valid-tooltip {
+ display: block;
+}
+
+.was-validated .form-control:valid, .form-control.is-valid {
+ border-color: #28a745;
+ padding-right: calc(1.5em + 0.75rem);
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");
+ background-repeat: no-repeat;
+ background-position: right calc(0.375em + 0.1875rem) center;
+ background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+}
+.was-validated .form-control:valid:focus, .form-control.is-valid:focus {
+ border-color: #28a745;
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
+}
+
+.was-validated textarea.form-control:valid, textarea.form-control.is-valid {
+ padding-right: calc(1.5em + 0.75rem);
+ background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);
+}
+
+.was-validated .custom-select:valid, .custom-select.is-valid {
+ border-color: #28a745;
+ padding-right: calc(0.75em + 2.3125rem);
+ background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+}
+.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus {
+ border-color: #28a745;
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
+}
+
+.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {
+ color: #28a745;
+}
+.was-validated .form-check-input:valid ~ .valid-feedback,
+.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,
+.form-check-input.is-valid ~ .valid-tooltip {
+ display: block;
+}
+
+.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {
+ color: #28a745;
+}
+.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {
+ border-color: #28a745;
+}
+.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {
+ border-color: #34ce57;
+ background-color: #34ce57;
+}
+.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
+}
+.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before {
+ border-color: #28a745;
+}
+
+.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {
+ border-color: #28a745;
+}
+.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {
+ border-color: #28a745;
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
+}
+
+.invalid-feedback {
+ display: none;
+ width: 100%;
+ margin-top: 0.25rem;
+ font-size: 80%;
+ color: #dc3545;
+}
+
+.invalid-tooltip {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 5;
+ display: none;
+ max-width: 100%;
+ padding: 0.25rem 0.5rem;
+ margin-top: 0.1rem;
+ font-size: 0.875rem;
+ line-height: 1.5;
+ color: #fff;
+ background-color: rgba(220, 53, 69, 0.9);
+ border-radius: 0.25rem;
+}
+
+.was-validated :invalid ~ .invalid-feedback,
+.was-validated :invalid ~ .invalid-tooltip,
+.is-invalid ~ .invalid-feedback,
+.is-invalid ~ .invalid-tooltip {
+ display: block;
+}
+
+.was-validated .form-control:invalid, .form-control.is-invalid {
+ border-color: #dc3545;
+ padding-right: calc(1.5em + 0.75rem);
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");
+ background-repeat: no-repeat;
+ background-position: right calc(0.375em + 0.1875rem) center;
+ background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+}
+.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus {
+ border-color: #dc3545;
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
+}
+
+.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid {
+ padding-right: calc(1.5em + 0.75rem);
+ background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem);
+}
+
+.was-validated .custom-select:invalid, .custom-select.is-invalid {
+ border-color: #dc3545;
+ padding-right: calc(0.75em + 2.3125rem);
+ background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
+}
+.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus {
+ border-color: #dc3545;
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
+}
+
+.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {
+ color: #dc3545;
+}
+.was-validated .form-check-input:invalid ~ .invalid-feedback,
+.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,
+.form-check-input.is-invalid ~ .invalid-tooltip {
+ display: block;
+}
+
+.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {
+ color: #dc3545;
+}
+.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {
+ border-color: #dc3545;
+}
+.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {
+ border-color: #e4606d;
+ background-color: #e4606d;
+}
+.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
+}
+.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before {
+ border-color: #dc3545;
+}
+
+.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {
+ border-color: #dc3545;
+}
+.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {
+ border-color: #dc3545;
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
+}
+
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+}
+.form-inline .form-check {
+ width: 100%;
+}
+@media (min-width: 576px) {
+ .form-inline label {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 0;
+ }
+ .form-inline .form-group {
+ display: flex;
+ flex: 0 0 auto;
+ flex-flow: row wrap;
+ align-items: center;
+ margin-bottom: 0;
+ }
+ .form-inline .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .form-inline .form-control-plaintext {
+ display: inline-block;
+ }
+ .form-inline .input-group,
+.form-inline .custom-select {
+ width: auto;
+ }
+ .form-inline .form-check {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: auto;
+ padding-left: 0;
+ }
+ .form-inline .form-check-input {
+ position: relative;
+ flex-shrink: 0;
+ margin-top: 0;
+ margin-right: 0.25rem;
+ margin-left: 0;
+ }
+ .form-inline .custom-control {
+ align-items: center;
+ justify-content: center;
+ }
+ .form-inline .custom-control-label {
+ margin-bottom: 0;
+ }
+}
+
+.btn {
+ display: inline-block;
+ font-weight: 400;
+ color: #212529;
+ text-align: center;
+ vertical-align: middle;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ line-height: 1.5;
+ border-radius: 0.25rem;
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+@media (prefers-reduced-motion: reduce) {
+ .btn {
+ transition: none;
+ }
+}
+.btn:hover {
+ color: #212529;
+ text-decoration: none;
+}
+.btn:focus, .btn.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.btn.disabled, .btn:disabled {
+ opacity: 0.65;
+}
+.btn:not(:disabled):not(.disabled) {
+ cursor: pointer;
+}
+a.btn.disabled,
+fieldset:disabled a.btn {
+ pointer-events: none;
+}
+
+.btn-primary {
+ color: #fff;
+ background-color: #007bff;
+ border-color: #007bff;
+}
+.btn-primary:hover {
+ color: #fff;
+ background-color: #0069d9;
+ border-color: #0062cc;
+}
+.btn-primary:focus, .btn-primary.focus {
+ color: #fff;
+ background-color: #0069d9;
+ border-color: #0062cc;
+ box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);
+}
+.btn-primary.disabled, .btn-primary:disabled {
+ color: #fff;
+ background-color: #007bff;
+ border-color: #007bff;
+}
+.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle {
+ color: #fff;
+ background-color: #0062cc;
+ border-color: #005cbf;
+}
+.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-primary.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5);
+}
+
+.btn-secondary {
+ color: #fff;
+ background-color: #6c757d;
+ border-color: #6c757d;
+}
+.btn-secondary:hover {
+ color: #fff;
+ background-color: #5a6268;
+ border-color: #545b62;
+}
+.btn-secondary:focus, .btn-secondary.focus {
+ color: #fff;
+ background-color: #5a6268;
+ border-color: #545b62;
+ box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);
+}
+.btn-secondary.disabled, .btn-secondary:disabled {
+ color: #fff;
+ background-color: #6c757d;
+ border-color: #6c757d;
+}
+.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, .show > .btn-secondary.dropdown-toggle {
+ color: #fff;
+ background-color: #545b62;
+ border-color: #4e555b;
+}
+.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-secondary.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5);
+}
+
+.btn-success {
+ color: #fff;
+ background-color: #28a745;
+ border-color: #28a745;
+}
+.btn-success:hover {
+ color: #fff;
+ background-color: #218838;
+ border-color: #1e7e34;
+}
+.btn-success:focus, .btn-success.focus {
+ color: #fff;
+ background-color: #218838;
+ border-color: #1e7e34;
+ box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);
+}
+.btn-success.disabled, .btn-success:disabled {
+ color: #fff;
+ background-color: #28a745;
+ border-color: #28a745;
+}
+.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, .show > .btn-success.dropdown-toggle {
+ color: #fff;
+ background-color: #1e7e34;
+ border-color: #1c7430;
+}
+.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, .show > .btn-success.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5);
+}
+
+.btn-info {
+ color: #fff;
+ background-color: #17a2b8;
+ border-color: #17a2b8;
+}
+.btn-info:hover {
+ color: #fff;
+ background-color: #138496;
+ border-color: #117a8b;
+}
+.btn-info:focus, .btn-info.focus {
+ color: #fff;
+ background-color: #138496;
+ border-color: #117a8b;
+ box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);
+}
+.btn-info.disabled, .btn-info:disabled {
+ color: #fff;
+ background-color: #17a2b8;
+ border-color: #17a2b8;
+}
+.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, .show > .btn-info.dropdown-toggle {
+ color: #fff;
+ background-color: #117a8b;
+ border-color: #10707f;
+}
+.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, .show > .btn-info.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);
+}
+
+.btn-warning {
+ color: #212529;
+ background-color: #ffc107;
+ border-color: #ffc107;
+}
+.btn-warning:hover {
+ color: #212529;
+ background-color: #e0a800;
+ border-color: #d39e00;
+}
+.btn-warning:focus, .btn-warning.focus {
+ color: #212529;
+ background-color: #e0a800;
+ border-color: #d39e00;
+ box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);
+}
+.btn-warning.disabled, .btn-warning:disabled {
+ color: #212529;
+ background-color: #ffc107;
+ border-color: #ffc107;
+}
+.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, .show > .btn-warning.dropdown-toggle {
+ color: #212529;
+ background-color: #d39e00;
+ border-color: #c69500;
+}
+.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-warning.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5);
+}
+
+.btn-danger {
+ color: #fff;
+ background-color: #dc3545;
+ border-color: #dc3545;
+}
+.btn-danger:hover {
+ color: #fff;
+ background-color: #c82333;
+ border-color: #bd2130;
+}
+.btn-danger:focus, .btn-danger.focus {
+ color: #fff;
+ background-color: #c82333;
+ border-color: #bd2130;
+ box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);
+}
+.btn-danger.disabled, .btn-danger:disabled {
+ color: #fff;
+ background-color: #dc3545;
+ border-color: #dc3545;
+}
+.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, .show > .btn-danger.dropdown-toggle {
+ color: #fff;
+ background-color: #bd2130;
+ border-color: #b21f2d;
+}
+.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-danger.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);
+}
+
+.btn-light {
+ color: #212529;
+ background-color: #f8f9fa;
+ border-color: #f8f9fa;
+}
+.btn-light:hover {
+ color: #212529;
+ background-color: #e2e6ea;
+ border-color: #dae0e5;
+}
+.btn-light:focus, .btn-light.focus {
+ color: #212529;
+ background-color: #e2e6ea;
+ border-color: #dae0e5;
+ box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);
+}
+.btn-light.disabled, .btn-light:disabled {
+ color: #212529;
+ background-color: #f8f9fa;
+ border-color: #f8f9fa;
+}
+.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, .show > .btn-light.dropdown-toggle {
+ color: #212529;
+ background-color: #dae0e5;
+ border-color: #d3d9df;
+}
+.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, .show > .btn-light.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5);
+}
+
+.btn-dark {
+ color: #fff;
+ background-color: #343a40;
+ border-color: #343a40;
+}
+.btn-dark:hover {
+ color: #fff;
+ background-color: #23272b;
+ border-color: #1d2124;
+}
+.btn-dark:focus, .btn-dark.focus {
+ color: #fff;
+ background-color: #23272b;
+ border-color: #1d2124;
+ box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);
+}
+.btn-dark.disabled, .btn-dark:disabled {
+ color: #fff;
+ background-color: #343a40;
+ border-color: #343a40;
+}
+.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, .show > .btn-dark.dropdown-toggle {
+ color: #fff;
+ background-color: #1d2124;
+ border-color: #171a1d;
+}
+.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-dark.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5);
+}
+
+.btn-outline-primary {
+ color: #007bff;
+ border-color: #007bff;
+}
+.btn-outline-primary:hover {
+ color: #fff;
+ background-color: #007bff;
+ border-color: #007bff;
+}
+.btn-outline-primary:focus, .btn-outline-primary.focus {
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);
+}
+.btn-outline-primary.disabled, .btn-outline-primary:disabled {
+ color: #007bff;
+ background-color: transparent;
+}
+.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, .show > .btn-outline-primary.dropdown-toggle {
+ color: #fff;
+ background-color: #007bff;
+ border-color: #007bff;
+}
+.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-primary.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);
+}
+
+.btn-outline-secondary {
+ color: #6c757d;
+ border-color: #6c757d;
+}
+.btn-outline-secondary:hover {
+ color: #fff;
+ background-color: #6c757d;
+ border-color: #6c757d;
+}
+.btn-outline-secondary:focus, .btn-outline-secondary.focus {
+ box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);
+}
+.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {
+ color: #6c757d;
+ background-color: transparent;
+}
+.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, .show > .btn-outline-secondary.dropdown-toggle {
+ color: #fff;
+ background-color: #6c757d;
+ border-color: #6c757d;
+}
+.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-secondary.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);
+}
+
+.btn-outline-success {
+ color: #28a745;
+ border-color: #28a745;
+}
+.btn-outline-success:hover {
+ color: #fff;
+ background-color: #28a745;
+ border-color: #28a745;
+}
+.btn-outline-success:focus, .btn-outline-success.focus {
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);
+}
+.btn-outline-success.disabled, .btn-outline-success:disabled {
+ color: #28a745;
+ background-color: transparent;
+}
+.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle {
+ color: #fff;
+ background-color: #28a745;
+ border-color: #28a745;
+}
+.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-success.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);
+}
+
+.btn-outline-info {
+ color: #17a2b8;
+ border-color: #17a2b8;
+}
+.btn-outline-info:hover {
+ color: #fff;
+ background-color: #17a2b8;
+ border-color: #17a2b8;
+}
+.btn-outline-info:focus, .btn-outline-info.focus {
+ box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);
+}
+.btn-outline-info.disabled, .btn-outline-info:disabled {
+ color: #17a2b8;
+ background-color: transparent;
+}
+.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, .show > .btn-outline-info.dropdown-toggle {
+ color: #fff;
+ background-color: #17a2b8;
+ border-color: #17a2b8;
+}
+.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-info.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);
+}
+
+.btn-outline-warning {
+ color: #ffc107;
+ border-color: #ffc107;
+}
+.btn-outline-warning:hover {
+ color: #212529;
+ background-color: #ffc107;
+ border-color: #ffc107;
+}
+.btn-outline-warning:focus, .btn-outline-warning.focus {
+ box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);
+}
+.btn-outline-warning.disabled, .btn-outline-warning:disabled {
+ color: #ffc107;
+ background-color: transparent;
+}
+.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, .show > .btn-outline-warning.dropdown-toggle {
+ color: #212529;
+ background-color: #ffc107;
+ border-color: #ffc107;
+}
+.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-warning.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);
+}
+
+.btn-outline-danger {
+ color: #dc3545;
+ border-color: #dc3545;
+}
+.btn-outline-danger:hover {
+ color: #fff;
+ background-color: #dc3545;
+ border-color: #dc3545;
+}
+.btn-outline-danger:focus, .btn-outline-danger.focus {
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);
+}
+.btn-outline-danger.disabled, .btn-outline-danger:disabled {
+ color: #dc3545;
+ background-color: transparent;
+}
+.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, .show > .btn-outline-danger.dropdown-toggle {
+ color: #fff;
+ background-color: #dc3545;
+ border-color: #dc3545;
+}
+.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-danger.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);
+}
+
+.btn-outline-light {
+ color: #f8f9fa;
+ border-color: #f8f9fa;
+}
+.btn-outline-light:hover {
+ color: #212529;
+ background-color: #f8f9fa;
+ border-color: #f8f9fa;
+}
+.btn-outline-light:focus, .btn-outline-light.focus {
+ box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);
+}
+.btn-outline-light.disabled, .btn-outline-light:disabled {
+ color: #f8f9fa;
+ background-color: transparent;
+}
+.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, .show > .btn-outline-light.dropdown-toggle {
+ color: #212529;
+ background-color: #f8f9fa;
+ border-color: #f8f9fa;
+}
+.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-light.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);
+}
+
+.btn-outline-dark {
+ color: #343a40;
+ border-color: #343a40;
+}
+.btn-outline-dark:hover {
+ color: #fff;
+ background-color: #343a40;
+ border-color: #343a40;
+}
+.btn-outline-dark:focus, .btn-outline-dark.focus {
+ box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);
+}
+.btn-outline-dark.disabled, .btn-outline-dark:disabled {
+ color: #343a40;
+ background-color: transparent;
+}
+.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, .show > .btn-outline-dark.dropdown-toggle {
+ color: #fff;
+ background-color: #343a40;
+ border-color: #343a40;
+}
+.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-dark.dropdown-toggle:focus {
+ box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);
+}
+
+.btn-link {
+ font-weight: 400;
+ color: #007bff;
+ text-decoration: none;
+}
+.btn-link:hover {
+ color: #0056b3;
+ text-decoration: underline;
+}
+.btn-link:focus, .btn-link.focus {
+ text-decoration: underline;
+}
+.btn-link:disabled, .btn-link.disabled {
+ color: #6c757d;
+ pointer-events: none;
+}
+
+.btn-lg, .btn-group-lg > .btn {
+ padding: 0.5rem 1rem;
+ font-size: 1.25rem;
+ line-height: 1.5;
+ border-radius: 0.3rem;
+}
+
+.btn-sm, .btn-group-sm > .btn {
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.5;
+ border-radius: 0.2rem;
+}
+
+.btn-block {
+ display: block;
+ width: 100%;
+}
+.btn-block + .btn-block {
+ margin-top: 0.5rem;
+}
+
+input[type=submit].btn-block,
+input[type=reset].btn-block,
+input[type=button].btn-block {
+ width: 100%;
+}
+
+.fade {
+ transition: opacity 0.15s linear;
+}
+@media (prefers-reduced-motion: reduce) {
+ .fade {
+ transition: none;
+ }
+}
+.fade:not(.show) {
+ opacity: 0;
+}
+
+.collapse:not(.show) {
+ display: none;
+}
+
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ transition: height 0.35s ease;
+}
+@media (prefers-reduced-motion: reduce) {
+ .collapsing {
+ transition: none;
+ }
+}
+
+.dropup,
+.dropright,
+.dropdown,
+.dropleft {
+ position: relative;
+}
+
+.dropdown-toggle {
+ white-space: nowrap;
+}
+.dropdown-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0;
+ border-left: 0.3em solid transparent;
+}
+.dropdown-toggle:empty::after {
+ margin-left: 0;
+}
+
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #212529;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem;
+}
+
+.dropdown-menu-left {
+ right: auto;
+ left: 0;
+}
+
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+
+@media (min-width: 576px) {
+ .dropdown-menu-sm-left {
+ right: auto;
+ left: 0;
+ }
+
+ .dropdown-menu-sm-right {
+ right: 0;
+ left: auto;
+ }
+}
+@media (min-width: 768px) {
+ .dropdown-menu-md-left {
+ right: auto;
+ left: 0;
+ }
+
+ .dropdown-menu-md-right {
+ right: 0;
+ left: auto;
+ }
+}
+@media (min-width: 992px) {
+ .dropdown-menu-lg-left {
+ right: auto;
+ left: 0;
+ }
+
+ .dropdown-menu-lg-right {
+ right: 0;
+ left: auto;
+ }
+}
+@media (min-width: 1200px) {
+ .dropdown-menu-xl-left {
+ right: auto;
+ left: 0;
+ }
+
+ .dropdown-menu-xl-right {
+ right: 0;
+ left: auto;
+ }
+}
+.dropup .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-top: 0;
+ margin-bottom: 0.125rem;
+}
+.dropup .dropdown-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0.3em solid;
+ border-left: 0.3em solid transparent;
+}
+.dropup .dropdown-toggle:empty::after {
+ margin-left: 0;
+}
+
+.dropright .dropdown-menu {
+ top: 0;
+ right: auto;
+ left: 100%;
+ margin-top: 0;
+ margin-left: 0.125rem;
+}
+.dropright .dropdown-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid transparent;
+ border-right: 0;
+ border-bottom: 0.3em solid transparent;
+ border-left: 0.3em solid;
+}
+.dropright .dropdown-toggle:empty::after {
+ margin-left: 0;
+}
+.dropright .dropdown-toggle::after {
+ vertical-align: 0;
+}
+
+.dropleft .dropdown-menu {
+ top: 0;
+ right: 100%;
+ left: auto;
+ margin-top: 0;
+ margin-right: 0.125rem;
+}
+.dropleft .dropdown-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+}
+.dropleft .dropdown-toggle::after {
+ display: none;
+}
+.dropleft .dropdown-toggle::before {
+ display: inline-block;
+ margin-right: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid transparent;
+ border-right: 0.3em solid;
+ border-bottom: 0.3em solid transparent;
+}
+.dropleft .dropdown-toggle:empty::after {
+ margin-left: 0;
+}
+.dropleft .dropdown-toggle::before {
+ vertical-align: 0;
+}
+
+.dropdown-menu[x-placement^=top], .dropdown-menu[x-placement^=right], .dropdown-menu[x-placement^=bottom], .dropdown-menu[x-placement^=left] {
+ right: auto;
+ bottom: auto;
+}
+
+.dropdown-divider {
+ height: 0;
+ margin: 0.5rem 0;
+ overflow: hidden;
+ border-top: 1px solid #e9ecef;
+}
+
+.dropdown-item {
+ display: block;
+ width: 100%;
+ padding: 0.25rem 1.5rem;
+ clear: both;
+ font-weight: 400;
+ color: #212529;
+ text-align: inherit;
+ white-space: nowrap;
+ background-color: transparent;
+ border: 0;
+}
+.dropdown-item:hover, .dropdown-item:focus {
+ color: #16181b;
+ text-decoration: none;
+ background-color: #f8f9fa;
+}
+.dropdown-item.active, .dropdown-item:active {
+ color: #fff;
+ text-decoration: none;
+ background-color: #007bff;
+}
+.dropdown-item.disabled, .dropdown-item:disabled {
+ color: #6c757d;
+ pointer-events: none;
+ background-color: transparent;
+}
+
+.dropdown-menu.show {
+ display: block;
+}
+
+.dropdown-header {
+ display: block;
+ padding: 0.5rem 1.5rem;
+ margin-bottom: 0;
+ font-size: 0.875rem;
+ color: #6c757d;
+ white-space: nowrap;
+}
+
+.dropdown-item-text {
+ display: block;
+ padding: 0.25rem 1.5rem;
+ color: #212529;
+}
+
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-flex;
+ vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+ position: relative;
+ flex: 1 1 auto;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover {
+ z-index: 1;
+}
+.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+.btn-group-vertical > .btn:focus,
+.btn-group-vertical > .btn:active,
+.btn-group-vertical > .btn.active {
+ z-index: 1;
+}
+
+.btn-toolbar {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+}
+.btn-toolbar .input-group {
+ width: auto;
+}
+
+.btn-group > .btn:not(:first-child),
+.btn-group > .btn-group:not(:first-child) {
+ margin-left: -1px;
+}
+.btn-group > .btn:not(:last-child):not(.dropdown-toggle),
+.btn-group > .btn-group:not(:last-child) > .btn {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.btn-group > .btn:not(:first-child),
+.btn-group > .btn-group:not(:first-child) > .btn {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+
+.dropdown-toggle-split {
+ padding-right: 0.5625rem;
+ padding-left: 0.5625rem;
+}
+.dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropright .dropdown-toggle-split::after {
+ margin-left: 0;
+}
+.dropleft .dropdown-toggle-split::before {
+ margin-right: 0;
+}
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+ padding-right: 0.375rem;
+ padding-left: 0.375rem;
+}
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+ padding-right: 0.75rem;
+ padding-left: 0.75rem;
+}
+
+.btn-group-vertical {
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: center;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group {
+ width: 100%;
+}
+.btn-group-vertical > .btn:not(:first-child),
+.btn-group-vertical > .btn-group:not(:first-child) {
+ margin-top: -1px;
+}
+.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),
+.btn-group-vertical > .btn-group:not(:last-child) > .btn {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:not(:first-child),
+.btn-group-vertical > .btn-group:not(:first-child) > .btn {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+
+.btn-group-toggle > .btn,
+.btn-group-toggle > .btn-group > .btn {
+ margin-bottom: 0;
+}
+.btn-group-toggle > .btn input[type=radio],
+.btn-group-toggle > .btn input[type=checkbox],
+.btn-group-toggle > .btn-group > .btn input[type=radio],
+.btn-group-toggle > .btn-group > .btn input[type=checkbox] {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none;
+}
+
+.input-group {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: stretch;
+ width: 100%;
+}
+.input-group > .form-control,
+.input-group > .form-control-plaintext,
+.input-group > .custom-select,
+.input-group > .custom-file {
+ position: relative;
+ flex: 1 1 auto;
+ width: 1%;
+ min-width: 0;
+ margin-bottom: 0;
+}
+.input-group > .form-control + .form-control,
+.input-group > .form-control + .custom-select,
+.input-group > .form-control + .custom-file,
+.input-group > .form-control-plaintext + .form-control,
+.input-group > .form-control-plaintext + .custom-select,
+.input-group > .form-control-plaintext + .custom-file,
+.input-group > .custom-select + .form-control,
+.input-group > .custom-select + .custom-select,
+.input-group > .custom-select + .custom-file,
+.input-group > .custom-file + .form-control,
+.input-group > .custom-file + .custom-select,
+.input-group > .custom-file + .custom-file {
+ margin-left: -1px;
+}
+.input-group > .form-control:focus,
+.input-group > .custom-select:focus,
+.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {
+ z-index: 3;
+}
+.input-group > .custom-file .custom-file-input:focus {
+ z-index: 4;
+}
+.input-group > .form-control:not(:last-child),
+.input-group > .custom-select:not(:last-child) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.input-group > .form-control:not(:first-child),
+.input-group > .custom-select:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.input-group > .custom-file {
+ display: flex;
+ align-items: center;
+}
+.input-group > .custom-file:not(:last-child) .custom-file-label, .input-group > .custom-file:not(:last-child) .custom-file-label::after {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.input-group > .custom-file:not(:first-child) .custom-file-label {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+
+.input-group-prepend,
+.input-group-append {
+ display: flex;
+}
+.input-group-prepend .btn,
+.input-group-append .btn {
+ position: relative;
+ z-index: 2;
+}
+.input-group-prepend .btn:focus,
+.input-group-append .btn:focus {
+ z-index: 3;
+}
+.input-group-prepend .btn + .btn,
+.input-group-prepend .btn + .input-group-text,
+.input-group-prepend .input-group-text + .input-group-text,
+.input-group-prepend .input-group-text + .btn,
+.input-group-append .btn + .btn,
+.input-group-append .btn + .input-group-text,
+.input-group-append .input-group-text + .input-group-text,
+.input-group-append .input-group-text + .btn {
+ margin-left: -1px;
+}
+
+.input-group-prepend {
+ margin-right: -1px;
+}
+
+.input-group-append {
+ margin-left: -1px;
+}
+
+.input-group-text {
+ display: flex;
+ align-items: center;
+ padding: 0.375rem 0.75rem;
+ margin-bottom: 0;
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #495057;
+ text-align: center;
+ white-space: nowrap;
+ background-color: #e9ecef;
+ border: 1px solid #ced4da;
+ border-radius: 0.25rem;
+}
+.input-group-text input[type=radio],
+.input-group-text input[type=checkbox] {
+ margin-top: 0;
+}
+
+.input-group-lg > .form-control:not(textarea),
+.input-group-lg > .custom-select {
+ height: calc(1.5em + 1rem + 2px);
+}
+
+.input-group-lg > .form-control,
+.input-group-lg > .custom-select,
+.input-group-lg > .input-group-prepend > .input-group-text,
+.input-group-lg > .input-group-append > .input-group-text,
+.input-group-lg > .input-group-prepend > .btn,
+.input-group-lg > .input-group-append > .btn {
+ padding: 0.5rem 1rem;
+ font-size: 1.25rem;
+ line-height: 1.5;
+ border-radius: 0.3rem;
+}
+
+.input-group-sm > .form-control:not(textarea),
+.input-group-sm > .custom-select {
+ height: calc(1.5em + 0.5rem + 2px);
+}
+
+.input-group-sm > .form-control,
+.input-group-sm > .custom-select,
+.input-group-sm > .input-group-prepend > .input-group-text,
+.input-group-sm > .input-group-append > .input-group-text,
+.input-group-sm > .input-group-prepend > .btn,
+.input-group-sm > .input-group-append > .btn {
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.5;
+ border-radius: 0.2rem;
+}
+
+.input-group-lg > .custom-select,
+.input-group-sm > .custom-select {
+ padding-right: 1.75rem;
+}
+
+.input-group > .input-group-prepend > .btn,
+.input-group > .input-group-prepend > .input-group-text,
+.input-group > .input-group-append:not(:last-child) > .btn,
+.input-group > .input-group-append:not(:last-child) > .input-group-text,
+.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+
+.input-group > .input-group-append > .btn,
+.input-group > .input-group-append > .input-group-text,
+.input-group > .input-group-prepend:not(:first-child) > .btn,
+.input-group > .input-group-prepend:not(:first-child) > .input-group-text,
+.input-group > .input-group-prepend:first-child > .btn:not(:first-child),
+.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+
+.custom-control {
+ position: relative;
+ z-index: 1;
+ display: block;
+ min-height: 1.5rem;
+ padding-left: 1.5rem;
+ -webkit-print-color-adjust: exact;
+ color-adjust: exact;
+}
+
+.custom-control-inline {
+ display: inline-flex;
+ margin-right: 1rem;
+}
+
+.custom-control-input {
+ position: absolute;
+ left: 0;
+ z-index: -1;
+ width: 1rem;
+ height: 1.25rem;
+ opacity: 0;
+}
+.custom-control-input:checked ~ .custom-control-label::before {
+ color: #fff;
+ border-color: #007bff;
+ background-color: #007bff;
+}
+.custom-control-input:focus ~ .custom-control-label::before {
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.custom-control-input:focus:not(:checked) ~ .custom-control-label::before {
+ border-color: #80bdff;
+}
+.custom-control-input:not(:disabled):active ~ .custom-control-label::before {
+ color: #fff;
+ background-color: #b3d7ff;
+ border-color: #b3d7ff;
+}
+.custom-control-input[disabled] ~ .custom-control-label, .custom-control-input:disabled ~ .custom-control-label {
+ color: #6c757d;
+}
+.custom-control-input[disabled] ~ .custom-control-label::before, .custom-control-input:disabled ~ .custom-control-label::before {
+ background-color: #e9ecef;
+}
+
+.custom-control-label {
+ position: relative;
+ margin-bottom: 0;
+ vertical-align: top;
+}
+.custom-control-label::before {
+ position: absolute;
+ top: 0.25rem;
+ left: -1.5rem;
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ pointer-events: none;
+ content: "";
+ background-color: #fff;
+ border: #adb5bd solid 1px;
+}
+.custom-control-label::after {
+ position: absolute;
+ top: 0.25rem;
+ left: -1.5rem;
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ content: "";
+ background: no-repeat 50%/50% 50%;
+}
+
+.custom-checkbox .custom-control-label::before {
+ border-radius: 0.25rem;
+}
+.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e");
+}
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {
+ border-color: #007bff;
+ background-color: #007bff;
+}
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e");
+}
+.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {
+ background-color: rgba(0, 123, 255, 0.5);
+}
+.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {
+ background-color: rgba(0, 123, 255, 0.5);
+}
+
+.custom-radio .custom-control-label::before {
+ border-radius: 50%;
+}
+.custom-radio .custom-control-input:checked ~ .custom-control-label::after {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
+}
+.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {
+ background-color: rgba(0, 123, 255, 0.5);
+}
+
+.custom-switch {
+ padding-left: 2.25rem;
+}
+.custom-switch .custom-control-label::before {
+ left: -2.25rem;
+ width: 1.75rem;
+ pointer-events: all;
+ border-radius: 0.5rem;
+}
+.custom-switch .custom-control-label::after {
+ top: calc(0.25rem + 2px);
+ left: calc(-2.25rem + 2px);
+ width: calc(1rem - 4px);
+ height: calc(1rem - 4px);
+ background-color: #adb5bd;
+ border-radius: 0.5rem;
+ transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+@media (prefers-reduced-motion: reduce) {
+ .custom-switch .custom-control-label::after {
+ transition: none;
+ }
+}
+.custom-switch .custom-control-input:checked ~ .custom-control-label::after {
+ background-color: #fff;
+ transform: translateX(0.75rem);
+}
+.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before {
+ background-color: rgba(0, 123, 255, 0.5);
+}
+
+.custom-select {
+ display: inline-block;
+ width: 100%;
+ height: calc(1.5em + 0.75rem + 2px);
+ padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #495057;
+ vertical-align: middle;
+ background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px;
+ border: 1px solid #ced4da;
+ border-radius: 0.25rem;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+}
+.custom-select:focus {
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.custom-select:focus::-ms-value {
+ color: #495057;
+ background-color: #fff;
+}
+.custom-select[multiple], .custom-select[size]:not([size="1"]) {
+ height: auto;
+ padding-right: 0.75rem;
+ background-image: none;
+}
+.custom-select:disabled {
+ color: #6c757d;
+ background-color: #e9ecef;
+}
+.custom-select::-ms-expand {
+ display: none;
+}
+.custom-select:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #495057;
+}
+
+.custom-select-sm {
+ height: calc(1.5em + 0.5rem + 2px);
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ padding-left: 0.5rem;
+ font-size: 0.875rem;
+}
+
+.custom-select-lg {
+ height: calc(1.5em + 1rem + 2px);
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ padding-left: 1rem;
+ font-size: 1.25rem;
+}
+
+.custom-file {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ height: calc(1.5em + 0.75rem + 2px);
+ margin-bottom: 0;
+}
+
+.custom-file-input {
+ position: relative;
+ z-index: 2;
+ width: 100%;
+ height: calc(1.5em + 0.75rem + 2px);
+ margin: 0;
+ opacity: 0;
+}
+.custom-file-input:focus ~ .custom-file-label {
+ border-color: #80bdff;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.custom-file-input[disabled] ~ .custom-file-label, .custom-file-input:disabled ~ .custom-file-label {
+ background-color: #e9ecef;
+}
+.custom-file-input:lang(en) ~ .custom-file-label::after {
+ content: "Browse";
+}
+.custom-file-input ~ .custom-file-label[data-browse]::after {
+ content: attr(data-browse);
+}
+
+.custom-file-label {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1;
+ height: calc(1.5em + 0.75rem + 2px);
+ padding: 0.375rem 0.75rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #495057;
+ background-color: #fff;
+ border: 1px solid #ced4da;
+ border-radius: 0.25rem;
+}
+.custom-file-label::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 3;
+ display: block;
+ height: calc(1.5em + 0.75rem);
+ padding: 0.375rem 0.75rem;
+ line-height: 1.5;
+ color: #495057;
+ content: "Browse";
+ background-color: #e9ecef;
+ border-left: inherit;
+ border-radius: 0 0.25rem 0.25rem 0;
+}
+
+.custom-range {
+ width: 100%;
+ height: 1.4rem;
+ padding: 0;
+ background-color: transparent;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+}
+.custom-range:focus {
+ outline: none;
+}
+.custom-range:focus::-webkit-slider-thumb {
+ box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.custom-range:focus::-moz-range-thumb {
+ box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.custom-range:focus::-ms-thumb {
+ box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.custom-range::-moz-focus-outer {
+ border: 0;
+}
+.custom-range::-webkit-slider-thumb {
+ width: 1rem;
+ height: 1rem;
+ margin-top: -0.25rem;
+ background-color: #007bff;
+ border: 0;
+ border-radius: 1rem;
+ -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ -webkit-appearance: none;
+ appearance: none;
+}
+@media (prefers-reduced-motion: reduce) {
+ .custom-range::-webkit-slider-thumb {
+ -webkit-transition: none;
+ transition: none;
+ }
+}
+.custom-range::-webkit-slider-thumb:active {
+ background-color: #b3d7ff;
+}
+.custom-range::-webkit-slider-runnable-track {
+ width: 100%;
+ height: 0.5rem;
+ color: transparent;
+ cursor: pointer;
+ background-color: #dee2e6;
+ border-color: transparent;
+ border-radius: 1rem;
+}
+.custom-range::-moz-range-thumb {
+ width: 1rem;
+ height: 1rem;
+ background-color: #007bff;
+ border: 0;
+ border-radius: 1rem;
+ -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ -moz-appearance: none;
+ appearance: none;
+}
+@media (prefers-reduced-motion: reduce) {
+ .custom-range::-moz-range-thumb {
+ -moz-transition: none;
+ transition: none;
+ }
+}
+.custom-range::-moz-range-thumb:active {
+ background-color: #b3d7ff;
+}
+.custom-range::-moz-range-track {
+ width: 100%;
+ height: 0.5rem;
+ color: transparent;
+ cursor: pointer;
+ background-color: #dee2e6;
+ border-color: transparent;
+ border-radius: 1rem;
+}
+.custom-range::-ms-thumb {
+ width: 1rem;
+ height: 1rem;
+ margin-top: 0;
+ margin-right: 0.2rem;
+ margin-left: 0.2rem;
+ background-color: #007bff;
+ border: 0;
+ border-radius: 1rem;
+ -ms-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ appearance: none;
+}
+@media (prefers-reduced-motion: reduce) {
+ .custom-range::-ms-thumb {
+ -ms-transition: none;
+ transition: none;
+ }
+}
+.custom-range::-ms-thumb:active {
+ background-color: #b3d7ff;
+}
+.custom-range::-ms-track {
+ width: 100%;
+ height: 0.5rem;
+ color: transparent;
+ cursor: pointer;
+ background-color: transparent;
+ border-color: transparent;
+ border-width: 0.5rem;
+}
+.custom-range::-ms-fill-lower {
+ background-color: #dee2e6;
+ border-radius: 1rem;
+}
+.custom-range::-ms-fill-upper {
+ margin-right: 15px;
+ background-color: #dee2e6;
+ border-radius: 1rem;
+}
+.custom-range:disabled::-webkit-slider-thumb {
+ background-color: #adb5bd;
+}
+.custom-range:disabled::-webkit-slider-runnable-track {
+ cursor: default;
+}
+.custom-range:disabled::-moz-range-thumb {
+ background-color: #adb5bd;
+}
+.custom-range:disabled::-moz-range-track {
+ cursor: default;
+}
+.custom-range:disabled::-ms-thumb {
+ background-color: #adb5bd;
+}
+
+.custom-control-label::before,
+.custom-file-label,
+.custom-select {
+ transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+@media (prefers-reduced-motion: reduce) {
+ .custom-control-label::before,
+.custom-file-label,
+.custom-select {
+ transition: none;
+ }
+}
+
+.nav {
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+
+.nav-link {
+ display: block;
+ padding: 0.5rem 1rem;
+}
+.nav-link:hover, .nav-link:focus {
+ text-decoration: none;
+}
+.nav-link.disabled {
+ color: #6c757d;
+ pointer-events: none;
+ cursor: default;
+}
+
+.nav-tabs {
+ border-bottom: 1px solid #dee2e6;
+}
+.nav-tabs .nav-item {
+ margin-bottom: -1px;
+}
+.nav-tabs .nav-link {
+ border: 1px solid transparent;
+ border-top-left-radius: 0.25rem;
+ border-top-right-radius: 0.25rem;
+}
+.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {
+ border-color: #e9ecef #e9ecef #dee2e6;
+}
+.nav-tabs .nav-link.disabled {
+ color: #6c757d;
+ background-color: transparent;
+ border-color: transparent;
+}
+.nav-tabs .nav-link.active,
+.nav-tabs .nav-item.show .nav-link {
+ color: #495057;
+ background-color: #fff;
+ border-color: #dee2e6 #dee2e6 #fff;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+
+.nav-pills .nav-link {
+ border-radius: 0.25rem;
+}
+.nav-pills .nav-link.active,
+.nav-pills .show > .nav-link {
+ color: #fff;
+ background-color: #007bff;
+}
+
+.nav-fill > .nav-link,
+.nav-fill .nav-item {
+ flex: 1 1 auto;
+ text-align: center;
+}
+
+.nav-justified > .nav-link,
+.nav-justified .nav-item {
+ flex-basis: 0;
+ flex-grow: 1;
+ text-align: center;
+}
+
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+
+.navbar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.5rem 1rem;
+}
+.navbar .container,
+.navbar .container-fluid,
+.navbar .container-sm,
+.navbar .container-md,
+.navbar .container-lg,
+.navbar .container-xl {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
+.navbar-brand {
+ display: inline-block;
+ padding-top: 0.3125rem;
+ padding-bottom: 0.3125rem;
+ margin-right: 1rem;
+ font-size: 1.25rem;
+ line-height: inherit;
+ white-space: nowrap;
+}
+.navbar-brand:hover, .navbar-brand:focus {
+ text-decoration: none;
+}
+
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar-nav .nav-link {
+ padding-right: 0;
+ padding-left: 0;
+}
+.navbar-nav .dropdown-menu {
+ position: static;
+ float: none;
+}
+
+.navbar-text {
+ display: inline-block;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+}
+
+.navbar-collapse {
+ flex-basis: 100%;
+ flex-grow: 1;
+ align-items: center;
+}
+
+.navbar-toggler {
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+.navbar-toggler:hover, .navbar-toggler:focus {
+ text-decoration: none;
+}
+
+.navbar-toggler-icon {
+ display: inline-block;
+ width: 1.5em;
+ height: 1.5em;
+ vertical-align: middle;
+ content: "";
+ background: no-repeat center center;
+ background-size: 100% 100%;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-expand-sm > .container,
+.navbar-expand-sm > .container-fluid,
+.navbar-expand-sm > .container-sm,
+.navbar-expand-sm > .container-md,
+.navbar-expand-sm > .container-lg,
+.navbar-expand-sm > .container-xl {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+@media (min-width: 576px) {
+ .navbar-expand-sm {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-sm .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-sm .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-sm .navbar-nav .nav-link {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ }
+ .navbar-expand-sm > .container,
+.navbar-expand-sm > .container-fluid,
+.navbar-expand-sm > .container-sm,
+.navbar-expand-sm > .container-md,
+.navbar-expand-sm > .container-lg,
+.navbar-expand-sm > .container-xl {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-sm .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-sm .navbar-toggler {
+ display: none;
+ }
+}
+@media (max-width: 767.98px) {
+ .navbar-expand-md > .container,
+.navbar-expand-md > .container-fluid,
+.navbar-expand-md > .container-sm,
+.navbar-expand-md > .container-md,
+.navbar-expand-md > .container-lg,
+.navbar-expand-md > .container-xl {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-expand-md {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-md .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-md .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-md .navbar-nav .nav-link {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ }
+ .navbar-expand-md > .container,
+.navbar-expand-md > .container-fluid,
+.navbar-expand-md > .container-sm,
+.navbar-expand-md > .container-md,
+.navbar-expand-md > .container-lg,
+.navbar-expand-md > .container-xl {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-md .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-md .navbar-toggler {
+ display: none;
+ }
+}
+@media (max-width: 991.98px) {
+ .navbar-expand-lg > .container,
+.navbar-expand-lg > .container-fluid,
+.navbar-expand-lg > .container-sm,
+.navbar-expand-lg > .container-md,
+.navbar-expand-lg > .container-lg,
+.navbar-expand-lg > .container-xl {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+@media (min-width: 992px) {
+ .navbar-expand-lg {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-lg .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-lg .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-lg .navbar-nav .nav-link {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ }
+ .navbar-expand-lg > .container,
+.navbar-expand-lg > .container-fluid,
+.navbar-expand-lg > .container-sm,
+.navbar-expand-lg > .container-md,
+.navbar-expand-lg > .container-lg,
+.navbar-expand-lg > .container-xl {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-lg .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-lg .navbar-toggler {
+ display: none;
+ }
+}
+@media (max-width: 1199.98px) {
+ .navbar-expand-xl > .container,
+.navbar-expand-xl > .container-fluid,
+.navbar-expand-xl > .container-sm,
+.navbar-expand-xl > .container-md,
+.navbar-expand-xl > .container-lg,
+.navbar-expand-xl > .container-xl {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+@media (min-width: 1200px) {
+ .navbar-expand-xl {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-xl .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-xl .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-xl .navbar-nav .nav-link {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ }
+ .navbar-expand-xl > .container,
+.navbar-expand-xl > .container-fluid,
+.navbar-expand-xl > .container-sm,
+.navbar-expand-xl > .container-md,
+.navbar-expand-xl > .container-lg,
+.navbar-expand-xl > .container-xl {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-xl .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-xl .navbar-toggler {
+ display: none;
+ }
+}
+.navbar-expand {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+}
+.navbar-expand > .container,
+.navbar-expand > .container-fluid,
+.navbar-expand > .container-sm,
+.navbar-expand > .container-md,
+.navbar-expand > .container-lg,
+.navbar-expand > .container-xl {
+ padding-right: 0;
+ padding-left: 0;
+}
+.navbar-expand .navbar-nav {
+ flex-direction: row;
+}
+.navbar-expand .navbar-nav .dropdown-menu {
+ position: absolute;
+}
+.navbar-expand .navbar-nav .nav-link {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+}
+.navbar-expand > .container,
+.navbar-expand > .container-fluid,
+.navbar-expand > .container-sm,
+.navbar-expand > .container-md,
+.navbar-expand > .container-lg,
+.navbar-expand > .container-xl {
+ flex-wrap: nowrap;
+}
+.navbar-expand .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+}
+.navbar-expand .navbar-toggler {
+ display: none;
+}
+
+.navbar-light .navbar-brand {
+ color: rgba(0, 0, 0, 0.9);
+}
+.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {
+ color: rgba(0, 0, 0, 0.9);
+}
+.navbar-light .navbar-nav .nav-link {
+ color: rgba(0, 0, 0, 0.5);
+}
+.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {
+ color: rgba(0, 0, 0, 0.7);
+}
+.navbar-light .navbar-nav .nav-link.disabled {
+ color: rgba(0, 0, 0, 0.3);
+}
+.navbar-light .navbar-nav .show > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .nav-link.show,
+.navbar-light .navbar-nav .nav-link.active {
+ color: rgba(0, 0, 0, 0.9);
+}
+.navbar-light .navbar-toggler {
+ color: rgba(0, 0, 0, 0.5);
+ border-color: rgba(0, 0, 0, 0.1);
+}
+.navbar-light .navbar-toggler-icon {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
+}
+.navbar-light .navbar-text {
+ color: rgba(0, 0, 0, 0.5);
+}
+.navbar-light .navbar-text a {
+ color: rgba(0, 0, 0, 0.9);
+}
+.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {
+ color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-dark .navbar-brand {
+ color: #fff;
+}
+.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {
+ color: #fff;
+}
+.navbar-dark .navbar-nav .nav-link {
+ color: rgba(255, 255, 255, 0.5);
+}
+.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {
+ color: rgba(255, 255, 255, 0.75);
+}
+.navbar-dark .navbar-nav .nav-link.disabled {
+ color: rgba(255, 255, 255, 0.25);
+}
+.navbar-dark .navbar-nav .show > .nav-link,
+.navbar-dark .navbar-nav .active > .nav-link,
+.navbar-dark .navbar-nav .nav-link.show,
+.navbar-dark .navbar-nav .nav-link.active {
+ color: #fff;
+}
+.navbar-dark .navbar-toggler {
+ color: rgba(255, 255, 255, 0.5);
+ border-color: rgba(255, 255, 255, 0.1);
+}
+.navbar-dark .navbar-toggler-icon {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
+}
+.navbar-dark .navbar-text {
+ color: rgba(255, 255, 255, 0.5);
+}
+.navbar-dark .navbar-text a {
+ color: #fff;
+}
+.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {
+ color: #fff;
+}
+
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: border-box;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 0.25rem;
+}
+.card > hr {
+ margin-right: 0;
+ margin-left: 0;
+}
+.card > .list-group {
+ border-top: inherit;
+ border-bottom: inherit;
+}
+.card > .list-group:first-child {
+ border-top-width: 0;
+ border-top-left-radius: calc(0.25rem - 1px);
+ border-top-right-radius: calc(0.25rem - 1px);
+}
+.card > .list-group:last-child {
+ border-bottom-width: 0;
+ border-bottom-right-radius: calc(0.25rem - 1px);
+ border-bottom-left-radius: calc(0.25rem - 1px);
+}
+.card > .card-header + .list-group,
+.card > .list-group + .card-footer {
+ border-top: 0;
+}
+
+.card-body {
+ flex: 1 1 auto;
+ min-height: 1px;
+ padding: 1.25rem;
+}
+
+.card-title {
+ margin-bottom: 0.75rem;
+}
+
+.card-subtitle {
+ margin-top: -0.375rem;
+ margin-bottom: 0;
+}
+
+.card-text:last-child {
+ margin-bottom: 0;
+}
+
+.card-link:hover {
+ text-decoration: none;
+}
+.card-link + .card-link {
+ margin-left: 1.25rem;
+}
+
+.card-header {
+ padding: 0.75rem 1.25rem;
+ margin-bottom: 0;
+ background-color: rgba(0, 0, 0, 0.03);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+.card-header:first-child {
+ border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
+}
+
+.card-footer {
+ padding: 0.75rem 1.25rem;
+ background-color: rgba(0, 0, 0, 0.03);
+ border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+.card-footer:last-child {
+ border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);
+}
+
+.card-header-tabs {
+ margin-right: -0.625rem;
+ margin-bottom: -0.75rem;
+ margin-left: -0.625rem;
+ border-bottom: 0;
+}
+
+.card-header-pills {
+ margin-right: -0.625rem;
+ margin-left: -0.625rem;
+}
+
+.card-img-overlay {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 1.25rem;
+ border-radius: calc(0.25rem - 1px);
+}
+
+.card-img,
+.card-img-top,
+.card-img-bottom {
+ flex-shrink: 0;
+ width: 100%;
+}
+
+.card-img,
+.card-img-top {
+ border-top-left-radius: calc(0.25rem - 1px);
+ border-top-right-radius: calc(0.25rem - 1px);
+}
+
+.card-img,
+.card-img-bottom {
+ border-bottom-right-radius: calc(0.25rem - 1px);
+ border-bottom-left-radius: calc(0.25rem - 1px);
+}
+
+.card-deck .card {
+ margin-bottom: 15px;
+}
+@media (min-width: 576px) {
+ .card-deck {
+ display: flex;
+ flex-flow: row wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+ }
+ .card-deck .card {
+ flex: 1 0 0%;
+ margin-right: 15px;
+ margin-bottom: 0;
+ margin-left: 15px;
+ }
+}
+
+.card-group > .card {
+ margin-bottom: 15px;
+}
+@media (min-width: 576px) {
+ .card-group {
+ display: flex;
+ flex-flow: row wrap;
+ }
+ .card-group > .card {
+ flex: 1 0 0%;
+ margin-bottom: 0;
+ }
+ .card-group > .card + .card {
+ margin-left: 0;
+ border-left: 0;
+ }
+ .card-group > .card:not(:last-child) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+ .card-group > .card:not(:last-child) .card-img-top,
+.card-group > .card:not(:last-child) .card-header {
+ border-top-right-radius: 0;
+ }
+ .card-group > .card:not(:last-child) .card-img-bottom,
+.card-group > .card:not(:last-child) .card-footer {
+ border-bottom-right-radius: 0;
+ }
+ .card-group > .card:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+ .card-group > .card:not(:first-child) .card-img-top,
+.card-group > .card:not(:first-child) .card-header {
+ border-top-left-radius: 0;
+ }
+ .card-group > .card:not(:first-child) .card-img-bottom,
+.card-group > .card:not(:first-child) .card-footer {
+ border-bottom-left-radius: 0;
+ }
+}
+
+.card-columns .card {
+ margin-bottom: 0.75rem;
+}
+@media (min-width: 576px) {
+ .card-columns {
+ -moz-column-count: 3;
+ column-count: 3;
+ -moz-column-gap: 1.25rem;
+ column-gap: 1.25rem;
+ orphans: 1;
+ widows: 1;
+ }
+ .card-columns .card {
+ display: inline-block;
+ width: 100%;
+ }
+}
+
+.accordion {
+ overflow-anchor: none;
+}
+.accordion > .card {
+ overflow: hidden;
+}
+.accordion > .card:not(:last-of-type) {
+ border-bottom: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.accordion > .card:not(:first-of-type) {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.accordion > .card > .card-header {
+ border-radius: 0;
+ margin-bottom: -1px;
+}
+
+.breadcrumb {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 0.75rem 1rem;
+ margin-bottom: 1rem;
+ list-style: none;
+ background-color: #e9ecef;
+ border-radius: 0.25rem;
+}
+
+.breadcrumb-item {
+ display: flex;
+}
+.breadcrumb-item + .breadcrumb-item {
+ padding-left: 0.5rem;
+}
+.breadcrumb-item + .breadcrumb-item::before {
+ display: inline-block;
+ padding-right: 0.5rem;
+ color: #6c757d;
+ content: "/";
+}
+.breadcrumb-item + .breadcrumb-item:hover::before {
+ text-decoration: underline;
+}
+.breadcrumb-item + .breadcrumb-item:hover::before {
+ text-decoration: none;
+}
+.breadcrumb-item.active {
+ color: #6c757d;
+}
+
+.pagination {
+ display: flex;
+ padding-left: 0;
+ list-style: none;
+ border-radius: 0.25rem;
+}
+
+.page-link {
+ position: relative;
+ display: block;
+ padding: 0.5rem 0.75rem;
+ margin-left: -1px;
+ line-height: 1.25;
+ color: #007bff;
+ background-color: #fff;
+ border: 1px solid #dee2e6;
+}
+.page-link:hover {
+ z-index: 2;
+ color: #0056b3;
+ text-decoration: none;
+ background-color: #e9ecef;
+ border-color: #dee2e6;
+}
+.page-link:focus {
+ z-index: 3;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+
+.page-item:first-child .page-link {
+ margin-left: 0;
+ border-top-left-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem;
+}
+.page-item:last-child .page-link {
+ border-top-right-radius: 0.25rem;
+ border-bottom-right-radius: 0.25rem;
+}
+.page-item.active .page-link {
+ z-index: 3;
+ color: #fff;
+ background-color: #007bff;
+ border-color: #007bff;
+}
+.page-item.disabled .page-link {
+ color: #6c757d;
+ pointer-events: none;
+ cursor: auto;
+ background-color: #fff;
+ border-color: #dee2e6;
+}
+
+.pagination-lg .page-link {
+ padding: 0.75rem 1.5rem;
+ font-size: 1.25rem;
+ line-height: 1.5;
+}
+.pagination-lg .page-item:first-child .page-link {
+ border-top-left-radius: 0.3rem;
+ border-bottom-left-radius: 0.3rem;
+}
+.pagination-lg .page-item:last-child .page-link {
+ border-top-right-radius: 0.3rem;
+ border-bottom-right-radius: 0.3rem;
+}
+
+.pagination-sm .page-link {
+ padding: 0.25rem 0.5rem;
+ font-size: 0.875rem;
+ line-height: 1.5;
+}
+.pagination-sm .page-item:first-child .page-link {
+ border-top-left-radius: 0.2rem;
+ border-bottom-left-radius: 0.2rem;
+}
+.pagination-sm .page-item:last-child .page-link {
+ border-top-right-radius: 0.2rem;
+ border-bottom-right-radius: 0.2rem;
+}
+
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: 700;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+@media (prefers-reduced-motion: reduce) {
+ .badge {
+ transition: none;
+ }
+}
+a.badge:hover, a.badge:focus {
+ text-decoration: none;
+}
+
+.badge:empty {
+ display: none;
+}
+
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+
+.badge-primary {
+ color: #fff;
+ background-color: #007bff;
+}
+a.badge-primary:hover, a.badge-primary:focus {
+ color: #fff;
+ background-color: #0062cc;
+}
+a.badge-primary:focus, a.badge-primary.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);
+}
+
+.badge-secondary {
+ color: #fff;
+ background-color: #6c757d;
+}
+a.badge-secondary:hover, a.badge-secondary:focus {
+ color: #fff;
+ background-color: #545b62;
+}
+a.badge-secondary:focus, a.badge-secondary.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);
+}
+
+.badge-success {
+ color: #fff;
+ background-color: #28a745;
+}
+a.badge-success:hover, a.badge-success:focus {
+ color: #fff;
+ background-color: #1e7e34;
+}
+a.badge-success:focus, a.badge-success.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);
+}
+
+.badge-info {
+ color: #fff;
+ background-color: #17a2b8;
+}
+a.badge-info:hover, a.badge-info:focus {
+ color: #fff;
+ background-color: #117a8b;
+}
+a.badge-info:focus, a.badge-info.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);
+}
+
+.badge-warning {
+ color: #212529;
+ background-color: #ffc107;
+}
+a.badge-warning:hover, a.badge-warning:focus {
+ color: #212529;
+ background-color: #d39e00;
+}
+a.badge-warning:focus, a.badge-warning.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);
+}
+
+.badge-danger {
+ color: #fff;
+ background-color: #dc3545;
+}
+a.badge-danger:hover, a.badge-danger:focus {
+ color: #fff;
+ background-color: #bd2130;
+}
+a.badge-danger:focus, a.badge-danger.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);
+}
+
+.badge-light {
+ color: #212529;
+ background-color: #f8f9fa;
+}
+a.badge-light:hover, a.badge-light:focus {
+ color: #212529;
+ background-color: #dae0e5;
+}
+a.badge-light:focus, a.badge-light.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);
+}
+
+.badge-dark {
+ color: #fff;
+ background-color: #343a40;
+}
+a.badge-dark:hover, a.badge-dark:focus {
+ color: #fff;
+ background-color: #1d2124;
+}
+a.badge-dark:focus, a.badge-dark.focus {
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);
+}
+
+.jumbotron {
+ padding: 2rem 1rem;
+ margin-bottom: 2rem;
+ background-color: #e9ecef;
+ border-radius: 0.3rem;
+}
+@media (min-width: 576px) {
+ .jumbotron {
+ padding: 4rem 2rem;
+ }
+}
+
+.jumbotron-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ border-radius: 0;
+}
+
+.alert {
+ position: relative;
+ padding: 0.75rem 1.25rem;
+ margin-bottom: 1rem;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+
+.alert-heading {
+ color: inherit;
+}
+
+.alert-link {
+ font-weight: 700;
+}
+
+.alert-dismissible {
+ padding-right: 4rem;
+}
+.alert-dismissible .close {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 2;
+ padding: 0.75rem 1.25rem;
+ color: inherit;
+}
+
+.alert-primary {
+ color: #004085;
+ background-color: #cce5ff;
+ border-color: #b8daff;
+}
+.alert-primary hr {
+ border-top-color: #9fcdff;
+}
+.alert-primary .alert-link {
+ color: #002752;
+}
+
+.alert-secondary {
+ color: #383d41;
+ background-color: #e2e3e5;
+ border-color: #d6d8db;
+}
+.alert-secondary hr {
+ border-top-color: #c8cbcf;
+}
+.alert-secondary .alert-link {
+ color: #202326;
+}
+
+.alert-success {
+ color: #155724;
+ background-color: #d4edda;
+ border-color: #c3e6cb;
+}
+.alert-success hr {
+ border-top-color: #b1dfbb;
+}
+.alert-success .alert-link {
+ color: #0b2e13;
+}
+
+.alert-info {
+ color: #0c5460;
+ background-color: #d1ecf1;
+ border-color: #bee5eb;
+}
+.alert-info hr {
+ border-top-color: #abdde5;
+}
+.alert-info .alert-link {
+ color: #062c33;
+}
+
+.alert-warning {
+ color: #856404;
+ background-color: #fff3cd;
+ border-color: #ffeeba;
+}
+.alert-warning hr {
+ border-top-color: #ffe8a1;
+}
+.alert-warning .alert-link {
+ color: #533f03;
+}
+
+.alert-danger {
+ color: #721c24;
+ background-color: #f8d7da;
+ border-color: #f5c6cb;
+}
+.alert-danger hr {
+ border-top-color: #f1b0b7;
+}
+.alert-danger .alert-link {
+ color: #491217;
+}
+
+.alert-light {
+ color: #818182;
+ background-color: #fefefe;
+ border-color: #fdfdfe;
+}
+.alert-light hr {
+ border-top-color: #ececf6;
+}
+.alert-light .alert-link {
+ color: #686868;
+}
+
+.alert-dark {
+ color: #1b1e21;
+ background-color: #d6d8d9;
+ border-color: #c6c8ca;
+}
+.alert-dark hr {
+ border-top-color: #b9bbbe;
+}
+.alert-dark .alert-link {
+ color: #040505;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 1rem 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 1rem 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+.progress {
+ display: flex;
+ height: 1rem;
+ overflow: hidden;
+ line-height: 0;
+ font-size: 0.75rem;
+ background-color: #e9ecef;
+ border-radius: 0.25rem;
+}
+
+.progress-bar {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ overflow: hidden;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ background-color: #007bff;
+ transition: width 0.6s ease;
+}
+@media (prefers-reduced-motion: reduce) {
+ .progress-bar {
+ transition: none;
+ }
+}
+
+.progress-bar-striped {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-size: 1rem 1rem;
+}
+
+.progress-bar-animated {
+ -webkit-animation: progress-bar-stripes 1s linear infinite;
+ animation: progress-bar-stripes 1s linear infinite;
+}
+@media (prefers-reduced-motion: reduce) {
+ .progress-bar-animated {
+ -webkit-animation: none;
+ animation: none;
+ }
+}
+
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+
+.media-body {
+ flex: 1;
+}
+
+.list-group {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ border-radius: 0.25rem;
+}
+
+.list-group-item-action {
+ width: 100%;
+ color: #495057;
+ text-align: inherit;
+}
+.list-group-item-action:hover, .list-group-item-action:focus {
+ z-index: 1;
+ color: #495057;
+ text-decoration: none;
+ background-color: #f8f9fa;
+}
+.list-group-item-action:active {
+ color: #212529;
+ background-color: #e9ecef;
+}
+
+.list-group-item {
+ position: relative;
+ display: block;
+ padding: 0.75rem 1.25rem;
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+}
+.list-group-item:first-child {
+ border-top-left-radius: inherit;
+ border-top-right-radius: inherit;
+}
+.list-group-item:last-child {
+ border-bottom-right-radius: inherit;
+ border-bottom-left-radius: inherit;
+}
+.list-group-item.disabled, .list-group-item:disabled {
+ color: #6c757d;
+ pointer-events: none;
+ background-color: #fff;
+}
+.list-group-item.active {
+ z-index: 2;
+ color: #fff;
+ background-color: #007bff;
+ border-color: #007bff;
+}
+.list-group-item + .list-group-item {
+ border-top-width: 0;
+}
+.list-group-item + .list-group-item.active {
+ margin-top: -1px;
+ border-top-width: 1px;
+}
+
+.list-group-horizontal {
+ flex-direction: row;
+}
+.list-group-horizontal > .list-group-item:first-child {
+ border-bottom-left-radius: 0.25rem;
+ border-top-right-radius: 0;
+}
+.list-group-horizontal > .list-group-item:last-child {
+ border-top-right-radius: 0.25rem;
+ border-bottom-left-radius: 0;
+}
+.list-group-horizontal > .list-group-item.active {
+ margin-top: 0;
+}
+.list-group-horizontal > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+}
+.list-group-horizontal > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+}
+
+@media (min-width: 576px) {
+ .list-group-horizontal-sm {
+ flex-direction: row;
+ }
+ .list-group-horizontal-sm > .list-group-item:first-child {
+ border-bottom-left-radius: 0.25rem;
+ border-top-right-radius: 0;
+ }
+ .list-group-horizontal-sm > .list-group-item:last-child {
+ border-top-right-radius: 0.25rem;
+ border-bottom-left-radius: 0;
+ }
+ .list-group-horizontal-sm > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-sm > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-sm > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
+}
+@media (min-width: 768px) {
+ .list-group-horizontal-md {
+ flex-direction: row;
+ }
+ .list-group-horizontal-md > .list-group-item:first-child {
+ border-bottom-left-radius: 0.25rem;
+ border-top-right-radius: 0;
+ }
+ .list-group-horizontal-md > .list-group-item:last-child {
+ border-top-right-radius: 0.25rem;
+ border-bottom-left-radius: 0;
+ }
+ .list-group-horizontal-md > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-md > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-md > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
+}
+@media (min-width: 992px) {
+ .list-group-horizontal-lg {
+ flex-direction: row;
+ }
+ .list-group-horizontal-lg > .list-group-item:first-child {
+ border-bottom-left-radius: 0.25rem;
+ border-top-right-radius: 0;
+ }
+ .list-group-horizontal-lg > .list-group-item:last-child {
+ border-top-right-radius: 0.25rem;
+ border-bottom-left-radius: 0;
+ }
+ .list-group-horizontal-lg > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-lg > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-lg > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
+}
+@media (min-width: 1200px) {
+ .list-group-horizontal-xl {
+ flex-direction: row;
+ }
+ .list-group-horizontal-xl > .list-group-item:first-child {
+ border-bottom-left-radius: 0.25rem;
+ border-top-right-radius: 0;
+ }
+ .list-group-horizontal-xl > .list-group-item:last-child {
+ border-top-right-radius: 0.25rem;
+ border-bottom-left-radius: 0;
+ }
+ .list-group-horizontal-xl > .list-group-item.active {
+ margin-top: 0;
+ }
+ .list-group-horizontal-xl > .list-group-item + .list-group-item {
+ border-top-width: 1px;
+ border-left-width: 0;
+ }
+ .list-group-horizontal-xl > .list-group-item + .list-group-item.active {
+ margin-left: -1px;
+ border-left-width: 1px;
+ }
+}
+.list-group-flush {
+ border-radius: 0;
+}
+.list-group-flush > .list-group-item {
+ border-width: 0 0 1px;
+}
+.list-group-flush > .list-group-item:last-child {
+ border-bottom-width: 0;
+}
+
+.list-group-item-primary {
+ color: #004085;
+ background-color: #b8daff;
+}
+.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {
+ color: #004085;
+ background-color: #9fcdff;
+}
+.list-group-item-primary.list-group-item-action.active {
+ color: #fff;
+ background-color: #004085;
+ border-color: #004085;
+}
+
+.list-group-item-secondary {
+ color: #383d41;
+ background-color: #d6d8db;
+}
+.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {
+ color: #383d41;
+ background-color: #c8cbcf;
+}
+.list-group-item-secondary.list-group-item-action.active {
+ color: #fff;
+ background-color: #383d41;
+ border-color: #383d41;
+}
+
+.list-group-item-success {
+ color: #155724;
+ background-color: #c3e6cb;
+}
+.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {
+ color: #155724;
+ background-color: #b1dfbb;
+}
+.list-group-item-success.list-group-item-action.active {
+ color: #fff;
+ background-color: #155724;
+ border-color: #155724;
+}
+
+.list-group-item-info {
+ color: #0c5460;
+ background-color: #bee5eb;
+}
+.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {
+ color: #0c5460;
+ background-color: #abdde5;
+}
+.list-group-item-info.list-group-item-action.active {
+ color: #fff;
+ background-color: #0c5460;
+ border-color: #0c5460;
+}
+
+.list-group-item-warning {
+ color: #856404;
+ background-color: #ffeeba;
+}
+.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {
+ color: #856404;
+ background-color: #ffe8a1;
+}
+.list-group-item-warning.list-group-item-action.active {
+ color: #fff;
+ background-color: #856404;
+ border-color: #856404;
+}
+
+.list-group-item-danger {
+ color: #721c24;
+ background-color: #f5c6cb;
+}
+.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {
+ color: #721c24;
+ background-color: #f1b0b7;
+}
+.list-group-item-danger.list-group-item-action.active {
+ color: #fff;
+ background-color: #721c24;
+ border-color: #721c24;
+}
+
+.list-group-item-light {
+ color: #818182;
+ background-color: #fdfdfe;
+}
+.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {
+ color: #818182;
+ background-color: #ececf6;
+}
+.list-group-item-light.list-group-item-action.active {
+ color: #fff;
+ background-color: #818182;
+ border-color: #818182;
+}
+
+.list-group-item-dark {
+ color: #1b1e21;
+ background-color: #c6c8ca;
+}
+.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {
+ color: #1b1e21;
+ background-color: #b9bbbe;
+}
+.list-group-item-dark.list-group-item-action.active {
+ color: #fff;
+ background-color: #1b1e21;
+ border-color: #1b1e21;
+}
+
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: 700;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ opacity: 0.5;
+}
+.close:hover {
+ color: #000;
+ text-decoration: none;
+}
+.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {
+ opacity: 0.75;
+}
+
+button.close {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+}
+
+a.close.disabled {
+ pointer-events: none;
+}
+
+.toast {
+ flex-basis: 350px;
+ max-width: 350px;
+ font-size: 0.875rem;
+ background-color: rgba(255, 255, 255, 0.85);
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
+ opacity: 0;
+ border-radius: 0.25rem;
+}
+.toast:not(:last-child) {
+ margin-bottom: 0.75rem;
+}
+.toast.showing {
+ opacity: 1;
+}
+.toast.show {
+ display: block;
+ opacity: 1;
+}
+.toast.hide {
+ display: none;
+}
+
+.toast-header {
+ display: flex;
+ align-items: center;
+ padding: 0.25rem 0.75rem;
+ color: #6c757d;
+ background-color: rgba(255, 255, 255, 0.85);
+ background-clip: padding-box;
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+ border-top-left-radius: calc(0.25rem - 1px);
+ border-top-right-radius: calc(0.25rem - 1px);
+}
+
+.toast-body {
+ padding: 0.75rem;
+}
+
+.modal-open {
+ overflow: hidden;
+}
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1050;
+ display: none;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ outline: 0;
+}
+
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0.5rem;
+ pointer-events: none;
+}
+.modal.fade .modal-dialog {
+ transition: transform 0.3s ease-out;
+ transform: translate(0, -50px);
+}
+@media (prefers-reduced-motion: reduce) {
+ .modal.fade .modal-dialog {
+ transition: none;
+ }
+}
+.modal.show .modal-dialog {
+ transform: none;
+}
+.modal.modal-static .modal-dialog {
+ transform: scale(1.02);
+}
+
+.modal-dialog-scrollable {
+ display: flex;
+ max-height: calc(100% - 1rem);
+}
+.modal-dialog-scrollable .modal-content {
+ max-height: calc(100vh - 1rem);
+ overflow: hidden;
+}
+.modal-dialog-scrollable .modal-header,
+.modal-dialog-scrollable .modal-footer {
+ flex-shrink: 0;
+}
+.modal-dialog-scrollable .modal-body {
+ overflow-y: auto;
+}
+
+.modal-dialog-centered {
+ display: flex;
+ align-items: center;
+ min-height: calc(100% - 1rem);
+}
+.modal-dialog-centered::before {
+ display: block;
+ height: calc(100vh - 1rem);
+ height: -webkit-min-content;
+ height: -moz-min-content;
+ height: min-content;
+ content: "";
+}
+.modal-dialog-centered.modal-dialog-scrollable {
+ flex-direction: column;
+ justify-content: center;
+ height: 100%;
+}
+.modal-dialog-centered.modal-dialog-scrollable .modal-content {
+ max-height: none;
+}
+.modal-dialog-centered.modal-dialog-scrollable::before {
+ content: none;
+}
+
+.modal-content {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ pointer-events: auto;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 0.3rem;
+ outline: 0;
+}
+
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1040;
+ width: 100vw;
+ height: 100vh;
+ background-color: #000;
+}
+.modal-backdrop.fade {
+ opacity: 0;
+}
+.modal-backdrop.show {
+ opacity: 0.5;
+}
+
+.modal-header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ padding: 1rem 1rem;
+ border-bottom: 1px solid #dee2e6;
+ border-top-left-radius: calc(0.3rem - 1px);
+ border-top-right-radius: calc(0.3rem - 1px);
+}
+.modal-header .close {
+ padding: 1rem 1rem;
+ margin: -1rem -1rem -1rem auto;
+}
+
+.modal-title {
+ margin-bottom: 0;
+ line-height: 1.5;
+}
+
+.modal-body {
+ position: relative;
+ flex: 1 1 auto;
+ padding: 1rem;
+}
+
+.modal-footer {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: flex-end;
+ padding: 0.75rem;
+ border-top: 1px solid #dee2e6;
+ border-bottom-right-radius: calc(0.3rem - 1px);
+ border-bottom-left-radius: calc(0.3rem - 1px);
+}
+.modal-footer > * {
+ margin: 0.25rem;
+}
+
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll;
+}
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 500px;
+ margin: 1.75rem auto;
+ }
+
+ .modal-dialog-scrollable {
+ max-height: calc(100% - 3.5rem);
+ }
+ .modal-dialog-scrollable .modal-content {
+ max-height: calc(100vh - 3.5rem);
+ }
+
+ .modal-dialog-centered {
+ min-height: calc(100% - 3.5rem);
+ }
+ .modal-dialog-centered::before {
+ height: calc(100vh - 3.5rem);
+ height: -webkit-min-content;
+ height: -moz-min-content;
+ height: min-content;
+ }
+
+ .modal-sm {
+ max-width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg,
+.modal-xl {
+ max-width: 800px;
+ }
+}
+@media (min-width: 1200px) {
+ .modal-xl {
+ max-width: 1140px;
+ }
+}
+.tooltip {
+ position: absolute;
+ z-index: 1070;
+ display: block;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-style: normal;
+ font-weight: 400;
+ line-height: 1.5;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-break: normal;
+ word-spacing: normal;
+ white-space: normal;
+ line-break: auto;
+ font-size: 0.875rem;
+ word-wrap: break-word;
+ opacity: 0;
+}
+.tooltip.show {
+ opacity: 0.9;
+}
+.tooltip .arrow {
+ position: absolute;
+ display: block;
+ width: 0.8rem;
+ height: 0.4rem;
+}
+.tooltip .arrow::before {
+ position: absolute;
+ content: "";
+ border-color: transparent;
+ border-style: solid;
+}
+
+.bs-tooltip-top, .bs-tooltip-auto[x-placement^=top] {
+ padding: 0.4rem 0;
+}
+.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^=top] .arrow {
+ bottom: 0;
+}
+.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^=top] .arrow::before {
+ top: 0;
+ border-width: 0.4rem 0.4rem 0;
+ border-top-color: #000;
+}
+
+.bs-tooltip-right, .bs-tooltip-auto[x-placement^=right] {
+ padding: 0 0.4rem;
+}
+.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^=right] .arrow {
+ left: 0;
+ width: 0.4rem;
+ height: 0.8rem;
+}
+.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^=right] .arrow::before {
+ right: 0;
+ border-width: 0.4rem 0.4rem 0.4rem 0;
+ border-right-color: #000;
+}
+
+.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^=bottom] {
+ padding: 0.4rem 0;
+}
+.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^=bottom] .arrow {
+ top: 0;
+}
+.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^=bottom] .arrow::before {
+ bottom: 0;
+ border-width: 0 0.4rem 0.4rem;
+ border-bottom-color: #000;
+}
+
+.bs-tooltip-left, .bs-tooltip-auto[x-placement^=left] {
+ padding: 0 0.4rem;
+}
+.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^=left] .arrow {
+ right: 0;
+ width: 0.4rem;
+ height: 0.8rem;
+}
+.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^=left] .arrow::before {
+ left: 0;
+ border-width: 0.4rem 0 0.4rem 0.4rem;
+ border-left-color: #000;
+}
+
+.tooltip-inner {
+ max-width: 200px;
+ padding: 0.25rem 0.5rem;
+ color: #fff;
+ text-align: center;
+ background-color: #000;
+ border-radius: 0.25rem;
+}
+
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1060;
+ display: block;
+ max-width: 276px;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-style: normal;
+ font-weight: 400;
+ line-height: 1.5;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-break: normal;
+ word-spacing: normal;
+ white-space: normal;
+ line-break: auto;
+ font-size: 0.875rem;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 0.3rem;
+}
+.popover .arrow {
+ position: absolute;
+ display: block;
+ width: 1rem;
+ height: 0.5rem;
+ margin: 0 0.3rem;
+}
+.popover .arrow::before, .popover .arrow::after {
+ position: absolute;
+ display: block;
+ content: "";
+ border-color: transparent;
+ border-style: solid;
+}
+
+.bs-popover-top, .bs-popover-auto[x-placement^=top] {
+ margin-bottom: 0.5rem;
+}
+.bs-popover-top > .arrow, .bs-popover-auto[x-placement^=top] > .arrow {
+ bottom: calc(-0.5rem - 1px);
+}
+.bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^=top] > .arrow::before {
+ bottom: 0;
+ border-width: 0.5rem 0.5rem 0;
+ border-top-color: rgba(0, 0, 0, 0.25);
+}
+.bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^=top] > .arrow::after {
+ bottom: 1px;
+ border-width: 0.5rem 0.5rem 0;
+ border-top-color: #fff;
+}
+
+.bs-popover-right, .bs-popover-auto[x-placement^=right] {
+ margin-left: 0.5rem;
+}
+.bs-popover-right > .arrow, .bs-popover-auto[x-placement^=right] > .arrow {
+ left: calc(-0.5rem - 1px);
+ width: 0.5rem;
+ height: 1rem;
+ margin: 0.3rem 0;
+}
+.bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^=right] > .arrow::before {
+ left: 0;
+ border-width: 0.5rem 0.5rem 0.5rem 0;
+ border-right-color: rgba(0, 0, 0, 0.25);
+}
+.bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^=right] > .arrow::after {
+ left: 1px;
+ border-width: 0.5rem 0.5rem 0.5rem 0;
+ border-right-color: #fff;
+}
+
+.bs-popover-bottom, .bs-popover-auto[x-placement^=bottom] {
+ margin-top: 0.5rem;
+}
+.bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^=bottom] > .arrow {
+ top: calc(-0.5rem - 1px);
+}
+.bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^=bottom] > .arrow::before {
+ top: 0;
+ border-width: 0 0.5rem 0.5rem 0.5rem;
+ border-bottom-color: rgba(0, 0, 0, 0.25);
+}
+.bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^=bottom] > .arrow::after {
+ top: 1px;
+ border-width: 0 0.5rem 0.5rem 0.5rem;
+ border-bottom-color: #fff;
+}
+.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^=bottom] .popover-header::before {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ display: block;
+ width: 1rem;
+ margin-left: -0.5rem;
+ content: "";
+ border-bottom: 1px solid #f7f7f7;
+}
+
+.bs-popover-left, .bs-popover-auto[x-placement^=left] {
+ margin-right: 0.5rem;
+}
+.bs-popover-left > .arrow, .bs-popover-auto[x-placement^=left] > .arrow {
+ right: calc(-0.5rem - 1px);
+ width: 0.5rem;
+ height: 1rem;
+ margin: 0.3rem 0;
+}
+.bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^=left] > .arrow::before {
+ right: 0;
+ border-width: 0.5rem 0 0.5rem 0.5rem;
+ border-left-color: rgba(0, 0, 0, 0.25);
+}
+.bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^=left] > .arrow::after {
+ right: 1px;
+ border-width: 0.5rem 0 0.5rem 0.5rem;
+ border-left-color: #fff;
+}
+
+.popover-header {
+ padding: 0.5rem 0.75rem;
+ margin-bottom: 0;
+ font-size: 1rem;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ border-top-left-radius: calc(0.3rem - 1px);
+ border-top-right-radius: calc(0.3rem - 1px);
+}
+.popover-header:empty {
+ display: none;
+}
+
+.popover-body {
+ padding: 0.5rem 0.75rem;
+ color: #212529;
+}
+
+.carousel {
+ position: relative;
+}
+
+.carousel.pointer-event {
+ touch-action: pan-y;
+}
+
+.carousel-inner {
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+}
+.carousel-inner::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+
+.carousel-item {
+ position: relative;
+ display: none;
+ float: left;
+ width: 100%;
+ margin-right: -100%;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ transition: transform 0.6s ease-in-out;
+}
+@media (prefers-reduced-motion: reduce) {
+ .carousel-item {
+ transition: none;
+ }
+}
+
+.carousel-item.active,
+.carousel-item-next,
+.carousel-item-prev {
+ display: block;
+}
+
+.carousel-item-next:not(.carousel-item-left),
+.active.carousel-item-right {
+ transform: translateX(100%);
+}
+
+.carousel-item-prev:not(.carousel-item-right),
+.active.carousel-item-left {
+ transform: translateX(-100%);
+}
+
+.carousel-fade .carousel-item {
+ opacity: 0;
+ transition-property: opacity;
+ transform: none;
+}
+.carousel-fade .carousel-item.active,
+.carousel-fade .carousel-item-next.carousel-item-left,
+.carousel-fade .carousel-item-prev.carousel-item-right {
+ z-index: 1;
+ opacity: 1;
+}
+.carousel-fade .active.carousel-item-left,
+.carousel-fade .active.carousel-item-right {
+ z-index: 0;
+ opacity: 0;
+ transition: opacity 0s 0.6s;
+}
+@media (prefers-reduced-motion: reduce) {
+ .carousel-fade .active.carousel-item-left,
+.carousel-fade .active.carousel-item-right {
+ transition: none;
+ }
+}
+
+.carousel-control-prev,
+.carousel-control-next {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ z-index: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 15%;
+ color: #fff;
+ text-align: center;
+ opacity: 0.5;
+ transition: opacity 0.15s ease;
+}
+@media (prefers-reduced-motion: reduce) {
+ .carousel-control-prev,
+.carousel-control-next {
+ transition: none;
+ }
+}
+.carousel-control-prev:hover, .carousel-control-prev:focus,
+.carousel-control-next:hover,
+.carousel-control-next:focus {
+ color: #fff;
+ text-decoration: none;
+ outline: 0;
+ opacity: 0.9;
+}
+
+.carousel-control-prev {
+ left: 0;
+}
+
+.carousel-control-next {
+ right: 0;
+}
+
+.carousel-control-prev-icon,
+.carousel-control-next-icon {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ background: no-repeat 50%/100% 100%;
+}
+
+.carousel-control-prev-icon {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e");
+}
+
+.carousel-control-next-icon {
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e");
+}
+
+.carousel-indicators {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 15;
+ display: flex;
+ justify-content: center;
+ padding-left: 0;
+ margin-right: 15%;
+ margin-left: 15%;
+ list-style: none;
+}
+.carousel-indicators li {
+ box-sizing: content-box;
+ flex: 0 1 auto;
+ width: 30px;
+ height: 3px;
+ margin-right: 3px;
+ margin-left: 3px;
+ text-indent: -999px;
+ cursor: pointer;
+ background-color: #fff;
+ background-clip: padding-box;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ opacity: 0.5;
+ transition: opacity 0.6s ease;
+}
+@media (prefers-reduced-motion: reduce) {
+ .carousel-indicators li {
+ transition: none;
+ }
+}
+.carousel-indicators .active {
+ opacity: 1;
+}
+
+.carousel-caption {
+ position: absolute;
+ right: 15%;
+ bottom: 20px;
+ left: 15%;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: #fff;
+ text-align: center;
+}
+
+@-webkit-keyframes spinner-border {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes spinner-border {
+ to {
+ transform: rotate(360deg);
+ }
+}
+.spinner-border {
+ display: inline-block;
+ width: 2rem;
+ height: 2rem;
+ vertical-align: text-bottom;
+ border: 0.25em solid currentColor;
+ border-right-color: transparent;
+ border-radius: 50%;
+ -webkit-animation: spinner-border 0.75s linear infinite;
+ animation: spinner-border 0.75s linear infinite;
+}
+
+.spinner-border-sm {
+ width: 1rem;
+ height: 1rem;
+ border-width: 0.2em;
+}
+
+@-webkit-keyframes spinner-grow {
+ 0% {
+ transform: scale(0);
+ }
+ 50% {
+ opacity: 1;
+ transform: none;
+ }
+}
+
+@keyframes spinner-grow {
+ 0% {
+ transform: scale(0);
+ }
+ 50% {
+ opacity: 1;
+ transform: none;
+ }
+}
+.spinner-grow {
+ display: inline-block;
+ width: 2rem;
+ height: 2rem;
+ vertical-align: text-bottom;
+ background-color: currentColor;
+ border-radius: 50%;
+ opacity: 0;
+ -webkit-animation: spinner-grow 0.75s linear infinite;
+ animation: spinner-grow 0.75s linear infinite;
+}
+
+.spinner-grow-sm {
+ width: 1rem;
+ height: 1rem;
+}
+
+.align-baseline {
+ vertical-align: baseline !important;
+}
+
+.align-top {
+ vertical-align: top !important;
+}
+
+.align-middle {
+ vertical-align: middle !important;
+}
+
+.align-bottom {
+ vertical-align: bottom !important;
+}
+
+.align-text-bottom {
+ vertical-align: text-bottom !important;
+}
+
+.align-text-top {
+ vertical-align: text-top !important;
+}
+
+.bg-primary {
+ background-color: #007bff !important;
+}
+
+a.bg-primary:hover, a.bg-primary:focus,
+button.bg-primary:hover,
+button.bg-primary:focus {
+ background-color: #0062cc !important;
+}
+
+.bg-secondary {
+ background-color: #6c757d !important;
+}
+
+a.bg-secondary:hover, a.bg-secondary:focus,
+button.bg-secondary:hover,
+button.bg-secondary:focus {
+ background-color: #545b62 !important;
+}
+
+.bg-success {
+ background-color: #28a745 !important;
+}
+
+a.bg-success:hover, a.bg-success:focus,
+button.bg-success:hover,
+button.bg-success:focus {
+ background-color: #1e7e34 !important;
+}
+
+.bg-info {
+ background-color: #17a2b8 !important;
+}
+
+a.bg-info:hover, a.bg-info:focus,
+button.bg-info:hover,
+button.bg-info:focus {
+ background-color: #117a8b !important;
+}
+
+.bg-warning {
+ background-color: #ffc107 !important;
+}
+
+a.bg-warning:hover, a.bg-warning:focus,
+button.bg-warning:hover,
+button.bg-warning:focus {
+ background-color: #d39e00 !important;
+}
+
+.bg-danger {
+ background-color: #dc3545 !important;
+}
+
+a.bg-danger:hover, a.bg-danger:focus,
+button.bg-danger:hover,
+button.bg-danger:focus {
+ background-color: #bd2130 !important;
+}
+
+.bg-light {
+ background-color: #f8f9fa !important;
+}
+
+a.bg-light:hover, a.bg-light:focus,
+button.bg-light:hover,
+button.bg-light:focus {
+ background-color: #dae0e5 !important;
+}
+
+.bg-dark {
+ background-color: #343a40 !important;
+}
+
+a.bg-dark:hover, a.bg-dark:focus,
+button.bg-dark:hover,
+button.bg-dark:focus {
+ background-color: #1d2124 !important;
+}
+
+.bg-white {
+ background-color: #fff !important;
+}
+
+.bg-transparent {
+ background-color: transparent !important;
+}
+
+.border {
+ border: 1px solid #dee2e6 !important;
+}
+
+.border-top {
+ border-top: 1px solid #dee2e6 !important;
+}
+
+.border-right {
+ border-right: 1px solid #dee2e6 !important;
+}
+
+.border-bottom {
+ border-bottom: 1px solid #dee2e6 !important;
+}
+
+.border-left {
+ border-left: 1px solid #dee2e6 !important;
+}
+
+.border-0 {
+ border: 0 !important;
+}
+
+.border-top-0 {
+ border-top: 0 !important;
+}
+
+.border-right-0 {
+ border-right: 0 !important;
+}
+
+.border-bottom-0 {
+ border-bottom: 0 !important;
+}
+
+.border-left-0 {
+ border-left: 0 !important;
+}
+
+.border-primary {
+ border-color: #007bff !important;
+}
+
+.border-secondary {
+ border-color: #6c757d !important;
+}
+
+.border-success {
+ border-color: #28a745 !important;
+}
+
+.border-info {
+ border-color: #17a2b8 !important;
+}
+
+.border-warning {
+ border-color: #ffc107 !important;
+}
+
+.border-danger {
+ border-color: #dc3545 !important;
+}
+
+.border-light {
+ border-color: #f8f9fa !important;
+}
+
+.border-dark {
+ border-color: #343a40 !important;
+}
+
+.border-white {
+ border-color: #fff !important;
+}
+
+.rounded-sm {
+ border-radius: 0.2rem !important;
+}
+
+.rounded {
+ border-radius: 0.25rem !important;
+}
+
+.rounded-top {
+ border-top-left-radius: 0.25rem !important;
+ border-top-right-radius: 0.25rem !important;
+}
+
+.rounded-right {
+ border-top-right-radius: 0.25rem !important;
+ border-bottom-right-radius: 0.25rem !important;
+}
+
+.rounded-bottom {
+ border-bottom-right-radius: 0.25rem !important;
+ border-bottom-left-radius: 0.25rem !important;
+}
+
+.rounded-left {
+ border-top-left-radius: 0.25rem !important;
+ border-bottom-left-radius: 0.25rem !important;
+}
+
+.rounded-lg {
+ border-radius: 0.3rem !important;
+}
+
+.rounded-circle {
+ border-radius: 50% !important;
+}
+
+.rounded-pill {
+ border-radius: 50rem !important;
+}
+
+.rounded-0 {
+ border-radius: 0 !important;
+}
+
+.clearfix::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+
+.d-none {
+ display: none !important;
+}
+
+.d-inline {
+ display: inline !important;
+}
+
+.d-inline-block {
+ display: inline-block !important;
+}
+
+.d-block {
+ display: block !important;
+}
+
+.d-table {
+ display: table !important;
+}
+
+.d-table-row {
+ display: table-row !important;
+}
+
+.d-table-cell {
+ display: table-cell !important;
+}
+
+.d-flex {
+ display: flex !important;
+}
+
+.d-inline-flex {
+ display: inline-flex !important;
+}
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important;
+ }
+
+ .d-sm-inline {
+ display: inline !important;
+ }
+
+ .d-sm-inline-block {
+ display: inline-block !important;
+ }
+
+ .d-sm-block {
+ display: block !important;
+ }
+
+ .d-sm-table {
+ display: table !important;
+ }
+
+ .d-sm-table-row {
+ display: table-row !important;
+ }
+
+ .d-sm-table-cell {
+ display: table-cell !important;
+ }
+
+ .d-sm-flex {
+ display: flex !important;
+ }
+
+ .d-sm-inline-flex {
+ display: inline-flex !important;
+ }
+}
+@media (min-width: 768px) {
+ .d-md-none {
+ display: none !important;
+ }
+
+ .d-md-inline {
+ display: inline !important;
+ }
+
+ .d-md-inline-block {
+ display: inline-block !important;
+ }
+
+ .d-md-block {
+ display: block !important;
+ }
+
+ .d-md-table {
+ display: table !important;
+ }
+
+ .d-md-table-row {
+ display: table-row !important;
+ }
+
+ .d-md-table-cell {
+ display: table-cell !important;
+ }
+
+ .d-md-flex {
+ display: flex !important;
+ }
+
+ .d-md-inline-flex {
+ display: inline-flex !important;
+ }
+}
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important;
+ }
+
+ .d-lg-inline {
+ display: inline !important;
+ }
+
+ .d-lg-inline-block {
+ display: inline-block !important;
+ }
+
+ .d-lg-block {
+ display: block !important;
+ }
+
+ .d-lg-table {
+ display: table !important;
+ }
+
+ .d-lg-table-row {
+ display: table-row !important;
+ }
+
+ .d-lg-table-cell {
+ display: table-cell !important;
+ }
+
+ .d-lg-flex {
+ display: flex !important;
+ }
+
+ .d-lg-inline-flex {
+ display: inline-flex !important;
+ }
+}
+@media (min-width: 1200px) {
+ .d-xl-none {
+ display: none !important;
+ }
+
+ .d-xl-inline {
+ display: inline !important;
+ }
+
+ .d-xl-inline-block {
+ display: inline-block !important;
+ }
+
+ .d-xl-block {
+ display: block !important;
+ }
+
+ .d-xl-table {
+ display: table !important;
+ }
+
+ .d-xl-table-row {
+ display: table-row !important;
+ }
+
+ .d-xl-table-cell {
+ display: table-cell !important;
+ }
+
+ .d-xl-flex {
+ display: flex !important;
+ }
+
+ .d-xl-inline-flex {
+ display: inline-flex !important;
+ }
+}
+@media print {
+ .d-print-none {
+ display: none !important;
+ }
+
+ .d-print-inline {
+ display: inline !important;
+ }
+
+ .d-print-inline-block {
+ display: inline-block !important;
+ }
+
+ .d-print-block {
+ display: block !important;
+ }
+
+ .d-print-table {
+ display: table !important;
+ }
+
+ .d-print-table-row {
+ display: table-row !important;
+ }
+
+ .d-print-table-cell {
+ display: table-cell !important;
+ }
+
+ .d-print-flex {
+ display: flex !important;
+ }
+
+ .d-print-inline-flex {
+ display: inline-flex !important;
+ }
+}
+.embed-responsive {
+ position: relative;
+ display: block;
+ width: 100%;
+ padding: 0;
+ overflow: hidden;
+}
+.embed-responsive::before {
+ display: block;
+ content: "";
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+}
+
+.embed-responsive-21by9::before {
+ padding-top: 42.8571428571%;
+}
+
+.embed-responsive-16by9::before {
+ padding-top: 56.25%;
+}
+
+.embed-responsive-4by3::before {
+ padding-top: 75%;
+}
+
+.embed-responsive-1by1::before {
+ padding-top: 100%;
+}
+
+.embed-responsive-21by9::before {
+ padding-top: 42.8571428571%;
+}
+
+.embed-responsive-16by9::before {
+ padding-top: 56.25%;
+}
+
+.embed-responsive-4by3::before {
+ padding-top: 75%;
+}
+
+.embed-responsive-1by1::before {
+ padding-top: 100%;
+}
+
+.flex-row {
+ flex-direction: row !important;
+}
+
+.flex-column {
+ flex-direction: column !important;
+}
+
+.flex-row-reverse {
+ flex-direction: row-reverse !important;
+}
+
+.flex-column-reverse {
+ flex-direction: column-reverse !important;
+}
+
+.flex-wrap {
+ flex-wrap: wrap !important;
+}
+
+.flex-nowrap {
+ flex-wrap: nowrap !important;
+}
+
+.flex-wrap-reverse {
+ flex-wrap: wrap-reverse !important;
+}
+
+.flex-fill {
+ flex: 1 1 auto !important;
+}
+
+.flex-grow-0 {
+ flex-grow: 0 !important;
+}
+
+.flex-grow-1 {
+ flex-grow: 1 !important;
+}
+
+.flex-shrink-0 {
+ flex-shrink: 0 !important;
+}
+
+.flex-shrink-1 {
+ flex-shrink: 1 !important;
+}
+
+.justify-content-start {
+ justify-content: flex-start !important;
+}
+
+.justify-content-end {
+ justify-content: flex-end !important;
+}
+
+.justify-content-center {
+ justify-content: center !important;
+}
+
+.justify-content-between {
+ justify-content: space-between !important;
+}
+
+.justify-content-around {
+ justify-content: space-around !important;
+}
+
+.align-items-start {
+ align-items: flex-start !important;
+}
+
+.align-items-end {
+ align-items: flex-end !important;
+}
+
+.align-items-center {
+ align-items: center !important;
+}
+
+.align-items-baseline {
+ align-items: baseline !important;
+}
+
+.align-items-stretch {
+ align-items: stretch !important;
+}
+
+.align-content-start {
+ align-content: flex-start !important;
+}
+
+.align-content-end {
+ align-content: flex-end !important;
+}
+
+.align-content-center {
+ align-content: center !important;
+}
+
+.align-content-between {
+ align-content: space-between !important;
+}
+
+.align-content-around {
+ align-content: space-around !important;
+}
+
+.align-content-stretch {
+ align-content: stretch !important;
+}
+
+.align-self-auto {
+ align-self: auto !important;
+}
+
+.align-self-start {
+ align-self: flex-start !important;
+}
+
+.align-self-end {
+ align-self: flex-end !important;
+}
+
+.align-self-center {
+ align-self: center !important;
+}
+
+.align-self-baseline {
+ align-self: baseline !important;
+}
+
+.align-self-stretch {
+ align-self: stretch !important;
+}
+
+@media (min-width: 576px) {
+ .flex-sm-row {
+ flex-direction: row !important;
+ }
+
+ .flex-sm-column {
+ flex-direction: column !important;
+ }
+
+ .flex-sm-row-reverse {
+ flex-direction: row-reverse !important;
+ }
+
+ .flex-sm-column-reverse {
+ flex-direction: column-reverse !important;
+ }
+
+ .flex-sm-wrap {
+ flex-wrap: wrap !important;
+ }
+
+ .flex-sm-nowrap {
+ flex-wrap: nowrap !important;
+ }
+
+ .flex-sm-wrap-reverse {
+ flex-wrap: wrap-reverse !important;
+ }
+
+ .flex-sm-fill {
+ flex: 1 1 auto !important;
+ }
+
+ .flex-sm-grow-0 {
+ flex-grow: 0 !important;
+ }
+
+ .flex-sm-grow-1 {
+ flex-grow: 1 !important;
+ }
+
+ .flex-sm-shrink-0 {
+ flex-shrink: 0 !important;
+ }
+
+ .flex-sm-shrink-1 {
+ flex-shrink: 1 !important;
+ }
+
+ .justify-content-sm-start {
+ justify-content: flex-start !important;
+ }
+
+ .justify-content-sm-end {
+ justify-content: flex-end !important;
+ }
+
+ .justify-content-sm-center {
+ justify-content: center !important;
+ }
+
+ .justify-content-sm-between {
+ justify-content: space-between !important;
+ }
+
+ .justify-content-sm-around {
+ justify-content: space-around !important;
+ }
+
+ .align-items-sm-start {
+ align-items: flex-start !important;
+ }
+
+ .align-items-sm-end {
+ align-items: flex-end !important;
+ }
+
+ .align-items-sm-center {
+ align-items: center !important;
+ }
+
+ .align-items-sm-baseline {
+ align-items: baseline !important;
+ }
+
+ .align-items-sm-stretch {
+ align-items: stretch !important;
+ }
+
+ .align-content-sm-start {
+ align-content: flex-start !important;
+ }
+
+ .align-content-sm-end {
+ align-content: flex-end !important;
+ }
+
+ .align-content-sm-center {
+ align-content: center !important;
+ }
+
+ .align-content-sm-between {
+ align-content: space-between !important;
+ }
+
+ .align-content-sm-around {
+ align-content: space-around !important;
+ }
+
+ .align-content-sm-stretch {
+ align-content: stretch !important;
+ }
+
+ .align-self-sm-auto {
+ align-self: auto !important;
+ }
+
+ .align-self-sm-start {
+ align-self: flex-start !important;
+ }
+
+ .align-self-sm-end {
+ align-self: flex-end !important;
+ }
+
+ .align-self-sm-center {
+ align-self: center !important;
+ }
+
+ .align-self-sm-baseline {
+ align-self: baseline !important;
+ }
+
+ .align-self-sm-stretch {
+ align-self: stretch !important;
+ }
+}
+@media (min-width: 768px) {
+ .flex-md-row {
+ flex-direction: row !important;
+ }
+
+ .flex-md-column {
+ flex-direction: column !important;
+ }
+
+ .flex-md-row-reverse {
+ flex-direction: row-reverse !important;
+ }
+
+ .flex-md-column-reverse {
+ flex-direction: column-reverse !important;
+ }
+
+ .flex-md-wrap {
+ flex-wrap: wrap !important;
+ }
+
+ .flex-md-nowrap {
+ flex-wrap: nowrap !important;
+ }
+
+ .flex-md-wrap-reverse {
+ flex-wrap: wrap-reverse !important;
+ }
+
+ .flex-md-fill {
+ flex: 1 1 auto !important;
+ }
+
+ .flex-md-grow-0 {
+ flex-grow: 0 !important;
+ }
+
+ .flex-md-grow-1 {
+ flex-grow: 1 !important;
+ }
+
+ .flex-md-shrink-0 {
+ flex-shrink: 0 !important;
+ }
+
+ .flex-md-shrink-1 {
+ flex-shrink: 1 !important;
+ }
+
+ .justify-content-md-start {
+ justify-content: flex-start !important;
+ }
+
+ .justify-content-md-end {
+ justify-content: flex-end !important;
+ }
+
+ .justify-content-md-center {
+ justify-content: center !important;
+ }
+
+ .justify-content-md-between {
+ justify-content: space-between !important;
+ }
+
+ .justify-content-md-around {
+ justify-content: space-around !important;
+ }
+
+ .align-items-md-start {
+ align-items: flex-start !important;
+ }
+
+ .align-items-md-end {
+ align-items: flex-end !important;
+ }
+
+ .align-items-md-center {
+ align-items: center !important;
+ }
+
+ .align-items-md-baseline {
+ align-items: baseline !important;
+ }
+
+ .align-items-md-stretch {
+ align-items: stretch !important;
+ }
+
+ .align-content-md-start {
+ align-content: flex-start !important;
+ }
+
+ .align-content-md-end {
+ align-content: flex-end !important;
+ }
+
+ .align-content-md-center {
+ align-content: center !important;
+ }
+
+ .align-content-md-between {
+ align-content: space-between !important;
+ }
+
+ .align-content-md-around {
+ align-content: space-around !important;
+ }
+
+ .align-content-md-stretch {
+ align-content: stretch !important;
+ }
+
+ .align-self-md-auto {
+ align-self: auto !important;
+ }
+
+ .align-self-md-start {
+ align-self: flex-start !important;
+ }
+
+ .align-self-md-end {
+ align-self: flex-end !important;
+ }
+
+ .align-self-md-center {
+ align-self: center !important;
+ }
+
+ .align-self-md-baseline {
+ align-self: baseline !important;
+ }
+
+ .align-self-md-stretch {
+ align-self: stretch !important;
+ }
+}
+@media (min-width: 992px) {
+ .flex-lg-row {
+ flex-direction: row !important;
+ }
+
+ .flex-lg-column {
+ flex-direction: column !important;
+ }
+
+ .flex-lg-row-reverse {
+ flex-direction: row-reverse !important;
+ }
+
+ .flex-lg-column-reverse {
+ flex-direction: column-reverse !important;
+ }
+
+ .flex-lg-wrap {
+ flex-wrap: wrap !important;
+ }
+
+ .flex-lg-nowrap {
+ flex-wrap: nowrap !important;
+ }
+
+ .flex-lg-wrap-reverse {
+ flex-wrap: wrap-reverse !important;
+ }
+
+ .flex-lg-fill {
+ flex: 1 1 auto !important;
+ }
+
+ .flex-lg-grow-0 {
+ flex-grow: 0 !important;
+ }
+
+ .flex-lg-grow-1 {
+ flex-grow: 1 !important;
+ }
+
+ .flex-lg-shrink-0 {
+ flex-shrink: 0 !important;
+ }
+
+ .flex-lg-shrink-1 {
+ flex-shrink: 1 !important;
+ }
+
+ .justify-content-lg-start {
+ justify-content: flex-start !important;
+ }
+
+ .justify-content-lg-end {
+ justify-content: flex-end !important;
+ }
+
+ .justify-content-lg-center {
+ justify-content: center !important;
+ }
+
+ .justify-content-lg-between {
+ justify-content: space-between !important;
+ }
+
+ .justify-content-lg-around {
+ justify-content: space-around !important;
+ }
+
+ .align-items-lg-start {
+ align-items: flex-start !important;
+ }
+
+ .align-items-lg-end {
+ align-items: flex-end !important;
+ }
+
+ .align-items-lg-center {
+ align-items: center !important;
+ }
+
+ .align-items-lg-baseline {
+ align-items: baseline !important;
+ }
+
+ .align-items-lg-stretch {
+ align-items: stretch !important;
+ }
+
+ .align-content-lg-start {
+ align-content: flex-start !important;
+ }
+
+ .align-content-lg-end {
+ align-content: flex-end !important;
+ }
+
+ .align-content-lg-center {
+ align-content: center !important;
+ }
+
+ .align-content-lg-between {
+ align-content: space-between !important;
+ }
+
+ .align-content-lg-around {
+ align-content: space-around !important;
+ }
+
+ .align-content-lg-stretch {
+ align-content: stretch !important;
+ }
+
+ .align-self-lg-auto {
+ align-self: auto !important;
+ }
+
+ .align-self-lg-start {
+ align-self: flex-start !important;
+ }
+
+ .align-self-lg-end {
+ align-self: flex-end !important;
+ }
+
+ .align-self-lg-center {
+ align-self: center !important;
+ }
+
+ .align-self-lg-baseline {
+ align-self: baseline !important;
+ }
+
+ .align-self-lg-stretch {
+ align-self: stretch !important;
+ }
+}
+@media (min-width: 1200px) {
+ .flex-xl-row {
+ flex-direction: row !important;
+ }
+
+ .flex-xl-column {
+ flex-direction: column !important;
+ }
+
+ .flex-xl-row-reverse {
+ flex-direction: row-reverse !important;
+ }
+
+ .flex-xl-column-reverse {
+ flex-direction: column-reverse !important;
+ }
+
+ .flex-xl-wrap {
+ flex-wrap: wrap !important;
+ }
+
+ .flex-xl-nowrap {
+ flex-wrap: nowrap !important;
+ }
+
+ .flex-xl-wrap-reverse {
+ flex-wrap: wrap-reverse !important;
+ }
+
+ .flex-xl-fill {
+ flex: 1 1 auto !important;
+ }
+
+ .flex-xl-grow-0 {
+ flex-grow: 0 !important;
+ }
+
+ .flex-xl-grow-1 {
+ flex-grow: 1 !important;
+ }
+
+ .flex-xl-shrink-0 {
+ flex-shrink: 0 !important;
+ }
+
+ .flex-xl-shrink-1 {
+ flex-shrink: 1 !important;
+ }
+
+ .justify-content-xl-start {
+ justify-content: flex-start !important;
+ }
+
+ .justify-content-xl-end {
+ justify-content: flex-end !important;
+ }
+
+ .justify-content-xl-center {
+ justify-content: center !important;
+ }
+
+ .justify-content-xl-between {
+ justify-content: space-between !important;
+ }
+
+ .justify-content-xl-around {
+ justify-content: space-around !important;
+ }
+
+ .align-items-xl-start {
+ align-items: flex-start !important;
+ }
+
+ .align-items-xl-end {
+ align-items: flex-end !important;
+ }
+
+ .align-items-xl-center {
+ align-items: center !important;
+ }
+
+ .align-items-xl-baseline {
+ align-items: baseline !important;
+ }
+
+ .align-items-xl-stretch {
+ align-items: stretch !important;
+ }
+
+ .align-content-xl-start {
+ align-content: flex-start !important;
+ }
+
+ .align-content-xl-end {
+ align-content: flex-end !important;
+ }
+
+ .align-content-xl-center {
+ align-content: center !important;
+ }
+
+ .align-content-xl-between {
+ align-content: space-between !important;
+ }
+
+ .align-content-xl-around {
+ align-content: space-around !important;
+ }
+
+ .align-content-xl-stretch {
+ align-content: stretch !important;
+ }
+
+ .align-self-xl-auto {
+ align-self: auto !important;
+ }
+
+ .align-self-xl-start {
+ align-self: flex-start !important;
+ }
+
+ .align-self-xl-end {
+ align-self: flex-end !important;
+ }
+
+ .align-self-xl-center {
+ align-self: center !important;
+ }
+
+ .align-self-xl-baseline {
+ align-self: baseline !important;
+ }
+
+ .align-self-xl-stretch {
+ align-self: stretch !important;
+ }
+}
+.float-left {
+ float: left !important;
+}
+
+.float-right {
+ float: right !important;
+}
+
+.float-none {
+ float: none !important;
+}
+
+@media (min-width: 576px) {
+ .float-sm-left {
+ float: left !important;
+ }
+
+ .float-sm-right {
+ float: right !important;
+ }
+
+ .float-sm-none {
+ float: none !important;
+ }
+}
+@media (min-width: 768px) {
+ .float-md-left {
+ float: left !important;
+ }
+
+ .float-md-right {
+ float: right !important;
+ }
+
+ .float-md-none {
+ float: none !important;
+ }
+}
+@media (min-width: 992px) {
+ .float-lg-left {
+ float: left !important;
+ }
+
+ .float-lg-right {
+ float: right !important;
+ }
+
+ .float-lg-none {
+ float: none !important;
+ }
+}
+@media (min-width: 1200px) {
+ .float-xl-left {
+ float: left !important;
+ }
+
+ .float-xl-right {
+ float: right !important;
+ }
+
+ .float-xl-none {
+ float: none !important;
+ }
+}
+.user-select-all {
+ -webkit-user-select: all !important;
+ -moz-user-select: all !important;
+ -ms-user-select: all !important;
+ user-select: all !important;
+}
+
+.user-select-auto {
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto !important;
+ -ms-user-select: auto !important;
+ user-select: auto !important;
+}
+
+.user-select-none {
+ -webkit-user-select: none !important;
+ -moz-user-select: none !important;
+ -ms-user-select: none !important;
+ user-select: none !important;
+}
+
+.overflow-auto {
+ overflow: auto !important;
+}
+
+.overflow-hidden {
+ overflow: hidden !important;
+}
+
+.position-static {
+ position: static !important;
+}
+
+.position-relative {
+ position: relative !important;
+}
+
+.position-absolute {
+ position: absolute !important;
+}
+
+.position-fixed {
+ position: fixed !important;
+}
+
+.position-sticky {
+ position: -webkit-sticky !important;
+ position: sticky !important;
+}
+
+.fixed-top, .sb-nav-fixed #layoutSidenav #layoutSidenav_nav, .sb-nav-fixed .sb-topnav {
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+
+.fixed-bottom {
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1030;
+}
+
+@supports ((position: -webkit-sticky) or (position: sticky)) {
+ .sticky-top {
+ position: -webkit-sticky;
+ position: sticky;
+ top: 0;
+ z-index: 1020;
+ }
+}
+
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ overflow: visible;
+ clip: auto;
+ white-space: normal;
+}
+
+.shadow-sm {
+ box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;
+}
+
+.shadow {
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
+}
+
+.shadow-lg {
+ box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;
+}
+
+.shadow-none {
+ box-shadow: none !important;
+}
+
+.w-25 {
+ width: 25% !important;
+}
+
+.w-50 {
+ width: 50% !important;
+}
+
+.w-75 {
+ width: 75% !important;
+}
+
+.w-100 {
+ width: 100% !important;
+}
+
+.w-auto {
+ width: auto !important;
+}
+
+.h-25 {
+ height: 25% !important;
+}
+
+.h-50 {
+ height: 50% !important;
+}
+
+.h-75 {
+ height: 75% !important;
+}
+
+.h-100 {
+ height: 100% !important;
+}
+
+.h-auto {
+ height: auto !important;
+}
+
+.mw-100 {
+ max-width: 100% !important;
+}
+
+.mh-100 {
+ max-height: 100% !important;
+}
+
+.min-vw-100 {
+ min-width: 100vw !important;
+}
+
+.min-vh-100 {
+ min-height: 100vh !important;
+}
+
+.vw-100 {
+ width: 100vw !important;
+}
+
+.vh-100 {
+ height: 100vh !important;
+}
+
+.m-0 {
+ margin: 0 !important;
+}
+
+.mt-0,
+.my-0 {
+ margin-top: 0 !important;
+}
+
+.mr-0,
+.mx-0 {
+ margin-right: 0 !important;
+}
+
+.mb-0,
+.my-0 {
+ margin-bottom: 0 !important;
+}
+
+.ml-0,
+.mx-0 {
+ margin-left: 0 !important;
+}
+
+.m-1 {
+ margin: 0.25rem !important;
+}
+
+.mt-1,
+.my-1 {
+ margin-top: 0.25rem !important;
+}
+
+.mr-1,
+.mx-1 {
+ margin-right: 0.25rem !important;
+}
+
+.mb-1,
+.my-1 {
+ margin-bottom: 0.25rem !important;
+}
+
+.ml-1,
+.mx-1 {
+ margin-left: 0.25rem !important;
+}
+
+.m-2 {
+ margin: 0.5rem !important;
+}
+
+.mt-2,
+.my-2 {
+ margin-top: 0.5rem !important;
+}
+
+.mr-2,
+.mx-2 {
+ margin-right: 0.5rem !important;
+}
+
+.mb-2,
+.my-2 {
+ margin-bottom: 0.5rem !important;
+}
+
+.ml-2,
+.mx-2 {
+ margin-left: 0.5rem !important;
+}
+
+.m-3 {
+ margin: 1rem !important;
+}
+
+.mt-3,
+.my-3 {
+ margin-top: 1rem !important;
+}
+
+.mr-3,
+.mx-3 {
+ margin-right: 1rem !important;
+}
+
+.mb-3,
+.my-3 {
+ margin-bottom: 1rem !important;
+}
+
+.ml-3,
+.mx-3 {
+ margin-left: 1rem !important;
+}
+
+.m-4 {
+ margin: 1.5rem !important;
+}
+
+.mt-4,
+.my-4 {
+ margin-top: 1.5rem !important;
+}
+
+.mr-4,
+.mx-4 {
+ margin-right: 1.5rem !important;
+}
+
+.mb-4,
+.my-4 {
+ margin-bottom: 1.5rem !important;
+}
+
+.ml-4,
+.mx-4 {
+ margin-left: 1.5rem !important;
+}
+
+.m-5 {
+ margin: 3rem !important;
+}
+
+.mt-5,
+.my-5 {
+ margin-top: 3rem !important;
+}
+
+.mr-5,
+.mx-5 {
+ margin-right: 3rem !important;
+}
+
+.mb-5,
+.my-5 {
+ margin-bottom: 3rem !important;
+}
+
+.ml-5,
+.mx-5 {
+ margin-left: 3rem !important;
+}
+
+.p-0 {
+ padding: 0 !important;
+}
+
+.pt-0,
+.py-0 {
+ padding-top: 0 !important;
+}
+
+.pr-0,
+.px-0 {
+ padding-right: 0 !important;
+}
+
+.pb-0,
+.py-0 {
+ padding-bottom: 0 !important;
+}
+
+.pl-0,
+.px-0 {
+ padding-left: 0 !important;
+}
+
+.p-1 {
+ padding: 0.25rem !important;
+}
+
+.pt-1,
+.py-1 {
+ padding-top: 0.25rem !important;
+}
+
+.pr-1,
+.px-1 {
+ padding-right: 0.25rem !important;
+}
+
+.pb-1,
+.py-1 {
+ padding-bottom: 0.25rem !important;
+}
+
+.pl-1,
+.px-1 {
+ padding-left: 0.25rem !important;
+}
+
+.p-2 {
+ padding: 0.5rem !important;
+}
+
+.pt-2,
+.py-2 {
+ padding-top: 0.5rem !important;
+}
+
+.pr-2,
+.px-2 {
+ padding-right: 0.5rem !important;
+}
+
+.pb-2,
+.py-2 {
+ padding-bottom: 0.5rem !important;
+}
+
+.pl-2,
+.px-2 {
+ padding-left: 0.5rem !important;
+}
+
+.p-3 {
+ padding: 1rem !important;
+}
+
+.pt-3,
+.py-3 {
+ padding-top: 1rem !important;
+}
+
+.pr-3,
+.px-3 {
+ padding-right: 1rem !important;
+}
+
+.pb-3,
+.py-3 {
+ padding-bottom: 1rem !important;
+}
+
+.pl-3,
+.px-3 {
+ padding-left: 1rem !important;
+}
+
+.p-4 {
+ padding: 1.5rem !important;
+}
+
+.pt-4,
+.py-4 {
+ padding-top: 1.5rem !important;
+}
+
+.pr-4,
+.px-4 {
+ padding-right: 1.5rem !important;
+}
+
+.pb-4,
+.py-4 {
+ padding-bottom: 1.5rem !important;
+}
+
+.pl-4,
+.px-4 {
+ padding-left: 1.5rem !important;
+}
+
+.p-5 {
+ padding: 3rem !important;
+}
+
+.pt-5,
+.py-5 {
+ padding-top: 3rem !important;
+}
+
+.pr-5,
+.px-5 {
+ padding-right: 3rem !important;
+}
+
+.pb-5,
+.py-5 {
+ padding-bottom: 3rem !important;
+}
+
+.pl-5,
+.px-5 {
+ padding-left: 3rem !important;
+}
+
+.m-n1 {
+ margin: -0.25rem !important;
+}
+
+.mt-n1,
+.my-n1 {
+ margin-top: -0.25rem !important;
+}
+
+.mr-n1,
+.mx-n1 {
+ margin-right: -0.25rem !important;
+}
+
+.mb-n1,
+.my-n1 {
+ margin-bottom: -0.25rem !important;
+}
+
+.ml-n1,
+.mx-n1 {
+ margin-left: -0.25rem !important;
+}
+
+.m-n2 {
+ margin: -0.5rem !important;
+}
+
+.mt-n2,
+.my-n2 {
+ margin-top: -0.5rem !important;
+}
+
+.mr-n2,
+.mx-n2 {
+ margin-right: -0.5rem !important;
+}
+
+.mb-n2,
+.my-n2 {
+ margin-bottom: -0.5rem !important;
+}
+
+.ml-n2,
+.mx-n2 {
+ margin-left: -0.5rem !important;
+}
+
+.m-n3 {
+ margin: -1rem !important;
+}
+
+.mt-n3,
+.my-n3 {
+ margin-top: -1rem !important;
+}
+
+.mr-n3,
+.mx-n3 {
+ margin-right: -1rem !important;
+}
+
+.mb-n3,
+.my-n3 {
+ margin-bottom: -1rem !important;
+}
+
+.ml-n3,
+.mx-n3 {
+ margin-left: -1rem !important;
+}
+
+.m-n4 {
+ margin: -1.5rem !important;
+}
+
+.mt-n4,
+.my-n4 {
+ margin-top: -1.5rem !important;
+}
+
+.mr-n4,
+.mx-n4 {
+ margin-right: -1.5rem !important;
+}
+
+.mb-n4,
+.my-n4 {
+ margin-bottom: -1.5rem !important;
+}
+
+.ml-n4,
+.mx-n4 {
+ margin-left: -1.5rem !important;
+}
+
+.m-n5 {
+ margin: -3rem !important;
+}
+
+.mt-n5,
+.my-n5 {
+ margin-top: -3rem !important;
+}
+
+.mr-n5,
+.mx-n5 {
+ margin-right: -3rem !important;
+}
+
+.mb-n5,
+.my-n5 {
+ margin-bottom: -3rem !important;
+}
+
+.ml-n5,
+.mx-n5 {
+ margin-left: -3rem !important;
+}
+
+.m-auto {
+ margin: auto !important;
+}
+
+.mt-auto,
+.my-auto {
+ margin-top: auto !important;
+}
+
+.mr-auto,
+.mx-auto {
+ margin-right: auto !important;
+}
+
+.mb-auto,
+.my-auto {
+ margin-bottom: auto !important;
+}
+
+.ml-auto,
+.mx-auto {
+ margin-left: auto !important;
+}
+
+@media (min-width: 576px) {
+ .m-sm-0 {
+ margin: 0 !important;
+ }
+
+ .mt-sm-0,
+.my-sm-0 {
+ margin-top: 0 !important;
+ }
+
+ .mr-sm-0,
+.mx-sm-0 {
+ margin-right: 0 !important;
+ }
+
+ .mb-sm-0,
+.my-sm-0 {
+ margin-bottom: 0 !important;
+ }
+
+ .ml-sm-0,
+.mx-sm-0 {
+ margin-left: 0 !important;
+ }
+
+ .m-sm-1 {
+ margin: 0.25rem !important;
+ }
+
+ .mt-sm-1,
+.my-sm-1 {
+ margin-top: 0.25rem !important;
+ }
+
+ .mr-sm-1,
+.mx-sm-1 {
+ margin-right: 0.25rem !important;
+ }
+
+ .mb-sm-1,
+.my-sm-1 {
+ margin-bottom: 0.25rem !important;
+ }
+
+ .ml-sm-1,
+.mx-sm-1 {
+ margin-left: 0.25rem !important;
+ }
+
+ .m-sm-2 {
+ margin: 0.5rem !important;
+ }
+
+ .mt-sm-2,
+.my-sm-2 {
+ margin-top: 0.5rem !important;
+ }
+
+ .mr-sm-2,
+.mx-sm-2 {
+ margin-right: 0.5rem !important;
+ }
+
+ .mb-sm-2,
+.my-sm-2 {
+ margin-bottom: 0.5rem !important;
+ }
+
+ .ml-sm-2,
+.mx-sm-2 {
+ margin-left: 0.5rem !important;
+ }
+
+ .m-sm-3 {
+ margin: 1rem !important;
+ }
+
+ .mt-sm-3,
+.my-sm-3 {
+ margin-top: 1rem !important;
+ }
+
+ .mr-sm-3,
+.mx-sm-3 {
+ margin-right: 1rem !important;
+ }
+
+ .mb-sm-3,
+.my-sm-3 {
+ margin-bottom: 1rem !important;
+ }
+
+ .ml-sm-3,
+.mx-sm-3 {
+ margin-left: 1rem !important;
+ }
+
+ .m-sm-4 {
+ margin: 1.5rem !important;
+ }
+
+ .mt-sm-4,
+.my-sm-4 {
+ margin-top: 1.5rem !important;
+ }
+
+ .mr-sm-4,
+.mx-sm-4 {
+ margin-right: 1.5rem !important;
+ }
+
+ .mb-sm-4,
+.my-sm-4 {
+ margin-bottom: 1.5rem !important;
+ }
+
+ .ml-sm-4,
+.mx-sm-4 {
+ margin-left: 1.5rem !important;
+ }
+
+ .m-sm-5 {
+ margin: 3rem !important;
+ }
+
+ .mt-sm-5,
+.my-sm-5 {
+ margin-top: 3rem !important;
+ }
+
+ .mr-sm-5,
+.mx-sm-5 {
+ margin-right: 3rem !important;
+ }
+
+ .mb-sm-5,
+.my-sm-5 {
+ margin-bottom: 3rem !important;
+ }
+
+ .ml-sm-5,
+.mx-sm-5 {
+ margin-left: 3rem !important;
+ }
+
+ .p-sm-0 {
+ padding: 0 !important;
+ }
+
+ .pt-sm-0,
+.py-sm-0 {
+ padding-top: 0 !important;
+ }
+
+ .pr-sm-0,
+.px-sm-0 {
+ padding-right: 0 !important;
+ }
+
+ .pb-sm-0,
+.py-sm-0 {
+ padding-bottom: 0 !important;
+ }
+
+ .pl-sm-0,
+.px-sm-0 {
+ padding-left: 0 !important;
+ }
+
+ .p-sm-1 {
+ padding: 0.25rem !important;
+ }
+
+ .pt-sm-1,
+.py-sm-1 {
+ padding-top: 0.25rem !important;
+ }
+
+ .pr-sm-1,
+.px-sm-1 {
+ padding-right: 0.25rem !important;
+ }
+
+ .pb-sm-1,
+.py-sm-1 {
+ padding-bottom: 0.25rem !important;
+ }
+
+ .pl-sm-1,
+.px-sm-1 {
+ padding-left: 0.25rem !important;
+ }
+
+ .p-sm-2 {
+ padding: 0.5rem !important;
+ }
+
+ .pt-sm-2,
+.py-sm-2 {
+ padding-top: 0.5rem !important;
+ }
+
+ .pr-sm-2,
+.px-sm-2 {
+ padding-right: 0.5rem !important;
+ }
+
+ .pb-sm-2,
+.py-sm-2 {
+ padding-bottom: 0.5rem !important;
+ }
+
+ .pl-sm-2,
+.px-sm-2 {
+ padding-left: 0.5rem !important;
+ }
+
+ .p-sm-3 {
+ padding: 1rem !important;
+ }
+
+ .pt-sm-3,
+.py-sm-3 {
+ padding-top: 1rem !important;
+ }
+
+ .pr-sm-3,
+.px-sm-3 {
+ padding-right: 1rem !important;
+ }
+
+ .pb-sm-3,
+.py-sm-3 {
+ padding-bottom: 1rem !important;
+ }
+
+ .pl-sm-3,
+.px-sm-3 {
+ padding-left: 1rem !important;
+ }
+
+ .p-sm-4 {
+ padding: 1.5rem !important;
+ }
+
+ .pt-sm-4,
+.py-sm-4 {
+ padding-top: 1.5rem !important;
+ }
+
+ .pr-sm-4,
+.px-sm-4 {
+ padding-right: 1.5rem !important;
+ }
+
+ .pb-sm-4,
+.py-sm-4 {
+ padding-bottom: 1.5rem !important;
+ }
+
+ .pl-sm-4,
+.px-sm-4 {
+ padding-left: 1.5rem !important;
+ }
+
+ .p-sm-5 {
+ padding: 3rem !important;
+ }
+
+ .pt-sm-5,
+.py-sm-5 {
+ padding-top: 3rem !important;
+ }
+
+ .pr-sm-5,
+.px-sm-5 {
+ padding-right: 3rem !important;
+ }
+
+ .pb-sm-5,
+.py-sm-5 {
+ padding-bottom: 3rem !important;
+ }
+
+ .pl-sm-5,
+.px-sm-5 {
+ padding-left: 3rem !important;
+ }
+
+ .m-sm-n1 {
+ margin: -0.25rem !important;
+ }
+
+ .mt-sm-n1,
+.my-sm-n1 {
+ margin-top: -0.25rem !important;
+ }
+
+ .mr-sm-n1,
+.mx-sm-n1 {
+ margin-right: -0.25rem !important;
+ }
+
+ .mb-sm-n1,
+.my-sm-n1 {
+ margin-bottom: -0.25rem !important;
+ }
+
+ .ml-sm-n1,
+.mx-sm-n1 {
+ margin-left: -0.25rem !important;
+ }
+
+ .m-sm-n2 {
+ margin: -0.5rem !important;
+ }
+
+ .mt-sm-n2,
+.my-sm-n2 {
+ margin-top: -0.5rem !important;
+ }
+
+ .mr-sm-n2,
+.mx-sm-n2 {
+ margin-right: -0.5rem !important;
+ }
+
+ .mb-sm-n2,
+.my-sm-n2 {
+ margin-bottom: -0.5rem !important;
+ }
+
+ .ml-sm-n2,
+.mx-sm-n2 {
+ margin-left: -0.5rem !important;
+ }
+
+ .m-sm-n3 {
+ margin: -1rem !important;
+ }
+
+ .mt-sm-n3,
+.my-sm-n3 {
+ margin-top: -1rem !important;
+ }
+
+ .mr-sm-n3,
+.mx-sm-n3 {
+ margin-right: -1rem !important;
+ }
+
+ .mb-sm-n3,
+.my-sm-n3 {
+ margin-bottom: -1rem !important;
+ }
+
+ .ml-sm-n3,
+.mx-sm-n3 {
+ margin-left: -1rem !important;
+ }
+
+ .m-sm-n4 {
+ margin: -1.5rem !important;
+ }
+
+ .mt-sm-n4,
+.my-sm-n4 {
+ margin-top: -1.5rem !important;
+ }
+
+ .mr-sm-n4,
+.mx-sm-n4 {
+ margin-right: -1.5rem !important;
+ }
+
+ .mb-sm-n4,
+.my-sm-n4 {
+ margin-bottom: -1.5rem !important;
+ }
+
+ .ml-sm-n4,
+.mx-sm-n4 {
+ margin-left: -1.5rem !important;
+ }
+
+ .m-sm-n5 {
+ margin: -3rem !important;
+ }
+
+ .mt-sm-n5,
+.my-sm-n5 {
+ margin-top: -3rem !important;
+ }
+
+ .mr-sm-n5,
+.mx-sm-n5 {
+ margin-right: -3rem !important;
+ }
+
+ .mb-sm-n5,
+.my-sm-n5 {
+ margin-bottom: -3rem !important;
+ }
+
+ .ml-sm-n5,
+.mx-sm-n5 {
+ margin-left: -3rem !important;
+ }
+
+ .m-sm-auto {
+ margin: auto !important;
+ }
+
+ .mt-sm-auto,
+.my-sm-auto {
+ margin-top: auto !important;
+ }
+
+ .mr-sm-auto,
+.mx-sm-auto {
+ margin-right: auto !important;
+ }
+
+ .mb-sm-auto,
+.my-sm-auto {
+ margin-bottom: auto !important;
+ }
+
+ .ml-sm-auto,
+.mx-sm-auto {
+ margin-left: auto !important;
+ }
+}
+@media (min-width: 768px) {
+ .m-md-0 {
+ margin: 0 !important;
+ }
+
+ .mt-md-0,
+.my-md-0 {
+ margin-top: 0 !important;
+ }
+
+ .mr-md-0,
+.mx-md-0 {
+ margin-right: 0 !important;
+ }
+
+ .mb-md-0,
+.my-md-0 {
+ margin-bottom: 0 !important;
+ }
+
+ .ml-md-0,
+.mx-md-0 {
+ margin-left: 0 !important;
+ }
+
+ .m-md-1 {
+ margin: 0.25rem !important;
+ }
+
+ .mt-md-1,
+.my-md-1 {
+ margin-top: 0.25rem !important;
+ }
+
+ .mr-md-1,
+.mx-md-1 {
+ margin-right: 0.25rem !important;
+ }
+
+ .mb-md-1,
+.my-md-1 {
+ margin-bottom: 0.25rem !important;
+ }
+
+ .ml-md-1,
+.mx-md-1 {
+ margin-left: 0.25rem !important;
+ }
+
+ .m-md-2 {
+ margin: 0.5rem !important;
+ }
+
+ .mt-md-2,
+.my-md-2 {
+ margin-top: 0.5rem !important;
+ }
+
+ .mr-md-2,
+.mx-md-2 {
+ margin-right: 0.5rem !important;
+ }
+
+ .mb-md-2,
+.my-md-2 {
+ margin-bottom: 0.5rem !important;
+ }
+
+ .ml-md-2,
+.mx-md-2 {
+ margin-left: 0.5rem !important;
+ }
+
+ .m-md-3 {
+ margin: 1rem !important;
+ }
+
+ .mt-md-3,
+.my-md-3 {
+ margin-top: 1rem !important;
+ }
+
+ .mr-md-3,
+.mx-md-3 {
+ margin-right: 1rem !important;
+ }
+
+ .mb-md-3,
+.my-md-3 {
+ margin-bottom: 1rem !important;
+ }
+
+ .ml-md-3,
+.mx-md-3 {
+ margin-left: 1rem !important;
+ }
+
+ .m-md-4 {
+ margin: 1.5rem !important;
+ }
+
+ .mt-md-4,
+.my-md-4 {
+ margin-top: 1.5rem !important;
+ }
+
+ .mr-md-4,
+.mx-md-4 {
+ margin-right: 1.5rem !important;
+ }
+
+ .mb-md-4,
+.my-md-4 {
+ margin-bottom: 1.5rem !important;
+ }
+
+ .ml-md-4,
+.mx-md-4 {
+ margin-left: 1.5rem !important;
+ }
+
+ .m-md-5 {
+ margin: 3rem !important;
+ }
+
+ .mt-md-5,
+.my-md-5 {
+ margin-top: 3rem !important;
+ }
+
+ .mr-md-5,
+.mx-md-5 {
+ margin-right: 3rem !important;
+ }
+
+ .mb-md-5,
+.my-md-5 {
+ margin-bottom: 3rem !important;
+ }
+
+ .ml-md-5,
+.mx-md-5 {
+ margin-left: 3rem !important;
+ }
+
+ .p-md-0 {
+ padding: 0 !important;
+ }
+
+ .pt-md-0,
+.py-md-0 {
+ padding-top: 0 !important;
+ }
+
+ .pr-md-0,
+.px-md-0 {
+ padding-right: 0 !important;
+ }
+
+ .pb-md-0,
+.py-md-0 {
+ padding-bottom: 0 !important;
+ }
+
+ .pl-md-0,
+.px-md-0 {
+ padding-left: 0 !important;
+ }
+
+ .p-md-1 {
+ padding: 0.25rem !important;
+ }
+
+ .pt-md-1,
+.py-md-1 {
+ padding-top: 0.25rem !important;
+ }
+
+ .pr-md-1,
+.px-md-1 {
+ padding-right: 0.25rem !important;
+ }
+
+ .pb-md-1,
+.py-md-1 {
+ padding-bottom: 0.25rem !important;
+ }
+
+ .pl-md-1,
+.px-md-1 {
+ padding-left: 0.25rem !important;
+ }
+
+ .p-md-2 {
+ padding: 0.5rem !important;
+ }
+
+ .pt-md-2,
+.py-md-2 {
+ padding-top: 0.5rem !important;
+ }
+
+ .pr-md-2,
+.px-md-2 {
+ padding-right: 0.5rem !important;
+ }
+
+ .pb-md-2,
+.py-md-2 {
+ padding-bottom: 0.5rem !important;
+ }
+
+ .pl-md-2,
+.px-md-2 {
+ padding-left: 0.5rem !important;
+ }
+
+ .p-md-3 {
+ padding: 1rem !important;
+ }
+
+ .pt-md-3,
+.py-md-3 {
+ padding-top: 1rem !important;
+ }
+
+ .pr-md-3,
+.px-md-3 {
+ padding-right: 1rem !important;
+ }
+
+ .pb-md-3,
+.py-md-3 {
+ padding-bottom: 1rem !important;
+ }
+
+ .pl-md-3,
+.px-md-3 {
+ padding-left: 1rem !important;
+ }
+
+ .p-md-4 {
+ padding: 1.5rem !important;
+ }
+
+ .pt-md-4,
+.py-md-4 {
+ padding-top: 1.5rem !important;
+ }
+
+ .pr-md-4,
+.px-md-4 {
+ padding-right: 1.5rem !important;
+ }
+
+ .pb-md-4,
+.py-md-4 {
+ padding-bottom: 1.5rem !important;
+ }
+
+ .pl-md-4,
+.px-md-4 {
+ padding-left: 1.5rem !important;
+ }
+
+ .p-md-5 {
+ padding: 3rem !important;
+ }
+
+ .pt-md-5,
+.py-md-5 {
+ padding-top: 3rem !important;
+ }
+
+ .pr-md-5,
+.px-md-5 {
+ padding-right: 3rem !important;
+ }
+
+ .pb-md-5,
+.py-md-5 {
+ padding-bottom: 3rem !important;
+ }
+
+ .pl-md-5,
+.px-md-5 {
+ padding-left: 3rem !important;
+ }
+
+ .m-md-n1 {
+ margin: -0.25rem !important;
+ }
+
+ .mt-md-n1,
+.my-md-n1 {
+ margin-top: -0.25rem !important;
+ }
+
+ .mr-md-n1,
+.mx-md-n1 {
+ margin-right: -0.25rem !important;
+ }
+
+ .mb-md-n1,
+.my-md-n1 {
+ margin-bottom: -0.25rem !important;
+ }
+
+ .ml-md-n1,
+.mx-md-n1 {
+ margin-left: -0.25rem !important;
+ }
+
+ .m-md-n2 {
+ margin: -0.5rem !important;
+ }
+
+ .mt-md-n2,
+.my-md-n2 {
+ margin-top: -0.5rem !important;
+ }
+
+ .mr-md-n2,
+.mx-md-n2 {
+ margin-right: -0.5rem !important;
+ }
+
+ .mb-md-n2,
+.my-md-n2 {
+ margin-bottom: -0.5rem !important;
+ }
+
+ .ml-md-n2,
+.mx-md-n2 {
+ margin-left: -0.5rem !important;
+ }
+
+ .m-md-n3 {
+ margin: -1rem !important;
+ }
+
+ .mt-md-n3,
+.my-md-n3 {
+ margin-top: -1rem !important;
+ }
+
+ .mr-md-n3,
+.mx-md-n3 {
+ margin-right: -1rem !important;
+ }
+
+ .mb-md-n3,
+.my-md-n3 {
+ margin-bottom: -1rem !important;
+ }
+
+ .ml-md-n3,
+.mx-md-n3 {
+ margin-left: -1rem !important;
+ }
+
+ .m-md-n4 {
+ margin: -1.5rem !important;
+ }
+
+ .mt-md-n4,
+.my-md-n4 {
+ margin-top: -1.5rem !important;
+ }
+
+ .mr-md-n4,
+.mx-md-n4 {
+ margin-right: -1.5rem !important;
+ }
+
+ .mb-md-n4,
+.my-md-n4 {
+ margin-bottom: -1.5rem !important;
+ }
+
+ .ml-md-n4,
+.mx-md-n4 {
+ margin-left: -1.5rem !important;
+ }
+
+ .m-md-n5 {
+ margin: -3rem !important;
+ }
+
+ .mt-md-n5,
+.my-md-n5 {
+ margin-top: -3rem !important;
+ }
+
+ .mr-md-n5,
+.mx-md-n5 {
+ margin-right: -3rem !important;
+ }
+
+ .mb-md-n5,
+.my-md-n5 {
+ margin-bottom: -3rem !important;
+ }
+
+ .ml-md-n5,
+.mx-md-n5 {
+ margin-left: -3rem !important;
+ }
+
+ .m-md-auto {
+ margin: auto !important;
+ }
+
+ .mt-md-auto,
+.my-md-auto {
+ margin-top: auto !important;
+ }
+
+ .mr-md-auto,
+.mx-md-auto {
+ margin-right: auto !important;
+ }
+
+ .mb-md-auto,
+.my-md-auto {
+ margin-bottom: auto !important;
+ }
+
+ .ml-md-auto,
+.mx-md-auto {
+ margin-left: auto !important;
+ }
+}
+@media (min-width: 992px) {
+ .m-lg-0 {
+ margin: 0 !important;
+ }
+
+ .mt-lg-0,
+.my-lg-0 {
+ margin-top: 0 !important;
+ }
+
+ .mr-lg-0,
+.mx-lg-0 {
+ margin-right: 0 !important;
+ }
+
+ .mb-lg-0,
+.my-lg-0 {
+ margin-bottom: 0 !important;
+ }
+
+ .ml-lg-0,
+.mx-lg-0 {
+ margin-left: 0 !important;
+ }
+
+ .m-lg-1 {
+ margin: 0.25rem !important;
+ }
+
+ .mt-lg-1,
+.my-lg-1 {
+ margin-top: 0.25rem !important;
+ }
+
+ .mr-lg-1,
+.mx-lg-1 {
+ margin-right: 0.25rem !important;
+ }
+
+ .mb-lg-1,
+.my-lg-1 {
+ margin-bottom: 0.25rem !important;
+ }
+
+ .ml-lg-1,
+.mx-lg-1 {
+ margin-left: 0.25rem !important;
+ }
+
+ .m-lg-2 {
+ margin: 0.5rem !important;
+ }
+
+ .mt-lg-2,
+.my-lg-2 {
+ margin-top: 0.5rem !important;
+ }
+
+ .mr-lg-2,
+.mx-lg-2 {
+ margin-right: 0.5rem !important;
+ }
+
+ .mb-lg-2,
+.my-lg-2 {
+ margin-bottom: 0.5rem !important;
+ }
+
+ .ml-lg-2,
+.mx-lg-2 {
+ margin-left: 0.5rem !important;
+ }
+
+ .m-lg-3 {
+ margin: 1rem !important;
+ }
+
+ .mt-lg-3,
+.my-lg-3 {
+ margin-top: 1rem !important;
+ }
+
+ .mr-lg-3,
+.mx-lg-3 {
+ margin-right: 1rem !important;
+ }
+
+ .mb-lg-3,
+.my-lg-3 {
+ margin-bottom: 1rem !important;
+ }
+
+ .ml-lg-3,
+.mx-lg-3 {
+ margin-left: 1rem !important;
+ }
+
+ .m-lg-4 {
+ margin: 1.5rem !important;
+ }
+
+ .mt-lg-4,
+.my-lg-4 {
+ margin-top: 1.5rem !important;
+ }
+
+ .mr-lg-4,
+.mx-lg-4 {
+ margin-right: 1.5rem !important;
+ }
+
+ .mb-lg-4,
+.my-lg-4 {
+ margin-bottom: 1.5rem !important;
+ }
+
+ .ml-lg-4,
+.mx-lg-4 {
+ margin-left: 1.5rem !important;
+ }
+
+ .m-lg-5 {
+ margin: 3rem !important;
+ }
+
+ .mt-lg-5,
+.my-lg-5 {
+ margin-top: 3rem !important;
+ }
+
+ .mr-lg-5,
+.mx-lg-5 {
+ margin-right: 3rem !important;
+ }
+
+ .mb-lg-5,
+.my-lg-5 {
+ margin-bottom: 3rem !important;
+ }
+
+ .ml-lg-5,
+.mx-lg-5 {
+ margin-left: 3rem !important;
+ }
+
+ .p-lg-0 {
+ padding: 0 !important;
+ }
+
+ .pt-lg-0,
+.py-lg-0 {
+ padding-top: 0 !important;
+ }
+
+ .pr-lg-0,
+.px-lg-0 {
+ padding-right: 0 !important;
+ }
+
+ .pb-lg-0,
+.py-lg-0 {
+ padding-bottom: 0 !important;
+ }
+
+ .pl-lg-0,
+.px-lg-0 {
+ padding-left: 0 !important;
+ }
+
+ .p-lg-1 {
+ padding: 0.25rem !important;
+ }
+
+ .pt-lg-1,
+.py-lg-1 {
+ padding-top: 0.25rem !important;
+ }
+
+ .pr-lg-1,
+.px-lg-1 {
+ padding-right: 0.25rem !important;
+ }
+
+ .pb-lg-1,
+.py-lg-1 {
+ padding-bottom: 0.25rem !important;
+ }
+
+ .pl-lg-1,
+.px-lg-1 {
+ padding-left: 0.25rem !important;
+ }
+
+ .p-lg-2 {
+ padding: 0.5rem !important;
+ }
+
+ .pt-lg-2,
+.py-lg-2 {
+ padding-top: 0.5rem !important;
+ }
+
+ .pr-lg-2,
+.px-lg-2 {
+ padding-right: 0.5rem !important;
+ }
+
+ .pb-lg-2,
+.py-lg-2 {
+ padding-bottom: 0.5rem !important;
+ }
+
+ .pl-lg-2,
+.px-lg-2 {
+ padding-left: 0.5rem !important;
+ }
+
+ .p-lg-3 {
+ padding: 1rem !important;
+ }
+
+ .pt-lg-3,
+.py-lg-3 {
+ padding-top: 1rem !important;
+ }
+
+ .pr-lg-3,
+.px-lg-3 {
+ padding-right: 1rem !important;
+ }
+
+ .pb-lg-3,
+.py-lg-3 {
+ padding-bottom: 1rem !important;
+ }
+
+ .pl-lg-3,
+.px-lg-3 {
+ padding-left: 1rem !important;
+ }
+
+ .p-lg-4 {
+ padding: 1.5rem !important;
+ }
+
+ .pt-lg-4,
+.py-lg-4 {
+ padding-top: 1.5rem !important;
+ }
+
+ .pr-lg-4,
+.px-lg-4 {
+ padding-right: 1.5rem !important;
+ }
+
+ .pb-lg-4,
+.py-lg-4 {
+ padding-bottom: 1.5rem !important;
+ }
+
+ .pl-lg-4,
+.px-lg-4 {
+ padding-left: 1.5rem !important;
+ }
+
+ .p-lg-5 {
+ padding: 3rem !important;
+ }
+
+ .pt-lg-5,
+.py-lg-5 {
+ padding-top: 3rem !important;
+ }
+
+ .pr-lg-5,
+.px-lg-5 {
+ padding-right: 3rem !important;
+ }
+
+ .pb-lg-5,
+.py-lg-5 {
+ padding-bottom: 3rem !important;
+ }
+
+ .pl-lg-5,
+.px-lg-5 {
+ padding-left: 3rem !important;
+ }
+
+ .m-lg-n1 {
+ margin: -0.25rem !important;
+ }
+
+ .mt-lg-n1,
+.my-lg-n1 {
+ margin-top: -0.25rem !important;
+ }
+
+ .mr-lg-n1,
+.mx-lg-n1 {
+ margin-right: -0.25rem !important;
+ }
+
+ .mb-lg-n1,
+.my-lg-n1 {
+ margin-bottom: -0.25rem !important;
+ }
+
+ .ml-lg-n1,
+.mx-lg-n1 {
+ margin-left: -0.25rem !important;
+ }
+
+ .m-lg-n2 {
+ margin: -0.5rem !important;
+ }
+
+ .mt-lg-n2,
+.my-lg-n2 {
+ margin-top: -0.5rem !important;
+ }
+
+ .mr-lg-n2,
+.mx-lg-n2 {
+ margin-right: -0.5rem !important;
+ }
+
+ .mb-lg-n2,
+.my-lg-n2 {
+ margin-bottom: -0.5rem !important;
+ }
+
+ .ml-lg-n2,
+.mx-lg-n2 {
+ margin-left: -0.5rem !important;
+ }
+
+ .m-lg-n3 {
+ margin: -1rem !important;
+ }
+
+ .mt-lg-n3,
+.my-lg-n3 {
+ margin-top: -1rem !important;
+ }
+
+ .mr-lg-n3,
+.mx-lg-n3 {
+ margin-right: -1rem !important;
+ }
+
+ .mb-lg-n3,
+.my-lg-n3 {
+ margin-bottom: -1rem !important;
+ }
+
+ .ml-lg-n3,
+.mx-lg-n3 {
+ margin-left: -1rem !important;
+ }
+
+ .m-lg-n4 {
+ margin: -1.5rem !important;
+ }
+
+ .mt-lg-n4,
+.my-lg-n4 {
+ margin-top: -1.5rem !important;
+ }
+
+ .mr-lg-n4,
+.mx-lg-n4 {
+ margin-right: -1.5rem !important;
+ }
+
+ .mb-lg-n4,
+.my-lg-n4 {
+ margin-bottom: -1.5rem !important;
+ }
+
+ .ml-lg-n4,
+.mx-lg-n4 {
+ margin-left: -1.5rem !important;
+ }
+
+ .m-lg-n5 {
+ margin: -3rem !important;
+ }
+
+ .mt-lg-n5,
+.my-lg-n5 {
+ margin-top: -3rem !important;
+ }
+
+ .mr-lg-n5,
+.mx-lg-n5 {
+ margin-right: -3rem !important;
+ }
+
+ .mb-lg-n5,
+.my-lg-n5 {
+ margin-bottom: -3rem !important;
+ }
+
+ .ml-lg-n5,
+.mx-lg-n5 {
+ margin-left: -3rem !important;
+ }
+
+ .m-lg-auto {
+ margin: auto !important;
+ }
+
+ .mt-lg-auto,
+.my-lg-auto {
+ margin-top: auto !important;
+ }
+
+ .mr-lg-auto,
+.mx-lg-auto {
+ margin-right: auto !important;
+ }
+
+ .mb-lg-auto,
+.my-lg-auto {
+ margin-bottom: auto !important;
+ }
+
+ .ml-lg-auto,
+.mx-lg-auto {
+ margin-left: auto !important;
+ }
+}
+@media (min-width: 1200px) {
+ .m-xl-0 {
+ margin: 0 !important;
+ }
+
+ .mt-xl-0,
+.my-xl-0 {
+ margin-top: 0 !important;
+ }
+
+ .mr-xl-0,
+.mx-xl-0 {
+ margin-right: 0 !important;
+ }
+
+ .mb-xl-0,
+.my-xl-0 {
+ margin-bottom: 0 !important;
+ }
+
+ .ml-xl-0,
+.mx-xl-0 {
+ margin-left: 0 !important;
+ }
+
+ .m-xl-1 {
+ margin: 0.25rem !important;
+ }
+
+ .mt-xl-1,
+.my-xl-1 {
+ margin-top: 0.25rem !important;
+ }
+
+ .mr-xl-1,
+.mx-xl-1 {
+ margin-right: 0.25rem !important;
+ }
+
+ .mb-xl-1,
+.my-xl-1 {
+ margin-bottom: 0.25rem !important;
+ }
+
+ .ml-xl-1,
+.mx-xl-1 {
+ margin-left: 0.25rem !important;
+ }
+
+ .m-xl-2 {
+ margin: 0.5rem !important;
+ }
+
+ .mt-xl-2,
+.my-xl-2 {
+ margin-top: 0.5rem !important;
+ }
+
+ .mr-xl-2,
+.mx-xl-2 {
+ margin-right: 0.5rem !important;
+ }
+
+ .mb-xl-2,
+.my-xl-2 {
+ margin-bottom: 0.5rem !important;
+ }
+
+ .ml-xl-2,
+.mx-xl-2 {
+ margin-left: 0.5rem !important;
+ }
+
+ .m-xl-3 {
+ margin: 1rem !important;
+ }
+
+ .mt-xl-3,
+.my-xl-3 {
+ margin-top: 1rem !important;
+ }
+
+ .mr-xl-3,
+.mx-xl-3 {
+ margin-right: 1rem !important;
+ }
+
+ .mb-xl-3,
+.my-xl-3 {
+ margin-bottom: 1rem !important;
+ }
+
+ .ml-xl-3,
+.mx-xl-3 {
+ margin-left: 1rem !important;
+ }
+
+ .m-xl-4 {
+ margin: 1.5rem !important;
+ }
+
+ .mt-xl-4,
+.my-xl-4 {
+ margin-top: 1.5rem !important;
+ }
+
+ .mr-xl-4,
+.mx-xl-4 {
+ margin-right: 1.5rem !important;
+ }
+
+ .mb-xl-4,
+.my-xl-4 {
+ margin-bottom: 1.5rem !important;
+ }
+
+ .ml-xl-4,
+.mx-xl-4 {
+ margin-left: 1.5rem !important;
+ }
+
+ .m-xl-5 {
+ margin: 3rem !important;
+ }
+
+ .mt-xl-5,
+.my-xl-5 {
+ margin-top: 3rem !important;
+ }
+
+ .mr-xl-5,
+.mx-xl-5 {
+ margin-right: 3rem !important;
+ }
+
+ .mb-xl-5,
+.my-xl-5 {
+ margin-bottom: 3rem !important;
+ }
+
+ .ml-xl-5,
+.mx-xl-5 {
+ margin-left: 3rem !important;
+ }
+
+ .p-xl-0 {
+ padding: 0 !important;
+ }
+
+ .pt-xl-0,
+.py-xl-0 {
+ padding-top: 0 !important;
+ }
+
+ .pr-xl-0,
+.px-xl-0 {
+ padding-right: 0 !important;
+ }
+
+ .pb-xl-0,
+.py-xl-0 {
+ padding-bottom: 0 !important;
+ }
+
+ .pl-xl-0,
+.px-xl-0 {
+ padding-left: 0 !important;
+ }
+
+ .p-xl-1 {
+ padding: 0.25rem !important;
+ }
+
+ .pt-xl-1,
+.py-xl-1 {
+ padding-top: 0.25rem !important;
+ }
+
+ .pr-xl-1,
+.px-xl-1 {
+ padding-right: 0.25rem !important;
+ }
+
+ .pb-xl-1,
+.py-xl-1 {
+ padding-bottom: 0.25rem !important;
+ }
+
+ .pl-xl-1,
+.px-xl-1 {
+ padding-left: 0.25rem !important;
+ }
+
+ .p-xl-2 {
+ padding: 0.5rem !important;
+ }
+
+ .pt-xl-2,
+.py-xl-2 {
+ padding-top: 0.5rem !important;
+ }
+
+ .pr-xl-2,
+.px-xl-2 {
+ padding-right: 0.5rem !important;
+ }
+
+ .pb-xl-2,
+.py-xl-2 {
+ padding-bottom: 0.5rem !important;
+ }
+
+ .pl-xl-2,
+.px-xl-2 {
+ padding-left: 0.5rem !important;
+ }
+
+ .p-xl-3 {
+ padding: 1rem !important;
+ }
+
+ .pt-xl-3,
+.py-xl-3 {
+ padding-top: 1rem !important;
+ }
+
+ .pr-xl-3,
+.px-xl-3 {
+ padding-right: 1rem !important;
+ }
+
+ .pb-xl-3,
+.py-xl-3 {
+ padding-bottom: 1rem !important;
+ }
+
+ .pl-xl-3,
+.px-xl-3 {
+ padding-left: 1rem !important;
+ }
+
+ .p-xl-4 {
+ padding: 1.5rem !important;
+ }
+
+ .pt-xl-4,
+.py-xl-4 {
+ padding-top: 1.5rem !important;
+ }
+
+ .pr-xl-4,
+.px-xl-4 {
+ padding-right: 1.5rem !important;
+ }
+
+ .pb-xl-4,
+.py-xl-4 {
+ padding-bottom: 1.5rem !important;
+ }
+
+ .pl-xl-4,
+.px-xl-4 {
+ padding-left: 1.5rem !important;
+ }
+
+ .p-xl-5 {
+ padding: 3rem !important;
+ }
+
+ .pt-xl-5,
+.py-xl-5 {
+ padding-top: 3rem !important;
+ }
+
+ .pr-xl-5,
+.px-xl-5 {
+ padding-right: 3rem !important;
+ }
+
+ .pb-xl-5,
+.py-xl-5 {
+ padding-bottom: 3rem !important;
+ }
+
+ .pl-xl-5,
+.px-xl-5 {
+ padding-left: 3rem !important;
+ }
+
+ .m-xl-n1 {
+ margin: -0.25rem !important;
+ }
+
+ .mt-xl-n1,
+.my-xl-n1 {
+ margin-top: -0.25rem !important;
+ }
+
+ .mr-xl-n1,
+.mx-xl-n1 {
+ margin-right: -0.25rem !important;
+ }
+
+ .mb-xl-n1,
+.my-xl-n1 {
+ margin-bottom: -0.25rem !important;
+ }
+
+ .ml-xl-n1,
+.mx-xl-n1 {
+ margin-left: -0.25rem !important;
+ }
+
+ .m-xl-n2 {
+ margin: -0.5rem !important;
+ }
+
+ .mt-xl-n2,
+.my-xl-n2 {
+ margin-top: -0.5rem !important;
+ }
+
+ .mr-xl-n2,
+.mx-xl-n2 {
+ margin-right: -0.5rem !important;
+ }
+
+ .mb-xl-n2,
+.my-xl-n2 {
+ margin-bottom: -0.5rem !important;
+ }
+
+ .ml-xl-n2,
+.mx-xl-n2 {
+ margin-left: -0.5rem !important;
+ }
+
+ .m-xl-n3 {
+ margin: -1rem !important;
+ }
+
+ .mt-xl-n3,
+.my-xl-n3 {
+ margin-top: -1rem !important;
+ }
+
+ .mr-xl-n3,
+.mx-xl-n3 {
+ margin-right: -1rem !important;
+ }
+
+ .mb-xl-n3,
+.my-xl-n3 {
+ margin-bottom: -1rem !important;
+ }
+
+ .ml-xl-n3,
+.mx-xl-n3 {
+ margin-left: -1rem !important;
+ }
+
+ .m-xl-n4 {
+ margin: -1.5rem !important;
+ }
+
+ .mt-xl-n4,
+.my-xl-n4 {
+ margin-top: -1.5rem !important;
+ }
+
+ .mr-xl-n4,
+.mx-xl-n4 {
+ margin-right: -1.5rem !important;
+ }
+
+ .mb-xl-n4,
+.my-xl-n4 {
+ margin-bottom: -1.5rem !important;
+ }
+
+ .ml-xl-n4,
+.mx-xl-n4 {
+ margin-left: -1.5rem !important;
+ }
+
+ .m-xl-n5 {
+ margin: -3rem !important;
+ }
+
+ .mt-xl-n5,
+.my-xl-n5 {
+ margin-top: -3rem !important;
+ }
+
+ .mr-xl-n5,
+.mx-xl-n5 {
+ margin-right: -3rem !important;
+ }
+
+ .mb-xl-n5,
+.my-xl-n5 {
+ margin-bottom: -3rem !important;
+ }
+
+ .ml-xl-n5,
+.mx-xl-n5 {
+ margin-left: -3rem !important;
+ }
+
+ .m-xl-auto {
+ margin: auto !important;
+ }
+
+ .mt-xl-auto,
+.my-xl-auto {
+ margin-top: auto !important;
+ }
+
+ .mr-xl-auto,
+.mx-xl-auto {
+ margin-right: auto !important;
+ }
+
+ .mb-xl-auto,
+.my-xl-auto {
+ margin-bottom: auto !important;
+ }
+
+ .ml-xl-auto,
+.mx-xl-auto {
+ margin-left: auto !important;
+ }
+}
+.stretched-link::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1;
+ pointer-events: auto;
+ content: "";
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.text-monospace {
+ font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
+}
+
+.text-justify {
+ text-align: justify !important;
+}
+
+.text-wrap {
+ white-space: normal !important;
+}
+
+.text-nowrap {
+ white-space: nowrap !important;
+}
+
+.text-truncate {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.text-left {
+ text-align: left !important;
+}
+
+.text-right {
+ text-align: right !important;
+}
+
+.text-center {
+ text-align: center !important;
+}
+
+@media (min-width: 576px) {
+ .text-sm-left {
+ text-align: left !important;
+ }
+
+ .text-sm-right {
+ text-align: right !important;
+ }
+
+ .text-sm-center {
+ text-align: center !important;
+ }
+}
+@media (min-width: 768px) {
+ .text-md-left {
+ text-align: left !important;
+ }
+
+ .text-md-right {
+ text-align: right !important;
+ }
+
+ .text-md-center {
+ text-align: center !important;
+ }
+}
+@media (min-width: 992px) {
+ .text-lg-left {
+ text-align: left !important;
+ }
+
+ .text-lg-right {
+ text-align: right !important;
+ }
+
+ .text-lg-center {
+ text-align: center !important;
+ }
+}
+@media (min-width: 1200px) {
+ .text-xl-left {
+ text-align: left !important;
+ }
+
+ .text-xl-right {
+ text-align: right !important;
+ }
+
+ .text-xl-center {
+ text-align: center !important;
+ }
+}
+.text-lowercase {
+ text-transform: lowercase !important;
+}
+
+.text-uppercase {
+ text-transform: uppercase !important;
+}
+
+.text-capitalize {
+ text-transform: capitalize !important;
+}
+
+.font-weight-light {
+ font-weight: 300 !important;
+}
+
+.font-weight-lighter {
+ font-weight: lighter !important;
+}
+
+.font-weight-normal {
+ font-weight: 400 !important;
+}
+
+.font-weight-bold {
+ font-weight: 700 !important;
+}
+
+.font-weight-bolder {
+ font-weight: bolder !important;
+}
+
+.font-italic {
+ font-style: italic !important;
+}
+
+.text-white {
+ color: #fff !important;
+}
+
+.text-primary {
+ color: #007bff !important;
+}
+
+a.text-primary:hover, a.text-primary:focus {
+ color: #0056b3 !important;
+}
+
+.text-secondary {
+ color: #6c757d !important;
+}
+
+a.text-secondary:hover, a.text-secondary:focus {
+ color: #494f54 !important;
+}
+
+.text-success {
+ color: #28a745 !important;
+}
+
+a.text-success:hover, a.text-success:focus {
+ color: #19692c !important;
+}
+
+.text-info {
+ color: #17a2b8 !important;
+}
+
+a.text-info:hover, a.text-info:focus {
+ color: #0f6674 !important;
+}
+
+.text-warning {
+ color: #ffc107 !important;
+}
+
+a.text-warning:hover, a.text-warning:focus {
+ color: #ba8b00 !important;
+}
+
+.text-danger {
+ color: #dc3545 !important;
+}
+
+a.text-danger:hover, a.text-danger:focus {
+ color: #a71d2a !important;
+}
+
+.text-light {
+ color: #f8f9fa !important;
+}
+
+a.text-light:hover, a.text-light:focus {
+ color: #cbd3da !important;
+}
+
+.text-dark {
+ color: #343a40 !important;
+}
+
+a.text-dark:hover, a.text-dark:focus {
+ color: #121416 !important;
+}
+
+.text-body {
+ color: #212529 !important;
+}
+
+.text-muted {
+ color: #6c757d !important;
+}
+
+.text-black-50 {
+ color: rgba(0, 0, 0, 0.5) !important;
+}
+
+.text-white-50 {
+ color: rgba(255, 255, 255, 0.5) !important;
+}
+
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+
+.text-decoration-none {
+ text-decoration: none !important;
+}
+
+.text-break {
+ word-break: break-word !important;
+ word-wrap: break-word !important;
+}
+
+.text-reset {
+ color: inherit !important;
+}
+
+.visible {
+ visibility: visible !important;
+}
+
+.invisible {
+ visibility: hidden !important;
+}
+
+@media print {
+ *,
+*::before,
+*::after {
+ text-shadow: none !important;
+ box-shadow: none !important;
+ }
+
+ a:not(.btn) {
+ text-decoration: underline;
+ }
+
+ abbr[title]::after {
+ content: " (" attr(title) ")";
+ }
+
+ pre {
+ white-space: pre-wrap !important;
+ }
+
+ pre,
+blockquote {
+ border: 1px solid #adb5bd;
+ page-break-inside: avoid;
+ }
+
+ thead {
+ display: table-header-group;
+ }
+
+ tr,
+img {
+ page-break-inside: avoid;
+ }
+
+ p,
+h2,
+h3 {
+ orphans: 3;
+ widows: 3;
+ }
+
+ h2,
+h3 {
+ page-break-after: avoid;
+ }
+
+ @page {
+ size: a3;
+ }
+ body {
+ min-width: 992px !important;
+ }
+
+ .container {
+ min-width: 992px !important;
+ }
+
+ .navbar {
+ display: none;
+ }
+
+ .badge {
+ border: 1px solid #000;
+ }
+
+ .table {
+ border-collapse: collapse !important;
+ }
+ .table td,
+.table th {
+ background-color: #fff !important;
+ }
+
+ .table-bordered th,
+.table-bordered td {
+ border: 1px solid #dee2e6 !important;
+ }
+
+ .table-dark {
+ color: inherit;
+ }
+ .table-dark th,
+.table-dark td,
+.table-dark thead th,
+.table-dark tbody + tbody {
+ border-color: #dee2e6;
+ }
+
+ .table .thead-dark th {
+ color: inherit;
+ border-color: #dee2e6;
+ }
+}
+html,
+body {
+ height: 100%;
+}
+
+.container,
+.container-fluid,
+.container-sm,
+.container-md,
+.container-lg,
+.container-xl {
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+}
+
+#layoutAuthentication {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+#layoutAuthentication #layoutAuthentication_content {
+ min-width: 0;
+ flex-grow: 1;
+}
+#layoutAuthentication #layoutAuthentication_footer {
+ min-width: 0;
+}
+
+#layoutSidenav {
+ display: flex;
+}
+#layoutSidenav #layoutSidenav_nav {
+ flex-basis: 225px;
+ flex-shrink: 0;
+ transition: transform 0.15s ease-in-out;
+ z-index: 1038;
+ transform: translateX(-225px);
+}
+#layoutSidenav #layoutSidenav_content {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ min-width: 0;
+ flex-grow: 1;
+ min-height: calc(100vh - 56px);
+ margin-left: -225px;
+}
+
+.sb-sidenav-toggled #layoutSidenav #layoutSidenav_nav {
+ transform: translateX(0);
+}
+.sb-sidenav-toggled #layoutSidenav #layoutSidenav_content:before {
+ content: "";
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: #000;
+ z-index: 1037;
+ opacity: 0.5;
+ transition: opacity 0.3s ease-in-out;
+}
+
+@media (min-width: 992px) {
+ #layoutSidenav #layoutSidenav_nav {
+ transform: translateX(0);
+ }
+ #layoutSidenav #layoutSidenav_content {
+ margin-left: 0;
+ transition: margin 0.15s ease-in-out;
+ }
+
+ .sb-sidenav-toggled #layoutSidenav #layoutSidenav_nav {
+ transform: translateX(-225px);
+ }
+ .sb-sidenav-toggled #layoutSidenav #layoutSidenav_content {
+ margin-left: -225px;
+ }
+ .sb-sidenav-toggled #layoutSidenav #layoutSidenav_content:before {
+ display: none;
+ }
+}
+.sb-nav-fixed .sb-topnav {
+ z-index: 1039;
+}
+.sb-nav-fixed #layoutSidenav #layoutSidenav_nav {
+ width: 225px;
+ height: 100vh;
+ z-index: 1038;
+}
+.sb-nav-fixed #layoutSidenav #layoutSidenav_nav .sb-sidenav {
+ padding-top: 56px;
+}
+.sb-nav-fixed #layoutSidenav #layoutSidenav_nav .sb-sidenav .sb-sidenav-menu {
+ overflow-y: auto;
+}
+.sb-nav-fixed #layoutSidenav #layoutSidenav_content {
+ padding-left: 225px;
+ top: 56px;
+}
+
+#layoutError {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+#layoutError #layoutError_content {
+ min-width: 0;
+ flex-grow: 1;
+}
+#layoutError #layoutError_footer {
+ min-width: 0;
+}
+
+.img-error {
+ max-width: 20rem;
+}
+
+.nav .nav-link .sb-nav-link-icon,
+.sb-sidenav-menu .nav-link .sb-nav-link-icon {
+ margin-right: 0.5rem;
+}
+
+.sb-topnav {
+ padding-left: 0;
+ height: 56px;
+ z-index: 1039;
+}
+.sb-topnav .navbar-brand {
+ width: 225px;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ margin: 0;
+}
+.sb-topnav.navbar-dark #sidebarToggle {
+ color: rgba(255, 255, 255, 0.5);
+}
+.sb-topnav.navbar-light #sidebarToggle {
+ color: #212529;
+}
+
+.sb-sidenav {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ flex-wrap: nowrap;
+}
+.sb-sidenav .sb-sidenav-menu {
+ flex-grow: 1;
+}
+.sb-sidenav .sb-sidenav-menu .nav {
+ flex-direction: column;
+ flex-wrap: nowrap;
+}
+.sb-sidenav .sb-sidenav-menu .nav .sb-sidenav-menu-heading {
+ padding: 1.75rem 1rem 0.75rem;
+ font-size: 0.75rem;
+ font-weight: bold;
+ text-transform: uppercase;
+}
+.sb-sidenav .sb-sidenav-menu .nav .nav-link {
+ display: flex;
+ align-items: center;
+ padding-top: 0.75rem;
+ padding-bottom: 0.75rem;
+ position: relative;
+}
+.sb-sidenav .sb-sidenav-menu .nav .nav-link .sb-nav-link-icon {
+ font-size: 0.9rem;
+}
+.sb-sidenav .sb-sidenav-menu .nav .nav-link .sb-sidenav-collapse-arrow {
+ display: inline-block;
+ margin-left: auto;
+ transition: transform 0.15s ease;
+}
+.sb-sidenav .sb-sidenav-menu .nav .nav-link.collapsed .sb-sidenav-collapse-arrow {
+ transform: rotate(-90deg);
+}
+.sb-sidenav .sb-sidenav-menu .nav .sb-sidenav-menu-nested {
+ margin-left: 1.5rem;
+ flex-direction: column;
+}
+.sb-sidenav .sb-sidenav-footer {
+ padding: 0.75rem;
+ flex-shrink: 0;
+}
+
+.sb-sidenav-dark {
+ background-color: #212529;
+ color: rgba(255, 255, 255, 0.5);
+}
+.sb-sidenav-dark .sb-sidenav-menu .sb-sidenav-menu-heading {
+ color: rgba(255, 255, 255, 0.25);
+}
+.sb-sidenav-dark .sb-sidenav-menu .nav-link {
+ color: rgba(255, 255, 255, 0.5);
+}
+.sb-sidenav-dark .sb-sidenav-menu .nav-link .sb-nav-link-icon {
+ color: rgba(255, 255, 255, 0.25);
+}
+.sb-sidenav-dark .sb-sidenav-menu .nav-link .sb-sidenav-collapse-arrow {
+ color: rgba(255, 255, 255, 0.25);
+}
+.sb-sidenav-dark .sb-sidenav-menu .nav-link:hover {
+ color: #fff;
+}
+.sb-sidenav-dark .sb-sidenav-menu .nav-link.active {
+ color: #fff;
+}
+.sb-sidenav-dark .sb-sidenav-menu .nav-link.active .sb-nav-link-icon {
+ color: #fff;
+}
+.sb-sidenav-dark .sb-sidenav-footer {
+ background-color: #343a40;
+}
+
+.sb-sidenav-light {
+ background-color: #f8f9fa;
+ color: #212529;
+}
+.sb-sidenav-light .sb-sidenav-menu .sb-sidenav-menu-heading {
+ color: #adb5bd;
+}
+.sb-sidenav-light .sb-sidenav-menu .nav-link {
+ color: #212529;
+}
+.sb-sidenav-light .sb-sidenav-menu .nav-link .sb-nav-link-icon {
+ color: #adb5bd;
+}
+.sb-sidenav-light .sb-sidenav-menu .nav-link .sb-sidenav-collapse-arrow {
+ color: #adb5bd;
+}
+.sb-sidenav-light .sb-sidenav-menu .nav-link:hover {
+ color: #007bff;
+}
+.sb-sidenav-light .sb-sidenav-menu .nav-link.active {
+ color: #007bff;
+}
+.sb-sidenav-light .sb-sidenav-menu .nav-link.active .sb-nav-link-icon {
+ color: #007bff;
+}
+.sb-sidenav-light .sb-sidenav-footer {
+ background-color: #e9ecef;
+}
\ No newline at end of file
diff --git a/assets/demo/chart-area-demo.js b/assets/demo/chart-area-demo.js
new file mode 100644
index 0000000..f63ff91
--- /dev/null
+++ b/assets/demo/chart-area-demo.js
@@ -0,0 +1,54 @@
+// Set new default font family and font color to mimic Bootstrap's default styling
+Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
+Chart.defaults.global.defaultFontColor = '#292b2c';
+
+// Area Chart Example
+var ctx = document.getElementById("myAreaChart");
+var myLineChart = new Chart(ctx, {
+ type: 'line',
+ data: {
+ labels: ["Mar 1", "Mar 2", "Mar 3", "Mar 4", "Mar 5", "Mar 6", "Mar 7", "Mar 8", "Mar 9", "Mar 10", "Mar 11", "Mar 12", "Mar 13"],
+ datasets: [{
+ label: "Sessions",
+ lineTension: 0.3,
+ backgroundColor: "rgba(2,117,216,0.2)",
+ borderColor: "rgba(2,117,216,1)",
+ pointRadius: 5,
+ pointBackgroundColor: "rgba(2,117,216,1)",
+ pointBorderColor: "rgba(255,255,255,0.8)",
+ pointHoverRadius: 5,
+ pointHoverBackgroundColor: "rgba(2,117,216,1)",
+ pointHitRadius: 50,
+ pointBorderWidth: 2,
+ data: [10000, 30162, 26263, 18394, 18287, 28682, 31274, 33259, 25849, 24159, 32651, 31984, 38451],
+ }],
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ time: {
+ unit: 'date'
+ },
+ gridLines: {
+ display: false
+ },
+ ticks: {
+ maxTicksLimit: 7
+ }
+ }],
+ yAxes: [{
+ ticks: {
+ min: 0,
+ max: 40000,
+ maxTicksLimit: 5
+ },
+ gridLines: {
+ color: "rgba(0, 0, 0, .125)",
+ }
+ }],
+ },
+ legend: {
+ display: false
+ }
+ }
+});
diff --git a/assets/demo/chart-bar-demo.js b/assets/demo/chart-bar-demo.js
new file mode 100644
index 0000000..049ad20
--- /dev/null
+++ b/assets/demo/chart-bar-demo.js
@@ -0,0 +1,46 @@
+// Set new default font family and font color to mimic Bootstrap's default styling
+Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
+Chart.defaults.global.defaultFontColor = '#292b2c';
+
+// Bar Chart Example
+var ctx = document.getElementById("myBarChart");
+var myLineChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: ["January", "February", "March", "April", "May", "June"],
+ datasets: [{
+ label: "Revenue",
+ backgroundColor: "rgba(2,117,216,1)",
+ borderColor: "rgba(2,117,216,1)",
+ data: [4215, 5312, 6251, 7841, 9821, 14984],
+ }],
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ time: {
+ unit: 'month'
+ },
+ gridLines: {
+ display: false
+ },
+ ticks: {
+ maxTicksLimit: 6
+ }
+ }],
+ yAxes: [{
+ ticks: {
+ min: 0,
+ max: 15000,
+ maxTicksLimit: 5
+ },
+ gridLines: {
+ display: true
+ }
+ }],
+ },
+ legend: {
+ display: false
+ }
+ }
+});
diff --git a/assets/demo/chart-pie-demo.js b/assets/demo/chart-pie-demo.js
new file mode 100644
index 0000000..4e16c41
--- /dev/null
+++ b/assets/demo/chart-pie-demo.js
@@ -0,0 +1,16 @@
+// Set new default font family and font color to mimic Bootstrap's default styling
+Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
+Chart.defaults.global.defaultFontColor = '#292b2c';
+
+// Pie Chart Example
+var ctx = document.getElementById("myPieChart");
+var myPieChart = new Chart(ctx, {
+ type: 'pie',
+ data: {
+ labels: ["Blue", "Red", "Yellow", "Green"],
+ datasets: [{
+ data: [12.21, 15.58, 11.25, 8.32],
+ backgroundColor: ['#007bff', '#dc3545', '#ffc107', '#28a745'],
+ }],
+ },
+});
diff --git a/assets/demo/datatables-demo.js b/assets/demo/datatables-demo.js
new file mode 100644
index 0000000..f2eecbf
--- /dev/null
+++ b/assets/demo/datatables-demo.js
@@ -0,0 +1,4 @@
+// Call the dataTables jQuery plugin
+$(document).ready(function() {
+ $('#dataTable').DataTable();
+});
diff --git a/assets/img/error-404-monochrome.svg b/assets/img/error-404-monochrome.svg
new file mode 100644
index 0000000..f0d345f
--- /dev/null
+++ b/assets/img/error-404-monochrome.svg
@@ -0,0 +1 @@
+
error-404-monochrome
\ No newline at end of file
diff --git a/assets/js/jquery.maskedinput.js b/assets/js/jquery.maskedinput.js
new file mode 100644
index 0000000..2228e8f
--- /dev/null
+++ b/assets/js/jquery.maskedinput.js
@@ -0,0 +1,329 @@
+function getPasteEvent() {
+ var el = document.createElement('input'),
+ name = 'onpaste';
+ el.setAttribute(name, '');
+ return (typeof el[name] === 'function')?'paste':'input';
+}
+
+var pasteEventName = getPasteEvent() + ".mask",
+ ua = navigator.userAgent,
+ iPhone = /iphone/i.test(ua),
+ android=/android/i.test(ua),
+ caretTimeoutId;
+
+$.mask = {
+ //Predefined character definitions
+ definitions: {
+ '9': "[0-9]",
+ 'a': "[A-Za-z]",
+ '*': "[A-Za-z0-9]"
+ },
+ dataName: "rawMaskFn",
+ placeholder: '_',
+};
+
+$.fn.extend({
+ //Helper Function for Caret positioning
+ caret: function(begin, end) {
+ var range;
+
+ if (this.length === 0 || this.is(":hidden")) {
+ return;
+ }
+
+ if (typeof begin == 'number') {
+ end = (typeof end === 'number') ? end : begin;
+ return this.each(function() {
+ if (this.setSelectionRange) {
+ this.setSelectionRange(begin, end);
+ } else if (this.createTextRange) {
+ range = this.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', end);
+ range.moveStart('character', begin);
+ range.select();
+ }
+ });
+ } else {
+ if (this[0].setSelectionRange) {
+ begin = this[0].selectionStart;
+ end = this[0].selectionEnd;
+ } else if (document.selection && document.selection.createRange) {
+ range = document.selection.createRange();
+ begin = 0 - range.duplicate().moveStart('character', -100000);
+ end = begin + range.text.length;
+ }
+ return { begin: begin, end: end };
+ }
+ },
+ unmask: function() {
+ return this.trigger("unmask");
+ },
+ mask: function(mask, settings) {
+ var input,
+ defs,
+ tests,
+ partialPosition,
+ firstNonMaskPos,
+ len;
+
+ if (!mask && this.length > 0) {
+ input = $(this[0]);
+ return input.data($.mask.dataName)();
+ }
+ settings = $.extend({
+ placeholder: $.mask.placeholder, // Load default placeholder
+ completed: null
+ }, settings);
+
+
+ defs = $.mask.definitions;
+ tests = [];
+ partialPosition = len = mask.length;
+ firstNonMaskPos = null;
+
+ $.each(mask.split(""), function(i, c) {
+ if (c == '?') {
+ len--;
+ partialPosition = i;
+ } else if (defs[c]) {
+ tests.push(new RegExp(defs[c]));
+ if (firstNonMaskPos === null) {
+ firstNonMaskPos = tests.length - 1;
+ }
+ } else {
+ tests.push(null);
+ }
+ });
+
+ return this.trigger("unmask").each(function() {
+ var input = $(this),
+ buffer = $.map(
+ mask.split(""),
+ function(c, i) {
+ if (c != '?') {
+ return defs[c] ? settings.placeholder : c;
+ }
+ }),
+ focusText = input.val();
+
+ function seekNext(pos) {
+ while (++pos < len && !tests[pos]);
+ return pos;
+ }
+
+ function seekPrev(pos) {
+ while (--pos >= 0 && !tests[pos]);
+ return pos;
+ }
+
+ function shiftL(begin,end) {
+ var i,
+ j;
+
+ if (begin<0) {
+ return;
+ }
+
+ for (i = begin, j = seekNext(end); i < len; i++) {
+ if (tests[i]) {
+ if (j < len && tests[i].test(buffer[j])) {
+ buffer[i] = buffer[j];
+ buffer[j] = settings.placeholder;
+ } else {
+ break;
+ }
+
+ j = seekNext(j);
+ }
+ }
+ writeBuffer();
+ input.caret(Math.max(firstNonMaskPos, begin));
+ }
+
+ function shiftR(pos) {
+ var i,
+ c,
+ j,
+ t;
+
+ for (i = pos, c = settings.placeholder; i < len; i++) {
+ if (tests[i]) {
+ j = seekNext(i);
+ t = buffer[i];
+ buffer[i] = c;
+ if (j < len && tests[j].test(t)) {
+ c = t;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ function keydownEvent(e) {
+ var k = e.which,
+ pos,
+ begin,
+ end;
+
+ //backspace, delete, and escape get special treatment
+ if (k === 8 || k === 46 || (iPhone && k === 127)) {
+ pos = input.caret();
+ begin = pos.begin;
+ end = pos.end;
+
+ if (end - begin === 0) {
+ begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
+ end=k===46?seekNext(end):end;
+ }
+ clearBuffer(begin, end);
+ shiftL(begin, end - 1);
+
+ e.preventDefault();
+ } else if (k == 27) {//escape
+ input.val(focusText);
+ input.caret(0, checkVal());
+ e.preventDefault();
+ }
+ }
+
+ function keypressEvent(e) {
+ var k = e.which,
+ pos = input.caret(),
+ p,
+ c,
+ next;
+
+ if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
+ return;
+ } else if (k) {
+ if (pos.end - pos.begin !== 0){
+ clearBuffer(pos.begin, pos.end);
+ shiftL(pos.begin, pos.end-1);
+ }
+
+ p = seekNext(pos.begin - 1);
+ if (p < len) {
+ c = String.fromCharCode(k);
+ if (tests[p].test(c)) {
+ shiftR(p);
+
+ buffer[p] = c;
+ writeBuffer();
+ next = seekNext(p);
+
+ if(android){
+ setTimeout($.proxy($.fn.caret,input,next),0);
+ }else{
+ input.caret(next);
+ }
+
+ if (settings.completed && next >= len) {
+ settings.completed.call(input);
+ }
+ }
+ }
+ e.preventDefault();
+ }
+ }
+
+ function clearBuffer(start, end) {
+ var i;
+ for (i = start; i < end && i < len; i++) {
+ if (tests[i]) {
+ buffer[i] = settings.placeholder;
+ }
+ }
+ }
+
+ function writeBuffer() { input.val(buffer.join('')); }
+
+ function checkVal(allow) {
+ //try to place characters where they belong
+ var test = input.val(),
+ lastMatch = -1,
+ i,
+ c;
+
+ for (i = 0, pos = 0; i < len; i++) {
+ if (tests[i]) {
+ buffer[i] = settings.placeholder;
+ while (pos++ < test.length) {
+ c = test.charAt(pos - 1);
+ if (tests[i].test(c)) {
+ buffer[i] = c;
+ lastMatch = i;
+ break;
+ }
+ }
+ if (pos > test.length) {
+ break;
+ }
+ } else if (buffer[i] === test.charAt(pos) && i !== partialPosition) {
+ pos++;
+ lastMatch = i;
+ }
+ }
+ if (allow) {
+ writeBuffer();
+ } else if (lastMatch + 1 < partialPosition) {
+ input.val("");
+ clearBuffer(0, len);
+ } else {
+ writeBuffer();
+ input.val(input.val().substring(0, lastMatch + 1));
+ }
+ return (partialPosition ? i : firstNonMaskPos);
+ }
+
+ input.data($.mask.dataName,function(){
+ return $.map(buffer, function(c, i) {
+ return tests[i]&&c!=settings.placeholder ? c : null;
+ }).join('');
+ });
+
+ if (!input.attr("readonly"))
+ input
+ .one("unmask", function() {
+ input
+ .unbind(".mask")
+ .removeData($.mask.dataName);
+ })
+ .bind("focus.mask", function() {
+ clearTimeout(caretTimeoutId);
+ var pos,
+ moveCaret;
+
+ focusText = input.val();
+ pos = checkVal();
+
+ caretTimeoutId = setTimeout(function(){
+ writeBuffer();
+ if (pos == mask.length) {
+ input.caret(0, pos);
+ } else {
+ input.caret(pos);
+ }
+ }, 10);
+ })
+ .bind("blur.mask", function() {
+ checkVal();
+ if (input.val() != focusText)
+ input.change();
+ })
+ .bind("keydown.mask", keydownEvent)
+ .bind("keypress.mask", keypressEvent)
+ .bind(pasteEventName, function() {
+ setTimeout(function() {
+ var pos=checkVal(true);
+ input.caret(pos);
+ if (settings.completed && pos == input.val().length)
+ settings.completed.call(input);
+ }, 0);
+ });
+ checkVal(); //Perform initial check for existing values
+ });
+ }
+});
+
diff --git a/assets/js/jquery.validate.min.js b/assets/js/jquery.validate.min.js
new file mode 100644
index 0000000..0d68514
--- /dev/null
+++ b/assets/js/jquery.validate.min.js
@@ -0,0 +1,4 @@
+/*! jQuery Validation Plugin - v1.19.2 - 5/23/2020
+ * https://jqueryvalidation.org/
+ * Copyright (c) 2020 Jörn Zaefferer; Licensed MIT */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.submitButton=b.currentTarget,a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return c.submitButton&&(c.settings.submitHandler||c.formSubmitted)&&(d=a("
").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!(c.settings.submitHandler&&!c.settings.debug)||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0],k="undefined"!=typeof this.attr("contenteditable")&&"false"!==this.attr("contenteditable");if(null!=j&&(!j.form&&k&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}});var b=function(a){return a.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")};a.extend(a.expr.pseudos||a.expr[":"],{blank:function(c){return!b(""+a(c).val())},filled:function(c){var d=a(c).val();return null!==d&&!!b(""+d)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");if(!this.form&&c&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name")),d===this.form){var e=a.data(this.form,"validator"),f="on"+b.type.replace(/^validate/,""),g=e.settings;g[f]&&!a(this).is(g.ignore)&&g[f].call(e,this,b)}}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.currentForm,e=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){e[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").trigger("focus").trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name"),e="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),e&&(this.form=a(this).closest("form")[0],this.name=d),this.form===b.currentForm&&(!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0))})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type,g="undefined"!=typeof e.attr("contenteditable")&&"false"!==e.attr("contenteditable");return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=g?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);"function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f&&(j=f.call(b,j),delete g.normalizer);for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a
Warning: No message defined for "+b.name+""),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,.\/:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur").find(".validate-lessThan-blur").off(".validate-lessThan").removeClass("validate-lessThan-blur").find(".validate-lessThanEqual-blur").off(".validate-lessThanEqual").removeClass("validate-lessThanEqual-blur").find(".validate-greaterThanEqual-blur").off(".validate-greaterThanEqual").removeClass("validate-greaterThanEqual-blur").find(".validate-greaterThan-blur").off(".validate-greaterThan").removeClass("validate-greaterThan-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),""===d&&(d=!0),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:void 0!==b&&null!==b&&b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[\/?#]\S*)?$/i.test(a)},date:function(){var a=!1;return function(b,c){return a||(a=!0,this.settings.debug&&window.console&&console.warn("The `date` method is deprecated and will be removed in version '2.0.0'.\nPlease don't use it, since it relies on the Date constructor, which\nbehaves very differently across browsers and locales. Use `dateISO`\ninstead or one of the locale specific methods in `localizations/`\nand `additional-methods.js`.")),this.optional(c)||!/Invalid|NaN/.test(new Date(b).toString())}}(),dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var c,d={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,c){var e=a.port;"abort"===a.mode&&(d[e]&&d[e].abort(),d[e]=c)}):(c=a.ajax,a.ajax=function(b){var e=("mode"in b?b:a.ajaxSettings).mode,f=("port"in b?b:a.ajaxSettings).port;return"abort"===e?(d[f]&&d[f].abort(),d[f]=c.apply(this,arguments),d[f]):c.apply(this,arguments)}),a});
\ No newline at end of file
diff --git a/assets/js/scripts.js b/assets/js/scripts.js
new file mode 100644
index 0000000..260783d
--- /dev/null
+++ b/assets/js/scripts.js
@@ -0,0 +1,22 @@
+/*!
+ * Start Bootstrap - SB Admin v6.0.2 (https://startbootstrap.com/template/sb-admin)
+ * Copyright 2013-2020 Start Bootstrap
+ * Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-sb-admin/blob/master/LICENSE)
+ */
+ (function($) {
+ "use strict";
+
+ // Add active state to sidbar nav links
+ var path = window.location.href; // because the 'href' property of the DOM element is the absolute path
+ $("#layoutSidenav_nav .sb-sidenav a.nav-link").each(function() {
+ if (this.href === path) {
+ $(this).addClass("active");
+ }
+ });
+
+ // Toggle the side navigation
+ $("#sidebarToggle").on("click", function(e) {
+ e.preventDefault();
+ $("body").toggleClass("sb-sidenav-toggled");
+ });
+})(jQuery);
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..30630e2
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,23 @@
+{
+ "description": "The CodeIgniter framework",
+ "name": "codeigniter/framework",
+ "type": "project",
+ "homepage": "https://codeigniter.com",
+ "license": "MIT",
+ "support": {
+ "forum": "http://forum.codeigniter.com/",
+ "wiki": "https://github.com/bcit-ci/CodeIgniter/wiki",
+ "slack": "https://codeigniterchat.slack.com",
+ "source": "https://github.com/bcit-ci/CodeIgniter"
+ },
+ "require": {
+ "php": ">=5.3.7"
+ },
+ "suggest": {
+ "paragonie/random_compat": "Provides better randomness in PHP 5.x"
+ },
+ "require-dev": {
+ "mikey179/vfsStream": "1.1.*",
+ "phpunit/phpunit": "4.* || 5.*"
+ }
+}
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..723239d
--- /dev/null
+++ b/index.php
@@ -0,0 +1,315 @@
+='))
+ {
+ error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
+ }
+ else
+ {
+ error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_USER_NOTICE);
+ }
+ break;
+
+ default:
+ header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
+ echo 'The application environment is not set correctly.';
+ exit(1); // EXIT_ERROR
+}
+
+/*
+ *---------------------------------------------------------------
+ * SYSTEM DIRECTORY NAME
+ *---------------------------------------------------------------
+ *
+ * This variable must contain the name of your "system" directory.
+ * Set the path if it is not in the same directory as this file.
+ */
+ $system_path = 'system';
+
+/*
+ *---------------------------------------------------------------
+ * APPLICATION DIRECTORY NAME
+ *---------------------------------------------------------------
+ *
+ * If you want this front controller to use a different "application"
+ * directory than the default one you can set its name here. The directory
+ * can also be renamed or relocated anywhere on your server. If you do,
+ * use an absolute (full) server path.
+ * For more info please see the user guide:
+ *
+ * https://codeigniter.com/user_guide/general/managing_apps.html
+ *
+ * NO TRAILING SLASH!
+ */
+ $application_folder = 'application';
+
+/*
+ *---------------------------------------------------------------
+ * VIEW DIRECTORY NAME
+ *---------------------------------------------------------------
+ *
+ * If you want to move the view directory out of the application
+ * directory, set the path to it here. The directory can be renamed
+ * and relocated anywhere on your server. If blank, it will default
+ * to the standard location inside your application directory.
+ * If you do move this, use an absolute (full) server path.
+ *
+ * NO TRAILING SLASH!
+ */
+ $view_folder = '';
+
+
+/*
+ * --------------------------------------------------------------------
+ * DEFAULT CONTROLLER
+ * --------------------------------------------------------------------
+ *
+ * Normally you will set your default controller in the routes.php file.
+ * You can, however, force a custom routing by hard-coding a
+ * specific controller class/function here. For most applications, you
+ * WILL NOT set your routing here, but it's an option for those
+ * special instances where you might want to override the standard
+ * routing in a specific front controller that shares a common CI installation.
+ *
+ * IMPORTANT: If you set the routing here, NO OTHER controller will be
+ * callable. In essence, this preference limits your application to ONE
+ * specific controller. Leave the function name blank if you need
+ * to call functions dynamically via the URI.
+ *
+ * Un-comment the $routing array below to use this feature
+ */
+ // The directory name, relative to the "controllers" directory. Leave blank
+ // if your controller is not in a sub-directory within the "controllers" one
+ // $routing['directory'] = '';
+
+ // The controller class file name. Example: mycontroller
+ // $routing['controller'] = '';
+
+ // The controller function you wish to be called.
+ // $routing['function'] = '';
+
+
+/*
+ * -------------------------------------------------------------------
+ * CUSTOM CONFIG VALUES
+ * -------------------------------------------------------------------
+ *
+ * The $assign_to_config array below will be passed dynamically to the
+ * config class when initialized. This allows you to set custom config
+ * items or override any default config values found in the config.php file.
+ * This can be handy as it permits you to share one application between
+ * multiple front controller files, with each file containing different
+ * config values.
+ *
+ * Un-comment the $assign_to_config array below to use this feature
+ */
+ // $assign_to_config['name_of_config_item'] = 'value of config item';
+
+
+
+// --------------------------------------------------------------------
+// END OF USER CONFIGURABLE SETTINGS. DO NOT EDIT BELOW THIS LINE
+// --------------------------------------------------------------------
+
+/*
+ * ---------------------------------------------------------------
+ * Resolve the system path for increased reliability
+ * ---------------------------------------------------------------
+ */
+
+ // Set the current directory correctly for CLI requests
+ if (defined('STDIN'))
+ {
+ chdir(dirname(__FILE__));
+ }
+
+ if (($_temp = realpath($system_path)) !== FALSE)
+ {
+ $system_path = $_temp.DIRECTORY_SEPARATOR;
+ }
+ else
+ {
+ // Ensure there's a trailing slash
+ $system_path = strtr(
+ rtrim($system_path, '/\\'),
+ '/\\',
+ DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
+ ).DIRECTORY_SEPARATOR;
+ }
+
+ // Is the system path correct?
+ if ( ! is_dir($system_path))
+ {
+ header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
+ echo 'Your system folder path does not appear to be set correctly. Please open the following file and correct this: '.pathinfo(__FILE__, PATHINFO_BASENAME);
+ exit(3); // EXIT_CONFIG
+ }
+
+/*
+ * -------------------------------------------------------------------
+ * Now that we know the path, set the main path constants
+ * -------------------------------------------------------------------
+ */
+ // The name of THIS file
+ define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));
+
+ // Path to the system directory
+ define('BASEPATH', $system_path);
+
+ // Path to the front controller (this file) directory
+ define('FCPATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
+
+ // Name of the "system" directory
+ define('SYSDIR', basename(BASEPATH));
+
+ // The path to the "application" directory
+ if (is_dir($application_folder))
+ {
+ if (($_temp = realpath($application_folder)) !== FALSE)
+ {
+ $application_folder = $_temp;
+ }
+ else
+ {
+ $application_folder = strtr(
+ rtrim($application_folder, '/\\'),
+ '/\\',
+ DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
+ );
+ }
+ }
+ elseif (is_dir(BASEPATH.$application_folder.DIRECTORY_SEPARATOR))
+ {
+ $application_folder = BASEPATH.strtr(
+ trim($application_folder, '/\\'),
+ '/\\',
+ DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
+ );
+ }
+ else
+ {
+ header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
+ echo 'Your application folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
+ exit(3); // EXIT_CONFIG
+ }
+
+ define('APPPATH', $application_folder.DIRECTORY_SEPARATOR);
+
+ // The path to the "views" directory
+ if ( ! isset($view_folder[0]) && is_dir(APPPATH.'views'.DIRECTORY_SEPARATOR))
+ {
+ $view_folder = APPPATH.'views';
+ }
+ elseif (is_dir($view_folder))
+ {
+ if (($_temp = realpath($view_folder)) !== FALSE)
+ {
+ $view_folder = $_temp;
+ }
+ else
+ {
+ $view_folder = strtr(
+ rtrim($view_folder, '/\\'),
+ '/\\',
+ DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
+ );
+ }
+ }
+ elseif (is_dir(APPPATH.$view_folder.DIRECTORY_SEPARATOR))
+ {
+ $view_folder = APPPATH.strtr(
+ trim($view_folder, '/\\'),
+ '/\\',
+ DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR
+ );
+ }
+ else
+ {
+ header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
+ echo 'Your view folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
+ exit(3); // EXIT_CONFIG
+ }
+
+ define('VIEWPATH', $view_folder.DIRECTORY_SEPARATOR);
+
+/*
+ * --------------------------------------------------------------------
+ * LOAD THE BOOTSTRAP FILE
+ * --------------------------------------------------------------------
+ *
+ * And away we go...
+ */
+require_once BASEPATH.'core/CodeIgniter.php';
diff --git a/system/.htaccess b/system/.htaccess
new file mode 100644
index 0000000..97c65d2
--- /dev/null
+++ b/system/.htaccess
@@ -0,0 +1,6 @@
+
+ Require all denied
+
+
+ Deny from all
+
\ No newline at end of file
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php
new file mode 100644
index 0000000..014220a
--- /dev/null
+++ b/system/core/Benchmark.php
@@ -0,0 +1,133 @@
+marker[$name] = microtime(TRUE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Elapsed time
+ *
+ * Calculates the time difference between two marked points.
+ *
+ * If the first parameter is empty this function instead returns the
+ * {elapsed_time} pseudo-variable. This permits the full system
+ * execution time to be shown in a template. The output class will
+ * swap the real value for this variable.
+ *
+ * @param string $point1 A particular marked point
+ * @param string $point2 A particular marked point
+ * @param int $decimals Number of decimal places
+ *
+ * @return string Calculated elapsed time on success,
+ * an '{elapsed_string}' if $point1 is empty
+ * or an empty string if $point1 is not found.
+ */
+ public function elapsed_time($point1 = '', $point2 = '', $decimals = 4)
+ {
+ if ($point1 === '')
+ {
+ return '{elapsed_time}';
+ }
+
+ if ( ! isset($this->marker[$point1]))
+ {
+ return '';
+ }
+
+ if ( ! isset($this->marker[$point2]))
+ {
+ $this->marker[$point2] = microtime(TRUE);
+ }
+
+ return number_format($this->marker[$point2] - $this->marker[$point1], $decimals);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Memory Usage
+ *
+ * Simply returns the {memory_usage} marker.
+ *
+ * This permits it to be put it anywhere in a template
+ * without the memory being calculated until the end.
+ * The output class will swap the real value for this variable.
+ *
+ * @return string '{memory_usage}'
+ */
+ public function memory_usage()
+ {
+ return '{memory_usage}';
+ }
+
+}
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
new file mode 100644
index 0000000..8aecc0a
--- /dev/null
+++ b/system/core/CodeIgniter.php
@@ -0,0 +1,559 @@
+ '_ENV', 'G' => '_GET', 'P' => '_POST', 'C' => '_COOKIE', 'S' => '_SERVER') as $key => $superglobal)
+ {
+ if (strpos($_registered, $key) === FALSE)
+ {
+ continue;
+ }
+
+ foreach (array_keys($$superglobal) as $var)
+ {
+ if (isset($GLOBALS[$var]) && ! in_array($var, $_protected, TRUE))
+ {
+ $GLOBALS[$var] = NULL;
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * ------------------------------------------------------
+ * Define a custom error handler so we can log PHP errors
+ * ------------------------------------------------------
+ */
+ set_error_handler('_error_handler');
+ set_exception_handler('_exception_handler');
+ register_shutdown_function('_shutdown_handler');
+
+/*
+ * ------------------------------------------------------
+ * Set the subclass_prefix
+ * ------------------------------------------------------
+ *
+ * Normally the "subclass_prefix" is set in the config file.
+ * The subclass prefix allows CI to know if a core class is
+ * being extended via a library in the local application
+ * "libraries" folder. Since CI allows config items to be
+ * overridden via data set in the main index.php file,
+ * before proceeding we need to know if a subclass_prefix
+ * override exists. If so, we will set this value now,
+ * before any classes are loaded
+ * Note: Since the config file data is cached it doesn't
+ * hurt to load it here.
+ */
+ if ( ! empty($assign_to_config['subclass_prefix']))
+ {
+ get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));
+ }
+
+/*
+ * ------------------------------------------------------
+ * Should we use a Composer autoloader?
+ * ------------------------------------------------------
+ */
+ if ($composer_autoload = config_item('composer_autoload'))
+ {
+ if ($composer_autoload === TRUE)
+ {
+ file_exists(APPPATH.'vendor/autoload.php')
+ ? require_once(APPPATH.'vendor/autoload.php')
+ : log_message('error', '$config[\'composer_autoload\'] is set to TRUE but '.APPPATH.'vendor/autoload.php was not found.');
+ }
+ elseif (file_exists($composer_autoload))
+ {
+ require_once($composer_autoload);
+ }
+ else
+ {
+ log_message('error', 'Could not find the specified $config[\'composer_autoload\'] path: '.$composer_autoload);
+ }
+ }
+
+/*
+ * ------------------------------------------------------
+ * Start the timer... tick tock tick tock...
+ * ------------------------------------------------------
+ */
+ $BM =& load_class('Benchmark', 'core');
+ $BM->mark('total_execution_time_start');
+ $BM->mark('loading_time:_base_classes_start');
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the hooks class
+ * ------------------------------------------------------
+ */
+ $EXT =& load_class('Hooks', 'core');
+
+/*
+ * ------------------------------------------------------
+ * Is there a "pre_system" hook?
+ * ------------------------------------------------------
+ */
+ $EXT->call_hook('pre_system');
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the config class
+ * ------------------------------------------------------
+ *
+ * Note: It is important that Config is loaded first as
+ * most other classes depend on it either directly or by
+ * depending on another class that uses it.
+ *
+ */
+ $CFG =& load_class('Config', 'core');
+
+ // Do we have any manually set config items in the index.php file?
+ if (isset($assign_to_config) && is_array($assign_to_config))
+ {
+ foreach ($assign_to_config as $key => $value)
+ {
+ $CFG->set_item($key, $value);
+ }
+ }
+
+/*
+ * ------------------------------------------------------
+ * Important charset-related stuff
+ * ------------------------------------------------------
+ *
+ * Configure mbstring and/or iconv if they are enabled
+ * and set MB_ENABLED and ICONV_ENABLED constants, so
+ * that we don't repeatedly do extension_loaded() or
+ * function_exists() calls.
+ *
+ * Note: UTF-8 class depends on this. It used to be done
+ * in it's constructor, but it's _not_ class-specific.
+ *
+ */
+ $charset = strtoupper(config_item('charset'));
+ ini_set('default_charset', $charset);
+
+ if (extension_loaded('mbstring'))
+ {
+ define('MB_ENABLED', TRUE);
+ // mbstring.internal_encoding is deprecated starting with PHP 5.6
+ // and it's usage triggers E_DEPRECATED messages.
+ @ini_set('mbstring.internal_encoding', $charset);
+ // This is required for mb_convert_encoding() to strip invalid characters.
+ // That's utilized by CI_Utf8, but it's also done for consistency with iconv.
+ mb_substitute_character('none');
+ }
+ else
+ {
+ define('MB_ENABLED', FALSE);
+ }
+
+ // There's an ICONV_IMPL constant, but the PHP manual says that using
+ // iconv's predefined constants is "strongly discouraged".
+ if (extension_loaded('iconv'))
+ {
+ define('ICONV_ENABLED', TRUE);
+ // iconv.internal_encoding is deprecated starting with PHP 5.6
+ // and it's usage triggers E_DEPRECATED messages.
+ @ini_set('iconv.internal_encoding', $charset);
+ }
+ else
+ {
+ define('ICONV_ENABLED', FALSE);
+ }
+
+ if (is_php('5.6'))
+ {
+ ini_set('php.internal_encoding', $charset);
+ }
+
+/*
+ * ------------------------------------------------------
+ * Load compatibility features
+ * ------------------------------------------------------
+ */
+
+ require_once(BASEPATH.'core/compat/mbstring.php');
+ require_once(BASEPATH.'core/compat/hash.php');
+ require_once(BASEPATH.'core/compat/password.php');
+ require_once(BASEPATH.'core/compat/standard.php');
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the UTF-8 class
+ * ------------------------------------------------------
+ */
+ $UNI =& load_class('Utf8', 'core');
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the URI class
+ * ------------------------------------------------------
+ */
+ $URI =& load_class('URI', 'core');
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the routing class and set the routing
+ * ------------------------------------------------------
+ */
+ $RTR =& load_class('Router', 'core', isset($routing) ? $routing : NULL);
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the output class
+ * ------------------------------------------------------
+ */
+ $OUT =& load_class('Output', 'core');
+
+/*
+ * ------------------------------------------------------
+ * Is there a valid cache file? If so, we're done...
+ * ------------------------------------------------------
+ */
+ if ($EXT->call_hook('cache_override') === FALSE && $OUT->_display_cache($CFG, $URI) === TRUE)
+ {
+ exit;
+ }
+
+/*
+ * -----------------------------------------------------
+ * Load the security class for xss and csrf support
+ * -----------------------------------------------------
+ */
+ $SEC =& load_class('Security', 'core');
+
+/*
+ * ------------------------------------------------------
+ * Load the Input class and sanitize globals
+ * ------------------------------------------------------
+ */
+ $IN =& load_class('Input', 'core');
+
+/*
+ * ------------------------------------------------------
+ * Load the Language class
+ * ------------------------------------------------------
+ */
+ $LANG =& load_class('Lang', 'core');
+
+/*
+ * ------------------------------------------------------
+ * Load the app controller and local controller
+ * ------------------------------------------------------
+ *
+ */
+ // Load the base controller class
+ require_once BASEPATH.'core/Controller.php';
+
+ /**
+ * Reference to the CI_Controller method.
+ *
+ * Returns current CI instance object
+ *
+ * @return CI_Controller
+ */
+ function &get_instance()
+ {
+ return CI_Controller::get_instance();
+ }
+
+ if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
+ {
+ require_once APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
+ }
+
+ // Set a mark point for benchmarking
+ $BM->mark('loading_time:_base_classes_end');
+
+/*
+ * ------------------------------------------------------
+ * Sanity checks
+ * ------------------------------------------------------
+ *
+ * The Router class has already validated the request,
+ * leaving us with 3 options here:
+ *
+ * 1) an empty class name, if we reached the default
+ * controller, but it didn't exist;
+ * 2) a query string which doesn't go through a
+ * file_exists() check
+ * 3) a regular request for a non-existing page
+ *
+ * We handle all of these as a 404 error.
+ *
+ * Furthermore, none of the methods in the app controller
+ * or the loader class can be called via the URI, nor can
+ * controller methods that begin with an underscore.
+ */
+
+ $e404 = FALSE;
+ $class = ucfirst($RTR->class);
+ $method = $RTR->method;
+
+ if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php'))
+ {
+ $e404 = TRUE;
+ }
+ else
+ {
+ require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php');
+
+ if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
+ {
+ $e404 = TRUE;
+ }
+ elseif (method_exists($class, '_remap'))
+ {
+ $params = array($method, array_slice($URI->rsegments, 2));
+ $method = '_remap';
+ }
+ elseif ( ! method_exists($class, $method))
+ {
+ $e404 = TRUE;
+ }
+ /**
+ * DO NOT CHANGE THIS, NOTHING ELSE WORKS!
+ *
+ * - method_exists() returns true for non-public methods, which passes the previous elseif
+ * - is_callable() returns false for PHP 4-style constructors, even if there's a __construct()
+ * - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited
+ * - People will only complain if this doesn't work, even though it is documented that it shouldn't.
+ *
+ * ReflectionMethod::isConstructor() is the ONLY reliable check,
+ * knowing which method will be executed as a constructor.
+ */
+ elseif ( ! is_callable(array($class, $method)))
+ {
+ $reflection = new ReflectionMethod($class, $method);
+ if ( ! $reflection->isPublic() OR $reflection->isConstructor())
+ {
+ $e404 = TRUE;
+ }
+ }
+ }
+
+ if ($e404)
+ {
+ if ( ! empty($RTR->routes['404_override']))
+ {
+ if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $error_class, $error_method) !== 2)
+ {
+ $error_method = 'index';
+ }
+
+ $error_class = ucfirst($error_class);
+
+ if ( ! class_exists($error_class, FALSE))
+ {
+ if (file_exists(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php'))
+ {
+ require_once(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php');
+ $e404 = ! class_exists($error_class, FALSE);
+ }
+ // Were we in a directory? If so, check for a global override
+ elseif ( ! empty($RTR->directory) && file_exists(APPPATH.'controllers/'.$error_class.'.php'))
+ {
+ require_once(APPPATH.'controllers/'.$error_class.'.php');
+ if (($e404 = ! class_exists($error_class, FALSE)) === FALSE)
+ {
+ $RTR->directory = '';
+ }
+ }
+ }
+ else
+ {
+ $e404 = FALSE;
+ }
+ }
+
+ // Did we reset the $e404 flag? If so, set the rsegments, starting from index 1
+ if ( ! $e404)
+ {
+ $class = $error_class;
+ $method = $error_method;
+
+ $URI->rsegments = array(
+ 1 => $class,
+ 2 => $method
+ );
+ }
+ else
+ {
+ show_404($RTR->directory.$class.'/'.$method);
+ }
+ }
+
+ if ($method !== '_remap')
+ {
+ $params = array_slice($URI->rsegments, 2);
+ }
+
+/*
+ * ------------------------------------------------------
+ * Is there a "pre_controller" hook?
+ * ------------------------------------------------------
+ */
+ $EXT->call_hook('pre_controller');
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the requested controller
+ * ------------------------------------------------------
+ */
+ // Mark a start point so we can benchmark the controller
+ $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');
+
+ $CI = new $class();
+
+/*
+ * ------------------------------------------------------
+ * Is there a "post_controller_constructor" hook?
+ * ------------------------------------------------------
+ */
+ $EXT->call_hook('post_controller_constructor');
+
+/*
+ * ------------------------------------------------------
+ * Call the requested method
+ * ------------------------------------------------------
+ */
+ call_user_func_array(array(&$CI, $method), $params);
+
+ // Mark a benchmark end point
+ $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');
+
+/*
+ * ------------------------------------------------------
+ * Is there a "post_controller" hook?
+ * ------------------------------------------------------
+ */
+ $EXT->call_hook('post_controller');
+
+/*
+ * ------------------------------------------------------
+ * Send the final rendered output to the browser
+ * ------------------------------------------------------
+ */
+ if ($EXT->call_hook('display_override') === FALSE)
+ {
+ $OUT->_display();
+ }
+
+/*
+ * ------------------------------------------------------
+ * Is there a "post_system" hook?
+ * ------------------------------------------------------
+ */
+ $EXT->call_hook('post_system');
diff --git a/system/core/Common.php b/system/core/Common.php
new file mode 100644
index 0000000..624b5a9
--- /dev/null
+++ b/system/core/Common.php
@@ -0,0 +1,849 @@
+=');
+ }
+
+ return $_is_php[$version];
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('is_really_writable'))
+{
+ /**
+ * Tests for file writability
+ *
+ * is_writable() returns TRUE on Windows servers when you really can't write to
+ * the file, based on the read-only attribute. is_writable() is also unreliable
+ * on Unix servers if safe_mode is on.
+ *
+ * @link https://bugs.php.net/bug.php?id=54709
+ * @param string
+ * @return bool
+ */
+ function is_really_writable($file)
+ {
+ // If we're on a Unix server with safe_mode off we call is_writable
+ if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR ! ini_get('safe_mode')))
+ {
+ return is_writable($file);
+ }
+
+ /* For Windows servers and safe_mode "on" installations we'll actually
+ * write a file then read it. Bah...
+ */
+ if (is_dir($file))
+ {
+ $file = rtrim($file, '/').'/'.md5(mt_rand());
+ if (($fp = @fopen($file, 'ab')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ fclose($fp);
+ @chmod($file, 0777);
+ @unlink($file);
+ return TRUE;
+ }
+ elseif ( ! is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ fclose($fp);
+ return TRUE;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('load_class'))
+{
+ /**
+ * Class registry
+ *
+ * This function acts as a singleton. If the requested class does not
+ * exist it is instantiated and set to a static variable. If it has
+ * previously been instantiated the variable is returned.
+ *
+ * @param string the class name being requested
+ * @param string the directory where the class should be found
+ * @param mixed an optional argument to pass to the class constructor
+ * @return object
+ */
+ function &load_class($class, $directory = 'libraries', $param = NULL)
+ {
+ static $_classes = array();
+
+ // Does the class exist? If so, we're done...
+ if (isset($_classes[$class]))
+ {
+ return $_classes[$class];
+ }
+
+ $name = FALSE;
+
+ // Look for the class first in the local application/libraries folder
+ // then in the native system/libraries folder
+ foreach (array(APPPATH, BASEPATH) as $path)
+ {
+ if (file_exists($path.$directory.'/'.$class.'.php'))
+ {
+ $name = 'CI_'.$class;
+
+ if (class_exists($name, FALSE) === FALSE)
+ {
+ require_once($path.$directory.'/'.$class.'.php');
+ }
+
+ break;
+ }
+ }
+
+ // Is the request a class extension? If so we load it too
+ if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
+ {
+ $name = config_item('subclass_prefix').$class;
+
+ if (class_exists($name, FALSE) === FALSE)
+ {
+ require_once(APPPATH.$directory.'/'.$name.'.php');
+ }
+ }
+
+ // Did we find the class?
+ if ($name === FALSE)
+ {
+ // Note: We use exit() rather than show_error() in order to avoid a
+ // self-referencing loop with the Exceptions class
+ set_status_header(503);
+ echo 'Unable to locate the specified class: '.$class.'.php';
+ exit(5); // EXIT_UNK_CLASS
+ }
+
+ // Keep track of what we just loaded
+ is_loaded($class);
+
+ $_classes[$class] = isset($param)
+ ? new $name($param)
+ : new $name();
+ return $_classes[$class];
+ }
+}
+
+// --------------------------------------------------------------------
+
+if ( ! function_exists('is_loaded'))
+{
+ /**
+ * Keeps track of which libraries have been loaded. This function is
+ * called by the load_class() function above
+ *
+ * @param string
+ * @return array
+ */
+ function &is_loaded($class = '')
+ {
+ static $_is_loaded = array();
+
+ if ($class !== '')
+ {
+ $_is_loaded[strtolower($class)] = $class;
+ }
+
+ return $_is_loaded;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('get_config'))
+{
+ /**
+ * Loads the main config.php file
+ *
+ * This function lets us grab the config file even if the Config class
+ * hasn't been instantiated yet
+ *
+ * @param array
+ * @return array
+ */
+ function &get_config(Array $replace = array())
+ {
+ static $config;
+
+ if (empty($config))
+ {
+ $file_path = APPPATH.'config/config.php';
+ $found = FALSE;
+ if (file_exists($file_path))
+ {
+ $found = TRUE;
+ require($file_path);
+ }
+
+ // Is the config file in the environment folder?
+ if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+ {
+ require($file_path);
+ }
+ elseif ( ! $found)
+ {
+ set_status_header(503);
+ echo 'The configuration file does not exist.';
+ exit(3); // EXIT_CONFIG
+ }
+
+ // Does the $config array exist in the file?
+ if ( ! isset($config) OR ! is_array($config))
+ {
+ set_status_header(503);
+ echo 'Your config file does not appear to be formatted correctly.';
+ exit(3); // EXIT_CONFIG
+ }
+ }
+
+ // Are any values being dynamically added or replaced?
+ foreach ($replace as $key => $val)
+ {
+ $config[$key] = $val;
+ }
+
+ return $config;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('config_item'))
+{
+ /**
+ * Returns the specified config item
+ *
+ * @param string
+ * @return mixed
+ */
+ function config_item($item)
+ {
+ static $_config;
+
+ if (empty($_config))
+ {
+ // references cannot be directly assigned to static variables, so we use an array
+ $_config[0] =& get_config();
+ }
+
+ return isset($_config[0][$item]) ? $_config[0][$item] : NULL;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('get_mimes'))
+{
+ /**
+ * Returns the MIME types array from config/mimes.php
+ *
+ * @return array
+ */
+ function &get_mimes()
+ {
+ static $_mimes;
+
+ if (empty($_mimes))
+ {
+ $_mimes = file_exists(APPPATH.'config/mimes.php')
+ ? include(APPPATH.'config/mimes.php')
+ : array();
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
+ {
+ $_mimes = array_merge($_mimes, include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'));
+ }
+ }
+
+ return $_mimes;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('is_https'))
+{
+ /**
+ * Is HTTPS?
+ *
+ * Determines if the application is accessed via an encrypted
+ * (HTTPS) connection.
+ *
+ * @return bool
+ */
+ function is_https()
+ {
+ if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
+ {
+ return TRUE;
+ }
+ elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
+ {
+ return TRUE;
+ }
+ elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('is_cli'))
+{
+
+ /**
+ * Is CLI?
+ *
+ * Test to see if a request was made from the command line.
+ *
+ * @return bool
+ */
+ function is_cli()
+ {
+ return (PHP_SAPI === 'cli' OR defined('STDIN'));
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('show_error'))
+{
+ /**
+ * Error Handler
+ *
+ * This function lets us invoke the exception class and
+ * display errors using the standard error template located
+ * in application/views/errors/error_general.php
+ * This function will send the error page directly to the
+ * browser and exit.
+ *
+ * @param string
+ * @param int
+ * @param string
+ * @return void
+ */
+ function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
+ {
+ $status_code = abs($status_code);
+ if ($status_code < 100)
+ {
+ $exit_status = $status_code + 9; // 9 is EXIT__AUTO_MIN
+ $status_code = 500;
+ }
+ else
+ {
+ $exit_status = 1; // EXIT_ERROR
+ }
+
+ $_error =& load_class('Exceptions', 'core');
+ echo $_error->show_error($heading, $message, 'error_general', $status_code);
+ exit($exit_status);
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('show_404'))
+{
+ /**
+ * 404 Page Handler
+ *
+ * This function is similar to the show_error() function above
+ * However, instead of the standard error template it displays
+ * 404 errors.
+ *
+ * @param string
+ * @param bool
+ * @return void
+ */
+ function show_404($page = '', $log_error = TRUE)
+ {
+ $_error =& load_class('Exceptions', 'core');
+ $_error->show_404($page, $log_error);
+ exit(4); // EXIT_UNKNOWN_FILE
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('log_message'))
+{
+ /**
+ * Error Logging Interface
+ *
+ * We use this as a simple mechanism to access the logging
+ * class and send messages to be logged.
+ *
+ * @param string the error level: 'error', 'debug' or 'info'
+ * @param string the error message
+ * @return void
+ */
+ function log_message($level, $message)
+ {
+ static $_log;
+
+ if ($_log === NULL)
+ {
+ // references cannot be directly assigned to static variables, so we use an array
+ $_log[0] =& load_class('Log', 'core');
+ }
+
+ $_log[0]->write_log($level, $message);
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('set_status_header'))
+{
+ /**
+ * Set HTTP Status Header
+ *
+ * @param int the status code
+ * @param string
+ * @return void
+ */
+ function set_status_header($code = 200, $text = '')
+ {
+ if (is_cli())
+ {
+ return;
+ }
+
+ if (empty($code) OR ! is_numeric($code))
+ {
+ show_error('Status codes must be numeric', 500);
+ }
+
+ if (empty($text))
+ {
+ is_int($code) OR $code = (int) $code;
+ $stati = array(
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary Redirect',
+
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 402 => 'Payment Required',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Timeout',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Long',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Requested Range Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 422 => 'Unprocessable Entity',
+ 426 => 'Upgrade Required',
+ 428 => 'Precondition Required',
+ 429 => 'Too Many Requests',
+ 431 => 'Request Header Fields Too Large',
+
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported',
+ 511 => 'Network Authentication Required',
+ );
+
+ if (isset($stati[$code]))
+ {
+ $text = $stati[$code];
+ }
+ else
+ {
+ show_error('No status text available. Please check your status code number or supply your own message text.', 500);
+ }
+ }
+
+ if (strpos(PHP_SAPI, 'cgi') === 0)
+ {
+ header('Status: '.$code.' '.$text, TRUE);
+ return;
+ }
+
+ $server_protocol = (isset($_SERVER['SERVER_PROTOCOL']) && in_array($_SERVER['SERVER_PROTOCOL'], array('HTTP/1.0', 'HTTP/1.1', 'HTTP/2'), TRUE))
+ ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
+ header($server_protocol.' '.$code.' '.$text, TRUE, $code);
+ }
+}
+
+// --------------------------------------------------------------------
+
+if ( ! function_exists('_error_handler'))
+{
+ /**
+ * Error Handler
+ *
+ * This is the custom error handler that is declared at the (relative)
+ * top of CodeIgniter.php. The main reason we use this is to permit
+ * PHP errors to be logged in our own log files since the user may
+ * not have access to server logs. Since this function effectively
+ * intercepts PHP errors, however, we also need to display errors
+ * based on the current error_reporting level.
+ * We do that with the use of a PHP error template.
+ *
+ * @param int $severity
+ * @param string $message
+ * @param string $filepath
+ * @param int $line
+ * @return void
+ */
+ function _error_handler($severity, $message, $filepath, $line)
+ {
+ $is_error = (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);
+
+ // When an error occurred, set the status header to '500 Internal Server Error'
+ // to indicate to the client something went wrong.
+ // This can't be done within the $_error->show_php_error method because
+ // it is only called when the display_errors flag is set (which isn't usually
+ // the case in a production environment) or when errors are ignored because
+ // they are above the error_reporting threshold.
+ if ($is_error)
+ {
+ set_status_header(500);
+ }
+
+ // Should we ignore the error? We'll get the current error_reporting
+ // level and add its bits with the severity bits to find out.
+ if (($severity & error_reporting()) !== $severity)
+ {
+ return;
+ }
+
+ $_error =& load_class('Exceptions', 'core');
+ $_error->log_exception($severity, $message, $filepath, $line);
+
+ // Should we display the error?
+ if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors')))
+ {
+ $_error->show_php_error($severity, $message, $filepath, $line);
+ }
+
+ // If the error is fatal, the execution of the script should be stopped because
+ // errors can't be recovered from. Halting the script conforms with PHP's
+ // default error handling. See http://www.php.net/manual/en/errorfunc.constants.php
+ if ($is_error)
+ {
+ exit(1); // EXIT_ERROR
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_exception_handler'))
+{
+ /**
+ * Exception Handler
+ *
+ * Sends uncaught exceptions to the logger and displays them
+ * only if display_errors is On so that they don't show up in
+ * production environments.
+ *
+ * @param Exception $exception
+ * @return void
+ */
+ function _exception_handler($exception)
+ {
+ $_error =& load_class('Exceptions', 'core');
+ $_error->log_exception('error', 'Exception: '.$exception->getMessage(), $exception->getFile(), $exception->getLine());
+
+ is_cli() OR set_status_header(500);
+ // Should we display the error?
+ if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors')))
+ {
+ $_error->show_exception($exception);
+ }
+
+ exit(1); // EXIT_ERROR
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_shutdown_handler'))
+{
+ /**
+ * Shutdown Handler
+ *
+ * This is the shutdown handler that is declared at the top
+ * of CodeIgniter.php. The main reason we use this is to simulate
+ * a complete custom exception handler.
+ *
+ * E_STRICT is purposively neglected because such events may have
+ * been caught. Duplication or none? None is preferred for now.
+ *
+ * @link http://insomanic.me.uk/post/229851073/php-trick-catching-fatal-errors-e-error-with-a
+ * @return void
+ */
+ function _shutdown_handler()
+ {
+ $last_error = error_get_last();
+ if (isset($last_error) &&
+ ($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING)))
+ {
+ _error_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']);
+ }
+ }
+}
+
+// --------------------------------------------------------------------
+
+if ( ! function_exists('remove_invisible_characters'))
+{
+ /**
+ * Remove Invisible Characters
+ *
+ * This prevents sandwiching null characters
+ * between ascii characters, like Java\0script.
+ *
+ * @param string
+ * @param bool
+ * @return string
+ */
+ function remove_invisible_characters($str, $url_encoded = TRUE)
+ {
+ $non_displayables = array();
+
+ // every control character except newline (dec 10),
+ // carriage return (dec 13) and horizontal tab (dec 09)
+ if ($url_encoded)
+ {
+ $non_displayables[] = '/%0[0-8bcef]/i'; // url encoded 00-08, 11, 12, 14, 15
+ $non_displayables[] = '/%1[0-9a-f]/i'; // url encoded 16-31
+ $non_displayables[] = '/%7f/i'; // url encoded 127
+ }
+
+ $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
+
+ do
+ {
+ $str = preg_replace($non_displayables, '', $str, -1, $count);
+ }
+ while ($count);
+
+ return $str;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('html_escape'))
+{
+ /**
+ * Returns HTML escaped variable.
+ *
+ * @param mixed $var The input string or array of strings to be escaped.
+ * @param bool $double_encode $double_encode set to FALSE prevents escaping twice.
+ * @return mixed The escaped string or array of strings as a result.
+ */
+ function html_escape($var, $double_encode = TRUE)
+ {
+ if (empty($var))
+ {
+ return $var;
+ }
+
+ if (is_array($var))
+ {
+ foreach (array_keys($var) as $key)
+ {
+ $var[$key] = html_escape($var[$key], $double_encode);
+ }
+
+ return $var;
+ }
+
+ return htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode);
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_stringify_attributes'))
+{
+ /**
+ * Stringify attributes for use in HTML tags.
+ *
+ * Helper function used to convert a string, array, or object
+ * of attributes to a string.
+ *
+ * @param mixed string, array, object
+ * @param bool
+ * @return string
+ */
+ function _stringify_attributes($attributes, $js = FALSE)
+ {
+ $atts = NULL;
+
+ if (empty($attributes))
+ {
+ return $atts;
+ }
+
+ if (is_string($attributes))
+ {
+ return ' '.$attributes;
+ }
+
+ $attributes = (array) $attributes;
+
+ foreach ($attributes as $key => $val)
+ {
+ $atts .= ($js) ? $key.'='.$val.',' : ' '.$key.'="'.$val.'"';
+ }
+
+ return rtrim($atts, ',');
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('function_usable'))
+{
+ /**
+ * Function usable
+ *
+ * Executes a function_exists() check, and if the Suhosin PHP
+ * extension is loaded - checks whether the function that is
+ * checked might be disabled in there as well.
+ *
+ * This is useful as function_exists() will return FALSE for
+ * functions disabled via the *disable_functions* php.ini
+ * setting, but not for *suhosin.executor.func.blacklist* and
+ * *suhosin.executor.disable_eval*. These settings will just
+ * terminate script execution if a disabled function is executed.
+ *
+ * The above described behavior turned out to be a bug in Suhosin,
+ * but even though a fix was committed for 0.9.34 on 2012-02-12,
+ * that version is yet to be released. This function will therefore
+ * be just temporary, but would probably be kept for a few years.
+ *
+ * @link http://www.hardened-php.net/suhosin/
+ * @param string $function_name Function to check for
+ * @return bool TRUE if the function exists and is safe to call,
+ * FALSE otherwise.
+ */
+ function function_usable($function_name)
+ {
+ static $_suhosin_func_blacklist;
+
+ if (function_exists($function_name))
+ {
+ if ( ! isset($_suhosin_func_blacklist))
+ {
+ $_suhosin_func_blacklist = extension_loaded('suhosin')
+ ? explode(',', trim(ini_get('suhosin.executor.func.blacklist')))
+ : array();
+ }
+
+ return ! in_array($function_name, $_suhosin_func_blacklist, TRUE);
+ }
+
+ return FALSE;
+ }
+}
diff --git a/system/core/Config.php b/system/core/Config.php
new file mode 100644
index 0000000..fc6c30f
--- /dev/null
+++ b/system/core/Config.php
@@ -0,0 +1,379 @@
+config =& get_config();
+
+ // Set the base_url automatically if none was provided
+ if (empty($this->config['base_url']))
+ {
+ if (isset($_SERVER['SERVER_ADDR']))
+ {
+ if (strpos($_SERVER['SERVER_ADDR'], ':') !== FALSE)
+ {
+ $server_addr = '['.$_SERVER['SERVER_ADDR'].']';
+ }
+ else
+ {
+ $server_addr = $_SERVER['SERVER_ADDR'];
+ }
+
+ $base_url = (is_https() ? 'https' : 'http').'://'.$server_addr
+ .substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));
+ }
+ else
+ {
+ $base_url = 'http://localhost/';
+ }
+
+ $this->set_item('base_url', $base_url);
+ }
+
+ log_message('info', 'Config Class Initialized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Config File
+ *
+ * @param string $file Configuration file name
+ * @param bool $use_sections Whether configuration values should be loaded into their own section
+ * @param bool $fail_gracefully Whether to just return FALSE or display an error message
+ * @return bool TRUE if the file was loaded correctly or FALSE on failure
+ */
+ public function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
+ {
+ $file = ($file === '') ? 'config' : str_replace('.php', '', $file);
+ $loaded = FALSE;
+
+ foreach ($this->_config_paths as $path)
+ {
+ foreach (array($file, ENVIRONMENT.DIRECTORY_SEPARATOR.$file) as $location)
+ {
+ $file_path = $path.'config/'.$location.'.php';
+ if (in_array($file_path, $this->is_loaded, TRUE))
+ {
+ return TRUE;
+ }
+
+ if ( ! file_exists($file_path))
+ {
+ continue;
+ }
+
+ include($file_path);
+
+ if ( ! isset($config) OR ! is_array($config))
+ {
+ if ($fail_gracefully === TRUE)
+ {
+ return FALSE;
+ }
+
+ show_error('Your '.$file_path.' file does not appear to contain a valid configuration array.');
+ }
+
+ if ($use_sections === TRUE)
+ {
+ $this->config[$file] = isset($this->config[$file])
+ ? array_merge($this->config[$file], $config)
+ : $config;
+ }
+ else
+ {
+ $this->config = array_merge($this->config, $config);
+ }
+
+ $this->is_loaded[] = $file_path;
+ $config = NULL;
+ $loaded = TRUE;
+ log_message('debug', 'Config file loaded: '.$file_path);
+ }
+ }
+
+ if ($loaded === TRUE)
+ {
+ return TRUE;
+ }
+ elseif ($fail_gracefully === TRUE)
+ {
+ return FALSE;
+ }
+
+ show_error('The configuration file '.$file.'.php does not exist.');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a config file item
+ *
+ * @param string $item Config item name
+ * @param string $index Index name
+ * @return string|null The configuration item or NULL if the item doesn't exist
+ */
+ public function item($item, $index = '')
+ {
+ if ($index == '')
+ {
+ return isset($this->config[$item]) ? $this->config[$item] : NULL;
+ }
+
+ return isset($this->config[$index], $this->config[$index][$item]) ? $this->config[$index][$item] : NULL;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a config file item with slash appended (if not empty)
+ *
+ * @param string $item Config item name
+ * @return string|null The configuration item or NULL if the item doesn't exist
+ */
+ public function slash_item($item)
+ {
+ if ( ! isset($this->config[$item]))
+ {
+ return NULL;
+ }
+ elseif (trim($this->config[$item]) === '')
+ {
+ return '';
+ }
+
+ return rtrim($this->config[$item], '/').'/';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Site URL
+ *
+ * Returns base_url . index_page [. uri_string]
+ *
+ * @uses CI_Config::_uri_string()
+ *
+ * @param string|string[] $uri URI string or an array of segments
+ * @param string $protocol
+ * @return string
+ */
+ public function site_url($uri = '', $protocol = NULL)
+ {
+ $base_url = $this->slash_item('base_url');
+
+ if (isset($protocol))
+ {
+ // For protocol-relative links
+ if ($protocol === '')
+ {
+ $base_url = substr($base_url, strpos($base_url, '//'));
+ }
+ else
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
+ }
+
+ if (empty($uri))
+ {
+ return $base_url.$this->item('index_page');
+ }
+
+ $uri = $this->_uri_string($uri);
+
+ if ($this->item('enable_query_strings') === FALSE)
+ {
+ $suffix = isset($this->config['url_suffix']) ? $this->config['url_suffix'] : '';
+
+ if ($suffix !== '')
+ {
+ if (($offset = strpos($uri, '?')) !== FALSE)
+ {
+ $uri = substr($uri, 0, $offset).$suffix.substr($uri, $offset);
+ }
+ else
+ {
+ $uri .= $suffix;
+ }
+ }
+
+ return $base_url.$this->slash_item('index_page').$uri;
+ }
+ elseif (strpos($uri, '?') === FALSE)
+ {
+ $uri = '?'.$uri;
+ }
+
+ return $base_url.$this->item('index_page').$uri;
+ }
+
+ // -------------------------------------------------------------
+
+ /**
+ * Base URL
+ *
+ * Returns base_url [. uri_string]
+ *
+ * @uses CI_Config::_uri_string()
+ *
+ * @param string|string[] $uri URI string or an array of segments
+ * @param string $protocol
+ * @return string
+ */
+ public function base_url($uri = '', $protocol = NULL)
+ {
+ $base_url = $this->slash_item('base_url');
+
+ if (isset($protocol))
+ {
+ // For protocol-relative links
+ if ($protocol === '')
+ {
+ $base_url = substr($base_url, strpos($base_url, '//'));
+ }
+ else
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
+ }
+
+ return $base_url.$this->_uri_string($uri);
+ }
+
+ // -------------------------------------------------------------
+
+ /**
+ * Build URI string
+ *
+ * @used-by CI_Config::site_url()
+ * @used-by CI_Config::base_url()
+ *
+ * @param string|string[] $uri URI string or an array of segments
+ * @return string
+ */
+ protected function _uri_string($uri)
+ {
+ if ($this->item('enable_query_strings') === FALSE)
+ {
+ is_array($uri) && $uri = implode('/', $uri);
+ return ltrim($uri, '/');
+ }
+ elseif (is_array($uri))
+ {
+ return http_build_query($uri);
+ }
+
+ return $uri;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * System URL
+ *
+ * @deprecated 3.0.0 Encourages insecure practices
+ * @return string
+ */
+ public function system_url()
+ {
+ $x = explode('/', preg_replace('|/*(.+?)/*$|', '\\1', BASEPATH));
+ return $this->slash_item('base_url').end($x).'/';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set a config file item
+ *
+ * @param string $item Config item key
+ * @param string $value Config item value
+ * @return void
+ */
+ public function set_item($item, $value)
+ {
+ $this->config[$item] = $value;
+ }
+
+}
diff --git a/system/core/Controller.php b/system/core/Controller.php
new file mode 100644
index 0000000..e25b847
--- /dev/null
+++ b/system/core/Controller.php
@@ -0,0 +1,103 @@
+ $class)
+ {
+ $this->$var =& load_class($class);
+ }
+
+ $this->load =& load_class('Loader', 'core');
+ $this->load->initialize();
+ log_message('info', 'Controller Class Initialized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get the CI singleton
+ *
+ * @static
+ * @return object
+ */
+ public static function &get_instance()
+ {
+ return self::$instance;
+ }
+
+}
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
new file mode 100644
index 0000000..90ff1ab
--- /dev/null
+++ b/system/core/Exceptions.php
@@ -0,0 +1,274 @@
+ 'Error',
+ E_WARNING => 'Warning',
+ E_PARSE => 'Parsing Error',
+ E_NOTICE => 'Notice',
+ E_CORE_ERROR => 'Core Error',
+ E_CORE_WARNING => 'Core Warning',
+ E_COMPILE_ERROR => 'Compile Error',
+ E_COMPILE_WARNING => 'Compile Warning',
+ E_USER_ERROR => 'User Error',
+ E_USER_WARNING => 'User Warning',
+ E_USER_NOTICE => 'User Notice',
+ E_STRICT => 'Runtime Notice'
+ );
+
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->ob_level = ob_get_level();
+ // Note: Do not log messages from this constructor.
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Exception Logger
+ *
+ * Logs PHP generated error messages
+ *
+ * @param int $severity Log level
+ * @param string $message Error message
+ * @param string $filepath File path
+ * @param int $line Line number
+ * @return void
+ */
+ public function log_exception($severity, $message, $filepath, $line)
+ {
+ $severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
+ log_message('error', 'Severity: '.$severity.' --> '.$message.' '.$filepath.' '.$line);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 404 Error Handler
+ *
+ * @uses CI_Exceptions::show_error()
+ *
+ * @param string $page Page URI
+ * @param bool $log_error Whether to log the error
+ * @return void
+ */
+ public function show_404($page = '', $log_error = TRUE)
+ {
+ if (is_cli())
+ {
+ $heading = 'Not Found';
+ $message = 'The controller/method pair you requested was not found.';
+ }
+ else
+ {
+ $heading = '404 Page Not Found';
+ $message = 'The page you requested was not found.';
+ }
+
+ // By default we log this, but allow a dev to skip it
+ if ($log_error)
+ {
+ log_message('error', $heading.': '.$page);
+ }
+
+ echo $this->show_error($heading, $message, 'error_404', 404);
+ exit(4); // EXIT_UNKNOWN_FILE
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * General Error Page
+ *
+ * Takes an error message as input (either as a string or an array)
+ * and displays it using the specified template.
+ *
+ * @param string $heading Page heading
+ * @param string|string[] $message Error message
+ * @param string $template Template name
+ * @param int $status_code (default: 500)
+ *
+ * @return string Error page output
+ */
+ public function show_error($heading, $message, $template = 'error_general', $status_code = 500)
+ {
+ $templates_path = config_item('error_views_path');
+ if (empty($templates_path))
+ {
+ $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
+ }
+
+ if (is_cli())
+ {
+ $message = "\t".(is_array($message) ? implode("\n\t", $message) : $message);
+ $template = 'cli'.DIRECTORY_SEPARATOR.$template;
+ }
+ else
+ {
+ set_status_header($status_code);
+ $message = ''.(is_array($message) ? implode('
', $message) : $message).'
';
+ $template = 'html'.DIRECTORY_SEPARATOR.$template;
+ }
+
+ if (ob_get_level() > $this->ob_level + 1)
+ {
+ ob_end_flush();
+ }
+ ob_start();
+ include($templates_path.$template.'.php');
+ $buffer = ob_get_contents();
+ ob_end_clean();
+ return $buffer;
+ }
+
+ // --------------------------------------------------------------------
+
+ public function show_exception($exception)
+ {
+ $templates_path = config_item('error_views_path');
+ if (empty($templates_path))
+ {
+ $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
+ }
+
+ $message = $exception->getMessage();
+ if (empty($message))
+ {
+ $message = '(null)';
+ }
+
+ if (is_cli())
+ {
+ $templates_path .= 'cli'.DIRECTORY_SEPARATOR;
+ }
+ else
+ {
+ $templates_path .= 'html'.DIRECTORY_SEPARATOR;
+ }
+
+ if (ob_get_level() > $this->ob_level + 1)
+ {
+ ob_end_flush();
+ }
+
+ ob_start();
+ include($templates_path.'error_exception.php');
+ $buffer = ob_get_contents();
+ ob_end_clean();
+ echo $buffer;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Native PHP error handler
+ *
+ * @param int $severity Error level
+ * @param string $message Error message
+ * @param string $filepath File path
+ * @param int $line Line number
+ * @return void
+ */
+ public function show_php_error($severity, $message, $filepath, $line)
+ {
+ $templates_path = config_item('error_views_path');
+ if (empty($templates_path))
+ {
+ $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
+ }
+
+ $severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
+
+ // For safety reasons we don't show the full file path in non-CLI requests
+ if ( ! is_cli())
+ {
+ $filepath = str_replace('\\', '/', $filepath);
+ if (FALSE !== strpos($filepath, '/'))
+ {
+ $x = explode('/', $filepath);
+ $filepath = $x[count($x)-2].'/'.end($x);
+ }
+
+ $template = 'html'.DIRECTORY_SEPARATOR.'error_php';
+ }
+ else
+ {
+ $template = 'cli'.DIRECTORY_SEPARATOR.'error_php';
+ }
+
+ if (ob_get_level() > $this->ob_level + 1)
+ {
+ ob_end_flush();
+ }
+ ob_start();
+ include($templates_path.$template.'.php');
+ $buffer = ob_get_contents();
+ ob_end_clean();
+ echo $buffer;
+ }
+
+}
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
new file mode 100644
index 0000000..6236dd4
--- /dev/null
+++ b/system/core/Hooks.php
@@ -0,0 +1,266 @@
+item('enable_hooks') === FALSE)
+ {
+ return;
+ }
+
+ // Grab the "hooks" definition file.
+ if (file_exists(APPPATH.'config/hooks.php'))
+ {
+ include(APPPATH.'config/hooks.php');
+ }
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'))
+ {
+ include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php');
+ }
+
+ // If there are no hooks, we're done.
+ if ( ! isset($hook) OR ! is_array($hook))
+ {
+ return;
+ }
+
+ $this->hooks =& $hook;
+ $this->enabled = TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Call Hook
+ *
+ * Calls a particular hook. Called by CodeIgniter.php.
+ *
+ * @uses CI_Hooks::_run_hook()
+ *
+ * @param string $which Hook name
+ * @return bool TRUE on success or FALSE on failure
+ */
+ public function call_hook($which = '')
+ {
+ if ( ! $this->enabled OR ! isset($this->hooks[$which]))
+ {
+ return FALSE;
+ }
+
+ if (is_array($this->hooks[$which]) && ! isset($this->hooks[$which]['function']))
+ {
+ foreach ($this->hooks[$which] as $val)
+ {
+ $this->_run_hook($val);
+ }
+ }
+ else
+ {
+ $this->_run_hook($this->hooks[$which]);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Run Hook
+ *
+ * Runs a particular hook
+ *
+ * @param array $data Hook details
+ * @return bool TRUE on success or FALSE on failure
+ */
+ protected function _run_hook($data)
+ {
+ // Closures/lambda functions and array($object, 'method') callables
+ if (is_callable($data))
+ {
+ is_array($data)
+ ? $data[0]->{$data[1]}()
+ : $data();
+
+ return TRUE;
+ }
+ elseif ( ! is_array($data))
+ {
+ return FALSE;
+ }
+
+ // -----------------------------------
+ // Safety - Prevents run-away loops
+ // -----------------------------------
+
+ // If the script being called happens to have the same
+ // hook call within it a loop can happen
+ if ($this->_in_progress === TRUE)
+ {
+ return;
+ }
+
+ // -----------------------------------
+ // Set file path
+ // -----------------------------------
+
+ if ( ! isset($data['filepath'], $data['filename']))
+ {
+ return FALSE;
+ }
+
+ $filepath = APPPATH.$data['filepath'].'/'.$data['filename'];
+
+ if ( ! file_exists($filepath))
+ {
+ return FALSE;
+ }
+
+ // Determine and class and/or function names
+ $class = empty($data['class']) ? FALSE : $data['class'];
+ $function = empty($data['function']) ? FALSE : $data['function'];
+ $params = isset($data['params']) ? $data['params'] : '';
+
+ if (empty($function))
+ {
+ return FALSE;
+ }
+
+ // Set the _in_progress flag
+ $this->_in_progress = TRUE;
+
+ // Call the requested class and/or function
+ if ($class !== FALSE)
+ {
+ // The object is stored?
+ if (isset($this->_objects[$class]))
+ {
+ if (method_exists($this->_objects[$class], $function))
+ {
+ $this->_objects[$class]->$function($params);
+ }
+ else
+ {
+ return $this->_in_progress = FALSE;
+ }
+ }
+ else
+ {
+ class_exists($class, FALSE) OR require_once($filepath);
+
+ if ( ! class_exists($class, FALSE) OR ! method_exists($class, $function))
+ {
+ return $this->_in_progress = FALSE;
+ }
+
+ // Store the object and execute the method
+ $this->_objects[$class] = new $class();
+ $this->_objects[$class]->$function($params);
+ }
+ }
+ else
+ {
+ function_exists($function) OR require_once($filepath);
+
+ if ( ! function_exists($function))
+ {
+ return $this->_in_progress = FALSE;
+ }
+
+ $function($params);
+ }
+
+ $this->_in_progress = FALSE;
+ return TRUE;
+ }
+
+}
diff --git a/system/core/Input.php b/system/core/Input.php
new file mode 100644
index 0000000..30b31d0
--- /dev/null
+++ b/system/core/Input.php
@@ -0,0 +1,895 @@
+_allow_get_array = (config_item('allow_get_array') !== FALSE);
+ $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
+ $this->_enable_csrf = (config_item('csrf_protection') === TRUE);
+ $this->_standardize_newlines = (bool) config_item('standardize_newlines');
+
+ $this->security =& load_class('Security', 'core');
+
+ // Do we need the UTF-8 class?
+ if (UTF8_ENABLED === TRUE)
+ {
+ $this->uni =& load_class('Utf8', 'core');
+ }
+
+ // Sanitize global arrays
+ $this->_sanitize_globals();
+
+ // CSRF Protection check
+ if ($this->_enable_csrf === TRUE && ! is_cli())
+ {
+ $this->security->csrf_verify();
+ }
+
+ log_message('info', 'Input Class Initialized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch from array
+ *
+ * Internal method used to retrieve values from global arrays.
+ *
+ * @param array &$array $_GET, $_POST, $_COOKIE, $_SERVER, etc.
+ * @param mixed $index Index for item to be fetched from $array
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL)
+ {
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
+ // If $index is NULL, it means that the whole $array is requested
+ isset($index) OR $index = array_keys($array);
+
+ // allow fetching multiple keys at once
+ if (is_array($index))
+ {
+ $output = array();
+ foreach ($index as $key)
+ {
+ $output[$key] = $this->_fetch_from_array($array, $key, $xss_clean);
+ }
+
+ return $output;
+ }
+
+ if (isset($array[$index]))
+ {
+ $value = $array[$index];
+ }
+ elseif (($count = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $index, $matches)) > 1) // Does the index contain array notation
+ {
+ $value = $array;
+ for ($i = 0; $i < $count; $i++)
+ {
+ $key = trim($matches[0][$i], '[]');
+ if ($key === '') // Empty notation will return the value as array
+ {
+ break;
+ }
+
+ if (isset($value[$key]))
+ {
+ $value = $value[$key];
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ return ($xss_clean === TRUE)
+ ? $this->security->xss_clean($value)
+ : $value;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the GET array
+ *
+ * @param mixed $index Index for item to be fetched from $_GET
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function get($index = NULL, $xss_clean = NULL)
+ {
+ return $this->_fetch_from_array($_GET, $index, $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the POST array
+ *
+ * @param mixed $index Index for item to be fetched from $_POST
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function post($index = NULL, $xss_clean = NULL)
+ {
+ return $this->_fetch_from_array($_POST, $index, $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from POST data with fallback to GET
+ *
+ * @param string $index Index for item to be fetched from $_POST or $_GET
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function post_get($index, $xss_clean = NULL)
+ {
+ return isset($_POST[$index])
+ ? $this->post($index, $xss_clean)
+ : $this->get($index, $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from GET data with fallback to POST
+ *
+ * @param string $index Index for item to be fetched from $_GET or $_POST
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function get_post($index, $xss_clean = NULL)
+ {
+ return isset($_GET[$index])
+ ? $this->get($index, $xss_clean)
+ : $this->post($index, $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the COOKIE array
+ *
+ * @param mixed $index Index for item to be fetched from $_COOKIE
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function cookie($index = NULL, $xss_clean = NULL)
+ {
+ return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the SERVER array
+ *
+ * @param mixed $index Index for item to be fetched from $_SERVER
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function server($index, $xss_clean = NULL)
+ {
+ return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the php://input stream
+ *
+ * Useful when you need to access PUT, DELETE or PATCH request data.
+ *
+ * @param string $index Index for item to be fetched
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function input_stream($index = NULL, $xss_clean = NULL)
+ {
+ // Prior to PHP 5.6, the input stream can only be read once,
+ // so we'll need to check if we have already done that first.
+ if ( ! is_array($this->_input_stream))
+ {
+ // $this->raw_input_stream will trigger __get().
+ parse_str($this->raw_input_stream, $this->_input_stream);
+ is_array($this->_input_stream) OR $this->_input_stream = array();
+ }
+
+ return $this->_fetch_from_array($this->_input_stream, $index, $xss_clean);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Set cookie
+ *
+ * Accepts an arbitrary number of parameters (up to 7) or an associative
+ * array in the first parameter containing all the values.
+ *
+ * @param string|mixed[] $name Cookie name or an array containing parameters
+ * @param string $value Cookie value
+ * @param int $expire Cookie expiration time in seconds
+ * @param string $domain Cookie domain (e.g.: '.yourdomain.com')
+ * @param string $path Cookie path (default: '/')
+ * @param string $prefix Cookie name prefix
+ * @param bool $secure Whether to only transfer cookies via SSL
+ * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
+ * @return void
+ */
+ public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL)
+ {
+ if (is_array($name))
+ {
+ // always leave 'name' in last place, as the loop will break otherwise, due to $$item
+ foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item)
+ {
+ if (isset($name[$item]))
+ {
+ $$item = $name[$item];
+ }
+ }
+ }
+
+ if ($prefix === '' && config_item('cookie_prefix') !== '')
+ {
+ $prefix = config_item('cookie_prefix');
+ }
+
+ if ($domain == '' && config_item('cookie_domain') != '')
+ {
+ $domain = config_item('cookie_domain');
+ }
+
+ if ($path === '/' && config_item('cookie_path') !== '/')
+ {
+ $path = config_item('cookie_path');
+ }
+
+ $secure = ($secure === NULL && config_item('cookie_secure') !== NULL)
+ ? (bool) config_item('cookie_secure')
+ : (bool) $secure;
+
+ $httponly = ($httponly === NULL && config_item('cookie_httponly') !== NULL)
+ ? (bool) config_item('cookie_httponly')
+ : (bool) $httponly;
+
+ if ( ! is_numeric($expire))
+ {
+ $expire = time() - 86500;
+ }
+ else
+ {
+ $expire = ($expire > 0) ? time() + $expire : 0;
+ }
+
+ setcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the IP Address
+ *
+ * Determines and validates the visitor's IP address.
+ *
+ * @return string IP address
+ */
+ public function ip_address()
+ {
+ if ($this->ip_address !== FALSE)
+ {
+ return $this->ip_address;
+ }
+
+ $proxy_ips = config_item('proxy_ips');
+ if ( ! empty($proxy_ips) && ! is_array($proxy_ips))
+ {
+ $proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));
+ }
+
+ $this->ip_address = $this->server('REMOTE_ADDR');
+
+ if ($proxy_ips)
+ {
+ foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header)
+ {
+ if (($spoof = $this->server($header)) !== NULL)
+ {
+ // Some proxies typically list the whole chain of IP
+ // addresses through which the client has reached us.
+ // e.g. client_ip, proxy_ip1, proxy_ip2, etc.
+ sscanf($spoof, '%[^,]', $spoof);
+
+ if ( ! $this->valid_ip($spoof))
+ {
+ $spoof = NULL;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if ($spoof)
+ {
+ for ($i = 0, $c = count($proxy_ips); $i < $c; $i++)
+ {
+ // Check if we have an IP address or a subnet
+ if (strpos($proxy_ips[$i], '/') === FALSE)
+ {
+ // An IP address (and not a subnet) is specified.
+ // We can compare right away.
+ if ($proxy_ips[$i] === $this->ip_address)
+ {
+ $this->ip_address = $spoof;
+ break;
+ }
+
+ continue;
+ }
+
+ // We have a subnet ... now the heavy lifting begins
+ isset($separator) OR $separator = $this->valid_ip($this->ip_address, 'ipv6') ? ':' : '.';
+
+ // If the proxy entry doesn't match the IP protocol - skip it
+ if (strpos($proxy_ips[$i], $separator) === FALSE)
+ {
+ continue;
+ }
+
+ // Convert the REMOTE_ADDR IP address to binary, if needed
+ if ( ! isset($ip, $sprintf))
+ {
+ if ($separator === ':')
+ {
+ // Make sure we're have the "full" IPv6 format
+ $ip = explode(':',
+ str_replace('::',
+ str_repeat(':', 9 - substr_count($this->ip_address, ':')),
+ $this->ip_address
+ )
+ );
+
+ for ($j = 0; $j < 8; $j++)
+ {
+ $ip[$j] = intval($ip[$j], 16);
+ }
+
+ $sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b';
+ }
+ else
+ {
+ $ip = explode('.', $this->ip_address);
+ $sprintf = '%08b%08b%08b%08b';
+ }
+
+ $ip = vsprintf($sprintf, $ip);
+ }
+
+ // Split the netmask length off the network address
+ sscanf($proxy_ips[$i], '%[^/]/%d', $netaddr, $masklen);
+
+ // Again, an IPv6 address is most likely in a compressed form
+ if ($separator === ':')
+ {
+ $netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr));
+ for ($j = 0; $j < 8; $j++)
+ {
+ $netaddr[$j] = intval($netaddr[$j], 16);
+ }
+ }
+ else
+ {
+ $netaddr = explode('.', $netaddr);
+ }
+
+ // Convert to binary and finally compare
+ if (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0)
+ {
+ $this->ip_address = $spoof;
+ break;
+ }
+ }
+ }
+ }
+
+ if ( ! $this->valid_ip($this->ip_address))
+ {
+ return $this->ip_address = '0.0.0.0';
+ }
+
+ return $this->ip_address;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Validate IP Address
+ *
+ * @param string $ip IP address
+ * @param string $which IP protocol: 'ipv4' or 'ipv6'
+ * @return bool
+ */
+ public function valid_ip($ip, $which = '')
+ {
+ switch (strtolower($which))
+ {
+ case 'ipv4':
+ $which = FILTER_FLAG_IPV4;
+ break;
+ case 'ipv6':
+ $which = FILTER_FLAG_IPV6;
+ break;
+ default:
+ $which = NULL;
+ break;
+ }
+
+ return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch User Agent string
+ *
+ * @return string|null User Agent string or NULL if it doesn't exist
+ */
+ public function user_agent($xss_clean = NULL)
+ {
+ return $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sanitize Globals
+ *
+ * Internal method serving for the following purposes:
+ *
+ * - Unsets $_GET data, if query strings are not enabled
+ * - Cleans POST, COOKIE and SERVER data
+ * - Standardizes newline characters to PHP_EOL
+ *
+ * @return void
+ */
+ protected function _sanitize_globals()
+ {
+ // Is $_GET data allowed? If not we'll set the $_GET to an empty array
+ if ($this->_allow_get_array === FALSE)
+ {
+ $_GET = array();
+ }
+ elseif (is_array($_GET))
+ {
+ foreach ($_GET as $key => $val)
+ {
+ $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+ }
+ }
+
+ // Clean $_POST Data
+ if (is_array($_POST))
+ {
+ foreach ($_POST as $key => $val)
+ {
+ $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+ }
+ }
+
+ // Clean $_COOKIE Data
+ if (is_array($_COOKIE))
+ {
+ // Also get rid of specially treated cookies that might be set by a server
+ // or silly application, that are of no use to a CI application anyway
+ // but that when present will trip our 'Disallowed Key Characters' alarm
+ // http://www.ietf.org/rfc/rfc2109.txt
+ // note that the key names below are single quoted strings, and are not PHP variables
+ unset(
+ $_COOKIE['$Version'],
+ $_COOKIE['$Path'],
+ $_COOKIE['$Domain']
+ );
+
+ foreach ($_COOKIE as $key => $val)
+ {
+ if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)
+ {
+ $_COOKIE[$cookie_key] = $this->_clean_input_data($val);
+ }
+ else
+ {
+ unset($_COOKIE[$key]);
+ }
+ }
+ }
+
+ // Sanitize PHP_SELF
+ $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
+
+ log_message('debug', 'Global POST, GET and COOKIE data sanitized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Clean Input Data
+ *
+ * Internal method that aids in escaping data and
+ * standardizing newline characters to PHP_EOL.
+ *
+ * @param string|string[] $str Input string(s)
+ * @return string
+ */
+ protected function _clean_input_data($str)
+ {
+ if (is_array($str))
+ {
+ $new_array = array();
+ foreach (array_keys($str) as $key)
+ {
+ $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]);
+ }
+ return $new_array;
+ }
+
+ /* We strip slashes if magic quotes is on to keep things consistent
+
+ NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
+ it will probably not exist in future versions at all.
+ */
+ if ( ! is_php('5.4') && get_magic_quotes_gpc())
+ {
+ $str = stripslashes($str);
+ }
+
+ // Clean UTF-8 if supported
+ if (UTF8_ENABLED === TRUE)
+ {
+ $str = $this->uni->clean_string($str);
+ }
+
+ // Remove control characters
+ $str = remove_invisible_characters($str, FALSE);
+
+ // Standardize newlines if needed
+ if ($this->_standardize_newlines === TRUE)
+ {
+ return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str);
+ }
+
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Clean Keys
+ *
+ * Internal method that helps to prevent malicious users
+ * from trying to exploit keys we make sure that keys are
+ * only named with alpha-numeric text and a few other items.
+ *
+ * @param string $str Input string
+ * @param bool $fatal Whether to terminate script exection
+ * or to return FALSE if an invalid
+ * key is encountered
+ * @return string|bool
+ */
+ protected function _clean_input_keys($str, $fatal = TRUE)
+ {
+ if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
+ {
+ if ($fatal === TRUE)
+ {
+ return FALSE;
+ }
+ else
+ {
+ set_status_header(503);
+ echo 'Disallowed Key Characters.';
+ exit(7); // EXIT_USER_INPUT
+ }
+ }
+
+ // Clean UTF-8 if supported
+ if (UTF8_ENABLED === TRUE)
+ {
+ return $this->uni->clean_string($str);
+ }
+
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Request Headers
+ *
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return array
+ */
+ public function request_headers($xss_clean = FALSE)
+ {
+ // If header is already defined, return it immediately
+ if ( ! empty($this->headers))
+ {
+ return $this->_fetch_from_array($this->headers, NULL, $xss_clean);
+ }
+
+ // In Apache, you can simply call apache_request_headers()
+ if (function_exists('apache_request_headers'))
+ {
+ $this->headers = apache_request_headers();
+ }
+ else
+ {
+ isset($_SERVER['CONTENT_TYPE']) && $this->headers['Content-Type'] = $_SERVER['CONTENT_TYPE'];
+
+ foreach ($_SERVER as $key => $val)
+ {
+ if (sscanf($key, 'HTTP_%s', $header) === 1)
+ {
+ // take SOME_HEADER and turn it into Some-Header
+ $header = str_replace('_', ' ', strtolower($header));
+ $header = str_replace(' ', '-', ucwords($header));
+
+ $this->headers[$header] = $_SERVER[$key];
+ }
+ }
+ }
+
+ return $this->_fetch_from_array($this->headers, NULL, $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Request Header
+ *
+ * Returns the value of a single member of the headers class member
+ *
+ * @param string $index Header name
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return string|null The requested header on success or NULL on failure
+ */
+ public function get_request_header($index, $xss_clean = FALSE)
+ {
+ static $headers;
+
+ if ( ! isset($headers))
+ {
+ empty($this->headers) && $this->request_headers();
+ foreach ($this->headers as $key => $value)
+ {
+ $headers[strtolower($key)] = $value;
+ }
+ }
+
+ $index = strtolower($index);
+
+ if ( ! isset($headers[$index]))
+ {
+ return NULL;
+ }
+
+ return ($xss_clean === TRUE)
+ ? $this->security->xss_clean($headers[$index])
+ : $headers[$index];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Is AJAX request?
+ *
+ * Test to see if a request contains the HTTP_X_REQUESTED_WITH header.
+ *
+ * @return bool
+ */
+ public function is_ajax_request()
+ {
+ return ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Is CLI request?
+ *
+ * Test to see if a request was made from the command line.
+ *
+ * @deprecated 3.0.0 Use is_cli() instead
+ * @return bool
+ */
+ public function is_cli_request()
+ {
+ return is_cli();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Request Method
+ *
+ * Return the request method
+ *
+ * @param bool $upper Whether to return in upper or lower case
+ * (default: FALSE)
+ * @return string
+ */
+ public function method($upper = FALSE)
+ {
+ return ($upper)
+ ? strtoupper($this->server('REQUEST_METHOD'))
+ : strtolower($this->server('REQUEST_METHOD'));
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Magic __get()
+ *
+ * Allows read access to protected properties
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function __get($name)
+ {
+ if ($name === 'raw_input_stream')
+ {
+ isset($this->_raw_input_stream) OR $this->_raw_input_stream = file_get_contents('php://input');
+ return $this->_raw_input_stream;
+ }
+ elseif ($name === 'ip_address')
+ {
+ return $this->ip_address;
+ }
+ }
+
+}
diff --git a/system/core/Lang.php b/system/core/Lang.php
new file mode 100644
index 0000000..2c8654d
--- /dev/null
+++ b/system/core/Lang.php
@@ -0,0 +1,203 @@
+load($value, $idiom, $return, $add_suffix, $alt_path);
+ }
+
+ return;
+ }
+
+ $langfile = str_replace('.php', '', $langfile);
+
+ if ($add_suffix === TRUE)
+ {
+ $langfile = preg_replace('/_lang$/', '', $langfile).'_lang';
+ }
+
+ $langfile .= '.php';
+
+ if (empty($idiom) OR ! preg_match('/^[a-z_-]+$/i', $idiom))
+ {
+ $config =& get_config();
+ $idiom = empty($config['language']) ? 'english' : $config['language'];
+ }
+
+ if ($return === FALSE && isset($this->is_loaded[$langfile]) && $this->is_loaded[$langfile] === $idiom)
+ {
+ return;
+ }
+
+ // Load the base file, so any others found can override it
+ $basepath = BASEPATH.'language/'.$idiom.'/'.$langfile;
+ if (($found = file_exists($basepath)) === TRUE)
+ {
+ include($basepath);
+ }
+
+ // Do we have an alternative path to look in?
+ if ($alt_path !== '')
+ {
+ $alt_path .= 'language/'.$idiom.'/'.$langfile;
+ if (file_exists($alt_path))
+ {
+ include($alt_path);
+ $found = TRUE;
+ }
+ }
+ else
+ {
+ foreach (get_instance()->load->get_package_paths(TRUE) as $package_path)
+ {
+ $package_path .= 'language/'.$idiom.'/'.$langfile;
+ if ($basepath !== $package_path && file_exists($package_path))
+ {
+ include($package_path);
+ $found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if ($found !== TRUE)
+ {
+ show_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile);
+ }
+
+ if ( ! isset($lang) OR ! is_array($lang))
+ {
+ log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);
+
+ if ($return === TRUE)
+ {
+ return array();
+ }
+ return;
+ }
+
+ if ($return === TRUE)
+ {
+ return $lang;
+ }
+
+ $this->is_loaded[$langfile] = $idiom;
+ $this->language = array_merge($this->language, $lang);
+
+ log_message('info', 'Language file loaded: language/'.$idiom.'/'.$langfile);
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Language line
+ *
+ * Fetches a single line of text from the language array
+ *
+ * @param string $line Language line key
+ * @param bool $log_errors Whether to log an error message if the line is not found
+ * @return string Translation
+ */
+ public function line($line, $log_errors = TRUE)
+ {
+ $value = isset($this->language[$line]) ? $this->language[$line] : FALSE;
+
+ // Because killer robots like unicorns!
+ if ($value === FALSE && $log_errors === TRUE)
+ {
+ log_message('error', 'Could not find the language line "'.$line.'"');
+ }
+
+ return $value;
+ }
+
+}
diff --git a/system/core/Loader.php b/system/core/Loader.php
new file mode 100644
index 0000000..14888e4
--- /dev/null
+++ b/system/core/Loader.php
@@ -0,0 +1,1415 @@
+ TRUE);
+
+ /**
+ * List of paths to load libraries from
+ *
+ * @var array
+ */
+ protected $_ci_library_paths = array(APPPATH, BASEPATH);
+
+ /**
+ * List of paths to load models from
+ *
+ * @var array
+ */
+ protected $_ci_model_paths = array(APPPATH);
+
+ /**
+ * List of paths to load helpers from
+ *
+ * @var array
+ */
+ protected $_ci_helper_paths = array(APPPATH, BASEPATH);
+
+ /**
+ * List of cached variables
+ *
+ * @var array
+ */
+ protected $_ci_cached_vars = array();
+
+ /**
+ * List of loaded classes
+ *
+ * @var array
+ */
+ protected $_ci_classes = array();
+
+ /**
+ * List of loaded models
+ *
+ * @var array
+ */
+ protected $_ci_models = array();
+
+ /**
+ * List of loaded helpers
+ *
+ * @var array
+ */
+ protected $_ci_helpers = array();
+
+ /**
+ * List of class name mappings
+ *
+ * @var array
+ */
+ protected $_ci_varmap = array(
+ 'unit_test' => 'unit',
+ 'user_agent' => 'agent'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Sets component load paths, gets the initial output buffering level.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->_ci_ob_level = ob_get_level();
+ $this->_ci_classes =& is_loaded();
+
+ log_message('info', 'Loader Class Initialized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initializer
+ *
+ * @todo Figure out a way to move this to the constructor
+ * without breaking *package_path*() methods.
+ * @uses CI_Loader::_ci_autoloader()
+ * @used-by CI_Controller::__construct()
+ * @return void
+ */
+ public function initialize()
+ {
+ $this->_ci_autoloader();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Is Loaded
+ *
+ * A utility method to test if a class is in the self::$_ci_classes array.
+ *
+ * @used-by Mainly used by Form Helper function _get_validation_object().
+ *
+ * @param string $class Class name to check for
+ * @return string|bool Class object name if loaded or FALSE
+ */
+ public function is_loaded($class)
+ {
+ return array_search(ucfirst($class), $this->_ci_classes, TRUE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Library Loader
+ *
+ * Loads and instantiates libraries.
+ * Designed to be called from application controllers.
+ *
+ * @param mixed $library Library name
+ * @param array $params Optional parameters to pass to the library class constructor
+ * @param string $object_name An optional object name to assign to
+ * @return object
+ */
+ public function library($library, $params = NULL, $object_name = NULL)
+ {
+ if (empty($library))
+ {
+ return $this;
+ }
+ elseif (is_array($library))
+ {
+ foreach ($library as $key => $value)
+ {
+ if (is_int($key))
+ {
+ $this->library($value, $params);
+ }
+ else
+ {
+ $this->library($key, $params, $value);
+ }
+ }
+
+ return $this;
+ }
+
+ if ($params !== NULL && ! is_array($params))
+ {
+ $params = NULL;
+ }
+
+ $this->_ci_load_library($library, $params, $object_name);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Model Loader
+ *
+ * Loads and instantiates models.
+ *
+ * @param mixed $model Model name
+ * @param string $name An optional object name to assign to
+ * @param bool $db_conn An optional database connection configuration to initialize
+ * @return object
+ */
+ public function model($model, $name = '', $db_conn = FALSE)
+ {
+ if (empty($model))
+ {
+ return $this;
+ }
+ elseif (is_array($model))
+ {
+ foreach ($model as $key => $value)
+ {
+ is_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn);
+ }
+
+ return $this;
+ }
+
+ $path = '';
+
+ // Is the model in a sub-folder? If so, parse out the filename and path.
+ if (($last_slash = strrpos($model, '/')) !== FALSE)
+ {
+ // The path is in front of the last slash
+ $path = substr($model, 0, ++$last_slash);
+
+ // And the model name behind it
+ $model = substr($model, $last_slash);
+ }
+
+ if (empty($name))
+ {
+ $name = $model;
+ }
+
+ if (in_array($name, $this->_ci_models, TRUE))
+ {
+ return $this;
+ }
+
+ $CI =& get_instance();
+ if (isset($CI->$name))
+ {
+ throw new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name);
+ }
+
+ if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
+ {
+ if ($db_conn === TRUE)
+ {
+ $db_conn = '';
+ }
+
+ $this->database($db_conn, FALSE, TRUE);
+ }
+
+ // Note: All of the code under this condition used to be just:
+ //
+ // load_class('Model', 'core');
+ //
+ // However, load_class() instantiates classes
+ // to cache them for later use and that prevents
+ // MY_Model from being an abstract class and is
+ // sub-optimal otherwise anyway.
+ if ( ! class_exists('CI_Model', FALSE))
+ {
+ $app_path = APPPATH.'core'.DIRECTORY_SEPARATOR;
+ if (file_exists($app_path.'Model.php'))
+ {
+ require_once($app_path.'Model.php');
+ if ( ! class_exists('CI_Model', FALSE))
+ {
+ throw new RuntimeException($app_path."Model.php exists, but doesn't declare class CI_Model");
+ }
+
+ log_message('info', 'CI_Model class loaded');
+ }
+ elseif ( ! class_exists('CI_Model', FALSE))
+ {
+ require_once(BASEPATH.'core'.DIRECTORY_SEPARATOR.'Model.php');
+ }
+
+ $class = config_item('subclass_prefix').'Model';
+ if (file_exists($app_path.$class.'.php'))
+ {
+ require_once($app_path.$class.'.php');
+ if ( ! class_exists($class, FALSE))
+ {
+ throw new RuntimeException($app_path.$class.".php exists, but doesn't declare class ".$class);
+ }
+
+ log_message('info', config_item('subclass_prefix').'Model class loaded');
+ }
+ }
+
+ $model = ucfirst($model);
+ if ( ! class_exists($model, FALSE))
+ {
+ foreach ($this->_ci_model_paths as $mod_path)
+ {
+ if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
+ {
+ continue;
+ }
+
+ require_once($mod_path.'models/'.$path.$model.'.php');
+ if ( ! class_exists($model, FALSE))
+ {
+ throw new RuntimeException($mod_path."models/".$path.$model.".php exists, but doesn't declare class ".$model);
+ }
+
+ break;
+ }
+
+ if ( ! class_exists($model, FALSE))
+ {
+ throw new RuntimeException('Unable to locate the model you have specified: '.$model);
+ }
+ }
+ elseif ( ! is_subclass_of($model, 'CI_Model'))
+ {
+ throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
+ }
+
+ $this->_ci_models[] = $name;
+ $model = new $model();
+ $CI->$name = $model;
+ log_message('info', 'Model "'.get_class($model).'" initialized');
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database Loader
+ *
+ * @param mixed $params Database configuration options
+ * @param bool $return Whether to return the database object
+ * @param bool $query_builder Whether to enable Query Builder
+ * (overrides the configuration setting)
+ *
+ * @return object|bool Database object if $return is set to TRUE,
+ * FALSE on failure, CI_Loader instance in any other case
+ */
+ public function database($params = '', $return = FALSE, $query_builder = NULL)
+ {
+ // Grab the super object
+ $CI =& get_instance();
+
+ // Do we even need to load the database class?
+ if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
+ {
+ return FALSE;
+ }
+
+ require_once(BASEPATH.'database/DB.php');
+
+ if ($return === TRUE)
+ {
+ return DB($params, $query_builder);
+ }
+
+ // Initialize the db variable. Needed to prevent
+ // reference errors with some configurations
+ $CI->db = '';
+
+ // Load the DB class
+ $CI->db =& DB($params, $query_builder);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load the Database Utilities Class
+ *
+ * @param object $db Database object
+ * @param bool $return Whether to return the DB Utilities class object or not
+ * @return object
+ */
+ public function dbutil($db = NULL, $return = FALSE)
+ {
+ $CI =& get_instance();
+
+ if ( ! is_object($db) OR ! ($db instanceof CI_DB))
+ {
+ class_exists('CI_DB', FALSE) OR $this->database();
+ $db =& $CI->db;
+ }
+
+ require_once(BASEPATH.'database/DB_utility.php');
+ require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_utility.php');
+ $class = 'CI_DB_'.$db->dbdriver.'_utility';
+
+ if ($return === TRUE)
+ {
+ return new $class($db);
+ }
+
+ $CI->dbutil = new $class($db);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load the Database Forge Class
+ *
+ * @param object $db Database object
+ * @param bool $return Whether to return the DB Forge class object or not
+ * @return object
+ */
+ public function dbforge($db = NULL, $return = FALSE)
+ {
+ $CI =& get_instance();
+ if ( ! is_object($db) OR ! ($db instanceof CI_DB))
+ {
+ class_exists('CI_DB', FALSE) OR $this->database();
+ $db =& $CI->db;
+ }
+
+ require_once(BASEPATH.'database/DB_forge.php');
+ require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_forge.php');
+
+ if ( ! empty($db->subdriver))
+ {
+ $driver_path = BASEPATH.'database/drivers/'.$db->dbdriver.'/subdrivers/'.$db->dbdriver.'_'.$db->subdriver.'_forge.php';
+ if (file_exists($driver_path))
+ {
+ require_once($driver_path);
+ $class = 'CI_DB_'.$db->dbdriver.'_'.$db->subdriver.'_forge';
+ }
+ }
+ else
+ {
+ $class = 'CI_DB_'.$db->dbdriver.'_forge';
+ }
+
+ if ($return === TRUE)
+ {
+ return new $class($db);
+ }
+
+ $CI->dbforge = new $class($db);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * View Loader
+ *
+ * Loads "view" files.
+ *
+ * @param string $view View name
+ * @param array $vars An associative array of data
+ * to be extracted for use in the view
+ * @param bool $return Whether to return the view output
+ * or leave it to the Output class
+ * @return object|string
+ */
+ public function view($view, $vars = array(), $return = FALSE)
+ {
+ return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generic File Loader
+ *
+ * @param string $path File path
+ * @param bool $return Whether to return the file output
+ * @return object|string
+ */
+ public function file($path, $return = FALSE)
+ {
+ return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Variables
+ *
+ * Once variables are set they become available within
+ * the controller class and its "view" files.
+ *
+ * @param array|object|string $vars
+ * An associative array or object containing values
+ * to be set, or a value's name if string
+ * @param string $val Value to set, only used if $vars is a string
+ * @return object
+ */
+ public function vars($vars, $val = '')
+ {
+ $vars = is_string($vars)
+ ? array($vars => $val)
+ : $this->_ci_prepare_view_vars($vars);
+
+ foreach ($vars as $key => $val)
+ {
+ $this->_ci_cached_vars[$key] = $val;
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Clear Cached Variables
+ *
+ * Clears the cached variables.
+ *
+ * @return CI_Loader
+ */
+ public function clear_vars()
+ {
+ $this->_ci_cached_vars = array();
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Variable
+ *
+ * Check if a variable is set and retrieve it.
+ *
+ * @param string $key Variable name
+ * @return mixed The variable or NULL if not found
+ */
+ public function get_var($key)
+ {
+ return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Variables
+ *
+ * Retrieves all loaded variables.
+ *
+ * @return array
+ */
+ public function get_vars()
+ {
+ return $this->_ci_cached_vars;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Helper Loader
+ *
+ * @param string|string[] $helpers Helper name(s)
+ * @return object
+ */
+ public function helper($helpers = array())
+ {
+ is_array($helpers) OR $helpers = array($helpers);
+ foreach ($helpers as &$helper)
+ {
+ $filename = basename($helper);
+ $filepath = ($filename === $helper) ? '' : substr($helper, 0, strlen($helper) - strlen($filename));
+ $filename = strtolower(preg_replace('#(_helper)?(\.php)?$#i', '', $filename)).'_helper';
+ $helper = $filepath.$filename;
+
+ if (isset($this->_ci_helpers[$helper]))
+ {
+ continue;
+ }
+
+ // Is this a helper extension request?
+ $ext_helper = config_item('subclass_prefix').$filename;
+ $ext_loaded = FALSE;
+ foreach ($this->_ci_helper_paths as $path)
+ {
+ if (file_exists($path.'helpers/'.$ext_helper.'.php'))
+ {
+ include_once($path.'helpers/'.$ext_helper.'.php');
+ $ext_loaded = TRUE;
+ }
+ }
+
+ // If we have loaded extensions - check if the base one is here
+ if ($ext_loaded === TRUE)
+ {
+ $base_helper = BASEPATH.'helpers/'.$helper.'.php';
+ if ( ! file_exists($base_helper))
+ {
+ show_error('Unable to load the requested file: helpers/'.$helper.'.php');
+ }
+
+ include_once($base_helper);
+ $this->_ci_helpers[$helper] = TRUE;
+ log_message('info', 'Helper loaded: '.$helper);
+ continue;
+ }
+
+ // No extensions found ... try loading regular helpers and/or overrides
+ foreach ($this->_ci_helper_paths as $path)
+ {
+ if (file_exists($path.'helpers/'.$helper.'.php'))
+ {
+ include_once($path.'helpers/'.$helper.'.php');
+
+ $this->_ci_helpers[$helper] = TRUE;
+ log_message('info', 'Helper loaded: '.$helper);
+ break;
+ }
+ }
+
+ // unable to load the helper
+ if ( ! isset($this->_ci_helpers[$helper]))
+ {
+ show_error('Unable to load the requested file: helpers/'.$helper.'.php');
+ }
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Helpers
+ *
+ * An alias for the helper() method in case the developer has
+ * written the plural form of it.
+ *
+ * @uses CI_Loader::helper()
+ * @param string|string[] $helpers Helper name(s)
+ * @return object
+ */
+ public function helpers($helpers = array())
+ {
+ return $this->helper($helpers);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Language Loader
+ *
+ * Loads language files.
+ *
+ * @param string|string[] $files List of language file names to load
+ * @param string Language name
+ * @return object
+ */
+ public function language($files, $lang = '')
+ {
+ get_instance()->lang->load($files, $lang);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Config Loader
+ *
+ * Loads a config file (an alias for CI_Config::load()).
+ *
+ * @uses CI_Config::load()
+ * @param string $file Configuration file name
+ * @param bool $use_sections Whether configuration values should be loaded into their own section
+ * @param bool $fail_gracefully Whether to just return FALSE or display an error message
+ * @return bool TRUE if the file was loaded correctly or FALSE on failure
+ */
+ public function config($file, $use_sections = FALSE, $fail_gracefully = FALSE)
+ {
+ return get_instance()->config->load($file, $use_sections, $fail_gracefully);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Driver Loader
+ *
+ * Loads a driver library.
+ *
+ * @param string|string[] $library Driver name(s)
+ * @param array $params Optional parameters to pass to the driver
+ * @param string $object_name An optional object name to assign to
+ *
+ * @return object|bool Object or FALSE on failure if $library is a string
+ * and $object_name is set. CI_Loader instance otherwise.
+ */
+ public function driver($library, $params = NULL, $object_name = NULL)
+ {
+ if (is_array($library))
+ {
+ foreach ($library as $key => $value)
+ {
+ if (is_int($key))
+ {
+ $this->driver($value, $params);
+ }
+ else
+ {
+ $this->driver($key, $params, $value);
+ }
+ }
+
+ return $this;
+ }
+ elseif (empty($library))
+ {
+ return FALSE;
+ }
+
+ if ( ! class_exists('CI_Driver_Library', FALSE))
+ {
+ // We aren't instantiating an object here, just making the base class available
+ require BASEPATH.'libraries/Driver.php';
+ }
+
+ // We can save the loader some time since Drivers will *always* be in a subfolder,
+ // and typically identically named to the library
+ if ( ! strpos($library, '/'))
+ {
+ $library = ucfirst($library).'/'.$library;
+ }
+
+ return $this->library($library, $params, $object_name);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Add Package Path
+ *
+ * Prepends a parent path to the library, model, helper and config
+ * path arrays.
+ *
+ * @see CI_Loader::$_ci_library_paths
+ * @see CI_Loader::$_ci_model_paths
+ * @see CI_Loader::$_ci_helper_paths
+ * @see CI_Config::$_config_paths
+ *
+ * @param string $path Path to add
+ * @param bool $view_cascade (default: TRUE)
+ * @return object
+ */
+ public function add_package_path($path, $view_cascade = TRUE)
+ {
+ $path = rtrim($path, '/').'/';
+
+ array_unshift($this->_ci_library_paths, $path);
+ array_unshift($this->_ci_model_paths, $path);
+ array_unshift($this->_ci_helper_paths, $path);
+
+ $this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
+
+ // Add config file path
+ $config =& $this->_ci_get_component('config');
+ $config->_config_paths[] = $path;
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Package Paths
+ *
+ * Return a list of all package paths.
+ *
+ * @param bool $include_base Whether to include BASEPATH (default: FALSE)
+ * @return array
+ */
+ public function get_package_paths($include_base = FALSE)
+ {
+ return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Remove Package Path
+ *
+ * Remove a path from the library, model, helper and/or config
+ * path arrays if it exists. If no path is provided, the most recently
+ * added path will be removed removed.
+ *
+ * @param string $path Path to remove
+ * @return object
+ */
+ public function remove_package_path($path = '')
+ {
+ $config =& $this->_ci_get_component('config');
+
+ if ($path === '')
+ {
+ array_shift($this->_ci_library_paths);
+ array_shift($this->_ci_model_paths);
+ array_shift($this->_ci_helper_paths);
+ array_shift($this->_ci_view_paths);
+ array_pop($config->_config_paths);
+ }
+ else
+ {
+ $path = rtrim($path, '/').'/';
+ foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
+ {
+ if (($key = array_search($path, $this->{$var})) !== FALSE)
+ {
+ unset($this->{$var}[$key]);
+ }
+ }
+
+ if (isset($this->_ci_view_paths[$path.'views/']))
+ {
+ unset($this->_ci_view_paths[$path.'views/']);
+ }
+
+ if (($key = array_search($path, $config->_config_paths)) !== FALSE)
+ {
+ unset($config->_config_paths[$key]);
+ }
+ }
+
+ // make sure the application default paths are still in the array
+ $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
+ $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
+ $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
+ $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
+ $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Internal CI Data Loader
+ *
+ * Used to load views and files.
+ *
+ * Variables are prefixed with _ci_ to avoid symbol collision with
+ * variables made available to view files.
+ *
+ * @used-by CI_Loader::view()
+ * @used-by CI_Loader::file()
+ * @param array $_ci_data Data to load
+ * @return object
+ */
+ protected function _ci_load($_ci_data)
+ {
+ // Set the default data variables
+ foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
+ {
+ $$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE;
+ }
+
+ $file_exists = FALSE;
+
+ // Set the path to the requested file
+ if (is_string($_ci_path) && $_ci_path !== '')
+ {
+ $_ci_x = explode('/', $_ci_path);
+ $_ci_file = end($_ci_x);
+ }
+ else
+ {
+ $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
+ $_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
+
+ foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
+ {
+ if (file_exists($_ci_view_file.$_ci_file))
+ {
+ $_ci_path = $_ci_view_file.$_ci_file;
+ $file_exists = TRUE;
+ break;
+ }
+
+ if ( ! $cascade)
+ {
+ break;
+ }
+ }
+ }
+
+ if ( ! $file_exists && ! file_exists($_ci_path))
+ {
+ show_error('Unable to load the requested file: '.$_ci_file);
+ }
+
+ // This allows anything loaded using $this->load (views, files, etc.)
+ // to become accessible from within the Controller and Model functions.
+ $_ci_CI =& get_instance();
+ foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
+ {
+ if ( ! isset($this->$_ci_key))
+ {
+ $this->$_ci_key =& $_ci_CI->$_ci_key;
+ }
+ }
+
+ /*
+ * Extract and cache variables
+ *
+ * You can either set variables using the dedicated $this->load->vars()
+ * function or via the second parameter of this function. We'll merge
+ * the two types and cache them so that views that are embedded within
+ * other views can have access to these variables.
+ */
+ empty($_ci_vars) OR $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
+ extract($this->_ci_cached_vars);
+
+ /*
+ * Buffer the output
+ *
+ * We buffer the output for two reasons:
+ * 1. Speed. You get a significant speed boost.
+ * 2. So that the final rendered template can be post-processed by
+ * the output class. Why do we need post processing? For one thing,
+ * in order to show the elapsed page load time. Unless we can
+ * intercept the content right before it's sent to the browser and
+ * then stop the timer it won't be accurate.
+ */
+ ob_start();
+
+ // If the PHP installation does not support short tags we'll
+ // do a little string replacement, changing the short tags
+ // to standard PHP echo statements.
+ if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
+ {
+ echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('=', ' $this->_ci_ob_level + 1)
+ {
+ ob_end_flush();
+ }
+ else
+ {
+ $_ci_CI->output->append_output(ob_get_contents());
+ @ob_end_clean();
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Internal CI Library Loader
+ *
+ * @used-by CI_Loader::library()
+ * @uses CI_Loader::_ci_init_library()
+ *
+ * @param string $class Class name to load
+ * @param mixed $params Optional parameters to pass to the class constructor
+ * @param string $object_name Optional object name to assign to
+ * @return void
+ */
+ protected function _ci_load_library($class, $params = NULL, $object_name = NULL)
+ {
+ // Get the class name, and while we're at it trim any slashes.
+ // The directory path can be included as part of the class name,
+ // but we don't want a leading slash
+ $class = str_replace('.php', '', trim($class, '/'));
+
+ // Was the path included with the class name?
+ // We look for a slash to determine this
+ if (($last_slash = strrpos($class, '/')) !== FALSE)
+ {
+ // Extract the path
+ $subdir = substr($class, 0, ++$last_slash);
+
+ // Get the filename from the path
+ $class = substr($class, $last_slash);
+ }
+ else
+ {
+ $subdir = '';
+ }
+
+ $class = ucfirst($class);
+
+ // Is this a stock library? There are a few special conditions if so ...
+ if (file_exists(BASEPATH.'libraries/'.$subdir.$class.'.php'))
+ {
+ return $this->_ci_load_stock_library($class, $subdir, $params, $object_name);
+ }
+
+ // Safety: Was the class already loaded by a previous call?
+ if (class_exists($class, FALSE))
+ {
+ $property = $object_name;
+ if (empty($property))
+ {
+ $property = strtolower($class);
+ isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property];
+ }
+
+ $CI =& get_instance();
+ if (isset($CI->$property))
+ {
+ log_message('debug', $class.' class already loaded. Second attempt ignored.');
+ return;
+ }
+
+ return $this->_ci_init_library($class, '', $params, $object_name);
+ }
+
+ // Let's search for the requested library file and load it.
+ foreach ($this->_ci_library_paths as $path)
+ {
+ // BASEPATH has already been checked for
+ if ($path === BASEPATH)
+ {
+ continue;
+ }
+
+ $filepath = $path.'libraries/'.$subdir.$class.'.php';
+ // Does the file exist? No? Bummer...
+ if ( ! file_exists($filepath))
+ {
+ continue;
+ }
+
+ include_once($filepath);
+ return $this->_ci_init_library($class, '', $params, $object_name);
+ }
+
+ // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
+ if ($subdir === '')
+ {
+ return $this->_ci_load_library($class.'/'.$class, $params, $object_name);
+ }
+
+ // If we got this far we were unable to find the requested class.
+ log_message('error', 'Unable to load the requested class: '.$class);
+ show_error('Unable to load the requested class: '.$class);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Internal CI Stock Library Loader
+ *
+ * @used-by CI_Loader::_ci_load_library()
+ * @uses CI_Loader::_ci_init_library()
+ *
+ * @param string $library_name Library name to load
+ * @param string $file_path Path to the library filename, relative to libraries/
+ * @param mixed $params Optional parameters to pass to the class constructor
+ * @param string $object_name Optional object name to assign to
+ * @return void
+ */
+ protected function _ci_load_stock_library($library_name, $file_path, $params, $object_name)
+ {
+ $prefix = 'CI_';
+
+ if (class_exists($prefix.$library_name, FALSE))
+ {
+ if (class_exists(config_item('subclass_prefix').$library_name, FALSE))
+ {
+ $prefix = config_item('subclass_prefix');
+ }
+
+ $property = $object_name;
+ if (empty($property))
+ {
+ $property = strtolower($library_name);
+ isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property];
+ }
+
+ $CI =& get_instance();
+ if ( ! isset($CI->$property))
+ {
+ return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
+ }
+
+ log_message('debug', $library_name.' class already loaded. Second attempt ignored.');
+ return;
+ }
+
+ $paths = $this->_ci_library_paths;
+ array_pop($paths); // BASEPATH
+ array_pop($paths); // APPPATH (needs to be the first path checked)
+ array_unshift($paths, APPPATH);
+
+ foreach ($paths as $path)
+ {
+ if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))
+ {
+ // Override
+ include_once($path);
+ if (class_exists($prefix.$library_name, FALSE))
+ {
+ return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
+ }
+
+ log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name);
+ }
+ }
+
+ include_once(BASEPATH.'libraries/'.$file_path.$library_name.'.php');
+
+ // Check for extensions
+ $subclass = config_item('subclass_prefix').$library_name;
+ foreach ($paths as $path)
+ {
+ if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))
+ {
+ include_once($path);
+ if (class_exists($subclass, FALSE))
+ {
+ $prefix = config_item('subclass_prefix');
+ break;
+ }
+
+ log_message('debug', $path.' exists, but does not declare '.$subclass);
+ }
+ }
+
+ return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Internal CI Library Instantiator
+ *
+ * @used-by CI_Loader::_ci_load_stock_library()
+ * @used-by CI_Loader::_ci_load_library()
+ *
+ * @param string $class Class name
+ * @param string $prefix Class name prefix
+ * @param array|null|bool $config Optional configuration to pass to the class constructor:
+ * FALSE to skip;
+ * NULL to search in config paths;
+ * array containing configuration data
+ * @param string $object_name Optional object name to assign to
+ * @return void
+ */
+ protected function _ci_init_library($class, $prefix, $config = FALSE, $object_name = NULL)
+ {
+ // Is there an associated config file for this class? Note: these should always be lowercase
+ if ($config === NULL)
+ {
+ // Fetch the config paths containing any package paths
+ $config_component = $this->_ci_get_component('config');
+
+ if (is_array($config_component->_config_paths))
+ {
+ $found = FALSE;
+ foreach ($config_component->_config_paths as $path)
+ {
+ // We test for both uppercase and lowercase, for servers that
+ // are case-sensitive with regard to file names. Load global first,
+ // override with environment next
+ if (file_exists($path.'config/'.strtolower($class).'.php'))
+ {
+ include($path.'config/'.strtolower($class).'.php');
+ $found = TRUE;
+ }
+ elseif (file_exists($path.'config/'.ucfirst(strtolower($class)).'.php'))
+ {
+ include($path.'config/'.ucfirst(strtolower($class)).'.php');
+ $found = TRUE;
+ }
+
+ if (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
+ {
+ include($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
+ $found = TRUE;
+ }
+ elseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
+ {
+ include($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
+ $found = TRUE;
+ }
+
+ // Break on the first found configuration, thus package
+ // files are not overridden by default paths
+ if ($found === TRUE)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ $class_name = $prefix.$class;
+
+ // Is the class name valid?
+ if ( ! class_exists($class_name, FALSE))
+ {
+ log_message('error', 'Non-existent class: '.$class_name);
+ show_error('Non-existent class: '.$class_name);
+ }
+
+ // Set the variable name we will assign the class to
+ // Was a custom class name supplied? If so we'll use it
+ if (empty($object_name))
+ {
+ $object_name = strtolower($class);
+ if (isset($this->_ci_varmap[$object_name]))
+ {
+ $object_name = $this->_ci_varmap[$object_name];
+ }
+ }
+
+ // Don't overwrite existing properties
+ $CI =& get_instance();
+ if (isset($CI->$object_name))
+ {
+ if ($CI->$object_name instanceof $class_name)
+ {
+ log_message('debug', $class_name." has already been instantiated as '".$object_name."'. Second attempt aborted.");
+ return;
+ }
+
+ show_error("Resource '".$object_name."' already exists and is not a ".$class_name." instance.");
+ }
+
+ // Save the class name and object name
+ $this->_ci_classes[$object_name] = $class;
+
+ // Instantiate the class
+ $CI->$object_name = isset($config)
+ ? new $class_name($config)
+ : new $class_name();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * CI Autoloader
+ *
+ * Loads component listed in the config/autoload.php file.
+ *
+ * @used-by CI_Loader::initialize()
+ * @return void
+ */
+ protected function _ci_autoloader()
+ {
+ if (file_exists(APPPATH.'config/autoload.php'))
+ {
+ include(APPPATH.'config/autoload.php');
+ }
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
+ {
+ include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
+ }
+
+ if ( ! isset($autoload))
+ {
+ return;
+ }
+
+ // Autoload packages
+ if (isset($autoload['packages']))
+ {
+ foreach ($autoload['packages'] as $package_path)
+ {
+ $this->add_package_path($package_path);
+ }
+ }
+
+ // Load any custom config file
+ if (count($autoload['config']) > 0)
+ {
+ foreach ($autoload['config'] as $val)
+ {
+ $this->config($val);
+ }
+ }
+
+ // Autoload helpers and languages
+ foreach (array('helper', 'language') as $type)
+ {
+ if (isset($autoload[$type]) && count($autoload[$type]) > 0)
+ {
+ $this->$type($autoload[$type]);
+ }
+ }
+
+ // Autoload drivers
+ if (isset($autoload['drivers']))
+ {
+ $this->driver($autoload['drivers']);
+ }
+
+ // Load libraries
+ if (isset($autoload['libraries']) && count($autoload['libraries']) > 0)
+ {
+ // Load the database driver.
+ if (in_array('database', $autoload['libraries']))
+ {
+ $this->database();
+ $autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
+ }
+
+ // Load all other libraries
+ $this->library($autoload['libraries']);
+ }
+
+ // Autoload models
+ if (isset($autoload['model']))
+ {
+ $this->model($autoload['model']);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prepare variables for _ci_vars, to be later extract()-ed inside views
+ *
+ * Converts objects to associative arrays and filters-out internal
+ * variable names (i.e. keys prefixed with '_ci_').
+ *
+ * @param mixed $vars
+ * @return array
+ */
+ protected function _ci_prepare_view_vars($vars)
+ {
+ if ( ! is_array($vars))
+ {
+ $vars = is_object($vars)
+ ? get_object_vars($vars)
+ : array();
+ }
+
+ foreach (array_keys($vars) as $key)
+ {
+ if (strncmp($key, '_ci_', 4) === 0)
+ {
+ unset($vars[$key]);
+ }
+ }
+
+ return $vars;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * CI Component getter
+ *
+ * Get a reference to a specific library or model.
+ *
+ * @param string $component Component name
+ * @return bool
+ */
+ protected function &_ci_get_component($component)
+ {
+ $CI =& get_instance();
+ return $CI->$component;
+ }
+}
diff --git a/system/core/Log.php b/system/core/Log.php
new file mode 100644
index 0000000..f37726e
--- /dev/null
+++ b/system/core/Log.php
@@ -0,0 +1,296 @@
+ 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
+
+ /**
+ * mbstring.func_overload flag
+ *
+ * @var bool
+ */
+ protected static $func_overload;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $config =& get_config();
+
+ isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'));
+
+ $this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/';
+ $this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '')
+ ? ltrim($config['log_file_extension'], '.') : 'php';
+
+ file_exists($this->_log_path) OR mkdir($this->_log_path, 0755, TRUE);
+
+ if ( ! is_dir($this->_log_path) OR ! is_really_writable($this->_log_path))
+ {
+ $this->_enabled = FALSE;
+ }
+
+ if (is_numeric($config['log_threshold']))
+ {
+ $this->_threshold = (int) $config['log_threshold'];
+ }
+ elseif (is_array($config['log_threshold']))
+ {
+ $this->_threshold = 0;
+ $this->_threshold_array = array_flip($config['log_threshold']);
+ }
+
+ if ( ! empty($config['log_date_format']))
+ {
+ $this->_date_fmt = $config['log_date_format'];
+ }
+
+ if ( ! empty($config['log_file_permissions']) && is_int($config['log_file_permissions']))
+ {
+ $this->_file_permissions = $config['log_file_permissions'];
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write Log File
+ *
+ * Generally this function will be called using the global log_message() function
+ *
+ * @param string $level The error level: 'error', 'debug' or 'info'
+ * @param string $msg The error message
+ * @return bool
+ */
+ public function write_log($level, $msg)
+ {
+ if ($this->_enabled === FALSE)
+ {
+ return FALSE;
+ }
+
+ $level = strtoupper($level);
+
+ if (( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
+ && ! isset($this->_threshold_array[$this->_levels[$level]]))
+ {
+ return FALSE;
+ }
+
+ $filepath = $this->_log_path.'log-'.date('Y-m-d').'.'.$this->_file_ext;
+ $message = '';
+
+ if ( ! file_exists($filepath))
+ {
+ $newfile = TRUE;
+ // Only add protection to php files
+ if ($this->_file_ext === 'php')
+ {
+ $message .= "\n\n";
+ }
+ }
+
+ if ( ! $fp = @fopen($filepath, 'ab'))
+ {
+ return FALSE;
+ }
+
+ flock($fp, LOCK_EX);
+
+ // Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format
+ if (strpos($this->_date_fmt, 'u') !== FALSE)
+ {
+ $microtime_full = microtime(TRUE);
+ $microtime_short = sprintf("%06d", ($microtime_full - floor($microtime_full)) * 1000000);
+ $date = new DateTime(date('Y-m-d H:i:s.'.$microtime_short, $microtime_full));
+ $date = $date->format($this->_date_fmt);
+ }
+ else
+ {
+ $date = date($this->_date_fmt);
+ }
+
+ $message .= $this->_format_line($level, $date, $msg);
+
+ for ($written = 0, $length = self::strlen($message); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, self::substr($message, $written))) === FALSE)
+ {
+ break;
+ }
+ }
+
+ flock($fp, LOCK_UN);
+ fclose($fp);
+
+ if (isset($newfile) && $newfile === TRUE)
+ {
+ chmod($filepath, $this->_file_permissions);
+ }
+
+ return is_int($result);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Format the log line.
+ *
+ * This is for extensibility of log formatting
+ * If you want to change the log format, extend the CI_Log class and override this method
+ *
+ * @param string $level The error level
+ * @param string $date Formatted date string
+ * @param string $message The log message
+ * @return string Formatted log line with a new line character at the end
+ */
+ protected function _format_line($level, $date, $message)
+ {
+ return $level.' - '.$date.' --> '.$message.PHP_EOL;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe strlen()
+ *
+ * @param string $str
+ * @return int
+ */
+ protected static function strlen($str)
+ {
+ return (self::$func_overload)
+ ? mb_strlen($str, '8bit')
+ : strlen($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe substr()
+ *
+ * @param string $str
+ * @param int $start
+ * @param int $length
+ * @return string
+ */
+ protected static function substr($str, $start, $length = NULL)
+ {
+ if (self::$func_overload)
+ {
+ // mb_substr($str, $start, null, '8bit') returns an empty
+ // string on PHP 5.3
+ isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
+ return mb_substr($str, $start, $length, '8bit');
+ }
+
+ return isset($length)
+ ? substr($str, $start, $length)
+ : substr($str, $start);
+ }
+}
diff --git a/system/core/Model.php b/system/core/Model.php
new file mode 100644
index 0000000..0aadbcd
--- /dev/null
+++ b/system/core/Model.php
@@ -0,0 +1,76 @@
+$key;
+ }
+
+}
diff --git a/system/core/Output.php b/system/core/Output.php
new file mode 100644
index 0000000..64e7ee1
--- /dev/null
+++ b/system/core/Output.php
@@ -0,0 +1,842 @@
+_zlib_oc = (bool) ini_get('zlib.output_compression');
+ $this->_compress_output = (
+ $this->_zlib_oc === FALSE
+ && config_item('compress_output') === TRUE
+ && extension_loaded('zlib')
+ );
+
+ isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'));
+
+ // Get mime types for later
+ $this->mimes =& get_mimes();
+
+ log_message('info', 'Output Class Initialized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Output
+ *
+ * Returns the current output string.
+ *
+ * @return string
+ */
+ public function get_output()
+ {
+ return $this->final_output;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Output
+ *
+ * Sets the output string.
+ *
+ * @param string $output Output data
+ * @return CI_Output
+ */
+ public function set_output($output)
+ {
+ $this->final_output = $output;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Append Output
+ *
+ * Appends data onto the output string.
+ *
+ * @param string $output Data to append
+ * @return CI_Output
+ */
+ public function append_output($output)
+ {
+ $this->final_output .= $output;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Header
+ *
+ * Lets you set a server header which will be sent with the final output.
+ *
+ * Note: If a file is cached, headers will not be sent.
+ * @todo We need to figure out how to permit headers to be cached.
+ *
+ * @param string $header Header
+ * @param bool $replace Whether to replace the old header value, if already set
+ * @return CI_Output
+ */
+ public function set_header($header, $replace = TRUE)
+ {
+ // If zlib.output_compression is enabled it will compress the output,
+ // but it will not modify the content-length header to compensate for
+ // the reduction, causing the browser to hang waiting for more data.
+ // We'll just skip content-length in those cases.
+ if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0)
+ {
+ return $this;
+ }
+
+ $this->headers[] = array($header, $replace);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Content-Type Header
+ *
+ * @param string $mime_type Extension of the file we're outputting
+ * @param string $charset Character set (default: NULL)
+ * @return CI_Output
+ */
+ public function set_content_type($mime_type, $charset = NULL)
+ {
+ if (strpos($mime_type, '/') === FALSE)
+ {
+ $extension = ltrim($mime_type, '.');
+
+ // Is this extension supported?
+ if (isset($this->mimes[$extension]))
+ {
+ $mime_type =& $this->mimes[$extension];
+
+ if (is_array($mime_type))
+ {
+ $mime_type = current($mime_type);
+ }
+ }
+ }
+
+ $this->mime_type = $mime_type;
+
+ if (empty($charset))
+ {
+ $charset = config_item('charset');
+ }
+
+ $header = 'Content-Type: '.$mime_type
+ .(empty($charset) ? '' : '; charset='.$charset);
+
+ $this->headers[] = array($header, TRUE);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Current Content-Type Header
+ *
+ * @return string 'text/html', if not already set
+ */
+ public function get_content_type()
+ {
+ for ($i = 0, $c = count($this->headers); $i < $c; $i++)
+ {
+ if (sscanf($this->headers[$i][0], 'Content-Type: %[^;]', $content_type) === 1)
+ {
+ return $content_type;
+ }
+ }
+
+ return 'text/html';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Header
+ *
+ * @param string $header
+ * @return string
+ */
+ public function get_header($header)
+ {
+ // Combine headers already sent with our batched headers
+ $headers = array_merge(
+ // We only need [x][0] from our multi-dimensional array
+ array_map('array_shift', $this->headers),
+ headers_list()
+ );
+
+ if (empty($headers) OR empty($header))
+ {
+ return NULL;
+ }
+
+ // Count backwards, in order to get the last matching header
+ for ($c = count($headers) - 1; $c > -1; $c--)
+ {
+ if (strncasecmp($header, $headers[$c], $l = self::strlen($header)) === 0)
+ {
+ return trim(self::substr($headers[$c], $l+1));
+ }
+ }
+
+ return NULL;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set HTTP Status Header
+ *
+ * As of version 1.7.2, this is an alias for common function
+ * set_status_header().
+ *
+ * @param int $code Status code (default: 200)
+ * @param string $text Optional message
+ * @return CI_Output
+ */
+ public function set_status_header($code = 200, $text = '')
+ {
+ set_status_header($code, $text);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Enable/disable Profiler
+ *
+ * @param bool $val TRUE to enable or FALSE to disable
+ * @return CI_Output
+ */
+ public function enable_profiler($val = TRUE)
+ {
+ $this->enable_profiler = is_bool($val) ? $val : TRUE;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Profiler Sections
+ *
+ * Allows override of default/config settings for
+ * Profiler section display.
+ *
+ * @param array $sections Profiler sections
+ * @return CI_Output
+ */
+ public function set_profiler_sections($sections)
+ {
+ if (isset($sections['query_toggle_count']))
+ {
+ $this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count'];
+ unset($sections['query_toggle_count']);
+ }
+
+ foreach ($sections as $section => $enable)
+ {
+ $this->_profiler_sections[$section] = ($enable !== FALSE);
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Cache
+ *
+ * @param int $time Cache expiration time in minutes
+ * @return CI_Output
+ */
+ public function cache($time)
+ {
+ $this->cache_expiration = is_numeric($time) ? $time : 0;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Display Output
+ *
+ * Processes and sends finalized output data to the browser along
+ * with any server headers and profile data. It also stops benchmark
+ * timers so the page rendering speed and memory usage can be shown.
+ *
+ * Note: All "view" data is automatically put into $this->final_output
+ * by controller class.
+ *
+ * @uses CI_Output::$final_output
+ * @param string $output Output data override
+ * @return void
+ */
+ public function _display($output = '')
+ {
+ // Note: We use load_class() because we can't use $CI =& get_instance()
+ // since this function is sometimes called by the caching mechanism,
+ // which happens before the CI super object is available.
+ $BM =& load_class('Benchmark', 'core');
+ $CFG =& load_class('Config', 'core');
+
+ // Grab the super object if we can.
+ if (class_exists('CI_Controller', FALSE))
+ {
+ $CI =& get_instance();
+ }
+
+ // --------------------------------------------------------------------
+
+ // Set the output data
+ if ($output === '')
+ {
+ $output =& $this->final_output;
+ }
+
+ // --------------------------------------------------------------------
+
+ // Do we need to write a cache file? Only if the controller does not have its
+ // own _output() method and we are not dealing with a cache file, which we
+ // can determine by the existence of the $CI object above
+ if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
+ {
+ $this->_write_cache($output);
+ }
+
+ // --------------------------------------------------------------------
+
+ // Parse out the elapsed time and memory usage,
+ // then swap the pseudo-variables with the data
+
+ $elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');
+
+ if ($this->parse_exec_vars === TRUE)
+ {
+ $memory = round(memory_get_usage() / 1024 / 1024, 2).'MB';
+ $output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
+ }
+
+ // --------------------------------------------------------------------
+
+ // Is compression requested?
+ if (isset($CI) // This means that we're not serving a cache file, if we were, it would already be compressed
+ && $this->_compress_output === TRUE
+ && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
+ {
+ ob_start('ob_gzhandler');
+ }
+
+ // --------------------------------------------------------------------
+
+ // Are there any server headers to send?
+ if (count($this->headers) > 0)
+ {
+ foreach ($this->headers as $header)
+ {
+ @header($header[0], $header[1]);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ // Does the $CI object exist?
+ // If not we know we are dealing with a cache file so we'll
+ // simply echo out the data and exit.
+ if ( ! isset($CI))
+ {
+ if ($this->_compress_output === TRUE)
+ {
+ if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
+ {
+ header('Content-Encoding: gzip');
+ header('Content-Length: '.self::strlen($output));
+ }
+ else
+ {
+ // User agent doesn't support gzip compression,
+ // so we'll have to decompress our cache
+ $output = gzinflate(self::substr($output, 10, -8));
+ }
+ }
+
+ echo $output;
+ log_message('info', 'Final output sent to browser');
+ log_message('debug', 'Total execution time: '.$elapsed);
+ return;
+ }
+
+ // --------------------------------------------------------------------
+
+ // Do we need to generate profile data?
+ // If so, load the Profile class and run it.
+ if ($this->enable_profiler === TRUE)
+ {
+ $CI->load->library('profiler');
+ if ( ! empty($this->_profiler_sections))
+ {
+ $CI->profiler->set_sections($this->_profiler_sections);
+ }
+
+ // If the output data contains closing