diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index b53626595059..c24e53c98fe0 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -742,6 +742,27 @@ class CreateSingleAccount extends Command $cg->fees_and_limits = $fees_and_limits; $cg->save(); } + + if (config('ninja.testvars.paytrace.decrypted') && ($this->gateway == 'all' || $this->gateway == 'paytrace')) { + $cg = new CompanyGateway; + $cg->company_id = $company->id; + $cg->user_id = $user->id; + $cg->gateway_key = 'bbd736b3254b0aabed6ad7fda1298c88'; + $cg->require_cvv = true; + $cg->require_billing_address = true; + $cg->require_shipping_address = true; + $cg->update_details = true; + $cg->config = encrypt(config('ninja.testvars.paytrace.decrypted')); + $cg->save(); + + $gateway_types = $cg->driver(new Client)->gatewayTypes(); + + $fees_and_limits = new stdClass; + $fees_and_limits->{$gateway_types[0]} = new FeesAndLimits; + + $cg->fees_and_limits = $fees_and_limits; + $cg->save(); + } } private function createRecurringInvoice($client) diff --git a/app/Mail/SupportMessageSent.php b/app/Mail/SupportMessageSent.php index 429202661a17..5e513c9eb015 100644 --- a/app/Mail/SupportMessageSent.php +++ b/app/Mail/SupportMessageSent.php @@ -60,11 +60,12 @@ class SupportMessageSent extends Mailable $company = auth()->user()->company(); $user = auth()->user(); + $db = str_replace("db-ninja-", "", $company->db); if(Ninja::isHosted()) - $subject = "{$priority}Hosted-{$company->db} :: Customer Support - {$plan} ".date('M jS, g:ia'); + $subject = "{$priority}Hosted-{$company->db} :: {$plan} :: ".date('M jS, g:ia'); else - $subject = "{$priority}Self Hosted :: Customer Support - [{$plan}] ".date('M jS, g:ia'); + $subject = "{$priority}Self Hosted :: {$plan} :: ".date('M jS, g:ia'); return $this->from(config('mail.from.address'), $user->present()->name()) ->replyTo($user->email, $user->present()->name()) diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index b9105b566e9e..1204b8e0ea1a 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -69,16 +69,20 @@ class CompanyGateway extends BaseModel // const TYPE_CUSTOM = 306; // const TYPE_BRAINTREE = 307; // const TYPE_WEPAY = 309; + // const TYPE_PAYFAST = 310; + // const TYPE_PAYTRACE = 311; public $gateway_consts = [ '38f2c48af60c7dd69e04248cbb24c36e' => 300, 'd14dd26a37cecc30fdd65700bfb55b23' => 301, + 'd14dd26a47cecc30fdd65700bfb67b34' => 301, '3758e7f7c6f4cecf0f4f348b9a00f456' => 304, '3b6621f970ab18887c4f6dca78d3f8bb' => 305, '54faab2ab6e3223dbe848b1686490baa' => 306, - 'd14dd26a47cecc30fdd65700bfb67b34' => 301, - '8fdeed552015b3c7b44ed6c8ebd9e992' => 309, 'f7ec488676d310683fb51802d076d713' => 307, + '8fdeed552015b3c7b44ed6c8ebd9e992' => 309, + 'd6814fc83f45d2935e7777071e629ef9' => 310, + 'bbd736b3254b0aabed6ad7fda1298c88' => 311, ]; protected $touches = []; diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 32fc20999409..7d22a21aa9f7 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -81,6 +81,9 @@ class Gateway extends StaticModel case 1: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]];//Authorize.net break; + case 1: + return [GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => false]];//Payfast + break; case 15: return [GatewayType::PAYPAL => ['refund' => true, 'token_billing' => false]]; //Paypal break; @@ -95,6 +98,8 @@ class Gateway extends StaticModel case 39: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Checkout break; + case 46: + return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true]]; //Paytrace case 49: return [GatewayType::CREDIT_CARD => ['refund' => true, 'token_billing' => true], GatewayType::BANK_TRANSFER => ['refund' => true, 'token_billing' => true]]; //WePay diff --git a/app/Models/SystemLog.php b/app/Models/SystemLog.php index 2823b1eb1736..f2ecdc9d5345 100644 --- a/app/Models/SystemLog.php +++ b/app/Models/SystemLog.php @@ -68,7 +68,7 @@ class SystemLog extends Model const TYPE_BRAINTREE = 307; const TYPE_WEPAY = 309; const TYPE_PAYFAST = 310; - + const TYPE_PAYTRACE = 311; const TYPE_QUOTA_EXCEEDED = 400; const TYPE_UPSTREAM_FAILURE = 401; diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index ef59a3d0d82c..2ad64c1ae8c3 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -431,6 +431,61 @@ class BaseDriver extends AbstractPaymentDriver return false; } + /*Generic Global unsuccessful transaction method when the client is present*/ + public function processUnsuccessfulTransaction($response, $client_present = true) + { + $error = $response['error']; + $error_code = $response['error_code']; + + $this->unWindGatewayFees($this->payment_hash); + + PaymentFailureMailer::dispatch($this->client, $error, $this->client->company, $this->payment_hash->data->amount_with_fee); + + $nmo = new NinjaMailerObject; + $nmo->mailable = new NinjaMailer( (new ClientPaymentFailureObject($this->client, $error, $this->client->company, $this->payment_hash))->build() ); + $nmo->company = $this->client->company; + $nmo->settings = $this->client->company->settings; + + $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get(); + + $invoices->each(function ($invoice){ + + $invoice->service()->deletePdf(); + + }); + + $invoices->first()->invitations->each(function ($invitation) use ($nmo){ + + if ($invitation->contact->send_email && $invitation->contact->email) { + + $nmo->to_user = $invitation->contact; + NinjaMailerJob::dispatch($nmo); + + } + + }); + + $message = [ + 'server_response' => $response, + 'data' => $this->payment_hash->data, + ]; + + SystemLogger::dispatch( + $message, + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + $this::SYSTEM_LOG_TYPE, + $this->client, + $this->client->company, + ); + + if($client_present) + throw new PaymentFailed($error, 500); + + } + + + public function checkRequirements() { if ($this->company_gateway->require_billing_address) { diff --git a/app/PaymentDrivers/PayTrace/CreditCard.php b/app/PaymentDrivers/PayTrace/CreditCard.php new file mode 100644 index 000000000000..f2a9a744aca7 --- /dev/null +++ b/app/PaymentDrivers/PayTrace/CreditCard.php @@ -0,0 +1,258 @@ +paytrace = $paytrace; + } + + public function authorizeView($data) + { + + $data['client_key'] = $this->paytrace->getAuthToken(); + $data['gateway'] = $this->paytrace; + + return render('gateways.paytrace.authorize', $data); + } + + // +"success": true + // +"response_code": 160 + // +"status_message": "The customer profile for PLS5U60OoLUfQXzcmtJYNefPA0gTthzT/11 was successfully created." + // +"customer_id": "PLS5U60OoLUfQXzcmtJYNefPA0gTthzT" + + //if(!$response->success) + //handle failure + + public function authorizeResponse($request) + { + $data = $request->all(); + + $response = $this->createCustomer($data); + + return redirect()->route('client.payment_methods.index'); + + } + + // "_token" => "Vl1xHflBYQt9YFSaNCPTJKlY5x3rwcFE9kvkw71I" + // "company_gateway_id" => "1" + // "HPF_Token" => "e484a92c-90ed-4468-ac4d-da66824c75de" + // "enc_key" => "zqz6HMHCXALWdX5hyBqrIbSwU7TBZ0FTjjLB3Cp0FQY=" + // "amount" => "Amount" + // "q" => "/client/payment_methods" + // "method" => "1" + // ] + + // "customer_id":"customer789", + // "hpf_token":"e369847e-3027-4174-9161-fa0d4e98d318", + // "enc_key":"lI785yOBMet4Rt9o4NLXEyV84WBU3tdStExcsfoaOoo=", + // "integrator_id":"xxxxxxxxxx", + // "billing_address":{ + // "name":"Mark Smith", + // "street_address":"8320 E. West St.", + // "city":"Spokane", + // "state":"WA", + // "zip":"85284" + // } + + private function createCustomer($data) + { + $post_data = [ + 'customer_id' => Str::random(32), + 'hpf_token' => $data['HPF_Token'], + 'enc_key' => $data['enc_key'], + 'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'), + 'billing_address' => $this->buildBillingAddress(), + ]; + + $response = $this->paytrace->gatewayRequest('/v1/customer/pt_protect_create', $post_data); + + $cgt = []; + $cgt['token'] = $response->customer_id; + $cgt['payment_method_id'] = GatewayType::CREDIT_CARD; + + $profile = $this->getCustomerProfile($response->customer_id); + + $payment_meta = new \stdClass; + $payment_meta->exp_month = $profile->credit_card->expiration_month; + $payment_meta->exp_year = $profile->credit_card->expiration_year; + $payment_meta->brand = 'CC'; + $payment_meta->last4 = $profile->credit_card->masked_number; + $payment_meta->type = GatewayType::CREDIT_CARD; + + $cgt['payment_meta'] = $payment_meta; + + $token = $this->paytrace->storeGatewayToken($cgt, []); + + return $response; + } + + private function getCustomerProfile($customer_id) + { + $profile = $this->paytrace->gatewayRequest('/v1/customer/export', [ + 'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'), + 'customer_id' => $customer_id, + // 'include_bin' => true, + ]); + + return $profile->customers[0]; + + } + + private function buildBillingAddress() + { + return [ + 'name' => $this->paytrace->client->present()->name(), + 'street_address' => $this->paytrace->client->address1, + 'city' => $this->paytrace->client->city, + 'state' => $this->paytrace->client->state, + 'zip' => $this->paytrace->client->postal_code + ]; + } + + public function paymentView($data) + { + + $data['client_key'] = $this->paytrace->getAuthToken(); + $data['gateway'] = $this->paytrace; + + return render('gateways.paytrace.pay', $data); + + } + + public function paymentResponse(Request $request) + { + $response_array = $request->all(); + + if($request->token){ + $token = ClientGatewayToken::find($this->decodePrimaryKey($request->token)); + return $this->processTokenPayment($token->token, $request); + } + + if ($request->has('store_card') && $request->input('store_card') === true) { + + $response = $this->createCustomer($request->all()); + + return $this->processTokenPayment($response->customer_id, $request); + } + + //process a regular charge here: + $data = [ + 'hpf_token' => $response_array['HPF_Token'], + 'enc_key' => $response_array['enc_key'], + 'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'), + 'billing_address' => $this->buildBillingAddress(), + 'amount' => $request->input('amount_with_fee'), + 'invoice_id' => $this->harvestInvoiceId(), + ]; + + $response = $this->paytrace->gatewayRequest('/v1/transactions/sale/pt_protect', $data); + + if($response->success) + return $this->processSuccessfulPayment($response); + + return $this->processUnsuccessfulPayment($response); + + } + + public function processTokenPayment($token, $request) + { + + $data = [ + 'customer_id' => $token, + 'integrator_id' => $this->paytrace->company_gateway->getConfigField('integratorId'), + 'amount' => $request->input('amount_with_fee'), + ]; + + $response = $this->paytrace->gatewayRequest('/v1/transactions/sale/by_customer', $data); + + if($response->success){ + $this->paytrace->logSuccessfulGatewayResponse(['response' => $response, 'data' => $this->paytrace->payment_hash], SystemLog::TYPE_PAYTRACE); + + return $this->processSuccessfulPayment($response); + } + + return $this->processUnsuccessfulPayment($response); + } + + private function harvestInvoiceId() + { + $_invoice = collect($this->paytrace->payment_hash->data->invoices)->first(); + $invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id)); + + if($invoice) + return ctrans('texts.invoice_number') . "# " . $invoice->number; + + return ctrans('texts.invoice_number') . "####"; + } + + private function processSuccessfulPayment($response) + { + $amount = array_sum(array_column($this->paytrace->payment_hash->invoices(), 'amount')) + $this->paytrace->payment_hash->fee_total; + + $payment_record = []; + $payment_record['amount'] = $amount; + $payment_record['payment_type'] = PaymentType::CREDIT_CARD_OTHER; + $payment_record['gateway_type_id'] = GatewayType::CREDIT_CARD; + $payment_record['transaction_reference'] = $response->transaction_id; + + $payment = $this->paytrace->createPayment($payment_record, Payment::STATUS_COMPLETED); + + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + + } + + private function processUnsuccessfulPayment($response) + { + + $error = $response->status_message; + + if(property_exists($response, 'approval_message') && $response->approval_message) + $error .= " - {$response->approval_message}"; + + $error_code = property_exists($response, 'approval_message') ? $response->approval_message : 'Undefined code'; + + $data = [ + 'response' => $response, + 'error' => $error, + 'error_code' => $error_code, + ]; + + return $this->paytrace->processUnsuccessfulTransaction($data); + + } + +} \ No newline at end of file diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php new file mode 100644 index 000000000000..9b103ca28eb9 --- /dev/null +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -0,0 +1,234 @@ + CreditCard::class, //maps GatewayType => Implementation class + ]; + + const SYSTEM_LOG_TYPE = SystemLog::TYPE_PAYTRACE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model + + public function init() + { + return $this; /* This is where you boot the gateway with your auth credentials*/ + } + + /* Returns an array of gateway types for the payment gateway */ + public function gatewayTypes(): array + { + $types = []; + + $types[] = GatewayType::CREDIT_CARD; + + return $types; + } + + /* Sets the payment method initialized */ + public function setPaymentMethod($payment_method_id) + { + $class = self::$methods[$payment_method_id]; + $this->payment_method = new $class($this); + return $this; + } + + public function authorizeView(array $data) + { + return $this->payment_method->authorizeView($data); //this is your custom implementation from here + } + + public function authorizeResponse($request) + { + return $this->payment_method->authorizeResponse($request); //this is your custom implementation from here + } + + public function processPaymentView(array $data) + { + return $this->payment_method->paymentView($data); //this is your custom implementation from here + } + + public function processPaymentResponse($request) + { + return $this->payment_method->paymentResponse($request); //this is your custom implementation from here + } + + public function refund(Payment $payment, $amount, $return_client_response = false) + { + // $cgt = ClientGatewayToken::where('company_gateway_id', $payment->company_gateway_id) + // ->where('gateway_type_id', $payment->gateway_type_id) + // ->first(); + + $data = [ + 'amount' => $amount, + //'customer_id' => $cgt->token, + 'transaction_id' => $payment->transaction_reference, + 'integrator_id' => '959195xd1CuC' + ]; + + $response = $this->gatewayRequest('/v1/transactions/refund/for_transaction', $data); + + if($response && $response->success) + { + + SystemLogger::dispatch(['server_response' => $response, 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_PAYTRACE, $this->client, $this->client->company); + + return [ + 'transaction_reference' => $response->transaction_id, + 'transaction_response' => json_encode($response), + 'success' => true, + 'description' => $response->status_message, + 'code' => $response->response_code, + ]; + + } + + SystemLogger::dispatch(['server_response' => $response, 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_PAYTRACE, $this->client, $this->client->company); + + return [ + 'transaction_reference' => null, + 'transaction_response' => json_encode($response), + 'success' => false, + 'description' => $response->status_message, + 'code' => 422, + ]; + + } + + public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) + { + $amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total; + + $data = [ + 'customer_id' => $cgt->token, + 'integrator_id' => $this->company_gateway->getConfigField('integratorId'), + 'amount' => $amount, + ]; + + $response = $this->gatewayRequest('/v1/transactions/sale/by_customer', $data); + + if($response && $response->success) + { + $data = [ + 'gateway_type_id' => $cgt->gateway_type_id, + 'payment_type' => PaymentType::CREDIT_CARD_OTHER, + 'transaction_reference' => $response->transaction_id, + 'amount' => $amount, + ]; + + $payment = $this->createPayment($data); + $payment->meta = $cgt->meta; + $payment->save(); + + $payment_hash->payment_id = $payment->id; + $payment_hash->save(); + + return $payment; + } + + $error = $response->status_message; + + if(property_exists($response, 'approval_message') && $response->approval_message) + $error .= " - {$response->approval_message}"; + + $data = [ + 'response' => $response, + 'error' => $error, + 'error_code' => 500, + ]; + + $this->processUnsuccessfulTransaction($data, false); + } + + public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null) + { + } + + /*Helpers*/ + private function generateAuthHeaders() + { + + $url = 'https://api.paytrace.com/oauth/token'; + $data = [ + 'grant_type' => 'password', + 'username' => $this->company_gateway->getConfigField('username'), + 'password' => $this->company_gateway->getConfigField('password') + ]; + + $response = CurlUtils::post($url, $data, $headers = false); + + $auth_data = json_decode($response); + + $headers = []; + $headers[] = 'Content-type: application/json'; + $headers[] = 'Authorization: Bearer '.$auth_data->access_token; + + return $headers; + + } + + public function getAuthToken() + { + + $headers = $this->generateAuthHeaders(); + + $response = CurlUtils::post('https://api.paytrace.com/v1/payment_fields/token/create', [], $headers); + + $response = json_decode($response); + + if($response) + return $response->clientKey; + + return false; + } + + public function gatewayRequest($uri, $data, $headers = false) + { + + $base_url = "https://api.paytrace.com{$uri}"; + + $headers = $this->generateAuthHeaders(); + + $response = CurlUtils::post($base_url, json_encode($data), $headers); + + $response = json_decode($response); + + if($response) + return $response; + + return false; + + } +} diff --git a/app/PaymentDrivers/Stripe/Charge.php b/app/PaymentDrivers/Stripe/Charge.php index 2e8c06d7d1bc..2ae298a335e2 100644 --- a/app/PaymentDrivers/Stripe/Charge.php +++ b/app/PaymentDrivers/Stripe/Charge.php @@ -74,7 +74,7 @@ class Charge 'confirm' => true, 'description' => $description, ]; -nlog($data); + $response = $this->stripe->createPaymentIntent($data, $this->stripe->stripe_connect_auth); // $response = $local_stripe->paymentIntents->create($data); diff --git a/config/ninja.php b/config/ninja.php index 1e96db4e99bb..8cb1a44f332a 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -84,6 +84,11 @@ return [ 'test_email' => env('TEST_EMAIL', 'test@example.com'), 'wepay' => env('WEPAY_KEYS', ''), 'braintree' => env('BRAINTREE_KEYS', ''), + 'paytrace' => [ + 'username' => env('PAYTRACE_U', ''), + 'password' => env('PAYTRACE_P',''), + 'decrypted' => env('PAYTRACE_KEYS', ''), + ], ], 'contact' => [ 'email' => env('MAIL_FROM_ADDRESS'), diff --git a/database/migrations/2021_07_20_095537_activate_paytrace_payment_driver.php b/database/migrations/2021_07_20_095537_activate_paytrace_payment_driver.php new file mode 100644 index 000000000000..e690af365e3c --- /dev/null +++ b/database/migrations/2021_07_20_095537_activate_paytrace_payment_driver.php @@ -0,0 +1,39 @@ +fields); + $fields->integratorId = ""; + + $paytrace->fields = json_encode($fields); + $paytrace->provider = 'Paytrace'; + $paytrace->visible = true; + $paytrace->save(); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index b9ff0f84146f..328282dee23c 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -70,7 +70,7 @@ class PaymentLibrariesSeeder extends Seeder ['id' => 43, 'name' => 'Fasapay', 'provider' => 'Fasapay', 'key' => '1b2cef0e8c800204a29f33953aaf3360', 'fields' => ''], ['id' => 44, 'name' => 'Komoju', 'provider' => 'Komoju', 'key' => '7ea2d40ecb1eb69ef8c3d03e5019028a', 'fields' => '{"apiKey":"","accountId":"","paymentMethod":"credit_card","testMode":false,"locale":"en"}'], ['id' => 45, 'name' => 'Paysafecard', 'provider' => 'Paysafecard', 'key' => '70ab90cd6c5c1ab13208b3cef51c0894', 'fields' => '{"username":"","password":"","testMode":false}'], - ['id' => 46, 'name' => 'Paytrace', 'provider' => 'Paytrace_CreditCard', 'key' => 'bbd736b3254b0aabed6ad7fda1298c88', 'fields' => '{"username":"","password":"","testMode":false,"endpoint":"https:\/\/paytrace.com\/api\/default.pay"}'], + ['id' => 46, 'name' => 'Paytrace', 'provider' => 'Paytrace', 'key' => 'bbd736b3254b0aabed6ad7fda1298c88', 'fields' => '{"username":"","password":"","integratorId":"","testMode":false,"endpoint":"https:\/\/paytrace.com\/api\/default.pay"}'], ['id' => 47, 'name' => 'Secure Trading', 'provider' => 'SecureTrading', 'key' => '231cb401487b9f15babe04b1ac4f7a27', 'fields' => '{"siteReference":"","username":"","password":"","applyThreeDSecure":false,"accountType":"ECOM"}'], ['id' => 48, 'name' => 'SecPay', 'provider' => 'SecPay', 'key' => 'bad8699d581d9fa040e59c0bb721a76c', 'fields' => '{"mid":"","vpnPswd":"","remotePswd":"","usageType":"","confirmEmail":"","testStatus":"true","mailCustomer":"true","additionalOptions":""}'], ['id' => 49, 'name' => 'WePay', 'provider' => 'WePay', 'is_offsite' => false, 'sort_order' => 3, 'key' => '8fdeed552015b3c7b44ed6c8ebd9e992', 'fields' => '{"accountId":"","accessToken":"","type":"goods","testMode":false,"feePayer":"payee"}'], @@ -96,7 +96,7 @@ class PaymentLibrariesSeeder extends Seeder Gateway::query()->update(['visible' => 0]); - Gateway::whereIn('id', [1,15,20,39,55,50])->update(['visible' => 1]); + Gateway::whereIn('id', [1,15,20,39,46,55,50])->update(['visible' => 1]); if (Ninja::isHosted()) { Gateway::whereIn('id', [20])->update(['visible' => 0]); diff --git a/public/css/app.css b/public/css/app.css index fbe3808e3bb2..3a3f11ebdf8a 100755 --- a/public/css/app.css +++ b/public/css/app.css @@ -1 +1 @@ -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}details{display:block}summary{display:list-item}[hidden],template{display:none}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}button{background-color:transparent;background-image:none}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}fieldset,ol,ul{margin:0;padding:0}ol,ul{list-style:none}html{font-family:Open Sans,system-ui,-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;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #d2d6dc}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#a0aec0}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#a0aec0}input::placeholder,textarea::placeholder{color:#a0aec0}[role=button],button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}.form-select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M7 7l3-3 3 3m0 6l-3 3-3-3' stroke='%239fa6b2' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;background-repeat:no-repeat;background-color:#fff;border-color:#d2d6dc;border-width:1px;border-radius:.375rem;padding:.5rem 2.5rem .5rem .75rem;font-size:1rem;line-height:1.5;background-position:right .5rem center;background-size:1.5em 1.5em}.form-select::-ms-expand{color:#9fa6b2;border:none}@media not print{.form-select::-ms-expand{display:none}}@media print and (-ms-high-contrast:active),print and (-ms-high-contrast:none){.form-select{padding-right:.75rem}}.form-select:focus{outline:none;box-shadow:0 0 0 3px rgba(164,202,254,.45);border-color:#a4cafe}.form-checkbox:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.707 7.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4a1 1 0 00-1.414-1.414L7 8.586 5.707 7.293z'/%3E%3C/svg%3E");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media not print{.form-checkbox::-ms-check{border-width:1px;color:transparent;background:inherit;border-color:inherit;border-radius:inherit}}.form-checkbox{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#3f83f8;background-color:#fff;border-color:#d2d6dc;border-width:1px;border-radius:.25rem}.form-checkbox:focus{outline:none;box-shadow:0 0 0 3px rgba(164,202,254,.45);border-color:#a4cafe}.form-checkbox:checked:focus,.form-radio:checked{border-color:transparent}.form-radio:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E");background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media not print{.form-radio::-ms-check{border-width:1px;color:transparent;background:inherit;border-color:inherit;border-radius:inherit}}.form-radio{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;flex-shrink:0;border-radius:100%;height:1rem;width:1rem;color:#3f83f8;background-color:#fff;border-color:#d2d6dc;border-width:1px}.form-radio:focus{outline:none;box-shadow:0 0 0 3px rgba(164,202,254,.45);border-color:#a4cafe}.form-radio:checked:focus{border-color:transparent}.button{border-radius:.25rem;padding:.75rem 1rem;font-size:.875rem;line-height:1rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}button:disabled{opacity:.5;cursor:not-allowed}.button-primary{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.button-primary:hover{font-weight:600}.button-block{display:block;width:100%}.button-danger{--bg-opacity:1;background-color:#f05252;background-color:rgba(240,82,82,var(--bg-opacity));--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.button-danger:hover{--bg-opacity:1;background-color:#e02424;background-color:rgba(224,36,36,var(--bg-opacity))}.button-secondary{--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity))}.button-secondary:hover{--bg-opacity:1;background-color:#e5e7eb;background-color:rgba(229,231,235,var(--bg-opacity))}.button-link:hover{font-weight:600;text-decoration:underline}.button-link:focus{outline:2px solid transparent;outline-offset:2px;text-decoration:underline}.validation{border-left-width:2px;margin-top:.5rem;margin-bottom:.25rem;--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity));padding:.25rem .75rem}.validation-fail{border-color:#f05252;border-color:rgba(240,82,82,var(--border-opacity))}.validation-fail,.validation-pass{--border-opacity:1;--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity));font-size:.875rem}.validation-pass{border-color:#0e9f6e;border-color:rgba(14,159,110,var(--border-opacity))}.input{align-items:center;border-width:1px;--border-opacity:1;border-color:#d2d6dc;border-color:rgba(210,214,220,var(--border-opacity));border-radius:.25rem;margin-top:.5rem;padding:.5rem 1rem;font-size:.875rem}.input:focus{outline:2px solid transparent;outline-offset:2px;--bg-opacity:1;background-color:#f9fafb;background-color:rgba(249,250,251,var(--bg-opacity))}.input-label{font-size:.875rem;--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.input-slim{padding-top:.5rem;padding-bottom:.5rem}.alert{padding:.75rem 1rem;font-size:.875rem;border-left-width:2px;margin-top:.5rem;margin-bottom:.25rem;--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity));--border-opacity:1;border-color:#9fa6b2;border-color:rgba(159,166,178,var(--border-opacity))}.alert-success{--border-opacity:1;border-color:#0e9f6e;border-color:rgba(14,159,110,var(--border-opacity))}.alert-failure{--border-opacity:1;border-color:#f05252;border-color:rgba(240,82,82,var(--border-opacity))}.badge{display:inline-flex;align-items:center;padding:.125rem .625rem;border-radius:9999px;font-size:.75rem;font-weight:500;line-height:1rem}.badge-light{background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity));color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.badge-light,.badge-primary{--bg-opacity:1;--text-opacity:1}.badge-primary{background-color:#c3ddfd;background-color:rgba(195,221,253,var(--bg-opacity));color:#3f83f8;color:rgba(63,131,248,var(--text-opacity))}.badge-danger{background-color:#fde8e8;background-color:rgba(253,232,232,var(--bg-opacity));color:#f05252;color:rgba(240,82,82,var(--text-opacity))}.badge-danger,.badge-success{--bg-opacity:1;--text-opacity:1}.badge-success{background-color:#def7ec;background-color:rgba(222,247,236,var(--bg-opacity));color:#0e9f6e;color:rgba(14,159,110,var(--text-opacity))}.badge-secondary{--bg-opacity:1;background-color:#252f3f;background-color:rgba(37,47,63,var(--bg-opacity));--text-opacity:1;color:#e5e7eb;color:rgba(229,231,235,var(--text-opacity))}.badge-warning{background-color:#feecdc;background-color:rgba(254,236,220,var(--bg-opacity));color:#ff5a1f;color:rgba(255,90,31,var(--text-opacity))}.badge-info,.badge-warning{--bg-opacity:1;--text-opacity:1}.badge-info{background-color:#e1effe;background-color:rgba(225,239,254,var(--bg-opacity));color:#3f83f8;color:rgba(63,131,248,var(--text-opacity))}@media (min-width:640px){.dataTables_length{margin-top:1.25rem!important;margin-bottom:1.25rem!important}}@media (min-width:1024px){.dataTables_length{margin-top:1rem!important;margin-bottom:1rem!important}}.dataTables_length select{--bg-opacity:1!important;background-color:#fff!important;background-color:rgba(255,255,255,var(--bg-opacity))!important;align-items:center!important;border-width:1px!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important;border-radius:.25rem!important;margin-top:.5rem!important;font-size:.875rem!important;margin-left:.5rem!important;margin-right:.5rem!important;padding:.5rem!important}.dataTables_filter{margin-bottom:1rem}.dataTables_filter input{-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;background-color:#fff!important;border-radius:.375rem!important;font-size:1rem!important;line-height:1.5!important;align-items:center!important;border-width:1px!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important;border-radius:.25rem!important;margin-top:.5rem!important;padding:.5rem 1rem!important;font-size:.875rem!important}@media (min-width:1024px){.dataTables_filter{margin-top:-3rem!important}}.dataTables_paginate{padding-bottom:1.5rem!important;padding-top:.5rem!important}.dataTables_paginate .paginate_button{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform!important;transition-duration:.15s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;--bg-opacity:1!important;background-color:#fff!important;background-color:rgba(255,255,255,var(--bg-opacity))!important;border-width:1px!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important;font-size:.875rem!important;line-height:1rem!important;font-weight:500!important;border-radius:.25rem!important;--text-opacity:1!important;color:#374151!important;color:rgba(55,65,81,var(--text-opacity))!important;margin-right:.25rem!important;padding:.5rem 1rem!important;cursor:pointer!important}.dataTables_paginate .current{--bg-opacity:1!important;background-color:#1c64f2!important;background-color:rgba(28,100,242,var(--bg-opacity))!important;--text-opacity:1!important;color:#fff!important;color:rgba(255,255,255,var(--text-opacity))!important}.dataTables_info{font-size:.875rem!important}.dataTables_empty{padding-top:1rem!important;padding-bottom:1rem!important}.pagination{display:flex!important;align-items:center!important}.pagination .page-link{margin-top:-1px!important;border-top-width:2px!important;border-color:transparent!important;padding-top:1rem!important;padding-left:1rem!important;padding-right:1rem!important;display:inline-flex!important;align-items:center!important;font-size:.875rem!important;line-height:1.25rem!important;font-weight:500!important;--text-opacity:1!important;color:#6b7280!important;color:rgba(107,114,128,var(--text-opacity))!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important;cursor:pointer!important}.pagination .page-link:hover{--text-opacity:1!important;color:#374151!important;color:rgba(55,65,81,var(--text-opacity))!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important}.pagination .page-link:focus{outline:2px solid transparent;outline-offset:2px;--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity));--border-opacity:1;border-color:#9fa6b2;border-color:rgba(159,166,178,var(--border-opacity))}.pagination .active>span{--text-opacity:1!important;color:#1c64f2!important;color:rgba(28,100,242,var(--text-opacity))!important;--border-opacity:1!important;border-color:#1c64f2!important;border-color:rgba(28,100,242,var(--border-opacity))!important}.space-x-1>:not(template)~:not(template){--space-x-reverse:0;margin-right:calc(0.25rem*var(--space-x-reverse));margin-left:calc(0.25rem*(1 - var(--space-x-reverse)))}.space-x-2>:not(template)~:not(template){--space-x-reverse:0;margin-right:calc(0.5rem*var(--space-x-reverse));margin-left:calc(0.5rem*(1 - var(--space-x-reverse)))}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-50{--bg-opacity:1;background-color:#f9fafb;background-color:rgba(249,250,251,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity))}.bg-gray-200{--bg-opacity:1;background-color:#e5e7eb;background-color:rgba(229,231,235,var(--bg-opacity))}.bg-gray-500{--bg-opacity:1;background-color:#6b7280;background-color:rgba(107,114,128,var(--bg-opacity))}.bg-gray-600{--bg-opacity:1;background-color:#4b5563;background-color:rgba(75,85,99,var(--bg-opacity))}.bg-red-100{--bg-opacity:1;background-color:#fde8e8;background-color:rgba(253,232,232,var(--bg-opacity))}.bg-blue-50{--bg-opacity:1;background-color:#ebf5ff;background-color:rgba(235,245,255,var(--bg-opacity))}.bg-blue-600{--bg-opacity:1;background-color:#1c64f2;background-color:rgba(28,100,242,var(--bg-opacity))}.focus\:bg-gray-100:focus,.hover\:bg-gray-100:hover{--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity))}.focus\:bg-gray-600:focus{--bg-opacity:1;background-color:#4b5563;background-color:rgba(75,85,99,var(--bg-opacity))}.active\:bg-gray-50:active{--bg-opacity:1;background-color:#f9fafb;background-color:rgba(249,250,251,var(--bg-opacity))}.border-collapse{border-collapse:collapse}.border-gray-100{--border-opacity:1;border-color:#f4f5f7;border-color:rgba(244,245,247,var(--border-opacity))}.border-gray-200{--border-opacity:1;border-color:#e5e7eb;border-color:rgba(229,231,235,var(--border-opacity))}.border-gray-300{--border-opacity:1;border-color:#d2d6dc;border-color:rgba(210,214,220,var(--border-opacity))}.border-red-300{--border-opacity:1;border-color:#f8b4b4;border-color:rgba(248,180,180,var(--border-opacity))}.border-red-400{--border-opacity:1;border-color:#f98080;border-color:rgba(249,128,128,var(--border-opacity))}.border-green-500{--border-opacity:1;border-color:#0e9f6e;border-color:rgba(14,159,110,var(--border-opacity))}.border-blue-500{--border-opacity:1;border-color:#3f83f8;border-color:rgba(63,131,248,var(--border-opacity))}.group:hover .group-hover\:border-transparent{border-color:transparent}.hover\:border-gray-800:hover{--border-opacity:1;border-color:#252f3f;border-color:rgba(37,47,63,var(--border-opacity))}.hover\:border-blue-600:hover{--border-opacity:1;border-color:#1c64f2;border-color:rgba(28,100,242,var(--border-opacity))}.focus\:border-blue-300:focus{--border-opacity:1;border-color:#a4cafe;border-color:rgba(164,202,254,var(--border-opacity))}.rounded-sm{border-radius:.125rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.rounded-full{border-radius:9999px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-0{border-width:0}.border-4{border-width:4px}.border{border-width:1px}.border-l-2{border-left-width:2px}.border-t{border-top-width:1px}.border-r{border-right-width:1px}.border-b{border-bottom-width:1px}.cursor-pointer{cursor:pointer}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.focus\:font-semibold:focus,.hover\:font-semibold:hover{font-weight:600}.h-0{height:0}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-32{height:8rem}.h-64{height:16rem}.h-auto{height:auto}.h-screen{height:100vh}.text-xs{font-size:.75rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.text-xl{font-size:1.25rem}.text-2xl{font-size:1.5rem}.text-3xl{font-size:1.875rem}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.m-0{margin:0}.m-auto{margin:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mx-4{margin-left:1rem;margin-right:1rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.mx-auto{margin-left:auto;margin-right:auto}.-my-2{margin-top:-.5rem;margin-bottom:-.5rem}.mt-0{margin-top:0}.mb-0{margin-bottom:0}.ml-0{margin-left:0}.mt-1{margin-top:.25rem}.mr-1{margin-right:.25rem}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.mb-2{margin-bottom:.5rem}.ml-2{margin-left:.5rem}.mt-3{margin-top:.75rem}.mr-3{margin-right:.75rem}.mb-3{margin-bottom:.75rem}.ml-3{margin-left:.75rem}.mt-4{margin-top:1rem}.mr-4{margin-right:1rem}.mb-4{margin-bottom:1rem}.ml-4{margin-left:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mb-6{margin-bottom:1.5rem}.mt-8{margin-top:2rem}.mt-10{margin-top:2.5rem}.mb-10{margin-bottom:2.5rem}.mt-16{margin-top:4rem}.-mr-1{margin-right:-.25rem}.-ml-1{margin-left:-.25rem}.-mt-4{margin-top:-1rem}.-ml-4{margin-left:-1rem}.-mr-14{margin-right:-3.5rem}.max-w-xs{max-width:20rem}.max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.min-h-screen{min-height:100vh}.min-w-full{min-width:100%}.object-cover{-o-object-fit:cover;object-fit:cover}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.opacity-100{opacity:1}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.p-10{padding:2.5rem}.py-0{padding-top:0;padding-bottom:0}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-4{padding-left:1rem;padding-right:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.pt-0{padding-top:0}.pl-0{padding-left:0}.pt-4{padding-top:1rem}.pr-4{padding-right:1rem}.pb-4{padding-bottom:1rem}.pt-5{padding-top:1.25rem}.pt-6{padding-top:1.5rem}.pb-20{padding-bottom:5rem}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{right:0;left:0}.inset-0,.inset-y-0{top:0;bottom:0}.inset-x-0{right:0;left:0}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.shadow-xs{box-shadow:0 0 0 1px rgba(0,0,0,.05)}.shadow-sm{box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.shadow-lg{box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05)}.shadow-xl{box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04)}.hover\:shadow-lg:hover{box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05)}.focus\:shadow-outline:focus{box-shadow:0 0 0 3px rgba(118,169,250,.45)}.focus\:shadow-outline-blue:focus{box-shadow:0 0 0 3px rgba(164,202,254,.45)}.fill-current{fill:currentColor}.table-auto{table-layout:auto}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.text-black{--text-opacity:1;color:#000;color:rgba(0,0,0,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#d2d6dc;color:rgba(210,214,220,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#9fa6b2;color:rgba(159,166,178,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity))}.text-gray-800{--text-opacity:1;color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#161e2e;color:rgba(22,30,46,var(--text-opacity))}.text-red-400{--text-opacity:1;color:#f98080;color:rgba(249,128,128,var(--text-opacity))}.text-red-600{--text-opacity:1;color:#e02424;color:rgba(224,36,36,var(--text-opacity))}.text-green-600{--text-opacity:1;color:#057a55;color:rgba(5,122,85,var(--text-opacity))}.text-blue-600{--text-opacity:1;color:#1c64f2;color:rgba(28,100,242,var(--text-opacity))}.hover\:text-gray-300:hover{--text-opacity:1;color:#d2d6dc;color:rgba(210,214,220,var(--text-opacity))}.hover\:text-gray-500:hover{--text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--text-opacity))}.hover\:text-gray-600:hover{--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.hover\:text-gray-700:hover{--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity))}.hover\:text-gray-800:hover{--text-opacity:1;color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.hover\:text-gray-900:hover{--text-opacity:1;color:#161e2e;color:rgba(22,30,46,var(--text-opacity))}.hover\:text-blue-600:hover{--text-opacity:1;color:#1c64f2;color:rgba(28,100,242,var(--text-opacity))}.hover\:text-indigo-900:hover{--text-opacity:1;color:#362f78;color:rgba(54,47,120,var(--text-opacity))}.focus\:text-gray-500:focus{--text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--text-opacity))}.focus\:text-gray-600:focus{--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.focus\:text-gray-900:focus{--text-opacity:1;color:#161e2e;color:rgba(22,30,46,var(--text-opacity))}.active\:text-gray-800:active{--text-opacity:1;color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.underline{text-decoration:underline}.line-through{text-decoration:line-through}.focus\:underline:focus,.hover\:underline:hover{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.whitespace-no-wrap{white-space:nowrap}.break-words{word-wrap:break-word;overflow-wrap:break-word}.break-all{word-break:break-all}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.w-0{width:0}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-48{width:12rem}.w-56{width:14rem}.w-64{width:16rem}.w-auto{width:auto}.w-1\/2{width:50%}.w-full{width:100%}.z-0{z-index:0}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.gap-4{grid-gap:1rem;gap:1rem}.gap-5{grid-gap:1.25rem;gap:1.25rem}.gap-6{grid-gap:1.5rem;gap:1.5rem}.gap-8{grid-gap:2rem;gap:2rem}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-4{grid-column:span 4/span 4}.col-span-6{grid-column:span 6/span 6}.col-span-12{grid-column:span 12/span 12}.transform{--transform-translate-x:0;--transform-translate-y:0;--transform-rotate:0;--transform-skew-x:0;--transform-skew-y:0;--transform-scale-x:1;--transform-scale-y:1;transform:translateX(var(--transform-translate-x)) translateY(var(--transform-translate-y)) rotate(var(--transform-rotate)) skewX(var(--transform-skew-x)) skewY(var(--transform-skew-y)) scaleX(var(--transform-scale-x)) scaleY(var(--transform-scale-y))}.origin-top-right{transform-origin:top right}.scale-95{--transform-scale-x:.95;--transform-scale-y:.95}.scale-100{--transform-scale-x:1;--transform-scale-y:1}.translate-x-0{--transform-translate-x:0}.-translate-x-full{--transform-translate-x:-100%}.translate-y-0{--transform-translate-y:0}.translate-y-4{--transform-translate-y:1rem}.transition-all{transition-property:all}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform}.transition-opacity{transition-property:opacity}.ease-linear{transition-timing-function:linear}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-75{transition-duration:75ms}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}@-webkit-keyframes spin{to{transform:rotate(1turn)}}@keyframes spin{to{transform:rotate(1turn)}}@-webkit-keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@-webkit-keyframes pulse{50%{opacity:.5}}@keyframes pulse{50%{opacity:.5}}@-webkit-keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}.animate-spin{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:inline-block{display:inline-block}.sm\:flex{display:flex}.sm\:grid{display:grid}.sm\:hidden{display:none}.sm\:flex-row-reverse{flex-direction:row-reverse}.sm\:flex-no-wrap{flex-wrap:nowrap}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-center{justify-content:center}.sm\:justify-between{justify-content:space-between}.sm\:flex-shrink-0{flex-shrink:0}.sm\:h-10{height:2.5rem}.sm\:h-screen{height:100vh}.sm\:mx-0{margin-left:0;margin-right:0}.sm\:my-8{margin-top:2rem;margin-bottom:2rem}.sm\:-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.sm\:mt-0{margin-top:0}.sm\:ml-3{margin-left:.75rem}.sm\:mt-4{margin-top:1rem}.sm\:ml-4{margin-left:1rem}.sm\:mt-6{margin-top:1.5rem}.sm\:ml-6{margin-left:1.5rem}.sm\:max-w-sm{max-width:24rem}.sm\:max-w-lg{max-width:32rem}.sm\:p-0{padding:0}.sm\:p-6{padding:1.5rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:inset-0{top:0;right:0;bottom:0;left:0}.sm\:text-left{text-align:left}.sm\:align-middle{vertical-align:middle}.sm\:w-10{width:2.5rem}.sm\:w-auto{width:auto}.sm\:w-full{width:100%}.sm\:gap-4{grid-gap:1rem;gap:1rem}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:col-span-2{grid-column:span 2/span 2}.sm\:col-span-3{grid-column:span 3/span 3}.sm\:col-span-4{grid-column:span 4/span 4}.sm\:col-span-6{grid-column:span 6/span 6}.sm\:scale-95{--transform-scale-x:.95;--transform-scale-y:.95}.sm\:scale-100{--transform-scale-x:1;--transform-scale-y:1}.sm\:translate-y-0{--transform-translate-y:0}}@media (min-width:768px){.md\:block{display:block}.md\:flex{display:flex}.md\:grid{display:grid}.md\:hidden{display:none}.md\:flex-row{flex-direction:row}.md\:justify-between{justify-content:space-between}.md\:flex-shrink-0{flex-shrink:0}.md\:text-sm{font-size:.875rem}.md\:mt-0{margin-top:0}.md\:mr-2{margin-right:.5rem}.md\:ml-2{margin-left:.5rem}.md\:ml-6{margin-left:1.5rem}.md\:mt-10{margin-top:2.5rem}.md\:-mr-1{margin-right:-.25rem}.md\:max-w-3xl{max-width:48rem}.md\:p-24{padding:6rem}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:w-1\/2{width:50%}.md\:w-1\/3{width:33.333333%}.md\:gap-6{grid-gap:1.5rem;gap:1.5rem}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:col-span-1{grid-column:span 1/span 1}.md\:col-span-2{grid-column:span 2/span 2}.md\:col-span-4{grid-column:span 4/span 4}.md\:col-span-5{grid-column:span 5/span 5}.md\:col-span-6{grid-column:span 6/span 6}.md\:col-start-2{grid-column-start:2}.md\:col-start-4{grid-column-start:4}}@media (min-width:1024px){.lg\:rounded-lg{border-radius:.5rem}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:grid{display:grid}.lg\:hidden{display:none}.lg\:items-center{align-items:center}.lg\:h-screen{height:100vh}.lg\:-mx-8{margin-left:-2rem;margin-right:-2rem}.lg\:mt-24{margin-top:6rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:w-1\/4{width:25%}.lg\:w-1\/5{width:20%}.lg\:gap-4{grid-gap:1rem;gap:1rem}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:col-span-6{grid-column:span 6/span 6}.lg\:col-span-7{grid-column:span 7/span 7}.lg\:col-span-8{grid-column:span 8/span 8}.lg\:col-start-3{grid-column-start:3}.lg\:col-start-4{grid-column-start:4}}@media (min-width:1280px){.xl\:mt-32{margin-top:8rem}.xl\:col-span-4{grid-column:span 4/span 4}.xl\:col-span-6{grid-column:span 6/span 6}.xl\:col-span-8{grid-column:span 8/span 8}.xl\:col-span-9{grid-column:span 9/span 9}.xl\:col-start-4{grid-column-start:4}} \ No newline at end of file +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}details{display:block}summary{display:list-item}[hidden],template{display:none}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}button{background-color:transparent;background-image:none}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}fieldset,ol,ul{margin:0;padding:0}ol,ul{list-style:none}html{font-family:Open Sans,system-ui,-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;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #d2d6dc}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#a0aec0}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#a0aec0}input::placeholder,textarea::placeholder{color:#a0aec0}[role=button],button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}.form-select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M7 7l3-3 3 3m0 6l-3 3-3-3' stroke='%239fa6b2' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;background-repeat:no-repeat;background-color:#fff;border-color:#d2d6dc;border-width:1px;border-radius:.375rem;padding:.5rem 2.5rem .5rem .75rem;font-size:1rem;line-height:1.5;background-position:right .5rem center;background-size:1.5em 1.5em}.form-select::-ms-expand{color:#9fa6b2;border:none}@media not print{.form-select::-ms-expand{display:none}}@media print and (-ms-high-contrast:active),print and (-ms-high-contrast:none){.form-select{padding-right:.75rem}}.form-select:focus{outline:none;box-shadow:0 0 0 3px rgba(164,202,254,.45);border-color:#a4cafe}.form-checkbox:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.707 7.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4a1 1 0 00-1.414-1.414L7 8.586 5.707 7.293z'/%3E%3C/svg%3E");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media not print{.form-checkbox::-ms-check{border-width:1px;color:transparent;background:inherit;border-color:inherit;border-radius:inherit}}.form-checkbox{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#3f83f8;background-color:#fff;border-color:#d2d6dc;border-width:1px;border-radius:.25rem}.form-checkbox:focus{outline:none;box-shadow:0 0 0 3px rgba(164,202,254,.45);border-color:#a4cafe}.form-checkbox:checked:focus,.form-radio:checked{border-color:transparent}.form-radio:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E");background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media not print{.form-radio::-ms-check{border-width:1px;color:transparent;background:inherit;border-color:inherit;border-radius:inherit}}.form-radio{-webkit-appearance:none;-moz-appearance:none;appearance:none;-webkit-print-color-adjust:exact;color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;flex-shrink:0;border-radius:100%;height:1rem;width:1rem;color:#3f83f8;background-color:#fff;border-color:#d2d6dc;border-width:1px}.form-radio:focus{outline:none;box-shadow:0 0 0 3px rgba(164,202,254,.45);border-color:#a4cafe}.form-radio:checked:focus{border-color:transparent}.button{border-radius:.25rem;padding:.75rem 1rem;font-size:.875rem;line-height:1rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}button:disabled{opacity:.5;cursor:not-allowed}.button-primary{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.button-primary:hover{font-weight:600}.button-block{display:block;width:100%}.button-danger{--bg-opacity:1;background-color:#f05252;background-color:rgba(240,82,82,var(--bg-opacity));--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.button-danger:hover{--bg-opacity:1;background-color:#e02424;background-color:rgba(224,36,36,var(--bg-opacity))}.button-secondary{--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity))}.button-secondary:hover{--bg-opacity:1;background-color:#e5e7eb;background-color:rgba(229,231,235,var(--bg-opacity))}.button-link:hover{font-weight:600;text-decoration:underline}.button-link:focus{outline:2px solid transparent;outline-offset:2px;text-decoration:underline}.validation{border-left-width:2px;margin-top:.5rem;margin-bottom:.25rem;--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity));padding:.25rem .75rem}.validation-fail{border-color:#f05252;border-color:rgba(240,82,82,var(--border-opacity))}.validation-fail,.validation-pass{--border-opacity:1;--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity));font-size:.875rem}.validation-pass{border-color:#0e9f6e;border-color:rgba(14,159,110,var(--border-opacity))}.input{align-items:center;border-width:1px;--border-opacity:1;border-color:#d2d6dc;border-color:rgba(210,214,220,var(--border-opacity));border-radius:.25rem;margin-top:.5rem;padding:.5rem 1rem;font-size:.875rem}.input:focus{outline:2px solid transparent;outline-offset:2px;--bg-opacity:1;background-color:#f9fafb;background-color:rgba(249,250,251,var(--bg-opacity))}.input-label{font-size:.875rem;--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.input-slim{padding-top:.5rem;padding-bottom:.5rem}.alert{padding:.75rem 1rem;font-size:.875rem;border-left-width:2px;margin-top:.5rem;margin-bottom:.25rem;--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity));--border-opacity:1;border-color:#9fa6b2;border-color:rgba(159,166,178,var(--border-opacity))}.alert-success{--border-opacity:1;border-color:#0e9f6e;border-color:rgba(14,159,110,var(--border-opacity))}.alert-failure{--border-opacity:1;border-color:#f05252;border-color:rgba(240,82,82,var(--border-opacity))}.badge{display:inline-flex;align-items:center;padding:.125rem .625rem;border-radius:9999px;font-size:.75rem;font-weight:500;line-height:1rem}.badge-light{background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity));color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.badge-light,.badge-primary{--bg-opacity:1;--text-opacity:1}.badge-primary{background-color:#c3ddfd;background-color:rgba(195,221,253,var(--bg-opacity));color:#3f83f8;color:rgba(63,131,248,var(--text-opacity))}.badge-danger{background-color:#fde8e8;background-color:rgba(253,232,232,var(--bg-opacity));color:#f05252;color:rgba(240,82,82,var(--text-opacity))}.badge-danger,.badge-success{--bg-opacity:1;--text-opacity:1}.badge-success{background-color:#def7ec;background-color:rgba(222,247,236,var(--bg-opacity));color:#0e9f6e;color:rgba(14,159,110,var(--text-opacity))}.badge-secondary{--bg-opacity:1;background-color:#252f3f;background-color:rgba(37,47,63,var(--bg-opacity));--text-opacity:1;color:#e5e7eb;color:rgba(229,231,235,var(--text-opacity))}.badge-warning{background-color:#feecdc;background-color:rgba(254,236,220,var(--bg-opacity));color:#ff5a1f;color:rgba(255,90,31,var(--text-opacity))}.badge-info,.badge-warning{--bg-opacity:1;--text-opacity:1}.badge-info{background-color:#e1effe;background-color:rgba(225,239,254,var(--bg-opacity));color:#3f83f8;color:rgba(63,131,248,var(--text-opacity))}@media (min-width:640px){.dataTables_length{margin-top:1.25rem!important;margin-bottom:1.25rem!important}}@media (min-width:1024px){.dataTables_length{margin-top:1rem!important;margin-bottom:1rem!important}}.dataTables_length select{--bg-opacity:1!important;background-color:#fff!important;background-color:rgba(255,255,255,var(--bg-opacity))!important;align-items:center!important;border-width:1px!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important;border-radius:.25rem!important;margin-top:.5rem!important;font-size:.875rem!important;margin-left:.5rem!important;margin-right:.5rem!important;padding:.5rem!important}.dataTables_filter{margin-bottom:1rem}.dataTables_filter input{-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;background-color:#fff!important;border-radius:.375rem!important;font-size:1rem!important;line-height:1.5!important;align-items:center!important;border-width:1px!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important;border-radius:.25rem!important;margin-top:.5rem!important;padding:.5rem 1rem!important;font-size:.875rem!important}@media (min-width:1024px){.dataTables_filter{margin-top:-3rem!important}}.dataTables_paginate{padding-bottom:1.5rem!important;padding-top:.5rem!important}.dataTables_paginate .paginate_button{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform!important;transition-duration:.15s!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;--bg-opacity:1!important;background-color:#fff!important;background-color:rgba(255,255,255,var(--bg-opacity))!important;border-width:1px!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important;font-size:.875rem!important;line-height:1rem!important;font-weight:500!important;border-radius:.25rem!important;--text-opacity:1!important;color:#374151!important;color:rgba(55,65,81,var(--text-opacity))!important;margin-right:.25rem!important;padding:.5rem 1rem!important;cursor:pointer!important}.dataTables_paginate .current{--bg-opacity:1!important;background-color:#1c64f2!important;background-color:rgba(28,100,242,var(--bg-opacity))!important;--text-opacity:1!important;color:#fff!important;color:rgba(255,255,255,var(--text-opacity))!important}.dataTables_info{font-size:.875rem!important}.dataTables_empty{padding-top:1rem!important;padding-bottom:1rem!important}.pagination{display:flex!important;align-items:center!important}.pagination .page-link{margin-top:-1px!important;border-top-width:2px!important;border-color:transparent!important;padding-top:1rem!important;padding-left:1rem!important;padding-right:1rem!important;display:inline-flex!important;align-items:center!important;font-size:.875rem!important;line-height:1.25rem!important;font-weight:500!important;--text-opacity:1!important;color:#6b7280!important;color:rgba(107,114,128,var(--text-opacity))!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-duration:.15s!important;cursor:pointer!important}.pagination .page-link:hover{--text-opacity:1!important;color:#374151!important;color:rgba(55,65,81,var(--text-opacity))!important;--border-opacity:1!important;border-color:#d2d6dc!important;border-color:rgba(210,214,220,var(--border-opacity))!important}.pagination .page-link:focus{outline:2px solid transparent;outline-offset:2px;--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity));--border-opacity:1;border-color:#9fa6b2;border-color:rgba(159,166,178,var(--border-opacity))}.pagination .active>span{--text-opacity:1!important;color:#1c64f2!important;color:rgba(28,100,242,var(--text-opacity))!important;--border-opacity:1!important;border-color:#1c64f2!important;border-color:rgba(28,100,242,var(--border-opacity))!important}.space-x-1>:not(template)~:not(template){--space-x-reverse:0;margin-right:calc(0.25rem*var(--space-x-reverse));margin-left:calc(0.25rem*(1 - var(--space-x-reverse)))}.space-x-2>:not(template)~:not(template){--space-x-reverse:0;margin-right:calc(0.5rem*var(--space-x-reverse));margin-left:calc(0.5rem*(1 - var(--space-x-reverse)))}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-50{--bg-opacity:1;background-color:#f9fafb;background-color:rgba(249,250,251,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity))}.bg-gray-200{--bg-opacity:1;background-color:#e5e7eb;background-color:rgba(229,231,235,var(--bg-opacity))}.bg-gray-500{--bg-opacity:1;background-color:#6b7280;background-color:rgba(107,114,128,var(--bg-opacity))}.bg-gray-600{--bg-opacity:1;background-color:#4b5563;background-color:rgba(75,85,99,var(--bg-opacity))}.bg-red-100{--bg-opacity:1;background-color:#fde8e8;background-color:rgba(253,232,232,var(--bg-opacity))}.bg-blue-50{--bg-opacity:1;background-color:#ebf5ff;background-color:rgba(235,245,255,var(--bg-opacity))}.bg-blue-600{--bg-opacity:1;background-color:#1c64f2;background-color:rgba(28,100,242,var(--bg-opacity))}.focus\:bg-gray-100:focus,.hover\:bg-gray-100:hover{--bg-opacity:1;background-color:#f4f5f7;background-color:rgba(244,245,247,var(--bg-opacity))}.focus\:bg-gray-600:focus{--bg-opacity:1;background-color:#4b5563;background-color:rgba(75,85,99,var(--bg-opacity))}.active\:bg-gray-50:active{--bg-opacity:1;background-color:#f9fafb;background-color:rgba(249,250,251,var(--bg-opacity))}.border-collapse{border-collapse:collapse}.border-gray-100{--border-opacity:1;border-color:#f4f5f7;border-color:rgba(244,245,247,var(--border-opacity))}.border-gray-200{--border-opacity:1;border-color:#e5e7eb;border-color:rgba(229,231,235,var(--border-opacity))}.border-gray-300{--border-opacity:1;border-color:#d2d6dc;border-color:rgba(210,214,220,var(--border-opacity))}.border-red-300{--border-opacity:1;border-color:#f8b4b4;border-color:rgba(248,180,180,var(--border-opacity))}.border-red-400{--border-opacity:1;border-color:#f98080;border-color:rgba(249,128,128,var(--border-opacity))}.border-green-500{--border-opacity:1;border-color:#0e9f6e;border-color:rgba(14,159,110,var(--border-opacity))}.border-blue-500{--border-opacity:1;border-color:#3f83f8;border-color:rgba(63,131,248,var(--border-opacity))}.group:hover .group-hover\:border-transparent{border-color:transparent}.hover\:border-gray-800:hover{--border-opacity:1;border-color:#252f3f;border-color:rgba(37,47,63,var(--border-opacity))}.hover\:border-blue-600:hover{--border-opacity:1;border-color:#1c64f2;border-color:rgba(28,100,242,var(--border-opacity))}.focus\:border-blue-300:focus{--border-opacity:1;border-color:#a4cafe;border-color:rgba(164,202,254,var(--border-opacity))}.rounded-sm{border-radius:.125rem}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.rounded-full{border-radius:9999px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-0{border-width:0}.border-4{border-width:4px}.border{border-width:1px}.border-l-2{border-left-width:2px}.border-t{border-top-width:1px}.border-r{border-right-width:1px}.border-b{border-bottom-width:1px}.cursor-pointer{cursor:pointer}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.focus\:font-semibold:focus,.hover\:font-semibold:hover{font-weight:600}.h-0{height:0}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-32{height:8rem}.h-64{height:16rem}.h-auto{height:auto}.h-screen{height:100vh}.text-xs{font-size:.75rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.text-xl{font-size:1.25rem}.text-2xl{font-size:1.5rem}.text-3xl{font-size:1.875rem}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.m-0{margin:0}.m-auto{margin:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mx-4{margin-left:1rem;margin-right:1rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.mx-auto{margin-left:auto;margin-right:auto}.-my-2{margin-top:-.5rem;margin-bottom:-.5rem}.mt-0{margin-top:0}.mb-0{margin-bottom:0}.ml-0{margin-left:0}.mt-1{margin-top:.25rem}.mr-1{margin-right:.25rem}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.mb-2{margin-bottom:.5rem}.ml-2{margin-left:.5rem}.mt-3{margin-top:.75rem}.mr-3{margin-right:.75rem}.mb-3{margin-bottom:.75rem}.ml-3{margin-left:.75rem}.mt-4{margin-top:1rem}.mr-4{margin-right:1rem}.mb-4{margin-bottom:1rem}.ml-4{margin-left:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mb-6{margin-bottom:1.5rem}.mt-8{margin-top:2rem}.mt-10{margin-top:2.5rem}.mb-10{margin-bottom:2.5rem}.mt-16{margin-top:4rem}.-mr-1{margin-right:-.25rem}.-ml-1{margin-left:-.25rem}.-mt-4{margin-top:-1rem}.-ml-4{margin-left:-1rem}.-mr-14{margin-right:-3.5rem}.max-w-xs{max-width:20rem}.max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.min-h-screen{min-height:100vh}.min-w-full{min-width:100%}.object-cover{-o-object-fit:cover;object-fit:cover}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.opacity-100{opacity:1}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.p-10{padding:2.5rem}.py-0{padding-top:0;padding-bottom:0}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-4{padding-left:1rem;padding-right:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.pt-0{padding-top:0}.pl-0{padding-left:0}.pt-4{padding-top:1rem}.pr-4{padding-right:1rem}.pb-4{padding-bottom:1rem}.pt-5{padding-top:1.25rem}.pt-6{padding-top:1.5rem}.pb-20{padding-bottom:5rem}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{right:0;left:0}.inset-0,.inset-y-0{top:0;bottom:0}.inset-x-0{right:0;left:0}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.shadow-xs{box-shadow:0 0 0 1px rgba(0,0,0,.05)}.shadow-sm{box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.shadow-lg{box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05)}.shadow-xl{box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04)}.hover\:shadow-lg:hover{box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05)}.focus\:shadow-outline:focus{box-shadow:0 0 0 3px rgba(118,169,250,.45)}.focus\:shadow-outline-blue:focus{box-shadow:0 0 0 3px rgba(164,202,254,.45)}.fill-current{fill:currentColor}.table-auto{table-layout:auto}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.text-black{--text-opacity:1;color:#000;color:rgba(0,0,0,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#d2d6dc;color:rgba(210,214,220,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#9fa6b2;color:rgba(159,166,178,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity))}.text-gray-800{--text-opacity:1;color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#161e2e;color:rgba(22,30,46,var(--text-opacity))}.text-red-400{--text-opacity:1;color:#f98080;color:rgba(249,128,128,var(--text-opacity))}.text-red-600{--text-opacity:1;color:#e02424;color:rgba(224,36,36,var(--text-opacity))}.text-green-600{--text-opacity:1;color:#057a55;color:rgba(5,122,85,var(--text-opacity))}.text-blue-600{--text-opacity:1;color:#1c64f2;color:rgba(28,100,242,var(--text-opacity))}.hover\:text-gray-300:hover{--text-opacity:1;color:#d2d6dc;color:rgba(210,214,220,var(--text-opacity))}.hover\:text-gray-500:hover{--text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--text-opacity))}.hover\:text-gray-600:hover{--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.hover\:text-gray-700:hover{--text-opacity:1;color:#374151;color:rgba(55,65,81,var(--text-opacity))}.hover\:text-gray-800:hover{--text-opacity:1;color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.hover\:text-gray-900:hover{--text-opacity:1;color:#161e2e;color:rgba(22,30,46,var(--text-opacity))}.hover\:text-blue-600:hover{--text-opacity:1;color:#1c64f2;color:rgba(28,100,242,var(--text-opacity))}.hover\:text-indigo-900:hover{--text-opacity:1;color:#362f78;color:rgba(54,47,120,var(--text-opacity))}.focus\:text-gray-500:focus{--text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--text-opacity))}.focus\:text-gray-600:focus{--text-opacity:1;color:#4b5563;color:rgba(75,85,99,var(--text-opacity))}.focus\:text-gray-900:focus{--text-opacity:1;color:#161e2e;color:rgba(22,30,46,var(--text-opacity))}.active\:text-gray-800:active{--text-opacity:1;color:#252f3f;color:rgba(37,47,63,var(--text-opacity))}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.underline{text-decoration:underline}.line-through{text-decoration:line-through}.focus\:underline:focus,.hover\:underline:hover{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.whitespace-no-wrap{white-space:nowrap}.break-words{word-wrap:break-word;overflow-wrap:break-word}.break-all{word-break:break-all}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.w-0{width:0}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-48{width:12rem}.w-56{width:14rem}.w-64{width:16rem}.w-auto{width:auto}.w-1\/2{width:50%}.w-full{width:100%}.w-screen{width:100vw}.z-0{z-index:0}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.gap-4{grid-gap:1rem;gap:1rem}.gap-5{grid-gap:1.25rem;gap:1.25rem}.gap-6{grid-gap:1.5rem;gap:1.5rem}.gap-8{grid-gap:2rem;gap:2rem}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-4{grid-column:span 4/span 4}.col-span-6{grid-column:span 6/span 6}.col-span-12{grid-column:span 12/span 12}.transform{--transform-translate-x:0;--transform-translate-y:0;--transform-rotate:0;--transform-skew-x:0;--transform-skew-y:0;--transform-scale-x:1;--transform-scale-y:1;transform:translateX(var(--transform-translate-x)) translateY(var(--transform-translate-y)) rotate(var(--transform-rotate)) skewX(var(--transform-skew-x)) skewY(var(--transform-skew-y)) scaleX(var(--transform-scale-x)) scaleY(var(--transform-scale-y))}.origin-top-right{transform-origin:top right}.scale-95{--transform-scale-x:.95;--transform-scale-y:.95}.scale-100{--transform-scale-x:1;--transform-scale-y:1}.translate-x-0{--transform-translate-x:0}.-translate-x-full{--transform-translate-x:-100%}.translate-y-0{--transform-translate-y:0}.translate-y-4{--transform-translate-y:1rem}.transition-all{transition-property:all}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform}.transition-opacity{transition-property:opacity}.ease-linear{transition-timing-function:linear}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-75{transition-duration:75ms}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}@-webkit-keyframes spin{to{transform:rotate(1turn)}}@keyframes spin{to{transform:rotate(1turn)}}@-webkit-keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@-webkit-keyframes pulse{50%{opacity:.5}}@keyframes pulse{50%{opacity:.5}}@-webkit-keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}.animate-spin{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:inline-block{display:inline-block}.sm\:flex{display:flex}.sm\:grid{display:grid}.sm\:hidden{display:none}.sm\:flex-row-reverse{flex-direction:row-reverse}.sm\:flex-no-wrap{flex-wrap:nowrap}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-center{justify-content:center}.sm\:justify-between{justify-content:space-between}.sm\:flex-shrink-0{flex-shrink:0}.sm\:h-10{height:2.5rem}.sm\:h-screen{height:100vh}.sm\:mx-0{margin-left:0;margin-right:0}.sm\:my-8{margin-top:2rem;margin-bottom:2rem}.sm\:-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.sm\:mt-0{margin-top:0}.sm\:ml-3{margin-left:.75rem}.sm\:mt-4{margin-top:1rem}.sm\:ml-4{margin-left:1rem}.sm\:mt-6{margin-top:1.5rem}.sm\:ml-6{margin-left:1.5rem}.sm\:max-w-sm{max-width:24rem}.sm\:max-w-lg{max-width:32rem}.sm\:p-0{padding:0}.sm\:p-6{padding:1.5rem}.sm\:px-0{padding-left:0;padding-right:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:inset-0{top:0;right:0;bottom:0;left:0}.sm\:text-left{text-align:left}.sm\:align-middle{vertical-align:middle}.sm\:w-10{width:2.5rem}.sm\:w-auto{width:auto}.sm\:w-full{width:100%}.sm\:gap-4{grid-gap:1rem;gap:1rem}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:col-span-2{grid-column:span 2/span 2}.sm\:col-span-3{grid-column:span 3/span 3}.sm\:col-span-4{grid-column:span 4/span 4}.sm\:col-span-6{grid-column:span 6/span 6}.sm\:scale-95{--transform-scale-x:.95;--transform-scale-y:.95}.sm\:scale-100{--transform-scale-x:1;--transform-scale-y:1}.sm\:translate-y-0{--transform-translate-y:0}}@media (min-width:768px){.md\:block{display:block}.md\:flex{display:flex}.md\:grid{display:grid}.md\:hidden{display:none}.md\:flex-row{flex-direction:row}.md\:justify-between{justify-content:space-between}.md\:flex-shrink-0{flex-shrink:0}.md\:text-sm{font-size:.875rem}.md\:mt-0{margin-top:0}.md\:mr-2{margin-right:.5rem}.md\:ml-2{margin-left:.5rem}.md\:ml-6{margin-left:1.5rem}.md\:mt-10{margin-top:2.5rem}.md\:-mr-1{margin-right:-.25rem}.md\:max-w-3xl{max-width:48rem}.md\:p-24{padding:6rem}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:w-1\/2{width:50%}.md\:w-1\/3{width:33.333333%}.md\:gap-6{grid-gap:1.5rem;gap:1.5rem}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:col-span-1{grid-column:span 1/span 1}.md\:col-span-2{grid-column:span 2/span 2}.md\:col-span-4{grid-column:span 4/span 4}.md\:col-span-5{grid-column:span 5/span 5}.md\:col-span-6{grid-column:span 6/span 6}.md\:col-start-2{grid-column-start:2}.md\:col-start-4{grid-column-start:4}}@media (min-width:1024px){.lg\:rounded-lg{border-radius:.5rem}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:grid{display:grid}.lg\:hidden{display:none}.lg\:items-center{align-items:center}.lg\:h-screen{height:100vh}.lg\:-mx-8{margin-left:-2rem;margin-right:-2rem}.lg\:mt-24{margin-top:6rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:w-1\/4{width:25%}.lg\:w-1\/5{width:20%}.lg\:gap-4{grid-gap:1rem;gap:1rem}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:col-span-6{grid-column:span 6/span 6}.lg\:col-span-7{grid-column:span 7/span 7}.lg\:col-span-8{grid-column:span 8/span 8}.lg\:col-start-3{grid-column-start:3}.lg\:col-start-4{grid-column-start:4}}@media (min-width:1280px){.xl\:mt-32{margin-top:8rem}.xl\:col-span-4{grid-column:span 4/span 4}.xl\:col-span-6{grid-column:span 6/span 6}.xl\:col-span-8{grid-column:span 8/span 8}.xl\:col-span-9{grid-column:span 9/span 9}.xl\:col-start-4{grid-column-start:4}} \ No newline at end of file diff --git a/public/js/clients/payments/paytrace-credit-card.js b/public/js/clients/payments/paytrace-credit-card.js new file mode 100644 index 000000000000..b9e91af4e42b --- /dev/null +++ b/public/js/clients/payments/paytrace-credit-card.js @@ -0,0 +1,2 @@ +/*! For license information please see paytrace-credit-card.js.LICENSE.txt */ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=21)}({"0Swb":function(e,t){function n(e,t){for(var n=0;n=1){var r=document.getElementById("errors");return r.textContent=n[0].description,r.hidden=!1,e.target.parentElement.disabled=!1}t.ptInstance.process().then((function(e){document.getElementById("HPF_Token").value=e.message.hpf_token,document.getElementById("enc_key").value=e.message.enc_key;var t=document.querySelector('input[name="token-billing-checkbox"]:checked');t&&(document.querySelector('input[name="store_card"]').value=t.value),document.getElementById("server_response").submit()})).catch((function(e){document.getElementById("errors").textContent=JSON.stringify(e),document.getElementById("errors").hidden=!1,console.log(e)}))}))}},{key:"handlePaymentWithToken",value:function(e){e.target.parentElement.disabled=!0,document.getElementById("server_response").submit()}},{key:"handle",value:function(){var e=this;this.setupPayTrace().then((function(t){var n;e.ptInstance=t,e.updatePayTraceLabels(),Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach((function(e){return e.addEventListener("click",(function(e){document.getElementById("paytrace--credit-card-container").classList.add("hidden"),document.getElementById("save-card--container").style.display="none",document.querySelector("input[name=token]").value=e.target.dataset.token}))})),null===(n=document.getElementById("toggle-payment-with-credit-card"))||void 0===n||n.addEventListener("click",(function(e){document.getElementById("paytrace--credit-card-container").classList.remove("hidden"),document.getElementById("save-card--container").style.display="grid",document.querySelector("input[name=token]").value=""})),document.getElementById("pay-now").addEventListener("click",(function(t){return""===document.querySelector("input[name=token]").value?e.handlePaymentWithCreditCard(t):e.handlePaymentWithToken(t)}))}))}}])&&n(t.prototype,r),o&&n(t,o),e}())).handle()},21:function(e,t,n){e.exports=n("0Swb")}}); \ No newline at end of file diff --git a/public/js/clients/payments/paytrace-credit-card.js.LICENSE.txt b/public/js/clients/payments/paytrace-credit-card.js.LICENSE.txt new file mode 100644 index 000000000000..6b30888ddb5b --- /dev/null +++ b/public/js/clients/payments/paytrace-credit-card.js.LICENSE.txt @@ -0,0 +1,9 @@ +/** + * Invoice Ninja (https://invoiceninja.com). + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://www.elastic.co/licensing/elastic-license + */ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index bfdb6e692247..c0c0eea30275 100755 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,6 +1,6 @@ { "/js/app.js": "/js/app.js?id=696e8203d5e8e7cf5ff5", - "/css/app.css": "/css/app.css?id=f4c07fdabcbe50c9f4be", + "/css/app.css": "/css/app.css?id=5d7e42fa72eef8af62f5", "/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=a09bb529b8e1826f13b4", "/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=8ce8955ba775ea5f47d1", "/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=0dc8c34010d09195d2f7", @@ -11,6 +11,7 @@ "/js/clients/payments/braintree-paypal.js": "/js/clients/payments/braintree-paypal.js?id=c35db3cbb65806ab6a8a", "/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=5469146cd629ea1b5c20", "/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=065e5450233cc5b47020", + "/js/clients/payments/paytrace-credit-card.js": "/js/clients/payments/paytrace-credit-card.js?id=c8d3808a4c02d1392e96", "/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=81c2623fc1e5769b51c7", "/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=665ddf663500767f1a17", "/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=a30464874dee84678344", diff --git a/resources/js/clients/payments/paytrace-credit-card.js b/resources/js/clients/payments/paytrace-credit-card.js new file mode 100644 index 000000000000..838c2333e50b --- /dev/null +++ b/resources/js/clients/payments/paytrace-credit-card.js @@ -0,0 +1,186 @@ +/** + * Invoice Ninja (https://invoiceninja.com). + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://www.elastic.co/licensing/elastic-license + */ + +class PayTraceCreditCard { + constructor() { + this.clientKey = document.querySelector( + 'meta[name=paytrace-client-key]' + )?.content; + } + + get creditCardStyles() { + return { + font_color: '#111827', + border_color: 'rgba(210,214,220,1)', + label_color: '#111827', + label_size: '12pt', + background_color: 'white', + border_style: 'solid', + font_size: '15pt', + height: '30px', + width: '100%', + }; + } + + get codeStyles() { + return { + font_color: '#111827', + border_color: 'rgba(210,214,220,1)', + label_color: '#111827', + label_size: '12pt', + background_color: 'white', + border_style: 'solid', + font_size: '15pt', + height: '30px', + width: '300px', + }; + } + + get expStyles() { + return { + font_color: '#111827', + border_color: 'rgba(210,214,220,1)', + label_color: '#111827', + label_size: '12pt', + background_color: 'white', + border_style: 'solid', + font_size: '15pt', + height: '30px', + width: '85px', + type: 'dropdown', + }; + } + + updatePayTraceLabels() { + window.PTPayment.getControl('securityCode').label.text( + document.querySelector('meta[name=ctrans-cvv]').content + ); + + window.PTPayment.getControl('creditCard').label.text( + document.querySelector('meta[name=ctrans-card_number]').content + ); + + window.PTPayment.getControl('expiration').label.text( + document.querySelector('meta[name=ctrans-expires]').content + ); + } + + setupPayTrace() { + return window.PTPayment.setup({ + styles: { + code: this.codeStyles, + cc: this.creditCardStyles, + exp: this.expStyles, + }, + authorization: { + clientKey: this.clientKey, + }, + }); + } + + handlePaymentWithCreditCard(event) { + event.target.parentElement.disabled = true; + document.getElementById('errors').hidden = true; + + window.PTPayment.validate((errors) => { + if (errors.length >= 1) { + let errorsContainer = document.getElementById('errors'); + + errorsContainer.textContent = errors[0].description; + errorsContainer.hidden = false; + + return (event.target.parentElement.disabled = false); + } + + this.ptInstance + .process() + .then((response) => { + document.getElementById('HPF_Token').value = + response.message.hpf_token; + document.getElementById('enc_key').value = + response.message.enc_key; + + let tokenBillingCheckbox = document.querySelector( + 'input[name="token-billing-checkbox"]:checked' + ); + + if (tokenBillingCheckbox) { + document.querySelector( + 'input[name="store_card"]' + ).value = tokenBillingCheckbox.value; + } + + document.getElementById('server_response').submit(); + }) + .catch((error) => { + document.getElementById( + 'errors' + ).textContent = JSON.stringify(error); + document.getElementById('errors').hidden = false; + + console.log(error); + }); + }); + } + + handlePaymentWithToken(event) { + event.target.parentElement.disabled = true; + + document.getElementById('server_response').submit(); + } + + handle() { + this.setupPayTrace().then((instance) => { + this.ptInstance = instance; + this.updatePayTraceLabels(); + + Array.from( + document.getElementsByClassName('toggle-payment-with-token') + ).forEach((element) => + element.addEventListener('click', (element) => { + document + .getElementById('paytrace--credit-card-container') + .classList.add('hidden'); + document.getElementById( + 'save-card--container' + ).style.display = 'none'; + document.querySelector('input[name=token]').value = + element.target.dataset.token; + }) + ); + + document + .getElementById('toggle-payment-with-credit-card') + ?.addEventListener('click', (element) => { + document + .getElementById('paytrace--credit-card-container') + .classList.remove('hidden'); + document.getElementById( + 'save-card--container' + ).style.display = 'grid'; + document.querySelector('input[name=token]').value = ''; + }); + + document + .getElementById('pay-now') + .addEventListener('click', (e) => { + if ( + document.querySelector('input[name=token]').value === '' + ) { + return this.handlePaymentWithCreditCard(e); + } + + return this.handlePaymentWithToken(e); + }); + }); + } +} + +new PayTraceCreditCard().handle(); diff --git a/resources/views/portal/ninja2020/gateways/includes/save_card.blade.php b/resources/views/portal/ninja2020/gateways/includes/save_card.blade.php index e6f7d55ea043..34a5b3671075 100644 --- a/resources/views/portal/ninja2020/gateways/includes/save_card.blade.php +++ b/resources/views/portal/ninja2020/gateways/includes/save_card.blade.php @@ -16,12 +16,12 @@ value="true"/> {{ ctrans('texts.yes') }} - + + @else diff --git a/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php new file mode 100644 index 000000000000..c84c6052171a --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/paytrace/authorize.blade.php @@ -0,0 +1,37 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' +=> ctrans('texts.payment_type_credit_card')]) + +@section('gateway_head') + + + + +@endsection + +@section('gateway_content') +
+ @csrf + + + + +
+ + + + @component('portal.ninja2020.components.general.card-element-single') +
+
+
+ @endcomponent + + @component('portal.ninja2020.gateways.includes.pay_now') + {{ ctrans('texts.add_payment_method') }} + @endcomponent +@endsection + +@section('gateway_footer') + + +@endsection diff --git a/resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php b/resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php new file mode 100644 index 000000000000..d7e752fea647 --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/paytrace/pay.blade.php @@ -0,0 +1,64 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' +=> ctrans('texts.payment_type_credit_card')]) + +@section('gateway_head') + + + + +@endsection + +@section('gateway_content') +
+ @csrf + + + + + + + + +
+ + + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')]) + {{ ctrans('texts.credit_card') }} + @endcomponent + + @include('portal.ninja2020.gateways.includes.payment_details') + + @component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')]) + @if (count($tokens) > 0) + @foreach ($tokens as $token) + + @endforeach + @endisset + + + @endcomponent + + @include('portal.ninja2020.gateways.includes.save_card') + + @component('portal.ninja2020.components.general.card-element-single') +
+
+
+ @endcomponent + + @include('portal.ninja2020.gateways.includes.pay_now') +@endsection + +@section('gateway_footer') + + +@endsection diff --git a/resources/views/vendor/livewire/simple-bootstrap.blade.php b/resources/views/vendor/livewire/simple-bootstrap.blade.php new file mode 100644 index 000000000000..dbc374434911 --- /dev/null +++ b/resources/views/vendor/livewire/simple-bootstrap.blade.php @@ -0,0 +1,29 @@ +
+ @if ($paginator->hasPages()) + + @endif +
diff --git a/tests/Browser/ClientPortal/Gateways/PayTrace/CreditCardTest.php b/tests/Browser/ClientPortal/Gateways/PayTrace/CreditCardTest.php new file mode 100644 index 000000000000..3809a8a048f8 --- /dev/null +++ b/tests/Browser/ClientPortal/Gateways/PayTrace/CreditCardTest.php @@ -0,0 +1,62 @@ +driver->manage()->deleteAllCookies(); + } + + $this->disableCompanyGateways(); + + CompanyGateway::where('gateway_key', 'bbd736b3254b0aabed6ad7fda1298c88')->restore(); + + $this->browse(function (Browser $browser) { + $browser + ->visit(new Login()) + ->auth(); + }); + } + + public function testPayingWithNewCreditCard() + { + $this->markTestSkipped('Credit card not supported.'); + + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.invoices.index') + ->click('@pay-now') + ->press('Pay Now') + ->clickLink('Credit Card') + ->withinFrame('iframe', function (Browser $browser) { + $browser + ->type('CC', '4012000098765439') + ->select('EXP_MM', '12') + ->select('EXP_YY', '30') + ->type('SEC', '999'); + }) + ->press('Pay Now') + ->waitForText('Details of the payment', 60); + }); + } +} diff --git a/webpack.mix.js b/webpack.mix.js index a5eafbedebe1..86fa1cea6d3f 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -81,6 +81,10 @@ mix.js("resources/js/app.js", "public/js") .js( "resources/js/clients/payment_methods/wepay-bank-account.js", "public/js/clients/payment_methods/wepay-bank-account.js" + ) + .js( + "resources/js/clients/payments/paytrace-credit-card.js", + "public/js/clients/payments/paytrace-credit-card.js" ); mix.copyDirectory('node_modules/card-js/card-js.min.css', 'public/css/card-js.min.css');