Compare commits
	
		
			9 Commits
		
	
	
		
			ac99d29109
			...
			5048abc3e6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						5048abc3e6
	
				 | 
					
					
						|||
| 
						
						
							
						
						afd34e9b4e
	
				 | 
					
					
						|||
| 
						
						
							
						
						a81ce8a922
	
				 | 
					
					
						|||
| 
						
						
							
						
						9d25befeba
	
				 | 
					
					
						|||
| 
						
						
							
						
						5d9f7e3997
	
				 | 
					
					
						|||
| 
						
						
							
						
						ecfae3e01a
	
				 | 
					
					
						|||
| 
						
						
							
						
						9e6c93ba95
	
				 | 
					
					
						|||
| 
						
						
							
						
						231dd959af
	
				 | 
					
					
						|||
| 
						
						
							
						
						5607425bde
	
				 | 
					
					
						
							
								
								
									
										30
									
								
								src/SECURITY.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/SECURITY.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<!-- AUTO-GENERATED, DO NOT EDIT! -->
 | 
				
			||||||
 | 
					<!-- Please edit the original at https://github.com/ory/meta/blob/master/templates/repository/common/SECURITY.md -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- START doctoc generated TOC please keep comment here to allow auto update -->
 | 
				
			||||||
 | 
					<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Security Policy](#security-policy)
 | 
				
			||||||
 | 
					  - [Supported Versions](#supported-versions)
 | 
				
			||||||
 | 
					  - [Reporting a Vulnerability](#reporting-a-vulnerability)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- END doctoc generated TOC please keep comment here to allow auto update -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Security Policy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Supported Versions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We release patches for security vulnerabilities. Which versions are eligible for
 | 
				
			||||||
 | 
					receiving such patches depends on the CVSS v3.0 Rating:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| CVSS v3.0 | Supported Versions                        |
 | 
				
			||||||
 | 
					| --------- | ----------------------------------------- |
 | 
				
			||||||
 | 
					| 9.0-10.0  | Releases within the previous three months |
 | 
				
			||||||
 | 
					| 4.0-8.9   | Most recent release                       |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Reporting a Vulnerability
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please report (suspected) security vulnerabilities to
 | 
				
			||||||
 | 
					**[security@ory.sh](mailto:security@ory.sh)**. You will receive a response from
 | 
				
			||||||
 | 
					us within 48 hours. If the issue is confirmed, we will release a patch as soon
 | 
				
			||||||
 | 
					as possible depending on complexity but historically within a few days.
 | 
				
			||||||
@@ -2,19 +2,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Models\Traits;
 | 
					namespace App\Models\Traits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Casts\Attribute;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
trait FormattedPhoneTrait
 | 
					trait FormattedPhoneTrait
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Format a phone number to be human readable.
 | 
					     * Format a phone number to be human readable.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 | 
					     * @package Namespace\App\Contact
 | 
				
			||||||
     * @since   1.0.0
 | 
					     * @since   1.0.0
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return string
 | 
					     * @return void
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getPhoneNumberAttribute(): string
 | 
					    protected function phoneNumber(): Attribute
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $phoneLength = strlen($this->phone);
 | 
					        return Attribute::make(
 | 
				
			||||||
        $phoneNumber = preg_replace('//', '', $this->phone);
 | 
					            get: function (mixed $value, array $attributes) {
 | 
				
			||||||
 | 
					                $phoneLength = strlen($attributes['phone_number']);
 | 
				
			||||||
 | 
					                $phoneNumber = preg_replace('/[^0-9]/', '', $attributes['phone_number']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ($phoneLength > 10) {
 | 
					                if ($phoneLength > 10) {
 | 
				
			||||||
                    $countryCode = substr($phoneNumber, 0, $phoneLength - 10);
 | 
					                    $countryCode = substr($phoneNumber, 0, $phoneLength - 10);
 | 
				
			||||||
@@ -37,19 +42,10 @@ trait FormattedPhoneTrait
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return $phoneNumber;
 | 
					                return $phoneNumber;
 | 
				
			||||||
    }
 | 
					            },
 | 
				
			||||||
 | 
					            set: function (mixed $value) {
 | 
				
			||||||
    /**
 | 
					                return preg_replace('/[^0-9]/', '', $value);
 | 
				
			||||||
     * Remove all non-numeric characters from the phone number.
 | 
					            },
 | 
				
			||||||
     *
 | 
					        );
 | 
				
			||||||
     * @since 1.0.0
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param string $value
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return void
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function setPhoneNumberAttribute($value): void
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->attributes['phone'] = preg_replace('/[^0-9]/', '', $value);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										88
									
								
								src/app/Models/Traits/HasProfilePhoto.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/app/Models/Traits/HasProfilePhoto.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Laravel\Jetstream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Casts\Attribute;
 | 
				
			||||||
 | 
					use Illuminate\Http\UploadedFile;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trait HasProfilePhoto
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Update the user's profile photo.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param  \Illuminate\Http\UploadedFile  $photo
 | 
				
			||||||
 | 
					     * @param  string  $storagePath
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function updateProfilePhoto(UploadedFile $photo, $storagePath = 'profile-photos')
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        tap($this->profile_photo_path, function ($previous) use ($photo, $storagePath) {
 | 
				
			||||||
 | 
					            $this->forceFill([
 | 
				
			||||||
 | 
					                'profile_photo_path' => $photo->storePublicly(
 | 
				
			||||||
 | 
					                    $storagePath, ['disk' => $this->profilePhotoDisk()]
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            ])->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($previous) {
 | 
				
			||||||
 | 
					                Storage::disk($this->profilePhotoDisk())->delete($previous);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Delete the user's profile photo.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function deleteProfilePhoto()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! Features::managesProfilePhotos()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (is_null($this->profile_photo_path)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Storage::disk($this->profilePhotoDisk())->delete($this->profile_photo_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->forceFill([
 | 
				
			||||||
 | 
					            'profile_photo_path' => null,
 | 
				
			||||||
 | 
					        ])->save();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the URL to the user's profile photo.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return \Illuminate\Database\Eloquent\Casts\Attribute
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function profilePhotoUrl(): Attribute
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Attribute::get(function () {
 | 
				
			||||||
 | 
					            return $this->profile_photo_path
 | 
				
			||||||
 | 
					                    ? Storage::disk($this->profilePhotoDisk())->url($this->profile_photo_path)
 | 
				
			||||||
 | 
					                    : $this->defaultProfilePhotoUrl();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the default profile photo URL if no profile photo has been uploaded.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected function defaultProfilePhotoUrl()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return 'https://avatars.test/avatar?size=256';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the disk that profile photos should be stored on.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected function profilePhotoDisk()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return isset($_ENV['VAPOR_ARTIFACT_NAME']) ? 's3' : config('jetstream.profile_photo_disk', 'public');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -30,6 +30,9 @@
 | 
				
			|||||||
        "torann/geoip": "", // support for multiple GeoIP services
 | 
					        "torann/geoip": "", // support for multiple GeoIP services
 | 
				
			||||||
        "coderjerk/nasa-php": "", // NASA API integrations
 | 
					        "coderjerk/nasa-php": "", // NASA API integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // File management
 | 
				
			||||||
 | 
					        "czim/laravel-paperclip": "", // attach files to an Eloquent model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Media (image/video/audio) Management
 | 
					        // Media (image/video/audio) Management
 | 
				
			||||||
        "intervention/image": "", // image manipulation
 | 
					        "intervention/image": "", // image manipulation
 | 
				
			||||||
        "intervention/imagecache": "", // caching for intervention/image
 | 
					        "intervention/imagecache": "", // caching for intervention/image
 | 
				
			||||||
@@ -37,6 +40,7 @@
 | 
				
			|||||||
        "spatie/laravel-image-optimizer": "", // optimize png, jpg, svg, and gif
 | 
					        "spatie/laravel-image-optimizer": "", // optimize png, jpg, svg, and gif
 | 
				
			||||||
        "unisharp/laravel-filemanager": "", // File manager (including uploads)
 | 
					        "unisharp/laravel-filemanager": "", // File manager (including uploads)
 | 
				
			||||||
        "pbmedia/laravel-ffmpeg": "", // Integration with FFMpeg
 | 
					        "pbmedia/laravel-ffmpeg": "", // Integration with FFMpeg
 | 
				
			||||||
 | 
					        "maestroerror/php-heic-to-jpg": "", // Use Go(?) to convert HEIC/HEIF to JPEG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Localization
 | 
					        // Localization
 | 
				
			||||||
        "mcamara/laravel-localization": "", // localization that also handles route translations
 | 
					        "mcamara/laravel-localization": "", // localization that also handles route translations
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ use App\Models\Language;
 | 
				
			|||||||
use App\Models\Team;
 | 
					use App\Models\Team;
 | 
				
			||||||
use App\Models\User;
 | 
					use App\Models\User;
 | 
				
			||||||
use Illuminate\Database\Eloquent\Factories\Factory;
 | 
					use Illuminate\Database\Eloquent\Factories\Factory;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
use Illuminate\Support\Str;
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
use Laravel\Jetstream\Features;
 | 
					use Laravel\Jetstream\Features;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -71,4 +72,25 @@ class UserFactory extends Factory
 | 
				
			|||||||
            'ownedTeams'
 | 
					            'ownedTeams'
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Indicate that the user should have an avatar image.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return $this
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function withAvatar()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (! Features::enabled(Features::profilePhotos())) {
 | 
				
			||||||
 | 
					            return $this->state([]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $imageUrl = 'https://avatars.test/';
 | 
				
			||||||
 | 
					        $imageContents = file_get_contents($imageUrl);
 | 
				
			||||||
 | 
					        $imageName = md5($imageContents) . '.jpg';
 | 
				
			||||||
 | 
					        Storage::put("public/avatars/{$imageName}", $imageContents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $this->state([
 | 
				
			||||||
 | 
					            'profile_photo_path' => "avatars/{$imageName}"
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,30 @@
 | 
				
			|||||||
@import 'components/navbars.css';
 | 
					@import 'components/navbars.css';
 | 
				
			||||||
@import 'components/pagination.css';
 | 
					@import 'components/pagination.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:root {
 | 
				
			||||||
 | 
					    --primary-text-color: hsl(0, 90.4%, 59.2%);
 | 
				
			||||||
 | 
					    --primary-text-color-gradient-start: hsl(270, 66.9%, 47.5%);
 | 
				
			||||||
 | 
					    --primary-text-color-gradient-end: hsl(330, 100%, 50%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    --text-info-color: hsl(191, 82%, 50%);
 | 
				
			||||||
 | 
					    --text-info-color-gradient-start: hsl(227, 100%, 56.5%);
 | 
				
			||||||
 | 
					    --text-info-color-gradient-end: hsl(191, 98.2%, 56.1%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    --text-success-color: hsl(86, 81.4%, 46.3%);
 | 
				
			||||||
 | 
					    --text-success-color-gradient-start: hsl(133, 76.5%, 38.4%);
 | 
				
			||||||
 | 
					    --text-success-color-gradient-end: hsl(72, 81.1%, 52.4%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    --text-warning-color: hsl(47, 96.2%, 59.2%);
 | 
				
			||||||
 | 
					    --text-warning-color-gradient-start: hsl(0, 90.4%, 59.2%);
 | 
				
			||||||
 | 
					    --text-warning-color-gradient-end: hsl(47, 96.2%, 59.2%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    --text-danger-color: hsl(0, 95%, 47.1%);
 | 
				
			||||||
 | 
					    --text-danger-color-gradient-start: hsl(0, 92.8%, 43.5%);
 | 
				
			||||||
 | 
					    --text-danger-color-gradient-end: hsl(344, 100%, 70%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
body {
 | 
					body {
 | 
				
			||||||
 | 
					    background-image: linear-gradient(100deg, hsl(0, 0%, 98%), hsl(240, 5.9%, 90%));
 | 
				
			||||||
    color: hsl(240, 5.9%, 10%);
 | 
					    color: hsl(240, 5.9%, 10%);
 | 
				
			||||||
    /*color: lch(8.35%, 2.25, 285.92);*/
 | 
					    /*color: lch(8.35%, 2.25, 285.92);*/
 | 
				
			||||||
    -webkit-font-smoothing: antialiased;
 | 
					    -webkit-font-smoothing: antialiased;
 | 
				
			||||||
@@ -50,6 +73,16 @@ nav {
 | 
				
			|||||||
    user-select: none;
 | 
					    user-select: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					img {
 | 
				
			||||||
 | 
					    max-width: 100%;
 | 
				
			||||||
 | 
					    height: auto;
 | 
				
			||||||
 | 
					    vertical-align: middle;
 | 
				
			||||||
 | 
					    font-style: italic;
 | 
				
			||||||
 | 
					    background-repeat: no-repeat;
 | 
				
			||||||
 | 
					    background-size: cover;
 | 
				
			||||||
 | 
					    shape-margin: 0.75rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media (max-width: 1023px) {
 | 
					@media (max-width: 1023px) {
 | 
				
			||||||
    .grid-container {
 | 
					    .grid-container {
 | 
				
			||||||
        @apply grid-cols-1;
 | 
					        @apply grid-cols-1;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										106
									
								
								src/resources/css/elements/glossy-buttons.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/resources/css/elements/glossy-buttons.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					.container {
 | 
				
			||||||
 | 
					    display: grid;
 | 
				
			||||||
 | 
					    gap: 4em 1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.primary-button {
 | 
				
			||||||
 | 
					    --h: 196;
 | 
				
			||||||
 | 
					    --s: 100%;
 | 
				
			||||||
 | 
					    --l: 41%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.secondary-button {
 | 
				
			||||||
 | 
					    --h: 28;
 | 
				
			||||||
 | 
					    --s: 100%;
 | 
				
			||||||
 | 
					    --l: 41%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.glass-button {
 | 
				
			||||||
 | 
					    font-size: clamp(1.2rem, 5vw + 1rem, 2.5rem);
 | 
				
			||||||
 | 
					    width: 10em;
 | 
				
			||||||
 | 
					    height: 4em;
 | 
				
			||||||
 | 
					    border-radius: 0.5em;
 | 
				
			||||||
 | 
					    background-image: linear-gradient(#0003,#0000);
 | 
				
			||||||
 | 
					    box-shadow:
 | 
				
			||||||
 | 
					          0 -0.125em 0.25em #0002,
 | 
				
			||||||
 | 
					          0 0.25em 0.25em hsl(var(--h) var(--s) var(--l) / 0.5),
 | 
				
			||||||
 | 
					          0 0 0 0.1em hsl(var(--h) var(--s) var(--l) / 0.5),
 | 
				
			||||||
 | 
					          0 0.175em 0.3em hsl(var(--h) var(--s) var(--l) / 0.5) inset,
 | 
				
			||||||
 | 
					          0 -0.025em 0.175em hsl(var(--h) var(--s) var(--l) / 0.4) inset,
 | 
				
			||||||
 | 
					          0 -0.25em 1em 0.3em hsl(var(--h) var(--s) var(--l) / 0.3) inset,
 | 
				
			||||||
 | 
					          0 0.6em 0 hsl(var(--h) var(--s) var(--l) / 0.3) inset,
 | 
				
			||||||
 | 
					          0 2em 1em #0004;
 | 
				
			||||||
 | 
					    backdrop-filter: blur(0.15em);
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    display: grid;
 | 
				
			||||||
 | 
					    place-content: center;
 | 
				
			||||||
 | 
					    color: hsl(var(--h) var(--s) var(--l) / .7);
 | 
				
			||||||
 | 
					    text-shadow: 
 | 
				
			||||||
 | 
					      0.03em 0.03em #fff5,
 | 
				
			||||||
 | 
					      -0.03em -0.03em #0005;
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    transition: 0.1s ease;
 | 
				
			||||||
 | 
					    padding-top: 0.2em;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					    background: transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.glass-button:before {
 | 
				
			||||||
 | 
					    content: '';
 | 
				
			||||||
 | 
					    height: 1.5em;
 | 
				
			||||||
 | 
					    left: 10%;
 | 
				
			||||||
 | 
					    top: 100%;
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    width: 80%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.glass-button:after {
 | 
				
			||||||
 | 
					    content: '';
 | 
				
			||||||
 | 
					    inset: 0;
 | 
				
			||||||
 | 
					    top: 0.5em;
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    background-image: 
 | 
				
			||||||
 | 
					      linear-gradient(
 | 
				
			||||||
 | 
					        105deg,
 | 
				
			||||||
 | 
					        transparent 20%,
 | 
				
			||||||
 | 
					        hsl(var(--h) var(--s) var(--l) / .2) 20%,
 | 
				
			||||||
 | 
					        hsl(var(--h) var(--s) var(--l) / .2) 30%,
 | 
				
			||||||
 | 
					        transparent 30%,
 | 
				
			||||||
 | 
					        transparent 32%,
 | 
				
			||||||
 | 
					        hsl(var(--h) var(--s) var(--l) / .2) 5%,
 | 
				
			||||||
 | 
					        hsl(var(--h) var(--s) var(--l) / .2) 40%,
 | 
				
			||||||
 | 
					        transparent 0%
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    background-size: 400% 100%;
 | 
				
			||||||
 | 
					    background-position: 100% 0%;
 | 
				
			||||||
 | 
					    transition: .3s ease;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.glass-button:active:after {
 | 
				
			||||||
 | 
					    background-position: -50% 0%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.glass-button:active {
 | 
				
			||||||
 | 
					    backdrop-filter: blur(0.08em);
 | 
				
			||||||
 | 
					    box-shadow:
 | 
				
			||||||
 | 
					      0 -0.125em 0.25em #0002,
 | 
				
			||||||
 | 
					      0 0.25em 0.25em hsl(var(--h) var(--s) var(--l) / 0.5),
 | 
				
			||||||
 | 
					      0 0 0 0.1em hsl(var(--h) var(--s) var(--l) / 0.5),
 | 
				
			||||||
 | 
					      0 0.175em 0.3em hsl(var(--h) var(--s) var(--l) / 0.8) inset,
 | 
				
			||||||
 | 
					      0 -0.025em 0.175em hsl(var(--h) var(--s) var(--l) / 0.4) inset,
 | 
				
			||||||
 | 
					      0 -0.25em 1em 0.3em hsl(var(--h) var(--s) var(--l) / 0.3) inset,
 | 
				
			||||||
 | 
					      0 0.6em 0 hsl(var(--h) var(--s) var(--l) / 0.3) inset,
 | 
				
			||||||
 | 
					      0 1em 0.5em #0004;
 | 
				
			||||||
 | 
					    translate: .01em .25em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.glass-button:active:before {
 | 
				
			||||||
 | 
					    height: 1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*body {
 | 
				
			||||||
 | 
					    background-color: #3d3d3d;
 | 
				
			||||||
 | 
					    display: grid;
 | 
				
			||||||
 | 
					    margin: 0;
 | 
				
			||||||
 | 
					    min-height: 100vh;
 | 
				
			||||||
 | 
					    place-content: center;
 | 
				
			||||||
 | 
					}*/
 | 
				
			||||||
							
								
								
									
										45
									
								
								src/resources/css/typography/text-gradient.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/resources/css/typography/text-gradient.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					.text-gradient {
 | 
				
			||||||
 | 
					    background-clip: text;
 | 
				
			||||||
 | 
					    -webkit-background-clip: text;
 | 
				
			||||||
 | 
					    -webkit-text-fill-color: transparent;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    z-index: 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.text-gradient.text-primary {
 | 
				
			||||||
 | 
					    background-image: linear-gradient(310deg, var(--primary-text-color-gradient-start), var(--primary-text-color-gradient-end));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.text-primary {
 | 
				
			||||||
 | 
					    color: var(--primary-text-color);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.text-gradient.text-info {
 | 
				
			||||||
 | 
					    background-image: linear-gradient(310deg, var(--text-info-color-gradient-start), var(--text-info-color-gradient-end));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.text-info {
 | 
				
			||||||
 | 
					    color: var(--text-info-color);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.text-gradient.text-success {
 | 
				
			||||||
 | 
					    background-image: linear-gradient(310deg, var(--text-success-color-gradient-start), var(--text-success-color-gradient-end));
 | 
				
			||||||
 | 
					    color: hsl(86, 81.4%, 46.3%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.text-success {
 | 
				
			||||||
 | 
					    color: var(--text-success-color);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.text-gradient.text-warning {
 | 
				
			||||||
 | 
					    background-image: linear-gradient(310deg, var(--text-warning-color-gradient-start), var(--text-warning-color-gradient-end));
 | 
				
			||||||
 | 
					    color: hsl(47, 96.2%, 59.2%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.text-warning {
 | 
				
			||||||
 | 
					    color: var(--text-warning-color);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.text-gradient.text-danger {
 | 
				
			||||||
 | 
					    background-image: linear-gradient(310deg, var(--text-danger-color-gradient-start), var(--text-danger-color-gradient-end));
 | 
				
			||||||
 | 
					    color: hsl(0, 95%, 47.1%);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.text-danger {
 | 
				
			||||||
 | 
					    color: var(--text-danger-color);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,30 @@
 | 
				
			|||||||
.button-row {
 | 
					.button-row {
 | 
				
			||||||
    @apply inline-grid grid-flow-col auto-cols-max items-center; /* intentionally leaving gap out so that it can be set on per-case basis */
 | 
					    @apply inline-grid grid-flow-col auto-cols-max items-center; /* intentionally leaving gap out so that it can be set on per-case basis */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .gradBorder i {
 | 
				
			||||||
 | 
					  content: '';
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  z-index: -1;
 | 
				
			||||||
 | 
					  inset: 0;
 | 
				
			||||||
 | 
					  border-radius: 30px;
 | 
				
			||||||
 | 
					  padding: 1.5px; /* the thickness of the border */
 | 
				
			||||||
 | 
					  /* the below will do the magic */
 | 
				
			||||||
 | 
					  mask:
 | 
				
			||||||
 | 
					    linear-gradient(#fff 0 0) content-box,
 | 
				
			||||||
 | 
					    /* this will cover only the content area (no padding) */
 | 
				
			||||||
 | 
					      linear-gradient(#fff 0 0); /* this will cover all the area */
 | 
				
			||||||
 | 
					  -webkit-mask-composite: xor; /* needed for old browsers until the below is more supported */
 | 
				
			||||||
 | 
					  mask-composite: exclude; /* this will exclude the first layer from the second so only the padding area will be kept visible */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.gradBorder i::before {
 | 
				
			||||||
 | 
					  content: '';
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  background: linear-gradient(180deg, #ffffff73 0%, #ffffff10 50%);
 | 
				
			||||||
 | 
					  transition: transform 0.7s linear;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user