Contact page implemented
This commit is contained in:
@@ -1,7 +1,493 @@
|
|||||||
@page "/contact"
|
@page "/contact"
|
||||||
|
@rendermode InteractiveServer
|
||||||
|
@using System
|
||||||
|
@using System.Collections.Generic
|
||||||
|
@using System.Linq
|
||||||
|
@using System.Threading.Tasks
|
||||||
|
|
||||||
<h3>Contact</h3>
|
<PageTitle>24/7 Travel Desk & Emergency Support</PageTitle>
|
||||||
|
|
||||||
|
<div class="max-w-[1600px] mx-auto pb-8">
|
||||||
|
<!-- Page Header -->
|
||||||
|
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-end mb-[22px] gap-3">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-[22px] font-bold text-[#1f2a3a] tracking-tight outline-none focus:outline-none select-none" tabindex="-1">24/7 Global Travel Desk</h2>
|
||||||
|
<p class="text-[13px] text-[#5a6577] mt-1">Dedicated VIP support, active security alerts, lounge access and after-hours incident response</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<span class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-semibold bg-[#fde5e8] text-[#c8102e] animate-pulse">
|
||||||
|
<span class="w-2 h-2 rounded-full bg-[#c8102e]"></span>
|
||||||
|
Live Emergency Support Active
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@* Alert / Feedback Notification *@
|
||||||
|
@if (!string.IsNullOrEmpty(_alertFeedback))
|
||||||
|
{
|
||||||
|
<div class="mb-6 p-4 bg-[#effaf3] border-l-4 border-[#22a06b] rounded-r-lg text-sm text-[#1b8054] flex items-center gap-2.5 shadow-xs animate-in fade-in duration-300">
|
||||||
|
<svg class="w-5 h-5 text-[#22a06b] shrink-0" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<span>@_alertFeedback</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- KPI Metrics -->
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
||||||
|
<!-- Duty Consultants -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-[18px] relative overflow-hidden">
|
||||||
|
<div class="absolute left-0 top-0 bottom-0 w-1 bg-[#0066b3]"></div>
|
||||||
|
<p class="text-[11px] font-semibold text-[#5a6577] tracking-[0.08em] uppercase mb-2">Consultants On Shift</p>
|
||||||
|
<div class="text-[26px] font-bold text-[#1f2a3a] tracking-tight leading-none">3</div>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-2">Active now · Average response < 90s</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Global Hotlines -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-[18px] relative overflow-hidden">
|
||||||
|
<div class="absolute left-0 top-0 bottom-0 w-1 bg-[#00a3a1]"></div>
|
||||||
|
<p class="text-[11px] font-semibold text-[#5a6577] tracking-[0.08em] uppercase mb-2">Dedicated VIP Lines</p>
|
||||||
|
<div class="text-[26px] font-bold text-[#1f2a3a] tracking-tight leading-none">4</div>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-2">Local ZA, UK, US & WhatsApp Business</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Disrupted Flights -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-[18px] relative overflow-hidden">
|
||||||
|
<div class="absolute left-0 top-0 bottom-0 w-1 bg-[#f4a300]"></div>
|
||||||
|
<p class="text-[11px] font-semibold text-[#5a6577] tracking-[0.08em] uppercase mb-2">Active Travel Alerts</p>
|
||||||
|
<div class="text-[26px] font-bold text-[#1f2a3a] tracking-tight leading-none">@_activeAlertsCount</div>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-2">Global airport disruptions tracked</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Lounge Passes Issued -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-[18px] relative overflow-hidden">
|
||||||
|
<div class="absolute left-0 top-0 bottom-0 w-1 bg-[#22a06b]"></div>
|
||||||
|
<p class="text-[11px] font-semibold text-[#5a6577] tracking-[0.08em] uppercase mb-2">Lounge Passes Issued</p>
|
||||||
|
<div class="text-[26px] font-bold text-[#1f2a3a] tracking-tight leading-none">@_loungePassesCount</div>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-2">Complimentary VIP access credits</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Grid Layout -->
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-[1.8fr_1.2fr] gap-6">
|
||||||
|
|
||||||
|
<!-- Left Column: Support Desks & Callbacks -->
|
||||||
|
<div class="space-y-6">
|
||||||
|
|
||||||
|
<!-- 1. VIP Consultant Support Shift -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-5 text-left">
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<div>
|
||||||
|
<h3 class="text-[15px] font-bold text-[#1f2a3a]">Active Support Consultants</h3>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-0.5">Assigned to SAQA after-hours VIP SLA framework</p>
|
||||||
|
</div>
|
||||||
|
<span class="bg-[#e3f6ed] text-[#22a06b] px-2.5 py-[3px] rounded-full text-[11px] font-semibold">Ready to Assist</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
@foreach (var consultant in _consultants)
|
||||||
|
{
|
||||||
|
<div class="p-4 border border-[#e4eaf2] rounded-xl hover:border-[#0066b3] transition-all flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-gradient-to-br from-[#003b71] to-[#00a3a1] text-white flex items-center justify-center font-bold text-sm">
|
||||||
|
@consultant.Initials
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 class="text-sm font-bold text-[#1f2a3a]">@consultant.Name</h4>
|
||||||
|
<p class="text-xs text-[#5a6577]">@consultant.Specialty · <span class="text-[#22a06b] font-semibold">On Duty</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap gap-2 w-full sm:w-auto">
|
||||||
|
<a href="tel:@consultant.Phone" @onclick="@(() => LogCallAction(consultant.Name, "Phone Call"))" class="flex-1 sm:flex-none inline-flex items-center justify-center gap-1.5 px-3 py-1.5 border border-[#e4eaf2] text-[12px] font-semibold rounded-lg hover:bg-[#f4f7fb] text-[#1f2a3a] transition-colors">
|
||||||
|
<svg class="w-3.5 h-3.5 text-[#0066b3]" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M3 5a2 2 0 012-2h3.28a1 1 0 01.94.725l.548 2.2a1 1 0 01-.321.988l-1.305.98a10.582 10.582 0 004.872 4.872l.98-1.305a1 1 0 01.988-.321l2.2.548a1 1 0 01.725.94V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" /></svg>
|
||||||
|
@consultant.Phone
|
||||||
|
</a>
|
||||||
|
<button @onclick="@(() => RequestCallback(consultant.Name))" class="flex-1 sm:flex-none inline-flex items-center justify-center gap-1.5 px-3 py-1.5 bg-[#0066b3] text-white text-[12px] font-bold rounded-lg hover:bg-[#003b71] transition-colors cursor-pointer">
|
||||||
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" /></svg>
|
||||||
|
Callback
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Fast Emergency Dispatch Bar -->
|
||||||
|
<div class="mt-4 p-4 bg-[#fde5e8] border border-[#fca5a5] rounded-xl flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3">
|
||||||
|
<div class="space-y-0.5">
|
||||||
|
<strong class="text-xs font-bold text-[#c8102e] uppercase tracking-wide">Instant SOS Protocol</strong>
|
||||||
|
<p class="text-[11px] text-[#7f1d1d]">Send automatic GPS & booking distress telemetry to all duty consultants instantly.</p>
|
||||||
|
</div>
|
||||||
|
<button @onclick="@(() => TriggerSosBeacon())" class="w-full sm:w-auto px-4 py-2 bg-[#c8102e] text-white font-bold text-xs rounded-lg hover:bg-[#990d20] cursor-pointer shadow-xs whitespace-nowrap">
|
||||||
|
🚨 Trigger SOS Beacon
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2. Active Travel & Aviation Alerts Desk -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-5 text-left">
|
||||||
|
<div class="flex justify-between items-center mb-3">
|
||||||
|
<div>
|
||||||
|
<h3 class="text-[15px] font-bold text-[#1f2a3a]">Live GDS Aviation & Weather Alerts</h3>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-0.5">Real-time alerts cross-referenced with active SAQA itineraries</p>
|
||||||
|
</div>
|
||||||
|
<button @onclick="@(() => SimulateNewAlert())" class="px-2.5 py-1 bg-white border border-[#e4eaf2] text-[11px] text-[#5a6577] hover:text-[#1f2a3a] font-semibold rounded-lg transition-colors cursor-pointer">
|
||||||
|
Simulate Alert
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-3.5">
|
||||||
|
@foreach (var alert in _alerts)
|
||||||
|
{
|
||||||
|
<div class="p-3.5 border border-[#e4eaf2] rounded-lg bg-gradient-to-r from-white to-[#fafcfe] relative">
|
||||||
|
<div class="absolute left-0 top-0 bottom-0 w-1 bg-[#f4a300]"></div>
|
||||||
|
<div class="flex justify-between items-start gap-4">
|
||||||
|
<div class="space-y-1">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-[10px] uppercase font-bold text-[#b06b00] bg-[#fff4dd] px-2 py-0.5 rounded-md">@alert.Category</span>
|
||||||
|
<span class="text-[10px] text-[#8a96a8]">@alert.Time</span>
|
||||||
|
</div>
|
||||||
|
<h4 class="text-xs font-bold text-[#1f2a3a]">@alert.Title</h4>
|
||||||
|
<p class="text-xs text-[#5a6577]">@alert.Description</p>
|
||||||
|
@if (alert.TravellersAffected.Any())
|
||||||
|
{
|
||||||
|
<div class="pt-2 flex items-center gap-2 flex-wrap">
|
||||||
|
<span class="text-[10px] font-bold text-[#5a6577] uppercase">SAQA Travellers in Region:</span>
|
||||||
|
@foreach (var t in alert.TravellersAffected)
|
||||||
|
{
|
||||||
|
<span class="text-[10px] font-semibold bg-[#e2eefb] text-[#0066b3] px-2 py-0.5 rounded">@t</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
@if (alert.TravellersAffected.Any() && !alert.Audited)
|
||||||
|
{
|
||||||
|
<button @onclick="@(() => TriggerAudit(alert.Id))" class="shrink-0 inline-flex items-center gap-1 px-2.5 py-1 bg-[#0066b3] hover:bg-[#003b71] text-white text-[11px] font-bold rounded-md transition-colors cursor-pointer shadow-xs">
|
||||||
|
Trigger Audit
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
else if (alert.Audited)
|
||||||
|
{
|
||||||
|
<span class="shrink-0 text-[10px] font-bold text-[#22a06b] bg-[#e3f6ed] px-2.5 py-1 rounded-md flex items-center gap-1">
|
||||||
|
✓ Safe Audited
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right Column: Lounge Pass Generator & Emergency VCC Card -->
|
||||||
|
<div class="space-y-6">
|
||||||
|
|
||||||
|
<!-- 1. VIP Airport Lounge Pass Generator -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-5 text-left flex flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<h3 class="text-[15px] font-bold text-[#1f2a3a]">Airport Lounge Pass Dispatch</h3>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-0.5">Generate electronic entry vouchers billed back to corporate accounts</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-3.5 text-xs">
|
||||||
|
<div>
|
||||||
|
<label class="block text-[10px] font-bold uppercase text-[#8a96a8] mb-1">Select VIP Traveller</label>
|
||||||
|
<select @bind="_loungeTraveller" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]">
|
||||||
|
<option value="J. Mokoena (Executive)">J. Mokoena (Executive)</option>
|
||||||
|
<option value="T. Maluleke (Director)">T. Maluleke (Director)</option>
|
||||||
|
<option value="N. Ndlovu (Manager)">N. Ndlovu (Manager)</option>
|
||||||
|
<option value="A. Dlamini (Senior)">A. Dlamini (Senior)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="block text-[10px] font-bold uppercase text-[#8a96a8] mb-1">Airport & Lounge Choice</label>
|
||||||
|
<select @bind="_loungeSelection" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]">
|
||||||
|
<option value="SLOW Lounge · OR Tambo International (JNB)">SLOW Lounge · OR Tambo (JNB) Dom</option>
|
||||||
|
<option value="Bidvest Premier Lounge · Cape Town (CPT)">Bidvest Premier Lounge · Cape Town (CPT)</option>
|
||||||
|
<option value="SLOW Lounge · King Shaka (DUR)">SLOW Lounge · King Shaka (DUR)</option>
|
||||||
|
<option value="No1 Lounge · London Heathrow (LHR) T3">No1 Lounge · London Heathrow (LHR) T3</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button @onclick="@(() => GenerateLoungePass())" class="w-full px-4 py-2.5 bg-[#0066b3] text-white font-bold rounded-lg text-xs hover:bg-[#003b71] transition-all cursor-pointer shadow-xs">
|
||||||
|
Generate Lounge Voucher
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (_showLoungePassResult)
|
||||||
|
{
|
||||||
|
<div class="mt-4 p-4 bg-slate-900 text-white rounded-xl border border-slate-800 space-y-3 animate-in fade-in slide-in-from-top-4 duration-200">
|
||||||
|
<div class="flex justify-between items-start border-b border-dashed border-slate-700 pb-2">
|
||||||
|
<div>
|
||||||
|
<span class="text-[9px] uppercase tracking-wider text-slate-400 font-bold">VIP Lounge Voucher</span>
|
||||||
|
<h4 class="text-xs font-bold font-mono text-cyan-400 mt-0.5">@_generatedLoungeName</h4>
|
||||||
|
</div>
|
||||||
|
<span class="text-[10px] bg-cyan-950 text-cyan-400 border border-cyan-800/40 px-2 py-0.5 rounded font-mono">ADMIT ONE</span>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-2 gap-2 text-[10px] font-mono leading-relaxed">
|
||||||
|
<div>
|
||||||
|
<span class="block text-slate-500">TRAVELLER</span>
|
||||||
|
<span class="text-slate-200 font-bold">@_generatedLoungeTraveller</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="block text-slate-500">EXPIRES</span>
|
||||||
|
<span class="text-slate-200 font-bold">@_generatedLoungeExpiry</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="block text-slate-500">REFERENCE</span>
|
||||||
|
<span class="text-slate-200 font-bold text-cyan-400">@_generatedLoungeRef</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="block text-slate-500">BILLING MODE</span>
|
||||||
|
<span class="text-slate-200 font-bold">Lodge Card (SAQA)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Styled Barcode -->
|
||||||
|
<div class="bg-white p-3 rounded-lg flex flex-col items-center gap-1.5">
|
||||||
|
<div class="w-full h-8 flex justify-center items-center select-none opacity-90">
|
||||||
|
@for (int i = 0; i < 24; i++)
|
||||||
|
{
|
||||||
|
int w = (i % 3 == 0) ? 3 : (i % 2 == 0) ? 1 : 2;
|
||||||
|
<span class="bg-black inline-block h-6 mr-0.5" style="width: @(w)px"></span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<span class="text-[9px] font-mono text-slate-800 select-all tracking-[0.2em] font-bold">@_generatedLoungeRef</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2. After-Hours Reimbursement & Emergency Virtual Card Issuer -->
|
||||||
|
<div class="bg-white rounded-[10px] shadow-[0_1px_2px_rgba(15,23,42,.06)] border border-[#e4eaf2] p-5 text-left">
|
||||||
|
<div class="mb-4">
|
||||||
|
<h3 class="text-[15px] font-bold text-[#1f2a3a]">Emergency Virtual MasterCard</h3>
|
||||||
|
<p class="text-[12px] text-[#8a96a8] mt-0.5">Issue single-use virtual credit cards instantly to stranded travellers for emergency accommodation & meals</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-3.5 text-xs">
|
||||||
|
<div>
|
||||||
|
<label class="block text-[10px] font-bold uppercase text-[#8a96a8] mb-1">Stranded Traveller</label>
|
||||||
|
<select @bind="_vccTraveller" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]">
|
||||||
|
<option value="T. Maluleke (Stranded at LHR)">T. Maluleke (Stranded at LHR)</option>
|
||||||
|
<option value="J. Mokoena (Delayed at CPT)">J. Mokoena (Delayed at CPT)</option>
|
||||||
|
<option value="S. Pillay (General emergency)">S. Pillay (General emergency)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 gap-3">
|
||||||
|
<div>
|
||||||
|
<label class="block text-[10px] font-bold uppercase text-[#8a96a8] mb-1">Limit (ZAR)</label>
|
||||||
|
<select @bind="_vccLimit" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]">
|
||||||
|
<option value="3000">R 3,000</option>
|
||||||
|
<option value="5000">R 5,000</option>
|
||||||
|
<option value="10000">R 10,000</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-[10px] font-bold uppercase text-[#8a96a8] mb-1">Reason</label>
|
||||||
|
<select @bind="_vccReason" class="w-full px-3 py-2 border border-[#c8d3e1] rounded-lg bg-white text-[#1f2a3a] outline-none focus:border-[#0066b3]">
|
||||||
|
<option value="Flight Cancelled">Flight Cancelled</option>
|
||||||
|
<option value="Lost Luggage Accommodation">Lost Luggage Accommodation</option>
|
||||||
|
<option value="Medical Emergency">Medical Emergency</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button @onclick="@(() => GenerateEmergencyVcc())" class="w-full px-4 py-2.5 bg-gradient-to-r from-[#003b71] to-[#0066b3] text-white font-bold rounded-lg text-xs hover:from-[#002244] hover:to-[#003b71] transition-all cursor-pointer shadow-xs flex items-center justify-center gap-1.5">
|
||||||
|
<svg class="w-4 h-4 text-cyan-300" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></svg>
|
||||||
|
Issue Single-Use Virtual Card
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (_showVccResult)
|
||||||
|
{
|
||||||
|
<div class="mt-4 p-5 rounded-2xl bg-gradient-to-br from-[#0c1e36] via-[#162e4e] to-[#091729] text-white relative overflow-hidden shadow-lg animate-in zoom-in-95 duration-200">
|
||||||
|
<!-- Chip & Card details -->
|
||||||
|
<div class="absolute -right-16 -bottom-16 w-44 h-44 rounded-full bg-cyan-500/10 blur-xl pointer-events-none"></div>
|
||||||
|
<div class="absolute -left-12 -top-12 w-32 h-32 rounded-full bg-blue-500/10 blur-lg pointer-events-none"></div>
|
||||||
|
|
||||||
|
<div class="flex justify-between items-start mb-6">
|
||||||
|
<div>
|
||||||
|
<span class="text-[9px] uppercase tracking-[0.2em] text-cyan-400 font-bold font-mono">SAQA EMERGENCY FUNDS</span>
|
||||||
|
<h4 class="text-[10px] text-slate-400 font-semibold mt-0.5">MasterCard Single-Use</h4>
|
||||||
|
</div>
|
||||||
|
<!-- Card Chip -->
|
||||||
|
<div class="w-8 h-6 bg-amber-400/80 rounded-md border border-amber-300 flex flex-col justify-between p-1 opacity-90 shadow-inner">
|
||||||
|
<span class="border-b border-amber-500/30 w-full h-0"></span>
|
||||||
|
<span class="border-b border-amber-500/30 w-full h-0"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Card Number -->
|
||||||
|
<div class="text-base font-bold font-mono tracking-widest text-slate-100 select-all mb-4">
|
||||||
|
@_vccNumber
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Expiry and CVC -->
|
||||||
|
<div class="flex justify-between items-end font-mono">
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<div>
|
||||||
|
<span class="block text-[8px] text-slate-500 uppercase">EXPIRY</span>
|
||||||
|
<span class="text-xs font-bold text-slate-200">07/26</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="block text-[8px] text-slate-500 uppercase">CVC</span>
|
||||||
|
<span class="text-xs font-bold text-slate-200">@_vccCvc</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="block text-[8px] text-slate-500 uppercase">LIMIT</span>
|
||||||
|
<span class="text-xs font-bold text-cyan-400">R @_vccLimitText</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-right">
|
||||||
|
<span class="block text-[8px] text-slate-500 uppercase">TRAVELLER</span>
|
||||||
|
<span class="text-[10px] font-bold text-slate-200 truncate max-w-[120px] inline-block">@_vccAssignedTraveller</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
// Alert feedback notification banner
|
||||||
|
private string _alertFeedback = string.Empty;
|
||||||
|
|
||||||
|
// Shift Consultants Class
|
||||||
|
public class SupportConsultant
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Specialty { get; set; } = string.Empty;
|
||||||
|
public string Initials { get; set; } = string.Empty;
|
||||||
|
public string Phone { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SupportConsultant> _consultants = new()
|
||||||
|
{
|
||||||
|
new() { Name = "Thabo Malgas", Specialty = "Senior Re-routing Expert", Initials = "TM", Phone = "+27 11 544 9101" },
|
||||||
|
new() { Name = "Sarah de Beer", Specialty = "VIP Lodge Card Lead", Initials = "SD", Phone = "+27 21 823 4410" },
|
||||||
|
new() { Name = "Michael Khumalo", Specialty = "Crisis Response Coordinator", Initials = "MK", Phone = "+27 82 911 3233" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Live Alert Class
|
||||||
|
public class GdsAlert
|
||||||
|
{
|
||||||
|
public string Id { get; set; } = string.Empty;
|
||||||
|
public string Category { get; set; } = string.Empty;
|
||||||
|
public string Time { get; set; } = string.Empty;
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public List<string> TravellersAffected { get; set; } = new();
|
||||||
|
public bool Audited { get; set; } = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GdsAlert> _alerts = new()
|
||||||
|
{
|
||||||
|
new() { Id = "A1", Category = "Aviation Strike", Time = "10 mins ago", Title = "London Heathrow (LHR) Ground Crew Walkout", Description = "Baggage handlers at Terminal 3 announced spontaneous strike. Moderate delays expected for departures & connections.", TravellersAffected = new() { "T. Maluleke" }, Audited = false },
|
||||||
|
new() { Id = "A2", Category = "Weather Warning", Time = "1 hr ago", Title = "Severe Storm Front - Cape Town Flight Vectors", Description = "A heavy cold front entering Table Mountain area is forcing arrivals to holding patterns. Expect 30-45 mins delay.", TravellersAffected = new() { "J. Mokoena", "N. Ndlovu" }, Audited = false }
|
||||||
|
};
|
||||||
|
|
||||||
|
private int _activeAlertsCount = 2;
|
||||||
|
private int _loungePassesCount = 12;
|
||||||
|
|
||||||
|
// Lounge pass generation state
|
||||||
|
private string _loungeTraveller = "J. Mokoena (Executive)";
|
||||||
|
private string _loungeSelection = "SLOW Lounge · OR Tambo International (JNB)";
|
||||||
|
private bool _showLoungePassResult = false;
|
||||||
|
private string _generatedLoungeTraveller = string.Empty;
|
||||||
|
private string _generatedLoungeName = string.Empty;
|
||||||
|
private string _generatedLoungeRef = string.Empty;
|
||||||
|
private string _generatedLoungeExpiry = string.Empty;
|
||||||
|
|
||||||
|
// Virtual credit card generation state
|
||||||
|
private string _vccTraveller = "T. Maluleke (Stranded at LHR)";
|
||||||
|
private string _vccLimit = "5000";
|
||||||
|
private string _vccReason = "Flight Cancelled";
|
||||||
|
private bool _showVccResult = false;
|
||||||
|
private string _vccNumber = string.Empty;
|
||||||
|
private string _vccCvc = string.Empty;
|
||||||
|
private string _vccLimitText = string.Empty;
|
||||||
|
private string _vccAssignedTraveller = string.Empty;
|
||||||
|
|
||||||
|
private void LogCallAction(string name, string method)
|
||||||
|
{
|
||||||
|
_alertFeedback = $"Initiating secure communication tunnel to {name} via {method}...";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RequestCallback(string name)
|
||||||
|
{
|
||||||
|
_alertFeedback = $"Callback request sent to {name}. A VIP consultant will phone you back on your registered corporate mobile profile within 90 seconds.";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TriggerSosBeacon()
|
||||||
|
{
|
||||||
|
_alertFeedback = "SOS Emergency Beacon activated! Instant GPS telemetry, hotel booking state & emergency notification dispatched to all duty travel coordinators and SAQA HR Lead.";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TriggerAudit(string alertId)
|
||||||
|
{
|
||||||
|
var targetAlert = _alerts.FirstOrDefault(a => a.Id == alertId);
|
||||||
|
if (targetAlert != null)
|
||||||
|
{
|
||||||
|
targetAlert.Audited = true;
|
||||||
|
_alertFeedback = $"Security roll-call completed for {string.Join(", ", targetAlert.TravellersAffected)}. Travel Desk verified all affected travellers are in safe holding states.";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SimulateNewAlert()
|
||||||
|
{
|
||||||
|
_alerts.Insert(0, new GdsAlert
|
||||||
|
{
|
||||||
|
Id = "A" + (_alerts.Count + 1),
|
||||||
|
Category = "Air Traffic Control",
|
||||||
|
Time = "Just now",
|
||||||
|
Title = "OR Tambo Radar Fault",
|
||||||
|
Description = "A primary transponder glitch at Johannesburg (JNB) has slowed down routing queues. All domestic flight boards showing 20m delays.",
|
||||||
|
TravellersAffected = new() { "S. Pillay" },
|
||||||
|
Audited = false
|
||||||
|
});
|
||||||
|
_activeAlertsCount = _alerts.Count;
|
||||||
|
_alertFeedback = "New live GDS aviation telemetry alert received and processed!";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateLoungePass()
|
||||||
|
{
|
||||||
|
_generatedLoungeTraveller = _loungeTraveller.Split('(')[0].Trim();
|
||||||
|
_generatedLoungeName = _loungeSelection;
|
||||||
|
_generatedLoungeExpiry = DateTime.Now.AddHours(24).ToString("dd MMM yyyy, HH:mm");
|
||||||
|
|
||||||
|
var random = new Random();
|
||||||
|
_generatedLoungeRef = "VIP-L" + random.Next(100000, 999999);
|
||||||
|
_loungePassesCount += 1;
|
||||||
|
|
||||||
|
_showLoungePassResult = true;
|
||||||
|
_alertFeedback = $"VIP Lounge access voucher successfully issued for {_generatedLoungeTraveller}!";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateEmergencyVcc()
|
||||||
|
{
|
||||||
|
var random = new Random();
|
||||||
|
_vccNumber = $"4922 8110 {random.Next(1000, 9999)} {random.Next(1000, 9999)}";
|
||||||
|
_vccCvc = random.Next(100, 999).ToString();
|
||||||
|
_vccLimitText = double.Parse(_vccLimit).ToString("N0");
|
||||||
|
_vccAssignedTraveller = _vccTraveller.Split('(')[0].Trim();
|
||||||
|
|
||||||
|
_showVccResult = true;
|
||||||
|
_alertFeedback = $"Emergency Single-Use Virtual Card successfully generated and dispatched via SMS to {_vccAssignedTraveller}. Linked to Lodge Card #4002.";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+210
@@ -14,6 +14,9 @@
|
|||||||
--color-red-500: oklch(63.7% 0.237 25.331);
|
--color-red-500: oklch(63.7% 0.237 25.331);
|
||||||
--color-red-600: oklch(57.7% 0.245 27.325);
|
--color-red-600: oklch(57.7% 0.245 27.325);
|
||||||
--color-red-700: oklch(50.5% 0.213 27.518);
|
--color-red-700: oklch(50.5% 0.213 27.518);
|
||||||
|
--color-amber-300: oklch(87.9% 0.169 91.605);
|
||||||
|
--color-amber-400: oklch(82.8% 0.189 84.429);
|
||||||
|
--color-amber-500: oklch(76.9% 0.188 70.08);
|
||||||
--color-amber-600: oklch(66.6% 0.179 58.318);
|
--color-amber-600: oklch(66.6% 0.179 58.318);
|
||||||
--color-yellow-500: oklch(79.5% 0.184 86.047);
|
--color-yellow-500: oklch(79.5% 0.184 86.047);
|
||||||
--color-green-100: oklch(96.2% 0.044 156.743);
|
--color-green-100: oklch(96.2% 0.044 156.743);
|
||||||
@@ -28,6 +31,11 @@
|
|||||||
--color-emerald-600: oklch(59.6% 0.145 163.225);
|
--color-emerald-600: oklch(59.6% 0.145 163.225);
|
||||||
--color-emerald-700: oklch(50.8% 0.118 165.612);
|
--color-emerald-700: oklch(50.8% 0.118 165.612);
|
||||||
--color-emerald-800: oklch(43.2% 0.095 166.913);
|
--color-emerald-800: oklch(43.2% 0.095 166.913);
|
||||||
|
--color-cyan-300: oklch(86.5% 0.127 207.078);
|
||||||
|
--color-cyan-400: oklch(78.9% 0.154 211.53);
|
||||||
|
--color-cyan-500: oklch(71.5% 0.143 215.221);
|
||||||
|
--color-cyan-800: oklch(45% 0.085 224.283);
|
||||||
|
--color-cyan-950: oklch(30.2% 0.056 229.695);
|
||||||
--color-sky-600: oklch(58.8% 0.158 241.966);
|
--color-sky-600: oklch(58.8% 0.158 241.966);
|
||||||
--color-blue-100: oklch(93.2% 0.032 255.585);
|
--color-blue-100: oklch(93.2% 0.032 255.585);
|
||||||
--color-blue-200: oklch(88.2% 0.059 254.128);
|
--color-blue-200: oklch(88.2% 0.059 254.128);
|
||||||
@@ -41,8 +49,11 @@
|
|||||||
--color-slate-50: oklch(98.4% 0.003 247.858);
|
--color-slate-50: oklch(98.4% 0.003 247.858);
|
||||||
--color-slate-100: oklch(96.8% 0.007 247.896);
|
--color-slate-100: oklch(96.8% 0.007 247.896);
|
||||||
--color-slate-200: oklch(92.9% 0.013 255.508);
|
--color-slate-200: oklch(92.9% 0.013 255.508);
|
||||||
|
--color-slate-400: oklch(70.4% 0.04 256.788);
|
||||||
|
--color-slate-500: oklch(55.4% 0.046 257.417);
|
||||||
--color-slate-700: oklch(37.2% 0.044 257.287);
|
--color-slate-700: oklch(37.2% 0.044 257.287);
|
||||||
--color-slate-800: oklch(27.9% 0.041 260.031);
|
--color-slate-800: oklch(27.9% 0.041 260.031);
|
||||||
|
--color-slate-900: oklch(20.8% 0.042 265.755);
|
||||||
--color-gray-50: oklch(98.5% 0.002 247.839);
|
--color-gray-50: oklch(98.5% 0.002 247.839);
|
||||||
--color-gray-100: oklch(96.7% 0.003 264.542);
|
--color-gray-100: oklch(96.7% 0.003 264.542);
|
||||||
--color-gray-200: oklch(92.8% 0.006 264.531);
|
--color-gray-200: oklch(92.8% 0.006 264.531);
|
||||||
@@ -101,6 +112,8 @@
|
|||||||
--animate-bounce: bounce 1s infinite;
|
--animate-bounce: bounce 1s infinite;
|
||||||
--blur-xs: 4px;
|
--blur-xs: 4px;
|
||||||
--blur-sm: 8px;
|
--blur-sm: 8px;
|
||||||
|
--blur-lg: 16px;
|
||||||
|
--blur-xl: 24px;
|
||||||
--default-transition-duration: 150ms;
|
--default-transition-duration: 150ms;
|
||||||
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
--default-font-family: var(--font-sans);
|
--default-font-family: var(--font-sans);
|
||||||
@@ -256,6 +269,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
|
.pointer-events-none {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
.visible {
|
.visible {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
@@ -277,6 +293,9 @@
|
|||||||
.-top-1 {
|
.-top-1 {
|
||||||
top: calc(var(--spacing) * -1);
|
top: calc(var(--spacing) * -1);
|
||||||
}
|
}
|
||||||
|
.-top-12 {
|
||||||
|
top: calc(var(--spacing) * -12);
|
||||||
|
}
|
||||||
.top-0 {
|
.top-0 {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
@@ -298,6 +317,9 @@
|
|||||||
.-right-8 {
|
.-right-8 {
|
||||||
right: calc(var(--spacing) * -8);
|
right: calc(var(--spacing) * -8);
|
||||||
}
|
}
|
||||||
|
.-right-16 {
|
||||||
|
right: calc(var(--spacing) * -16);
|
||||||
|
}
|
||||||
.right-0 {
|
.right-0 {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
@@ -313,12 +335,18 @@
|
|||||||
.-bottom-8 {
|
.-bottom-8 {
|
||||||
bottom: calc(var(--spacing) * -8);
|
bottom: calc(var(--spacing) * -8);
|
||||||
}
|
}
|
||||||
|
.-bottom-16 {
|
||||||
|
bottom: calc(var(--spacing) * -16);
|
||||||
|
}
|
||||||
.bottom-0 {
|
.bottom-0 {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
.bottom-8 {
|
.bottom-8 {
|
||||||
bottom: calc(var(--spacing) * 8);
|
bottom: calc(var(--spacing) * 8);
|
||||||
}
|
}
|
||||||
|
.-left-12 {
|
||||||
|
left: calc(var(--spacing) * -12);
|
||||||
|
}
|
||||||
.left-0 {
|
.left-0 {
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
@@ -391,6 +419,9 @@
|
|||||||
.mt-auto {
|
.mt-auto {
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
}
|
}
|
||||||
|
.mr-0\.5 {
|
||||||
|
margin-right: calc(var(--spacing) * 0.5);
|
||||||
|
}
|
||||||
.mr-3 {
|
.mr-3 {
|
||||||
margin-right: calc(var(--spacing) * 3);
|
margin-right: calc(var(--spacing) * 3);
|
||||||
}
|
}
|
||||||
@@ -505,6 +536,12 @@
|
|||||||
.h-24 {
|
.h-24 {
|
||||||
height: calc(var(--spacing) * 24);
|
height: calc(var(--spacing) * 24);
|
||||||
}
|
}
|
||||||
|
.h-32 {
|
||||||
|
height: calc(var(--spacing) * 32);
|
||||||
|
}
|
||||||
|
.h-44 {
|
||||||
|
height: calc(var(--spacing) * 44);
|
||||||
|
}
|
||||||
.h-\[18px\] {
|
.h-\[18px\] {
|
||||||
height: 18px;
|
height: 18px;
|
||||||
}
|
}
|
||||||
@@ -610,6 +647,12 @@
|
|||||||
.w-28 {
|
.w-28 {
|
||||||
width: calc(var(--spacing) * 28);
|
width: calc(var(--spacing) * 28);
|
||||||
}
|
}
|
||||||
|
.w-32 {
|
||||||
|
width: calc(var(--spacing) * 32);
|
||||||
|
}
|
||||||
|
.w-44 {
|
||||||
|
width: calc(var(--spacing) * 44);
|
||||||
|
}
|
||||||
.w-48 {
|
.w-48 {
|
||||||
width: calc(var(--spacing) * 48);
|
width: calc(var(--spacing) * 48);
|
||||||
}
|
}
|
||||||
@@ -640,6 +683,9 @@
|
|||||||
.max-w-\[85\%\] {
|
.max-w-\[85\%\] {
|
||||||
max-width: 85%;
|
max-width: 85%;
|
||||||
}
|
}
|
||||||
|
.max-w-\[120px\] {
|
||||||
|
max-width: 120px;
|
||||||
|
}
|
||||||
.max-w-\[140px\] {
|
.max-w-\[140px\] {
|
||||||
max-width: 140px;
|
max-width: 140px;
|
||||||
}
|
}
|
||||||
@@ -785,6 +831,13 @@
|
|||||||
.gap-\[6px\] {
|
.gap-\[6px\] {
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
.space-y-0\.5 {
|
||||||
|
:where(& > :not(:last-child)) {
|
||||||
|
--tw-space-y-reverse: 0;
|
||||||
|
margin-block-start: calc(calc(var(--spacing) * 0.5) * var(--tw-space-y-reverse));
|
||||||
|
margin-block-end: calc(calc(var(--spacing) * 0.5) * calc(1 - var(--tw-space-y-reverse)));
|
||||||
|
}
|
||||||
|
}
|
||||||
.space-y-1 {
|
.space-y-1 {
|
||||||
:where(& > :not(:last-child)) {
|
:where(& > :not(:last-child)) {
|
||||||
--tw-space-y-reverse: 0;
|
--tw-space-y-reverse: 0;
|
||||||
@@ -1027,9 +1080,21 @@
|
|||||||
.border-\[\#fbd897\] {
|
.border-\[\#fbd897\] {
|
||||||
border-color: #fbd897;
|
border-color: #fbd897;
|
||||||
}
|
}
|
||||||
|
.border-\[\#fca5a5\] {
|
||||||
|
border-color: #fca5a5;
|
||||||
|
}
|
||||||
.border-\[\#fde5e8\] {
|
.border-\[\#fde5e8\] {
|
||||||
border-color: #fde5e8;
|
border-color: #fde5e8;
|
||||||
}
|
}
|
||||||
|
.border-amber-300 {
|
||||||
|
border-color: var(--color-amber-300);
|
||||||
|
}
|
||||||
|
.border-amber-500\/30 {
|
||||||
|
border-color: color-mix(in srgb, oklch(76.9% 0.188 70.08) 30%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
border-color: color-mix(in oklab, var(--color-amber-500) 30%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
.border-blue-100 {
|
.border-blue-100 {
|
||||||
border-color: var(--color-blue-100);
|
border-color: var(--color-blue-100);
|
||||||
}
|
}
|
||||||
@@ -1042,6 +1107,12 @@
|
|||||||
.border-current {
|
.border-current {
|
||||||
border-color: currentcolor;
|
border-color: currentcolor;
|
||||||
}
|
}
|
||||||
|
.border-cyan-800\/40 {
|
||||||
|
border-color: color-mix(in srgb, oklch(45% 0.085 224.283) 40%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
border-color: color-mix(in oklab, var(--color-cyan-800) 40%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
.border-emerald-100 {
|
.border-emerald-100 {
|
||||||
border-color: var(--color-emerald-100);
|
border-color: var(--color-emerald-100);
|
||||||
}
|
}
|
||||||
@@ -1084,6 +1155,12 @@
|
|||||||
.border-red-500 {
|
.border-red-500 {
|
||||||
border-color: var(--color-red-500);
|
border-color: var(--color-red-500);
|
||||||
}
|
}
|
||||||
|
.border-slate-700 {
|
||||||
|
border-color: var(--color-slate-700);
|
||||||
|
}
|
||||||
|
.border-slate-800 {
|
||||||
|
border-color: var(--color-slate-800);
|
||||||
|
}
|
||||||
.border-transparent {
|
.border-transparent {
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
@@ -1207,6 +1284,15 @@
|
|||||||
.bg-\[\#ffffff14\] {
|
.bg-\[\#ffffff14\] {
|
||||||
background-color: #ffffff14;
|
background-color: #ffffff14;
|
||||||
}
|
}
|
||||||
|
.bg-amber-400\/80 {
|
||||||
|
background-color: color-mix(in srgb, oklch(82.8% 0.189 84.429) 80%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
background-color: color-mix(in oklab, var(--color-amber-400) 80%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bg-black {
|
||||||
|
background-color: var(--color-black);
|
||||||
|
}
|
||||||
.bg-black\/30 {
|
.bg-black\/30 {
|
||||||
background-color: color-mix(in srgb, #000 30%, transparent);
|
background-color: color-mix(in srgb, #000 30%, transparent);
|
||||||
@supports (color: color-mix(in lab, red, red)) {
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
@@ -1222,12 +1308,27 @@
|
|||||||
.bg-blue-500 {
|
.bg-blue-500 {
|
||||||
background-color: var(--color-blue-500);
|
background-color: var(--color-blue-500);
|
||||||
}
|
}
|
||||||
|
.bg-blue-500\/10 {
|
||||||
|
background-color: color-mix(in srgb, oklch(62.3% 0.214 259.815) 10%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
background-color: color-mix(in oklab, var(--color-blue-500) 10%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
.bg-blue-950\/60 {
|
.bg-blue-950\/60 {
|
||||||
background-color: color-mix(in srgb, oklch(28.2% 0.091 267.935) 60%, transparent);
|
background-color: color-mix(in srgb, oklch(28.2% 0.091 267.935) 60%, transparent);
|
||||||
@supports (color: color-mix(in lab, red, red)) {
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
background-color: color-mix(in oklab, var(--color-blue-950) 60%, transparent);
|
background-color: color-mix(in oklab, var(--color-blue-950) 60%, transparent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.bg-cyan-500\/10 {
|
||||||
|
background-color: color-mix(in srgb, oklch(71.5% 0.143 215.221) 10%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
background-color: color-mix(in oklab, var(--color-cyan-500) 10%, transparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bg-cyan-950 {
|
||||||
|
background-color: var(--color-cyan-950);
|
||||||
|
}
|
||||||
.bg-emerald-50 {
|
.bg-emerald-50 {
|
||||||
background-color: var(--color-emerald-50);
|
background-color: var(--color-emerald-50);
|
||||||
}
|
}
|
||||||
@@ -1276,6 +1377,9 @@
|
|||||||
.bg-slate-100 {
|
.bg-slate-100 {
|
||||||
background-color: var(--color-slate-100);
|
background-color: var(--color-slate-100);
|
||||||
}
|
}
|
||||||
|
.bg-slate-900 {
|
||||||
|
background-color: var(--color-slate-900);
|
||||||
|
}
|
||||||
.bg-transparent {
|
.bg-transparent {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
@@ -1310,6 +1414,10 @@
|
|||||||
--tw-gradient-position: to bottom right in oklab;
|
--tw-gradient-position: to bottom right in oklab;
|
||||||
background-image: linear-gradient(var(--tw-gradient-stops));
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||||
}
|
}
|
||||||
|
.bg-gradient-to-r {
|
||||||
|
--tw-gradient-position: to right in oklab;
|
||||||
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||||
|
}
|
||||||
.bg-gradient-to-tr {
|
.bg-gradient-to-tr {
|
||||||
--tw-gradient-position: to top right in oklab;
|
--tw-gradient-position: to top right in oklab;
|
||||||
background-image: linear-gradient(var(--tw-gradient-stops));
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||||
@@ -1317,6 +1425,10 @@
|
|||||||
.bg-\[url\(\'data\:image\/svg\+xml\,\%3csvg_xmlns\=\%27http\:\/\/www\.w3\.org\/2000\/svg\%27_viewBox\=\%270_0_24_24\%27_fill\=\%27none\%27_stroke\=\%27currentColor\%27_stroke-width\=\%272\%27\%3e\%3cline_x1\=\%273\%27_y1\=\%276\%27_x2\=\%2721\%27_y2\=\%276\%27\/\%3e\%3cline_x1\=\%273\%27_y1\=\%2712\%27_x2\=\%2721\%27_y2\=\%2712\%27\/\%3e\%3cline_x1\=\%273\%27_y1\=\%2718\%27_x2\=\%2721\%27_y2\=\%2718\%27\/\%3e\%3c\/svg\%3e\'\)\] {
|
.bg-\[url\(\'data\:image\/svg\+xml\,\%3csvg_xmlns\=\%27http\:\/\/www\.w3\.org\/2000\/svg\%27_viewBox\=\%270_0_24_24\%27_fill\=\%27none\%27_stroke\=\%27currentColor\%27_stroke-width\=\%272\%27\%3e\%3cline_x1\=\%273\%27_y1\=\%276\%27_x2\=\%2721\%27_y2\=\%276\%27\/\%3e\%3cline_x1\=\%273\%27_y1\=\%2712\%27_x2\=\%2721\%27_y2\=\%2712\%27\/\%3e\%3cline_x1\=\%273\%27_y1\=\%2718\%27_x2\=\%2721\%27_y2\=\%2718\%27\/\%3e\%3c\/svg\%3e\'\)\] {
|
||||||
background-image: url('data:image/svg+xml,%3csvg_xmlns=%27http://www.w3.org/2000/svg%27_viewBox=%270_0_24_24%27_fill=%27none%27_stroke=%27currentColor%27_stroke-width=%272%27%3e%3cline_x1=%273%27_y1=%276%27_x2=%2721%27_y2=%276%27/%3e%3cline_x1=%273%27_y1=%2712%27_x2=%2721%27_y2=%2712%27/%3e%3cline_x1=%273%27_y1=%2718%27_x2=%2721%27_y2=%2718%27/%3e%3c/svg%3e');
|
background-image: url('data:image/svg+xml,%3csvg_xmlns=%27http://www.w3.org/2000/svg%27_viewBox=%270_0_24_24%27_fill=%27none%27_stroke=%27currentColor%27_stroke-width=%272%27%3e%3cline_x1=%273%27_y1=%276%27_x2=%2721%27_y2=%276%27/%3e%3cline_x1=%273%27_y1=%2712%27_x2=%2721%27_y2=%2712%27/%3e%3cline_x1=%273%27_y1=%2718%27_x2=%2721%27_y2=%2718%27/%3e%3c/svg%3e');
|
||||||
}
|
}
|
||||||
|
.from-\[\#0c1e36\] {
|
||||||
|
--tw-gradient-from: #0c1e36;
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
.from-\[\#00a3a1\] {
|
.from-\[\#00a3a1\] {
|
||||||
--tw-gradient-from: #00a3a1;
|
--tw-gradient-from: #00a3a1;
|
||||||
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
@@ -1329,11 +1441,20 @@
|
|||||||
--tw-gradient-from: #0066b3;
|
--tw-gradient-from: #0066b3;
|
||||||
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
}
|
}
|
||||||
|
.from-white {
|
||||||
|
--tw-gradient-from: var(--color-white);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
.via-\[\#0066b3\] {
|
.via-\[\#0066b3\] {
|
||||||
--tw-gradient-via: #0066b3;
|
--tw-gradient-via: #0066b3;
|
||||||
--tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);
|
--tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);
|
||||||
--tw-gradient-stops: var(--tw-gradient-via-stops);
|
--tw-gradient-stops: var(--tw-gradient-via-stops);
|
||||||
}
|
}
|
||||||
|
.via-\[\#162e4e\] {
|
||||||
|
--tw-gradient-via: #162e4e;
|
||||||
|
--tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops);
|
||||||
|
}
|
||||||
.to-\[\#00a3a1\] {
|
.to-\[\#00a3a1\] {
|
||||||
--tw-gradient-to: #00a3a1;
|
--tw-gradient-to: #00a3a1;
|
||||||
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
@@ -1342,6 +1463,14 @@
|
|||||||
--tw-gradient-to: #0066b3;
|
--tw-gradient-to: #0066b3;
|
||||||
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
}
|
}
|
||||||
|
.to-\[\#091729\] {
|
||||||
|
--tw-gradient-to: #091729;
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
.to-\[\#fafcfe\] {
|
||||||
|
--tw-gradient-to: #fafcfe;
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
.bg-\[length\:20px\] {
|
.bg-\[length\:20px\] {
|
||||||
background-size: 20px;
|
background-size: 20px;
|
||||||
}
|
}
|
||||||
@@ -1363,6 +1492,9 @@
|
|||||||
.p-0\.5 {
|
.p-0\.5 {
|
||||||
padding: calc(var(--spacing) * 0.5);
|
padding: calc(var(--spacing) * 0.5);
|
||||||
}
|
}
|
||||||
|
.p-1 {
|
||||||
|
padding: var(--spacing);
|
||||||
|
}
|
||||||
.p-1\.5 {
|
.p-1\.5 {
|
||||||
padding: calc(var(--spacing) * 1.5);
|
padding: calc(var(--spacing) * 1.5);
|
||||||
}
|
}
|
||||||
@@ -1694,6 +1826,10 @@
|
|||||||
--tw-tracking: 0.02em;
|
--tw-tracking: 0.02em;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
}
|
}
|
||||||
|
.tracking-\[0\.2em\] {
|
||||||
|
--tw-tracking: 0.2em;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
}
|
||||||
.tracking-\[0\.04em\] {
|
.tracking-\[0\.04em\] {
|
||||||
--tw-tracking: 0.04em;
|
--tw-tracking: 0.04em;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
@@ -1758,6 +1894,9 @@
|
|||||||
.text-\[\#5a6577\] {
|
.text-\[\#5a6577\] {
|
||||||
color: #5a6577;
|
color: #5a6577;
|
||||||
}
|
}
|
||||||
|
.text-\[\#7f1d1d\] {
|
||||||
|
color: #7f1d1d;
|
||||||
|
}
|
||||||
.text-\[\#8a96a8\] {
|
.text-\[\#8a96a8\] {
|
||||||
color: #8a96a8;
|
color: #8a96a8;
|
||||||
}
|
}
|
||||||
@@ -1815,6 +1954,12 @@
|
|||||||
.text-blue-400 {
|
.text-blue-400 {
|
||||||
color: var(--color-blue-400);
|
color: var(--color-blue-400);
|
||||||
}
|
}
|
||||||
|
.text-cyan-300 {
|
||||||
|
color: var(--color-cyan-300);
|
||||||
|
}
|
||||||
|
.text-cyan-400 {
|
||||||
|
color: var(--color-cyan-400);
|
||||||
|
}
|
||||||
.text-emerald-500 {
|
.text-emerald-500 {
|
||||||
color: var(--color-emerald-500);
|
color: var(--color-emerald-500);
|
||||||
}
|
}
|
||||||
@@ -1869,6 +2014,18 @@
|
|||||||
.text-sky-600 {
|
.text-sky-600 {
|
||||||
color: var(--color-sky-600);
|
color: var(--color-sky-600);
|
||||||
}
|
}
|
||||||
|
.text-slate-100 {
|
||||||
|
color: var(--color-slate-100);
|
||||||
|
}
|
||||||
|
.text-slate-200 {
|
||||||
|
color: var(--color-slate-200);
|
||||||
|
}
|
||||||
|
.text-slate-400 {
|
||||||
|
color: var(--color-slate-400);
|
||||||
|
}
|
||||||
|
.text-slate-500 {
|
||||||
|
color: var(--color-slate-500);
|
||||||
|
}
|
||||||
.text-slate-700 {
|
.text-slate-700 {
|
||||||
color: var(--color-slate-700);
|
color: var(--color-slate-700);
|
||||||
}
|
}
|
||||||
@@ -1912,6 +2069,9 @@
|
|||||||
.opacity-85 {
|
.opacity-85 {
|
||||||
opacity: 85%;
|
opacity: 85%;
|
||||||
}
|
}
|
||||||
|
.opacity-90 {
|
||||||
|
opacity: 90%;
|
||||||
|
}
|
||||||
.shadow-2xl {
|
.shadow-2xl {
|
||||||
--tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));
|
--tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));
|
||||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
@@ -1956,6 +2116,14 @@
|
|||||||
--tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.05));
|
--tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.05));
|
||||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
}
|
}
|
||||||
|
.blur-lg {
|
||||||
|
--tw-blur: blur(var(--blur-lg));
|
||||||
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||||
|
}
|
||||||
|
.blur-xl {
|
||||||
|
--tw-blur: blur(var(--blur-xl));
|
||||||
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||||
|
}
|
||||||
.brightness-75 {
|
.brightness-75 {
|
||||||
--tw-brightness: brightness(75%);
|
--tw-brightness: brightness(75%);
|
||||||
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||||
@@ -2080,6 +2248,10 @@
|
|||||||
--tw-outline-style: none;
|
--tw-outline-style: none;
|
||||||
outline-style: none;
|
outline-style: none;
|
||||||
}
|
}
|
||||||
|
.select-all {
|
||||||
|
-webkit-user-select: all;
|
||||||
|
user-select: all;
|
||||||
|
}
|
||||||
.select-none {
|
.select-none {
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@@ -2397,6 +2569,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.hover\:bg-\[\#990d20\] {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
background-color: #990d20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.hover\:bg-\[\#008280\] {
|
.hover\:bg-\[\#008280\] {
|
||||||
&:hover {
|
&:hover {
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
@@ -2547,6 +2726,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.hover\:from-\[\#002244\] {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
--tw-gradient-from: #002244;
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hover\:to-\[\#003b71\] {
|
||||||
|
&:hover {
|
||||||
|
@media (hover: hover) {
|
||||||
|
--tw-gradient-to: #003b71;
|
||||||
|
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.hover\:text-\[\#1f2a3a\] {
|
.hover\:text-\[\#1f2a3a\] {
|
||||||
&:hover {
|
&:hover {
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
@@ -2624,6 +2819,16 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.sm\:w-auto {
|
||||||
|
@media (width >= 40rem) {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sm\:flex-none {
|
||||||
|
@media (width >= 40rem) {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
.sm\:grid-cols-2 {
|
.sm\:grid-cols-2 {
|
||||||
@media (width >= 40rem) {
|
@media (width >= 40rem) {
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
@@ -2789,6 +2994,11 @@
|
|||||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.lg\:grid-cols-\[1\.8fr_1\.2fr\] {
|
||||||
|
@media (width >= 64rem) {
|
||||||
|
grid-template-columns: 1.8fr 1.2fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
.lg\:grid-cols-\[1fr_1fr_1fr_1fr_auto\] {
|
.lg\:grid-cols-\[1fr_1fr_1fr_1fr_auto\] {
|
||||||
@media (width >= 64rem) {
|
@media (width >= 64rem) {
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr auto;
|
grid-template-columns: 1fr 1fr 1fr 1fr auto;
|
||||||
|
|||||||
Reference in New Issue
Block a user