diff --git a/Controllers/SpjDriverController/HomeController.cs b/Controllers/SpjDriverController/HomeController.cs index f210047..3eb9350 100644 --- a/Controllers/SpjDriverController/HomeController.cs +++ b/Controllers/SpjDriverController/HomeController.cs @@ -4,26 +4,26 @@ using eSPJ.Models; namespace eSPJ.Controllers.SpjDriverController; + [Route("")] public class HomeController : Controller { - private readonly ILogger _logger; public HomeController(ILogger logger) { _logger = logger; } - + [HttpGet("")] public IActionResult Index() { - return View("~/Views/Admin/Transport/SpjDriver/Home/Index.cshtml"); + return View("~/Views/Admin/Transport/SpjDriver/Home/Index.cshtml"); } - - public IActionResult Privacy() + [HttpGet("kosong")] + public IActionResult Kosong() { - return View("~/Views/Admin/Transport/SpjDriver/Home/Privacy.cshtml"); + return View("~/Views/Admin/Transport/SpjDriver/Home/Kosong.cshtml"); } - + [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { diff --git a/Controllers/SpjDriverController/ScanController.cs b/Controllers/SpjDriverController/ScanController.cs index 26856a0..39412b2 100644 --- a/Controllers/SpjDriverController/ScanController.cs +++ b/Controllers/SpjDriverController/ScanController.cs @@ -17,7 +17,7 @@ namespace eSPJ.Controllers.SpjDriverController { return View("~/Views/Admin/Transport/SpjDriver/Scan/Detail.cshtml"); } - + [HttpGet("create")] public IActionResult Create() { @@ -29,30 +29,19 @@ namespace eSPJ.Controllers.SpjDriverController { try { - // Validate barcode if (string.IsNullOrEmpty(barcode)) { TempData["Error"] = "Kode barcode tidak boleh kosong."; return RedirectToAction("Index"); } - // Basic validation for SPJ barcode format if (barcode.Length < 5) { TempData["Error"] = "Format kode SPJ tidak valid. Minimal 5 karakter."; return RedirectToAction("Index"); } - // Clean the barcode (remove any whitespace) barcode = barcode.Trim(); - - // TODO: Add your SPJ validation logic here - // For example: - // - Check if SPJ exists in database - // - Validate SPJ format according to your business rules - // - Check SPJ status (active, completed, etc.) - - // Simulate SPJ lookup (replace with your actual database logic) var spjData = await ValidateSpjCode(barcode); if (spjData == null) @@ -61,20 +50,13 @@ namespace eSPJ.Controllers.SpjDriverController return RedirectToAction("Index"); } - // Success - redirect to detail page or next step TempData["Success"] = $"SPJ '{barcode}' berhasil ditemukan!"; - - // Redirect to appropriate page based on your workflow - // For example, redirect to detail page: return RedirectToAction("Index", "Detail", new { spjCode = barcode }); - // Or redirect to submission page: - // return RedirectToAction("Index", "Submit", new { spjCode = barcode }); } catch (Exception) { - // Log the error (add your logging here) TempData["Error"] = "Terjadi kesalahan saat memproses scan. Silakan coba lagi."; return RedirectToAction("Index"); } @@ -82,20 +64,10 @@ namespace eSPJ.Controllers.SpjDriverController private async Task ValidateSpjCode(string barcode) { - // TODO: Implement your SPJ validation logic here - // This is just a sample implementation try { - // Simulate database lookup - await Task.Delay(100); // Simulate async operation - - // Example validation rules: - // 1. Check format (e.g., starts with "SPJ" or specific pattern) - // 2. Check if exists in database - // 3. Check status - - // For demo purposes, accept codes that start with "SPJ" + await Task.Delay(100); if (barcode.ToUpper().StartsWith("SPJ")) { return new SpjData @@ -107,7 +79,6 @@ namespace eSPJ.Controllers.SpjDriverController }; } - // Return null if not found or invalid return null; } catch @@ -116,7 +87,6 @@ namespace eSPJ.Controllers.SpjDriverController } } - // Sample model for SPJ data (replace with your actual model) public class SpjData { public string Code { get; set; } = string.Empty; diff --git a/Controllers/SpjDriverController/SubmitController.cs b/Controllers/SpjDriverController/SubmitController.cs index 1dac2d0..ca6aeed 100644 --- a/Controllers/SpjDriverController/SubmitController.cs +++ b/Controllers/SpjDriverController/SubmitController.cs @@ -18,5 +18,43 @@ namespace eSPJ.Controllers.SpjDriverController { return View("~/Views/Admin/Transport/SpjDriver/Submit/Struk.cshtml"); } + + [HttpPost("struk")] + public IActionResult ProcessStruk(string NomorStruk, string BeratMuatan) + { + try + { + // Validate inputs + if (string.IsNullOrEmpty(NomorStruk) || string.IsNullOrEmpty(BeratMuatan)) + { + TempData["Error"] = "Nomor struk dan berat muatan harus diisi."; + return RedirectToAction("Struk"); + } + + if (NomorStruk.Length < 6) + { + TempData["Error"] = "Nomor struk minimal 6 digit."; + return RedirectToAction("Struk"); + } + + if (!decimal.TryParse(BeratMuatan, out decimal berat) || berat <= 0) + { + TempData["Error"] = "Berat muatan harus berupa angka yang valid."; + return RedirectToAction("Struk"); + } + + // Here you would normally save to database + // For now, just simulate success + + TempData["Success"] = $"Struk berhasil disubmit! No: {NomorStruk}, Berat: {BeratMuatan} kg"; + return RedirectToAction("Index", "Home"); + + } + catch (Exception) + { + TempData["Error"] = "Terjadi kesalahan saat memproses struk. Silakan coba lagi."; + return RedirectToAction("Struk"); + } + } } } diff --git a/Views/Admin/Transport/SpjDriver/History/IndexAdmin.cshtml b/Views/Admin/Transport/SpjDriver/History/IndexAdmin.cshtml new file mode 100644 index 0000000..c156df3 --- /dev/null +++ b/Views/Admin/Transport/SpjDriver/History/IndexAdmin.cshtml @@ -0,0 +1,155 @@ +@{ + Layout = "~/Views/Admin/Transport/SpjDriver/Shared/_Layout.cshtml"; + ViewData["Title"] = "History - DLH"; +} + +
+
+
+ + + +

Riwayat Perjalanan

+
+
+
+ + @{ + var spjList = new[] + { + new { + Id = 1, + NoSpj = "SPJ/07-2025/PKM/000478", + Plat = "B 5678 ABC", + Kode = "JRC 007", + Tujuan = "Bantar Gebang", + Status = "In Progress", + Tanggal = "28 Jul 2025", + Waktu = "16:45" + }, + new { + Id = 2, + NoSpj = "SPJ/07-2025/PKM/000476", + Plat = "B 9632 TOR", + Kode = "JRC 005", + Tujuan = "RDF Rorotan", + Status = "Completed", + Tanggal = "27 Jul 2025", + Waktu = "14:30" + }, + new { + Id = 3, + NoSpj = "SPJ/07-2025/PKM/000477", + Plat = "B 1234 XYZ", + Kode = "JRC 006", + Tujuan = "RDF Pesanggarahan", + Status = "Completed", + Tanggal = "26 Jul 2025", + Waktu = "09:15" + }, + new { + Id = 4, + NoSpj = "SPJ/07-2025/PKM/000479", + Plat = "B 9876 DEF", + Kode = "JRC 008", + Tujuan = "RDF Sunter", + Status = "Completed", + Tanggal = "25 Jul 2025", + Waktu = "11:20" + }, + new { + Id = 5, + NoSpj = "SPJ/07-2025/PKM/000480", + Plat = "B 4321 GHI", + Kode = "JRC 009", + Tujuan = "Bantar Gebang", + Status = "Completed", + Tanggal = "24 Jul 2025", + Waktu = "08:45" + } + }; + } + + + + + + + + + + @*
+
+ +
+

Belum Ada Riwayat

+

Riwayat perjalanan Anda akan muncul di sini setelah melakukan perjalanan pertama.

+
*@ + +
\ No newline at end of file diff --git a/Views/Admin/Transport/SpjDriver/Home/Kosong.cshtml b/Views/Admin/Transport/SpjDriver/Home/Kosong.cshtml new file mode 100644 index 0000000..d6d6989 --- /dev/null +++ b/Views/Admin/Transport/SpjDriver/Home/Kosong.cshtml @@ -0,0 +1,221 @@ +@{ + Layout = "~/Views/Admin/Transport/SpjDriver/Shared/_Layout.cshtml"; + ViewData["Title"] = "Home Page"; +} + +
+ +
+
+

Bonny Agung Putra

+

Driver UPST

+
+ + Lokasi Anda: +
+

+ Mendeteksi lokasi... +

+
+
+
+
+ +
+ +
+ +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+

+ Belum Ada SPJ +

+

+ Anda belum memiliki Surat Perintah Jalan yang aktif saat ini. +

+
+ +
+
+
+
+

SPJ akan diterbitkan oleh admin sesuai jadwal kerja

+
+
+
+

Periksa koneksi internet dan aktifkan lokasi GPS

+
+
+
+ + +
+
+ + + +
+ + + + + + + + + \ No newline at end of file diff --git a/Views/Admin/Transport/SpjDriver/Scan/Index.cshtml b/Views/Admin/Transport/SpjDriver/Scan/Index.cshtml index b291fd6..03c4c2e 100644 --- a/Views/Admin/Transport/SpjDriver/Scan/Index.cshtml +++ b/Views/Admin/Transport/SpjDriver/Scan/Index.cshtml @@ -5,30 +5,6 @@ @section Styles { - } @@ -43,9 +19,7 @@ -
- @if (TempData["Success"] != null) {
@@ -66,12 +40,9 @@
} -
- -
@@ -81,7 +52,6 @@
-
- - -
@@ -143,7 +110,6 @@
-

Atau input manual:

@@ -160,7 +126,6 @@
- -
- +
- - diff --git a/Views/Admin/Transport/SpjDriver/Shared/Components/_NavigationAdmin.cshtml b/Views/Admin/Transport/SpjDriver/Shared/Components/_NavigationAdmin.cshtml new file mode 100644 index 0000000..4a6a66c --- /dev/null +++ b/Views/Admin/Transport/SpjDriver/Shared/Components/_NavigationAdmin.cshtml @@ -0,0 +1,48 @@ +
+
+
+
+
+
+
+
+ + + +
+ + +
+ + + +
+
+ +
+ + + + + diff --git a/Views/Admin/Transport/SpjDriver/Submit/Struk.cshtml b/Views/Admin/Transport/SpjDriver/Submit/Struk.cshtml index d04c3cc..4c2ec62 100644 --- a/Views/Admin/Transport/SpjDriver/Submit/Struk.cshtml +++ b/Views/Admin/Transport/SpjDriver/Submit/Struk.cshtml @@ -3,6 +3,9 @@ ViewData["Title"] = "Submit Struk"; } +@section Styles { + +}
@@ -16,13 +19,134 @@
-
+
+ +
+
+
+ +
+

Scan Struk Otomatis

+

Arahkan kamera ke struk untuk membaca data secara otomatis.

+
+ + +
+
+
+
+
+

Memuat scanner...

+
+
+
+
+ + +
+ + + + + + + + + + + + + + + + +
+
+ +
+

Tips Scan Struk:

+
    +
  • • Pastikan struk dalam pencahayaan yang cukup
  • +
  • • Letakkan struk rata tanpa lipatan
  • +
  • • Jaga jarak 15-30cm dari kamera
  • +
  • • Tunggu beberapa detik untuk proses OCR
  • +
  • • Periksa data yang terdeteksi sebelum submit
  • +
+
+
+
+
+
+ + +
+
+ atau input manual +
+
+
+ +
- +
-

Isi Data Struk

-

Masukkan nomor struk dan berat muatan dengan benar.

+

Input Manual

+

Masukkan nomor struk dan berat muatan secara manual.

@@ -65,11 +189,13 @@
+ \ No newline at end of file diff --git a/wwwroot/driver/css/scanner.css b/wwwroot/driver/css/scanner.css index e1ddbc2..e57d75d 100644 --- a/wwwroot/driver/css/scanner.css +++ b/wwwroot/driver/css/scanner.css @@ -1,4 +1,3 @@ -/* Scanner specific styles */ .scanner-container { position: relative; background: #1a1a1a; @@ -47,15 +46,13 @@ } } -/* Video element styling */ #video-preview { width: 100%; height: 100%; object-fit: cover; - transform: scaleX(-1); /* Mirror effect for better UX */ + transform: scaleX(-1); } -/* Canvas overlay for QuaggaJS */ .drawingBuffer { position: absolute !important; top: 0 !important; @@ -63,7 +60,6 @@ z-index: 5 !important; } -/* Button states */ .btn-scanner { transition: all 0.3s ease; } @@ -72,7 +68,6 @@ transform: scale(0.98); } -/* Loading animation improvements */ .loading-spinner { border: 2px solid rgba(255, 255, 255, 0.3); border-top: 2px solid white; @@ -82,6 +77,15 @@ animation: spin 1s linear infinite; } +.loading-spinner-small { + border: 2px solid rgba(245, 158, 11, 0.3); + border-top: 2px solid #f59e0b; + border-radius: 50%; + width: 16px; + height: 16px; + animation: spin 1s linear infinite; +} + @keyframes spin { 0% { transform: rotate(0deg); @@ -91,7 +95,6 @@ } } -/* Result card styling */ .scan-result-card { animation: slideInUp 0.3s ease-out; } @@ -107,7 +110,58 @@ } } -/* Mobile optimizations */ +/* OCR Processing Animation */ +.ocr-processing { + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.7; + } +} + +/* Receipt capture overlay */ +.receipt-overlay { + position: absolute; + top: 10%; + left: 10%; + right: 10%; + bottom: 10%; + border: 2px dashed rgba(245, 158, 11, 0.8); + border-radius: 8px; + pointer-events: none; + z-index: 10; +} + +.receipt-overlay::before { + content: "Arahkan ke teks struk"; + position: absolute; + top: -30px; + left: 50%; + transform: translateX(-50%); + background: rgba(245, 158, 11, 0.9); + color: white; + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + white-space: nowrap; +} + +/* Form transition effects */ +.form-section { + transition: all 0.3s ease; +} + +.form-section.disabled { + opacity: 0.6; + pointer-events: none; +} + @media (max-width: 640px) { .scanner-overlay { width: 200px; @@ -117,11 +171,74 @@ .scanner-container { height: 250px !important; } + + .receipt-overlay::before { + font-size: 11px; + padding: 3px 6px; + } } -/* Dark mode support */ @media (prefers-color-scheme: dark) { .scanner-container { background: #0a0a0a; } } + +#scanner-container video { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; + border-radius: 8px; +} + +#scanner-container canvas { + position: absolute !important; + top: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100% !important; + border-radius: 8px; +} + +#scanner-container select, +#scanner-container button { + display: none !important; +} + +/* Success feedback */ +.success-flash { + position: absolute; + inset: 0; + background: rgba(34, 197, 94, 0.3); + border-radius: 8px; + z-index: 15; + animation: flash 0.3s ease-out; +} + +@keyframes flash { + 0% { + opacity: 0; + } + 50% { + opacity: 1; + } + 100% { + opacity: 0; + } +} + +/* Input highlight when auto-filled */ +.auto-filled { + background-color: rgba(34, 197, 94, 0.1) !important; + border-color: rgb(34, 197, 94) !important; + animation: highlight 1s ease-out; +} + +@keyframes highlight { + 0% { + box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.3); + } + 100% { + box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); + } +} diff --git a/wwwroot/driver/css/watch.css b/wwwroot/driver/css/watch.css index b2721f6..c88a210 100644 --- a/wwwroot/driver/css/watch.css +++ b/wwwroot/driver/css/watch.css @@ -54,11 +54,15 @@ --color-blue-50: oklch(97% 0.014 254.604); --color-blue-100: oklch(93.2% 0.032 255.585); --color-blue-200: oklch(88.2% 0.059 254.128); + --color-blue-400: oklch(70.7% 0.165 254.624); --color-blue-500: oklch(62.3% 0.214 259.815); --color-blue-600: oklch(54.6% 0.245 262.881); --color-blue-700: oklch(48.8% 0.243 264.376); --color-blue-800: oklch(42.4% 0.199 265.638); --color-indigo-50: oklch(96.2% 0.018 272.314); + --color-indigo-100: oklch(93% 0.034 272.788); + --color-indigo-200: oklch(87% 0.065 274.039); + --color-indigo-300: oklch(78.5% 0.115 274.713); --color-purple-50: oklch(97.7% 0.014 308.299); --color-purple-100: oklch(94.6% 0.033 307.174); --color-purple-400: oklch(71.4% 0.203 305.504); @@ -69,8 +73,10 @@ --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-600: oklch(44.6% 0.043 257.281); --color-slate-700: oklch(37.2% 0.044 257.287); --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-100: oklch(96.7% 0.003 264.542); --color-gray-200: oklch(92.8% 0.006 264.531); @@ -84,6 +90,7 @@ --color-black: #000; --color-white: #fff; --spacing: 0.25rem; + --container-xs: 20rem; --container-sm: 24rem; --text-xs: 0.75rem; --text-xs--line-height: calc(1 / 0.75); @@ -95,6 +102,8 @@ --text-lg--line-height: calc(1.75 / 1.125); --text-xl: 1.25rem; --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; @@ -113,7 +122,9 @@ --ease-out: cubic-bezier(0, 0, 0.2, 1); --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); --animate-spin: spin 1s linear infinite; + --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + --animate-bounce: bounce 1s infinite; --blur-sm: 8px; --blur-lg: 16px; --default-transition-duration: 150ms; @@ -352,6 +363,12 @@ .right-4 { right: calc(var(--spacing) * 4); } + .right-8 { + right: calc(var(--spacing) * 8); + } + .right-16 { + right: calc(var(--spacing) * 16); + } .right-full { right: 100%; } @@ -373,6 +390,9 @@ .bottom-8 { bottom: calc(var(--spacing) * 8); } + .bottom-16 { + bottom: calc(var(--spacing) * 16); + } .bottom-50 { bottom: calc(var(--spacing) * 50); } @@ -388,6 +408,12 @@ .left-1\/2 { left: calc(1/2 * 100%); } + .left-8 { + left: calc(var(--spacing) * 8); + } + .left-12 { + left: calc(var(--spacing) * 12); + } .z-0 { z-index: 0; } @@ -568,6 +594,9 @@ .my-5 { margin-block: calc(var(--spacing) * 5); } + .my-6 { + margin-block: calc(var(--spacing) * 6); + } .my-auto { margin-block: auto; } @@ -637,6 +666,9 @@ .mt-1 { margin-top: calc(var(--spacing) * 1); } + .mt-1\.5 { + margin-top: calc(var(--spacing) * 1.5); + } .mt-2 { margin-top: calc(var(--spacing) * 2); } @@ -655,6 +687,9 @@ .mt-8 { margin-top: calc(var(--spacing) * 8); } + .mt-10 { + margin-top: calc(var(--spacing) * 10); + } .mt-40 { margin-top: calc(var(--spacing) * 40); } @@ -688,6 +723,9 @@ .mb-6 { margin-bottom: calc(var(--spacing) * 6); } + .mb-8 { + margin-bottom: calc(var(--spacing) * 8); + } .mb-auto { margin-bottom: auto; } @@ -748,6 +786,9 @@ .h-1 { height: calc(var(--spacing) * 1); } + .h-1\.5 { + height: calc(var(--spacing) * 1.5); + } .h-2 { height: calc(var(--spacing) * 2); } @@ -790,6 +831,9 @@ .h-25 { height: calc(var(--spacing) * 25); } + .h-28 { + height: calc(var(--spacing) * 28); + } .h-30 { height: calc(var(--spacing) * 30); } @@ -820,6 +864,12 @@ .w-0 { width: calc(var(--spacing) * 0); } + .w-1 { + width: calc(var(--spacing) * 1); + } + .w-1\.5 { + width: calc(var(--spacing) * 1.5); + } .w-2 { width: calc(var(--spacing) * 2); } @@ -865,6 +915,9 @@ .w-25 { width: calc(var(--spacing) * 25); } + .w-28 { + width: calc(var(--spacing) * 28); + } .w-32 { width: calc(var(--spacing) * 32); } @@ -892,6 +945,9 @@ .max-w-sm { max-width: var(--container-sm); } + .max-w-xs { + max-width: var(--container-xs); + } .min-w-0 { min-width: calc(var(--spacing) * 0); } @@ -940,6 +996,10 @@ --tw-translate-x: calc(var(--spacing) * -12); translate: var(--tw-translate-x) var(--tw-translate-y); } + .translate-x-10 { + --tw-translate-x: calc(var(--spacing) * 10); + translate: var(--tw-translate-x) var(--tw-translate-y); + } .translate-x-16 { --tw-translate-x: calc(var(--spacing) * 16); translate: var(--tw-translate-x) var(--tw-translate-y); @@ -952,6 +1012,10 @@ --tw-translate-y: calc(calc(1/2 * 100%) * -1); translate: var(--tw-translate-x) var(--tw-translate-y); } + .-translate-y-10 { + --tw-translate-y: calc(var(--spacing) * -10); + translate: var(--tw-translate-x) var(--tw-translate-y); + } .-translate-y-16 { --tw-translate-y: calc(var(--spacing) * -16); translate: var(--tw-translate-x) var(--tw-translate-y); @@ -969,6 +1033,12 @@ .transform { transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); } + .animate-bounce { + animation: var(--animate-bounce); + } + .animate-ping { + animation: var(--animate-ping); + } .animate-pulse { animation: var(--animate-pulse); } @@ -1145,6 +1215,9 @@ .rounded-2xl { border-radius: var(--radius-2xl); } + .rounded-3xl { + border-radius: var(--radius-3xl); + } .rounded-full { border-radius: calc(infinity * 1px); } @@ -1302,6 +1375,12 @@ .border-white { border-color: var(--color-white); } + .border-white\/30 { + border-color: color-mix(in srgb, #fff 30%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-white) 30%, transparent); + } + } .border-yellow-200 { border-color: var(--color-yellow-200); } @@ -1323,6 +1402,9 @@ .bg-blue-100 { background-color: var(--color-blue-100); } + .bg-blue-400 { + background-color: var(--color-blue-400); + } .bg-blue-500 { background-color: var(--color-blue-500); } @@ -1362,12 +1444,18 @@ .bg-green-600 { background-color: var(--color-green-600); } + .bg-indigo-300 { + background-color: var(--color-indigo-300); + } .bg-orange-50 { background-color: var(--color-orange-50); } .bg-orange-100 { background-color: var(--color-orange-100); } + .bg-orange-300 { + background-color: var(--color-orange-300); + } .bg-orange-400 { background-color: var(--color-orange-400); } @@ -1389,6 +1477,9 @@ .bg-slate-100 { background-color: var(--color-slate-100); } + .bg-slate-400 { + background-color: var(--color-slate-400); + } .bg-transparent { background-color: transparent; } @@ -1407,6 +1498,12 @@ background-color: color-mix(in oklab, var(--color-white) 10%, transparent); } } + .bg-white\/70 { + background-color: color-mix(in srgb, #fff 70%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-white) 70%, transparent); + } + } .bg-yellow-50 { background-color: var(--color-yellow-50); } @@ -1439,6 +1536,10 @@ --tw-gradient-from: var(--color-blue-100); --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-blue-500 { + --tw-gradient-from: var(--color-blue-500); + --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-blue-600 { --tw-gradient-from: var(--color-blue-600); --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)); @@ -1491,6 +1592,15 @@ --tw-gradient-from: var(--color-slate-100); --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-slate-700 { + --tw-gradient-from: var(--color-slate-700); + --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-blue-50 { + --tw-gradient-via: var(--color-blue-50); + --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); + } .via-orange-400 { --tw-gradient-via: var(--color-orange-400); --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); @@ -1505,6 +1615,10 @@ --tw-gradient-to: var(--color-blue-200); --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-blue-600 { + --tw-gradient-to: var(--color-blue-600); + --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-emerald-600 { --tw-gradient-to: var(--color-emerald-600); --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)); @@ -1521,6 +1635,10 @@ --tw-gradient-to: var(--color-indigo-50); --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-indigo-100 { + --tw-gradient-to: var(--color-indigo-100); + --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-orange-50 { --tw-gradient-to: var(--color-orange-50); --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)); @@ -1577,6 +1695,14 @@ --tw-gradient-to: var(--color-slate-100); --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-slate-200 { + --tw-gradient-to: var(--color-slate-200); + --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-slate-900 { + --tw-gradient-to: var(--color-slate-900); + --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-teal-50 { --tw-gradient-to: var(--color-teal-50); --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)); @@ -1585,6 +1711,9 @@ --tw-gradient-to: var(--color-yellow-50); --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-clip-text { + background-clip: text; + } .object-contain { object-fit: contain; } @@ -1660,6 +1789,9 @@ .py-8 { padding-block: calc(var(--spacing) * 8); } + .py-12 { + padding-block: calc(var(--spacing) * 12); + } .py-16 { padding-block: calc(var(--spacing) * 16); } @@ -1783,6 +1915,10 @@ .font-mono { font-family: var(--font-mono); } + .text-2xl { + font-size: var(--text-2xl); + line-height: var(--tw-leading, var(--text-2xl--line-height)); + } .text-base { font-size: var(--text-base); line-height: var(--tw-leading, var(--text-base--line-height)); @@ -1935,12 +2071,18 @@ .text-slate-500 { color: var(--color-slate-500); } + .text-slate-600 { + color: var(--color-slate-600); + } .text-slate-700 { color: var(--color-slate-700); } .text-slate-800 { color: var(--color-slate-800); } + .text-transparent { + color: transparent; + } .text-white { color: var(--color-white); } @@ -1977,9 +2119,15 @@ .opacity-30 { opacity: 30%; } + .opacity-40 { + opacity: 40%; + } .opacity-50 { opacity: 50%; } + .opacity-60 { + opacity: 60%; + } .opacity-75 { opacity: 75%; } @@ -1996,6 +2144,10 @@ --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); } + .shadow-2xl { + --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); + } .shadow-lg { --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); @@ -2016,6 +2168,10 @@ --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); } + .ring { + --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } .ring-2 { --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); @@ -2092,6 +2248,16 @@ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); transition-duration: var(--tw-duration, var(--default-transition-duration)); } + .transition-shadow { + transition-property: box-shadow; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .transition-transform { + transition-property: transform, translate, scale, rotate; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } .duration-150 { --tw-duration: 150ms; transition-duration: 150ms; @@ -2104,6 +2270,10 @@ --tw-duration: 300ms; transition-duration: 300ms; } + .duration-500 { + --tw-duration: 500ms; + transition-duration: 500ms; + } .ease-in-out { --tw-ease: var(--ease-in-out); transition-timing-function: var(--ease-in-out); @@ -2127,6 +2297,59 @@ } } } + .group-hover\:rotate-180 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + rotate: 180deg; + } + } + } + .group-hover\:from-blue-100 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + --tw-gradient-from: var(--color-blue-100); + --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)); + } + } + } + .group-hover\:from-orange-100 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + --tw-gradient-from: var(--color-orange-100); + --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)); + } + } + } + .group-hover\:to-indigo-200 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + --tw-gradient-to: var(--color-indigo-200); + --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)); + } + } + } + .group-hover\:to-orange-200 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + --tw-gradient-to: var(--color-orange-200); + --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)); + } + } + } + .group-hover\:text-blue-600 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + color: var(--color-blue-600); + } + } + } + .group-hover\:text-blue-700 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + color: var(--color-blue-700); + } + } + } .group-hover\:text-orange-500 { &:is(:where(.group):hover *) { @media (hover: hover) { @@ -2134,6 +2357,20 @@ } } } + .group-hover\:text-orange-600 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + color: var(--color-orange-600); + } + } + } + .group-hover\:text-orange-700 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + color: var(--color-orange-700); + } + } + } .group-hover\:opacity-100 { &:is(:where(.group):hover *) { @media (hover: hover) { @@ -2175,6 +2412,13 @@ } } } + .hover\:border-blue-200 { + &:hover { + @media (hover: hover) { + border-color: var(--color-blue-200); + } + } + } .hover\:border-orange-200 { &:hover { @media (hover: hover) { @@ -2259,6 +2503,13 @@ } } } + .hover\:bg-slate-50 { + &:hover { + @media (hover: hover) { + background-color: var(--color-slate-50); + } + } + } .hover\:bg-white\/10 { &:hover { @media (hover: hover) { @@ -2279,6 +2530,30 @@ } } } + .hover\:bg-gradient-to-br { + &:hover { + @media (hover: hover) { + --tw-gradient-position: to bottom right in oklab; + background-image: linear-gradient(var(--tw-gradient-stops)); + } + } + } + .hover\:from-blue-50 { + &:hover { + @media (hover: hover) { + --tw-gradient-from: var(--color-blue-50); + --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\:from-orange-50 { + &:hover { + @media (hover: hover) { + --tw-gradient-from: var(--color-orange-50); + --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\:from-orange-600 { &:hover { @media (hover: hover) { @@ -2287,6 +2562,22 @@ } } } + .hover\:to-indigo-100 { + &:hover { + @media (hover: hover) { + --tw-gradient-to: var(--color-indigo-100); + --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-orange-100 { + &:hover { + @media (hover: hover) { + --tw-gradient-to: var(--color-orange-100); + --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-orange-500 { &:hover { @media (hover: hover) { @@ -2346,6 +2637,22 @@ } } } + .hover\:shadow-md { + &:hover { + @media (hover: hover) { + --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + } + } + .hover\:shadow-xl { + &:hover { + @media (hover: hover) { + --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + } + } .focus\:border-orange-500 { &:focus { border-color: var(--color-orange-500); @@ -2680,11 +2987,27 @@ transform: rotate(360deg); } } +@keyframes ping { + 75%, 100% { + transform: scale(2); + opacity: 0; + } +} @keyframes pulse { 50% { opacity: 0.5; } } +@keyframes bounce { + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8, 0, 1, 1); + } + 50% { + transform: none; + animation-timing-function: cubic-bezier(0, 0, 0.2, 1); + } +} @layer properties { @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { *, ::before, ::after, ::backdrop {