kinda working
This commit is contained in:
parent
8b6ea946bf
commit
b3ded91d01
13
README.md
13
README.md
@ -8,6 +8,19 @@
|
||||
|
||||
## Start Dev
|
||||
|
||||
### Beim ersten Start
|
||||
|
||||
Config file erstellen bzw kopieren
|
||||
|
||||
1. `cd web/api/inc`
|
||||
2. Datei `example.config.inc.php` umbenennen auf `config.inc.php`
|
||||
3. Gegebenenfalls Werte anpassen in der Config
|
||||
|
||||
Composer sachen holen
|
||||
|
||||
1. `cd web/api/inc`
|
||||
2. `composer install`
|
||||
|
||||
### Linux
|
||||
|
||||
Erst Tailwind starten
|
||||
|
2
web/api/inc/.gitignore
vendored
Normal file
2
web/api/inc/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
vendor
|
||||
config.inc.php
|
113
web/api/inc/classes/Page.class.php
Normal file
113
web/api/inc/classes/Page.class.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* Page is the Controller Class
|
||||
* which should be extended by any page
|
||||
*
|
||||
* @author Christian Haschek
|
||||
*/
|
||||
class Page
|
||||
{
|
||||
protected $_controller;
|
||||
protected $_action;
|
||||
protected $_template;
|
||||
public $variables;
|
||||
public $params;
|
||||
public $render;
|
||||
public $menu_text;
|
||||
public $menu_image;
|
||||
public $menu_priority;
|
||||
public $submenu;
|
||||
|
||||
function __construct($controller, $action, $r = 1, $params = [])
|
||||
{
|
||||
$this->_controller = $controller;
|
||||
$this->_action = $action;
|
||||
$this->render = $r;
|
||||
$this->submenu = array();
|
||||
$this->setMenu();
|
||||
$this->params = $params;
|
||||
if(is_array($GLOBALS['vars']) && is_array($this->params))
|
||||
$this->params = array_merge($this->params, $GLOBALS['vars']);
|
||||
$this->menu_image = '/css/imgs/empty.png';
|
||||
}
|
||||
|
||||
function setMenu()
|
||||
{
|
||||
$this->menu_text = '';
|
||||
$this->menu_priority = 1;
|
||||
}
|
||||
|
||||
function redirect($url)
|
||||
{
|
||||
header("Location: $url");
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* override this function to check if a user can use this object
|
||||
* @return true -> user will be able to access
|
||||
* @return false -> user will not be able to access and this page won't
|
||||
* be shown in the menu
|
||||
*
|
||||
*/
|
||||
public function maySeeThisPage()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function set($name, $value)
|
||||
{
|
||||
$this->variables[$name] = $value;
|
||||
}
|
||||
|
||||
function get($name)
|
||||
{
|
||||
return $this->variables[$name];
|
||||
}
|
||||
|
||||
function __destruct()
|
||||
{
|
||||
// if($this->render)
|
||||
// $this->_template->render();
|
||||
}
|
||||
|
||||
function addHelpers($m)
|
||||
{
|
||||
$m->addHelper('case', [
|
||||
'lower' => function($value) { return strtolower((string) $value); },
|
||||
'upper' => function($value) { return strtoupper((string) $value); }
|
||||
]);
|
||||
$m->addHelper('!!', function($value) { return $value . '!!'; });
|
||||
|
||||
return $m;
|
||||
}
|
||||
|
||||
function renderPagecontent()
|
||||
{
|
||||
$controller_dir = ROOT . DS . 'pages' . DS . $this->_controller . DS;
|
||||
$partials = [];
|
||||
if(is_dir($controller_dir.'partials'))
|
||||
$partials[] = new Mustache_Loader_FilesystemLoader($controller_dir.'partials');
|
||||
$partials[] = new Mustache_Loader_FilesystemLoader(ROOT.DS.'..'.DS.'templates'.DS.'partials');
|
||||
$m = new Mustache_Engine(array(
|
||||
'entity_flags' => ENT_QUOTES,
|
||||
'partials_loader' => new Mustache_Loader_CascadingLoader($partials)
|
||||
));
|
||||
|
||||
$this->variables['translate'] = function($value) { return translate($value); };
|
||||
|
||||
$m = $this->addHelpers($m);
|
||||
|
||||
if($this->variables['template'] && file_exists(ROOT . DS . 'pages' . DS . $this->_controller . DS . $this->variables['template']))
|
||||
$template = file_get_contents(ROOT . DS . 'pages' . DS . $this->_controller . DS . $this->variables['template']);
|
||||
else
|
||||
$template = file_get_contents(ROOT . DS . 'views' . DS . 'defaultcontainer.mustache');
|
||||
|
||||
|
||||
$pagecontent = $m->render($template, $this->variables);
|
||||
|
||||
return $pagecontent;
|
||||
}
|
||||
}
|
5
web/api/inc/composer.json
Normal file
5
web/api/inc/composer.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"mustache/mustache": "^2.14"
|
||||
}
|
||||
}
|
69
web/api/inc/composer.lock
generated
Normal file
69
web/api/inc/composer.lock
generated
Normal file
@ -0,0 +1,69 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e982fabf51f3a80b1d9fcbcdb4621616",
|
||||
"packages": [
|
||||
{
|
||||
"name": "mustache/mustache",
|
||||
"version": "v2.14.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bobthecow/mustache.php.git",
|
||||
"reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/e62b7c3849d22ec55f3ec425507bf7968193a6cb",
|
||||
"reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "~1.11",
|
||||
"phpunit/phpunit": "~3.7|~4.0|~5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Mustache": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Justin Hileman",
|
||||
"email": "justin@justinhileman.info",
|
||||
"homepage": "http://justinhileman.com"
|
||||
}
|
||||
],
|
||||
"description": "A Mustache implementation in PHP.",
|
||||
"homepage": "https://github.com/bobthecow/mustache.php",
|
||||
"keywords": [
|
||||
"mustache",
|
||||
"templating"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/bobthecow/mustache.php/issues",
|
||||
"source": "https://github.com/bobthecow/mustache.php/tree/v2.14.2"
|
||||
},
|
||||
"time": "2022-08-23T13:07:01+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.2.0"
|
||||
}
|
72
web/api/inc/core.php
Normal file
72
web/api/inc/core.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
spl_autoload_register('autoload');
|
||||
function autoload($className)
|
||||
{
|
||||
//one of the global classes?
|
||||
if (file_exists(ROOT . DS . 'inc'. DS. 'classes' . DS . $className . '.class.php'))
|
||||
require_once(ROOT . DS . 'inc'. DS. 'classes' . DS . $className . '.class.php');
|
||||
else if (file_exists(ROOT . DS . 'pages' . DS . strtolower($className) . DS . 'controller.php'))
|
||||
require_once(ROOT . DS . 'pages' . DS . strtolower($className) . DS . 'controller.php');
|
||||
}
|
||||
|
||||
function includeManagement()
|
||||
{
|
||||
require_once(ROOT.DS.'inc'.DS.'helpers.php');
|
||||
require_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
|
||||
//settings from config
|
||||
if(defined('DEV') && DEV===true)
|
||||
ini_set("display_errors", 1);
|
||||
else ini_set("display_errors", 0);
|
||||
|
||||
if(file_exists(ROOT.DS.'inc'.DS.'vendor'.DS.'autoload.php'))
|
||||
require_once(ROOT.DS.'inc'.DS.'vendor'.DS.'autoload.php');
|
||||
}
|
||||
|
||||
function callHook($url)
|
||||
{
|
||||
$queryString = array();
|
||||
|
||||
if (!$url[0]) {
|
||||
$component = 'home';
|
||||
$action = 'index';
|
||||
} else {
|
||||
$urlArray = $url;
|
||||
$component = $urlArray[0];
|
||||
array_shift($urlArray);
|
||||
$params = $urlArray;
|
||||
if (isset($urlArray[0])) {
|
||||
$action = $urlArray[0];
|
||||
array_shift($urlArray);
|
||||
} else
|
||||
$action = 'index'; // Default Action
|
||||
$queryString = $urlArray;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!file_exists(ROOT . DS . 'pages' . DS . $component . DS . 'controller.php')) {
|
||||
$component = 'err';
|
||||
$action = 'notfound';
|
||||
$queryString = array($url);
|
||||
}
|
||||
|
||||
$componentName = ucfirst($component);
|
||||
|
||||
$dispatch = new $componentName($component, $action, false);
|
||||
|
||||
if (!$dispatch->maySeeThisPage()) {
|
||||
$componentName = 'err';
|
||||
$action = 'notallowed';
|
||||
$dispatch = new $componentName('error', $action, true);
|
||||
} else
|
||||
$dispatch = new $componentName($component, $action, true, $queryString);
|
||||
|
||||
if (method_exists($componentName, $action)) {
|
||||
call_user_func_array(array($dispatch, $action), $queryString);
|
||||
} else if (method_exists($componentName, 'catchAll'))
|
||||
call_user_func_array(array($dispatch, 'catchAll'), array($params));
|
||||
|
||||
return $dispatch->renderPagecontent();
|
||||
}
|
2
web/api/inc/example.config.inc.php
Normal file
2
web/api/inc/example.config.inc.php
Normal file
@ -0,0 +1,2 @@
|
||||
<?php
|
||||
|
170
web/api/inc/helpers.php
Normal file
170
web/api/inc/helpers.php
Normal file
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
function sendMail($rcpt,$subject,$markdown)
|
||||
{
|
||||
$mail = new PHPMailer();
|
||||
$pd = new Parsedown();
|
||||
|
||||
$html = $pd->text($markdown);
|
||||
|
||||
ob_start();
|
||||
|
||||
$mail->CharSet ="UTF-8";
|
||||
$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
|
||||
$mail->isSMTP(); // Send using SMTP
|
||||
$mail->Host = SMTP_HOST; // Set the SMTP server to send through
|
||||
$mail->SMTPAuth = (defined('SMTP_AUTH')?SMTP_AUTH:true); // Enable SMTP authentication
|
||||
$mail->Username = SMTP_USER; // SMTP username
|
||||
$mail->Password = SMTP_PW; // SMTP password
|
||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
|
||||
$mail->Port = (defined('SMTP_PORT')?SMTP_PORT:587); // TCP port to connect to
|
||||
if(defined('SMTP_EHLO_DOMAIN') && SMTP_EHLO_DOMAIN)
|
||||
$mail->Hostname = SMTP_EHLO_DOMAIN;
|
||||
|
||||
//make sure we use ipv4
|
||||
$mail->SMTPOptions = [
|
||||
'socket' => [
|
||||
'bindto' => "0:0",
|
||||
],
|
||||
];
|
||||
|
||||
//Recipients
|
||||
$mail->setFrom(EMAIL_FROM_EMAIL, EMAIL_FROM_NAME);
|
||||
$mail->addAddress($rcpt); // Add a recipient
|
||||
|
||||
// Content
|
||||
$mail->isHTML(true); // Set email format to HTML
|
||||
$mail->Subject = $subject;
|
||||
$mail->Body = $html;
|
||||
$mail->AltBody = $markdown;
|
||||
|
||||
$mail->send();
|
||||
|
||||
$output = ob_get_clean();
|
||||
|
||||
addToMailLog($rcpt,$subject,$output);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
// found on https://html-online.com/articles/php-get-ip-cloudflare-proxy/
|
||||
function getUserIP() {
|
||||
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
|
||||
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
|
||||
$_SERVER['HTTP_CLIENT_IP'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
|
||||
}
|
||||
$client = @$_SERVER['HTTP_CLIENT_IP'];
|
||||
$forward = @$_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
$remote = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
if(filter_var($client, FILTER_VALIDATE_IP)) { $ip = $client; }
|
||||
elseif(filter_var($forward, FILTER_VALIDATE_IP)) { $ip = $forward; }
|
||||
else { $ip = $remote; }
|
||||
|
||||
return $ip;
|
||||
}
|
||||
|
||||
|
||||
// from https://stackoverflow.com/a/834355/1174516
|
||||
function startsWith( $haystack, $needle ) {
|
||||
$length = strlen( $needle );
|
||||
return substr( $haystack, 0, $length ) === $needle;
|
||||
}
|
||||
function endsWith( $haystack, $needle ) {
|
||||
$length = strlen( $needle );
|
||||
if( !$length ) {
|
||||
return true;
|
||||
}
|
||||
return substr( $haystack, -$length ) === $needle;
|
||||
}
|
||||
|
||||
function is_cli()
|
||||
{
|
||||
if ( defined('STDIN') )
|
||||
return true;
|
||||
if ( php_sapi_name() === 'cli' )
|
||||
return true;
|
||||
if ( array_key_exists('SHELL', $_ENV) )
|
||||
return true;
|
||||
if ( empty($_SERVER['REMOTE_ADDR']) and !isset($_SERVER['HTTP_USER_AGENT']) and count($_SERVER['argv']) > 0)
|
||||
return true;
|
||||
if ( !array_key_exists('REQUEST_METHOD', $_SERVER) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function addToLog($text,$module='general')
|
||||
{
|
||||
$fp = fopen(ROOT.DS.'..'.DS.'log'.DS.$module.'.log','a');
|
||||
fwrite($fp,'['.date("y.m.d H:i").']'.$text.PHP_EOL);
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
function addToMailLog($rcpt,$subject,$response)
|
||||
{
|
||||
$rcpt_esc = str_replace('@','_at_',$rcpt);
|
||||
$dir = ROOT.DS.'..'.DS.'log'.DS.'maillog';
|
||||
if(!is_dir($dir))
|
||||
mkdir($dir);
|
||||
$fp = fopen($dir.DS.$rcpt_esc.'.log','a');
|
||||
fwrite($fp,"========= NEW MAIL ========\n[".date("y.m.d H:i")."] To: $rcpt\nSubject: $subject\n\n$response\n\n");
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
function translate($what)
|
||||
{
|
||||
$what = trim($what);
|
||||
return ($GLOBALS['translations'][$what]?:$what);
|
||||
}
|
||||
|
||||
function getFilesOfFolder($dir)
|
||||
{
|
||||
return array_diff(scandir($dir), array('.', '..'));
|
||||
}
|
||||
|
||||
function dbNeedsToBeUpgraded()
|
||||
{
|
||||
if(DB_TYPE=='sqlite' && !file_exists(ROOT.DS.'..'.DS.'data'.DS.'db.sqlite3'))
|
||||
return true;
|
||||
else if(!file_exists(ROOT.DS.'..'.DS.'log'.DS.'db_version'))
|
||||
return true;
|
||||
else if($GLOBALS['db_version']<getHighestSQLVersion())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getHighestSQLVersion()
|
||||
{
|
||||
$dir = ROOT.DS.'..'.DS.'sql'.DS;
|
||||
$files = array_diff(scandir($dir), array('..', '.'));
|
||||
$files = array_map(function($e){
|
||||
return pathinfo($e, PATHINFO_FILENAME);
|
||||
}, $files);
|
||||
|
||||
sort($files);
|
||||
|
||||
return end($files);
|
||||
}
|
||||
|
||||
function gen_uuid() {
|
||||
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
// 32 bits for "time_low"
|
||||
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
|
||||
|
||||
// 16 bits for "time_mid"
|
||||
mt_rand( 0, 0xffff ),
|
||||
|
||||
// 16 bits for "time_hi_and_version",
|
||||
// four most significant bits holds version number 4
|
||||
mt_rand( 0, 0x0fff ) | 0x4000,
|
||||
|
||||
// 16 bits, 8 bits for "clk_seq_hi_res",
|
||||
// 8 bits for "clk_seq_low",
|
||||
// two most significant bits holds zero and one for variant DCE1.1
|
||||
mt_rand( 0, 0x3fff ) | 0x8000,
|
||||
|
||||
// 48 bits for "node"
|
||||
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
|
||||
);
|
||||
}
|
33
web/api/index.php
Normal file
33
web/api/index.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
define('ROOT', dirname(__FILE__));
|
||||
|
||||
// if(file_exists(ROOT.DS.'inc'.DS.'config.inc.php'))
|
||||
// include_once(ROOT.DS.'inc'.DS.'config.inc.php');
|
||||
// else die('ERR: no config file found :(');
|
||||
|
||||
include_once(ROOT.DS.'inc'.DS.'core.php');
|
||||
includeManagement();
|
||||
|
||||
if($_GET['url'])
|
||||
$url = explode('/',ltrim(parse_url($_GET['url'], PHP_URL_PATH),'/'));
|
||||
else if($_SERVER['HTTP_HX_CURRENT_URL'])
|
||||
$url = explode('/',ltrim(parse_url($_SERVER['HTTP_HX_CURRENT_URL'], PHP_URL_PATH),'/'));
|
||||
else $url = array_filter(explode('/',ltrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH),'/')));
|
||||
|
||||
if(count($url) > 0 && ($url[0]=='api' || $url[0]=='backend'))
|
||||
array_shift($url);
|
||||
|
||||
//echo print_r(['url'=>$url,'server'=>$_SERVER,'request'=>$_REQUEST,'cookie'=>$_COOKIE,'session'=>$_SESSION],true);
|
||||
|
||||
|
||||
$response = callHook($url);
|
||||
|
||||
if(is_string($response))
|
||||
echo $response;
|
||||
else if(is_array($response))
|
||||
echo json_encode($response);
|
||||
else if(is_object($response))
|
||||
echo json_encode($response);
|
||||
else echo json_encode(['error'=>'unknown response type']);
|
19
web/api/pages/home/controller.php
Normal file
19
web/api/pages/home/controller.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
class Home extends Page
|
||||
{
|
||||
function setMenu()
|
||||
{
|
||||
$this->menu_text = 'home';
|
||||
$this->menu_image = 'mdi-action-home';
|
||||
$this->menu_priority = 0;
|
||||
}
|
||||
|
||||
function index()
|
||||
{
|
||||
$this->set('template', "home.mustache");
|
||||
return $this->renderPagecontent();
|
||||
}
|
||||
|
||||
function maySeeThisPage(){return true;}
|
||||
}
|
20
web/api/pages/home/home.mustache
Normal file
20
web/api/pages/home/home.mustache
Normal file
@ -0,0 +1,20 @@
|
||||
<div class="hidden sm:mb-8 sm:flex sm:justify-center">
|
||||
<div
|
||||
class="relative rounded-full px-3 py-1 text-sm leading-6 text-gray-600 ring-1 ring-gray-900/10 hover:ring-gray-900/20">
|
||||
Announcing our next round of funding. <a href="#" class="font-semibold text-indigo-600"><span
|
||||
class="absolute inset-0" aria-hidden="true"></span>Read more <span
|
||||
aria-hidden="true">→</span></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h1 class="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">Dogstats - der Agilityhelfer</h1>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-600">Anim aute id magna aliqua ad ad non deserunt sunt.
|
||||
Qui irure qui lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.</p>
|
||||
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||
<a href="#"
|
||||
class="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Get
|
||||
started</a>
|
||||
<a href="#" class="text-sm font-semibold leading-6 text-gray-900">Learn more <span
|
||||
aria-hidden="true">→</span></a>
|
||||
</div>
|
||||
</div>
|
@ -534,27 +534,622 @@ video {
|
||||
--tw-backdrop-sepia: ;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.absolute {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inset-0 {
|
||||
inset: 0px;
|
||||
}
|
||||
|
||||
.inset-x-0 {
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.inset-y-0 {
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.-top-40 {
|
||||
top: -10rem;
|
||||
}
|
||||
|
||||
.left-\[calc\(50\%\+3rem\)\] {
|
||||
left: calc(50% + 3rem);
|
||||
}
|
||||
|
||||
.left-\[calc\(50\%-11rem\)\] {
|
||||
left: calc(50% - 11rem);
|
||||
}
|
||||
|
||||
.right-0 {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.top-0 {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.top-\[calc\(100\%-13rem\)\] {
|
||||
top: calc(100% - 13rem);
|
||||
}
|
||||
|
||||
.isolate {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.-z-10 {
|
||||
z-index: -10;
|
||||
}
|
||||
|
||||
.z-50 {
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.-m-1 {
|
||||
margin: -0.25rem;
|
||||
}
|
||||
|
||||
.-m-1\.5 {
|
||||
margin: -0.375rem;
|
||||
}
|
||||
|
||||
.-m-2 {
|
||||
margin: -0.5rem;
|
||||
}
|
||||
|
||||
.-m-2\.5 {
|
||||
margin: -0.625rem;
|
||||
}
|
||||
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.-mx-3 {
|
||||
margin-left: -0.75rem;
|
||||
margin-right: -0.75rem;
|
||||
}
|
||||
|
||||
.-my-6 {
|
||||
margin-top: -1.5rem;
|
||||
margin-bottom: -1.5rem;
|
||||
}
|
||||
|
||||
.mt-10 {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
|
||||
.mt-6 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.mb-2 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.mb-6 {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.ml-3 {
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.mr-2 {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.inline-flex {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.table {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.flow-root {
|
||||
display: flow-root;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.aspect-\[1155\/678\] {
|
||||
aspect-ratio: 1155/678;
|
||||
}
|
||||
|
||||
.h-24 {
|
||||
height: 6rem;
|
||||
}
|
||||
|
||||
.h-6 {
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.h-8 {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.h-12 {
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
.h-4 {
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.h-5 {
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.w-24 {
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.w-6 {
|
||||
width: 1.5rem;
|
||||
}
|
||||
|
||||
.w-\[36\.125rem\] {
|
||||
width: 36.125rem;
|
||||
}
|
||||
|
||||
.w-auto {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.w-12 {
|
||||
width: 3rem;
|
||||
}
|
||||
|
||||
.w-4 {
|
||||
width: 1rem;
|
||||
}
|
||||
|
||||
.w-8 {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.max-w-2xl {
|
||||
max-width: 42rem;
|
||||
}
|
||||
|
||||
.max-w-sm {
|
||||
max-width: 24rem;
|
||||
}
|
||||
|
||||
.shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.-translate-x-1\/2 {
|
||||
--tw-translate-x: -50%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.rotate-\[30deg\] {
|
||||
--tw-rotate: 30deg;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.transform-gpu {
|
||||
transform: translate3d(var(--tw-translate-x), var(--tw-translate-y), 0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.items-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.gap-x-6 {
|
||||
-moz-column-gap: 1.5rem;
|
||||
column-gap: 1.5rem;
|
||||
}
|
||||
|
||||
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(1rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-x-reverse: 0;
|
||||
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
||||
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
|
||||
.divide-y > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-divide-y-reverse: 0;
|
||||
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
||||
border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
|
||||
}
|
||||
|
||||
.divide-gray-500\/10 > :not([hidden]) ~ :not([hidden]) {
|
||||
border-color: rgb(107 114 128 / 0.1);
|
||||
}
|
||||
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.overflow-y-auto {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.rounded-full {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.rounded-xl {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.rounded-lg {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-md {
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.border {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.border-gray-300 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.bg-slate-100 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(241 245 249 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-indigo-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(79 70 229 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-white {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gray-50 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.bg-gradient-to-tr {
|
||||
background-image: linear-gradient(to top right, var(--tw-gradient-stops));
|
||||
}
|
||||
|
||||
.from-\[\#ff80b5\] {
|
||||
--tw-gradient-from: #ff80b5 var(--tw-gradient-from-position);
|
||||
--tw-gradient-to: rgb(255 128 181 / 0) var(--tw-gradient-to-position);
|
||||
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
||||
}
|
||||
|
||||
.to-\[\#9089fc\] {
|
||||
--tw-gradient-to: #9089fc var(--tw-gradient-to-position);
|
||||
}
|
||||
|
||||
.p-8 {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.p-1 {
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
.p-1\.5 {
|
||||
padding: 0.375rem;
|
||||
}
|
||||
|
||||
.p-2 {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.p-2\.5 {
|
||||
padding: 0.625rem;
|
||||
}
|
||||
|
||||
.p-6 {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.px-3 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
|
||||
.px-3\.5 {
|
||||
padding-left: 0.875rem;
|
||||
padding-right: 0.875rem;
|
||||
}
|
||||
|
||||
.px-6 {
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
|
||||
.py-1 {
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.py-2\.5 {
|
||||
padding-top: 0.625rem;
|
||||
padding-bottom: 0.625rem;
|
||||
}
|
||||
|
||||
.py-32 {
|
||||
padding-top: 8rem;
|
||||
padding-bottom: 8rem;
|
||||
}
|
||||
|
||||
.py-6 {
|
||||
padding-top: 1.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.px-5 {
|
||||
padding-left: 1.25rem;
|
||||
padding-right: 1.25rem;
|
||||
}
|
||||
|
||||
.py-8 {
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.py-5 {
|
||||
padding-top: 1.25rem;
|
||||
padding-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.pt-6 {
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
|
||||
.pt-14 {
|
||||
padding-top: 3.5rem;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-3xl {
|
||||
font-size: 1.875rem;
|
||||
line-height: 2.25rem;
|
||||
}
|
||||
|
||||
.text-lg {
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
.text-4xl {
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
|
||||
.text-base {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
.text-sm {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
.text-xl {
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
.text-2xl {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.font-semibold {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.font-light {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.leading-6 {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
.leading-7 {
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
.leading-8 {
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.leading-tight {
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.tracking-tight {
|
||||
letter-spacing: -0.025em;
|
||||
}
|
||||
|
||||
.text-sky-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(14 165 233 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-slate-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(51 65 85 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-600 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(75 85 99 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-700 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(55 65 81 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-900 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-indigo-600 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(79 70 229 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-black {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(0 0 0 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-slate-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(100 116 139 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-gray-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(107 114 128 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.underline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.opacity-30 {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-lg {
|
||||
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow {
|
||||
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
|
||||
.ring-1 {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.ring-gray-900\/10 {
|
||||
--tw-ring-color: rgb(17 24 39 / 0.1);
|
||||
}
|
||||
|
||||
.blur-3xl {
|
||||
--tw-blur: blur(64px);
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
@ -570,3 +1165,269 @@ video {
|
||||
.\[a-zA-Z\:\\-\\\.\] {
|
||||
a-z-a--z: \-\.;
|
||||
}
|
||||
|
||||
.hover\:bg-gray-50:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:bg-indigo-500:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(99 102 241 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.hover\:underline:hover {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.hover\:ring-gray-900\/20:hover {
|
||||
--tw-ring-color: rgb(17 24 39 / 0.2);
|
||||
}
|
||||
|
||||
.focus\:outline-none:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.focus\:ring-4:focus {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.focus-visible\:outline:focus-visible {
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
.focus-visible\:outline-2:focus-visible {
|
||||
outline-width: 2px;
|
||||
}
|
||||
|
||||
.focus-visible\:outline-offset-2:focus-visible {
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.focus-visible\:outline-indigo-600:focus-visible {
|
||||
outline-color: #4f46e5;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.dark\:border {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.dark\:border-gray-600 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(75 85 99 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:border-gray-700 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(55 65 81 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-slate-800 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(30 41 59 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-gray-700 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-gray-800 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:bg-gray-900 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-sky-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(56 189 248 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-slate-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(100 116 139 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-gray-300 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(209 213 219 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-gray-400 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.dark\:placeholder-gray-400::-moz-placeholder {
|
||||
--tw-placeholder-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
|
||||
}
|
||||
|
||||
.dark\:placeholder-gray-400::placeholder {
|
||||
--tw-placeholder-opacity: 1;
|
||||
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
|
||||
}
|
||||
|
||||
.dark\:ring-offset-gray-800 {
|
||||
--tw-ring-offset-color: #1f2937;
|
||||
}
|
||||
|
||||
.dark\:focus\:border-blue-500:focus {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(59 130 246 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.dark\:focus\:ring-blue-500:focus {
|
||||
--tw-ring-opacity: 1;
|
||||
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.sm\:-top-80 {
|
||||
top: -20rem;
|
||||
}
|
||||
|
||||
.sm\:left-\[calc\(50\%\+36rem\)\] {
|
||||
left: calc(50% + 36rem);
|
||||
}
|
||||
|
||||
.sm\:left-\[calc\(50\%-30rem\)\] {
|
||||
left: calc(50% - 30rem);
|
||||
}
|
||||
|
||||
.sm\:top-\[calc\(100\%-30rem\)\] {
|
||||
top: calc(100% - 30rem);
|
||||
}
|
||||
|
||||
.sm\:mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.sm\:flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sm\:w-\[72\.1875rem\] {
|
||||
width: 72.1875rem;
|
||||
}
|
||||
|
||||
.sm\:max-w-sm {
|
||||
max-width: 24rem;
|
||||
}
|
||||
|
||||
.sm\:max-w-md {
|
||||
max-width: 28rem;
|
||||
}
|
||||
|
||||
.sm\:justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sm\:p-8 {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.sm\:py-48 {
|
||||
padding-top: 12rem;
|
||||
padding-bottom: 12rem;
|
||||
}
|
||||
|
||||
.sm\:text-6xl {
|
||||
font-size: 3.75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.sm\:text-sm {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
.sm\:ring-1 {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.sm\:ring-gray-900\/10 {
|
||||
--tw-ring-color: rgb(17 24 39 / 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.md\:mt-0 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.md\:h-screen {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.md\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.md\:text-2xl {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.lg\:flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.lg\:hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lg\:flex-1 {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
|
||||
.lg\:justify-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.lg\:gap-x-12 {
|
||||
-moz-column-gap: 3rem;
|
||||
column-gap: 3rem;
|
||||
}
|
||||
|
||||
.lg\:px-8 {
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.lg\:py-56 {
|
||||
padding-top: 14rem;
|
||||
padding-bottom: 14rem;
|
||||
}
|
||||
|
||||
.lg\:py-0 {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.xl\:p-0 {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
BIN
web/imgs/dogstats-50.png
Normal file
BIN
web/imgs/dogstats-50.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
web/imgs/dogstats.png
Normal file
BIN
web/imgs/dogstats.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 MiB |
117
web/index.html
117
web/index.html
@ -1,17 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<!-- Tailwind CSS -->
|
||||
<title>Dogstats</title>
|
||||
<link href="/css/output.css" rel="stylesheet">
|
||||
<!-- htmx -->
|
||||
<script src="/js/htmx.min"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="text-3xl font-bold underline">
|
||||
Hello world!
|
||||
</h1>
|
||||
</body>
|
||||
<script src="/js/htmx.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body></body>
|
||||
<div class="bg-white">
|
||||
<header class="absolute inset-x-0 top-0 z-50">
|
||||
<nav class="flex items-center justify-between p-6 lg:px-8" aria-label="Global">
|
||||
<div class="flex lg:flex-1">
|
||||
<a href="#" hx-get="/api" hx-target="#main" class="-m-1.5 p-1.5">
|
||||
<span class="sr-only">Dogstats</span>
|
||||
<img class="h-8 w-auto" src="/imgs/dogstats-50.png" alt="">
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex lg:hidden">
|
||||
<button type="button"
|
||||
class="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700">
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="hidden lg:flex lg:gap-x-12">
|
||||
<a href="#" hx-get="/templates/product.html" hx-target="#main" class="text-sm font-semibold leading-6 text-gray-900">Product</a>
|
||||
<a href="#" hx-get="/templates/features.html" hx-target="#main" class="text-sm font-semibold leading-6 text-gray-900">Features</a>
|
||||
</div>
|
||||
<div class="hidden lg:flex lg:flex-1 lg:justify-end">
|
||||
<a href="#" hx-get="/templates/login.html" hx-target="#main" class="text-sm font-semibold leading-6 text-gray-900">Log in <span
|
||||
aria-hidden="true">→</span></a>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- Mobile menu, show/hide based on menu open state. -->
|
||||
<div class="lg:hidden" role="dialog" aria-modal="true">
|
||||
<!-- Background backdrop, show/hide based on slide-over state. -->
|
||||
<div class="fixed inset-0 z-50"></div>
|
||||
<div
|
||||
class="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
|
||||
<div class="flex items-center justify-between">
|
||||
<a href="#" class="-m-1.5 p-1.5">
|
||||
<span class="sr-only">Dogstatsy</span>
|
||||
<img class="h-8 w-auto"
|
||||
src="/imgs/dogstats-50.png" alt="">
|
||||
</a>
|
||||
<button type="button" class="-m-2.5 rounded-md p-2.5 text-gray-700">
|
||||
<span class="sr-only">Close menu</span>
|
||||
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-6 flow-root">
|
||||
<div class="-my-6 divide-y divide-gray-500/10">
|
||||
<div class="space-y-2 py-6">
|
||||
<a href="#"
|
||||
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Product</a>
|
||||
<a href="#"
|
||||
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Features</a>
|
||||
</div>
|
||||
<div class="py-6">
|
||||
<a href="#"
|
||||
class="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Log
|
||||
in</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="relative isolate px-6 pt-14 lg:px-8">
|
||||
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||
aria-hidden="true">
|
||||
<div class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
|
||||
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)">
|
||||
</div>
|
||||
</div>
|
||||
<div id="main" hx-get="/api" hx-trigger="load" class="mx-auto max-w-2xl">
|
||||
<div class="hidden sm:mb-8 sm:flex sm:justify-center">
|
||||
<div
|
||||
class="relative rounded-full px-3 py-1 text-sm leading-6 text-gray-600 ring-1 ring-gray-900/10 hover:ring-gray-900/20">
|
||||
Announcing our next round of funding. <a href="#" class="font-semibold text-indigo-600"><span
|
||||
class="absolute inset-0" aria-hidden="true"></span>Read more <span
|
||||
aria-hidden="true">→</span></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<h1 class="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">Dogstats - der Agilityhelfer</h1>
|
||||
<p class="mt-6 text-lg leading-8 text-gray-600">Anim aute id magna aliqua ad ad non deserunt sunt.
|
||||
Qui irure qui lorem cupidatat commodo. Elit sunt amet fugiat veniam occaecat fugiat aliqua.</p>
|
||||
<div class="mt-10 flex items-center justify-center gap-x-6">
|
||||
<a href="#"
|
||||
class="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Get
|
||||
started</a>
|
||||
<a href="#" class="text-sm font-semibold leading-6 text-gray-900">Learn more <span
|
||||
aria-hidden="true">→</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</html>
|
1
web/templates/features.html
Normal file
1
web/templates/features.html
Normal file
@ -0,0 +1 @@
|
||||
soo many features prolly
|
36
web/templates/login.html
Normal file
36
web/templates/login.html
Normal file
@ -0,0 +1,36 @@
|
||||
<section class="">
|
||||
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
|
||||
<div class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
|
||||
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
|
||||
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
|
||||
Sign in to your account
|
||||
</h1>
|
||||
<form class="space-y-4 md:space-y-6" action="#">
|
||||
<div>
|
||||
<label for="email" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your email</label>
|
||||
<input type="email" name="email" id="email" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="name@company.com" required="">
|
||||
</div>
|
||||
<div>
|
||||
<label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Password</label>
|
||||
<input type="password" name="password" id="password" placeholder="••••••••" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-start">
|
||||
<div class="flex items-center h-5">
|
||||
<input id="remember" aria-describedby="remember" type="checkbox" class="w-4 h-4 border border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-primary-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-primary-600 dark:ring-offset-gray-800" required="">
|
||||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label for="remember" class="text-gray-500 dark:text-gray-300">Remember me</label>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="text-sm font-medium text-primary-600 hover:underline dark:text-primary-500">Forgot password?</a>
|
||||
</div>
|
||||
<button type="submit" class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">Sign in</button>
|
||||
<p class="text-sm font-light text-gray-500 dark:text-gray-400">
|
||||
Don’t have an account yet? <a href="#" class="font-medium text-primary-600 hover:underline dark:text-primary-500">Sign up</a>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
9
web/templates/product.html
Normal file
9
web/templates/product.html
Normal file
@ -0,0 +1,9 @@
|
||||
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
|
||||
<div class="shrink-0">
|
||||
<img class="h-12 w-12" src="/imgs/dogstats.png" alt="Logo">
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-xl font-medium text-black">Dogstats is super</div>
|
||||
<p class="text-slate-500">You have a new message!</p>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user