chore/tailwind-conversion #32
@@ -1,5 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
	"useTabs": true,
 | 
			
		||||
	"useTabs": false,
 | 
			
		||||
	"tabWidth": 4,
 | 
			
		||||
	"singleQuote": true,
 | 
			
		||||
	"trailingComma": "none",
 | 
			
		||||
	"printWidth": 100,
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@
 | 
			
		||||
	"type": "module",
 | 
			
		||||
	"dependencies": {
 | 
			
		||||
		"@tailwindcss/vite": "^4.1.6",
 | 
			
		||||
		"svelte-toasts": "^1.1.2",
 | 
			
		||||
		"tailwindcss": "^4.1.6"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@@ -11,6 +11,9 @@ importers:
 | 
			
		||||
      '@tailwindcss/vite':
 | 
			
		||||
        specifier: ^4.1.6
 | 
			
		||||
        version: 4.1.6(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))
 | 
			
		||||
      svelte-toasts:
 | 
			
		||||
        specifier: ^1.1.2
 | 
			
		||||
        version: 1.1.2
 | 
			
		||||
      tailwindcss:
 | 
			
		||||
        specifier: ^4.1.6
 | 
			
		||||
        version: 4.1.6
 | 
			
		||||
@@ -789,6 +792,9 @@ packages:
 | 
			
		||||
      svelte: ^4.0.0 || ^5.0.0-next.0
 | 
			
		||||
      typescript: '>=5.0.0'
 | 
			
		||||
 | 
			
		||||
  svelte-toasts@1.1.2:
 | 
			
		||||
    resolution: {integrity: sha512-m+yL4eEKXyJoyjTYaH1j1GFwF0Pi8YDqnVfwWPDmwi4712iZesv+TNCmToSNlav3R5Vkmc8ZBRkT8DOcu3sywQ==}
 | 
			
		||||
 | 
			
		||||
  svelte@5.28.2:
 | 
			
		||||
    resolution: {integrity: sha512-FbWBxgWOpQfhKvoGJv/TFwzqb4EhJbwCD17dB0tEpQiw1XyUEKZJtgm4nA4xq3LLsMo7hu5UY/BOFmroAxKTMg==}
 | 
			
		||||
    engines: {node: '>=18'}
 | 
			
		||||
@@ -1461,6 +1467,8 @@ snapshots:
 | 
			
		||||
    transitivePeerDependencies:
 | 
			
		||||
      - picomatch
 | 
			
		||||
 | 
			
		||||
  svelte-toasts@1.1.2: {}
 | 
			
		||||
 | 
			
		||||
  svelte@5.28.2:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@ampproject/remapping': 2.3.0
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
@import "tailwindcss";
 | 
			
		||||
@import "tailwindcss"
 | 
			
		||||
@@ -1,95 +0,0 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import { browser } from '$app/environment';
 | 
			
		||||
 | 
			
		||||
    export let darkMode: boolean = true;
 | 
			
		||||
 | 
			
		||||
    function onThemeSwitch() {
 | 
			
		||||
        darkMode = !darkMode;
 | 
			
		||||
 | 
			
		||||
        localStorage.setItem('theme', darkMode ? 'dark' : 'light');
 | 
			
		||||
 | 
			
		||||
        darkMode
 | 
			
		||||
            ? document.documentElement.classList.add('dark')
 | 
			
		||||
            : document.documentElement.classList.remove('dark');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    if (browser) {
 | 
			
		||||
        if (
 | 
			
		||||
            localStorage.theme === 'dark' ||
 | 
			
		||||
            (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
 | 
			
		||||
        ) {
 | 
			
		||||
            document.documentElement.classList.add('dark');
 | 
			
		||||
            darkMode = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            document.documentElement.classList.remove('dark');
 | 
			
		||||
            darkMode = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
    input {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .switch {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 0em;
 | 
			
		||||
        right: 0em;
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        width: 3.75em;
 | 
			
		||||
        height: 2.125em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .slider {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        background-color: var(--accent);
 | 
			
		||||
        top: 0;
 | 
			
		||||
        left: 0;
 | 
			
		||||
        right: 0;
 | 
			
		||||
        bottom: 0;
 | 
			
		||||
        background-color: var(--accent);
 | 
			
		||||
        -webkit-transition: .4s;
 | 
			
		||||
        transition: .4s;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .slider:before {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        content: "";
 | 
			
		||||
        height: 80%;
 | 
			
		||||
        width: 45%;
 | 
			
		||||
        left: 4px;
 | 
			
		||||
        bottom: 4px;
 | 
			
		||||
        background-color: var(--bg);
 | 
			
		||||
        -webkit-transition: .4s;
 | 
			
		||||
        transition: .4s;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    input:checked + .slider:before {
 | 
			
		||||
        -webkit-transform: translateX(1.625em);
 | 
			
		||||
        -ms-transform: translateX(1.625em);
 | 
			
		||||
        transform: translateX(1.625em);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .slider.round {
 | 
			
		||||
        border-radius: 2.125em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .slider.round:before {
 | 
			
		||||
        border-radius: 50%;
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<svelte:head>
 | 
			
		||||
    <link rel="stylesheet" href={`/themes/${darkMode ? 'dark' : 'light'}.css`} />
 | 
			
		||||
</svelte:head>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<div class="toggle-wrapper not-required">
 | 
			
		||||
    <label class="switch">
 | 
			
		||||
        <input type="checkbox" checked={darkMode} on:click={onThemeSwitch}>
 | 
			
		||||
        <span class="slider round"></span>
 | 
			
		||||
    </label>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
<script>
 | 
			
		||||
	export let width = "1em"
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
  width={width}
 | 
			
		||||
	style="text-align: center; display: inline-block;"
 | 
			
		||||
  aria-hidden="true"
 | 
			
		||||
  focusable="false"
 | 
			
		||||
  role="img"
 | 
			
		||||
  xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
  viewBox="0 0 352 512"
 | 
			
		||||
>
 | 
			
		||||
  <path
 | 
			
		||||
    fill="currentColor"
 | 
			
		||||
    d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"
 | 
			
		||||
  />
 | 
			
		||||
</svg>
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
<script>
 | 
			
		||||
	export let width = "1em"
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
  width={width}
 | 
			
		||||
	style="text-align: center; display: inline-block;"
 | 
			
		||||
  aria-hidden="true"
 | 
			
		||||
  focusable="false"
 | 
			
		||||
  role="img"
 | 
			
		||||
  xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
  viewBox="0 0 512 512"
 | 
			
		||||
>
 | 
			
		||||
  <path
 | 
			
		||||
    fill="currentColor"
 | 
			
		||||
    d="M256 40c118.621 0 216 96.075 216 216 0 119.291-96.61 216-216 216-119.244 0-216-96.562-216-216 0-119.203 96.602-216 216-216m0-32C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm-11.49 120h22.979c6.823 0 12.274 5.682 11.99 12.5l-7 168c-.268 6.428-5.556 11.5-11.99 11.5h-8.979c-6.433 0-11.722-5.073-11.99-11.5l-7-168c-.283-6.818 5.167-12.5 11.99-12.5zM256 340c-15.464 0-28 12.536-28 28s12.536 28 28 28 28-12.536 28-28-12.536-28-28-28z"
 | 
			
		||||
    class=""
 | 
			
		||||
  ></path>
 | 
			
		||||
</svg>
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
<script>
 | 
			
		||||
	export let width = "1em"
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
  width={width}
 | 
			
		||||
	style="text-align: center; display: inline-block;"
 | 
			
		||||
  aria-hidden="true"
 | 
			
		||||
  focusable="false"
 | 
			
		||||
  role="img"
 | 
			
		||||
  xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
  viewBox="0 0 512 512"
 | 
			
		||||
>
 | 
			
		||||
  <path
 | 
			
		||||
    fill="currentColor"
 | 
			
		||||
    d="M256 40c118.621 0 216 96.075 216 216 0 119.291-96.61 216-216 216-119.244 0-216-96.562-216-216 0-119.203 96.602-216 216-216m0-32C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm-36 344h12V232h-12c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h48c6.627 0 12 5.373 12 12v140h12c6.627 0 12 5.373 12 12v8c0 6.627-5.373 12-12 12h-72c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12zm36-240c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32z"
 | 
			
		||||
  />
 | 
			
		||||
</svg>
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
<script>
 | 
			
		||||
	export let width = "1em"
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<svg
 | 
			
		||||
  width={width}
 | 
			
		||||
	style="text-align: center; display: inline-block;"
 | 
			
		||||
  aria-hidden="true"
 | 
			
		||||
  focusable="false"
 | 
			
		||||
  role="img"
 | 
			
		||||
  xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
  viewBox="0 0 512 512"
 | 
			
		||||
>
 | 
			
		||||
  <path
 | 
			
		||||
    fill="currentColor"
 | 
			
		||||
    d="M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 464c-118.664 0-216-96.055-216-216 0-118.663 96.055-216 216-216 118.664 0 216 96.055 216 216 0 118.663-96.055 216-216 216zm141.63-274.961L217.15 376.071c-4.705 4.667-12.303 4.637-16.97-.068l-85.878-86.572c-4.667-4.705-4.637-12.303.068-16.97l8.52-8.451c4.705-4.667 12.303-4.637 16.97.068l68.976 69.533 163.441-162.13c4.705-4.667 12.303-4.637 16.97.068l8.451 8.52c4.668 4.705 4.637 12.303-.068 16.97z"
 | 
			
		||||
  />
 | 
			
		||||
</svg>
 | 
			
		||||
@@ -1,67 +0,0 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
  import { createEventDispatcher } from "svelte";
 | 
			
		||||
  import { fade } from "svelte/transition";
 | 
			
		||||
  import { Toast, ToastType } from "$lib/toast";
 | 
			
		||||
  import SuccessIcon from "./SuccessIcon.svelte";
 | 
			
		||||
  import ErrorIcon from "./ErrorIcon.svelte";
 | 
			
		||||
  import InfoIcon from "./InfoIcon.svelte";
 | 
			
		||||
  import CloseIcon from "./CloseIcon.svelte";
 | 
			
		||||
 | 
			
		||||
  const dispatch = createEventDispatcher();
 | 
			
		||||
 | 
			
		||||
  export let toastData: Toast;
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<article class={toastData.type.toString().toLowerCase()} role="alert" transition:fade>
 | 
			
		||||
  {#if toastData.type === ToastType.Success}
 | 
			
		||||
    <SuccessIcon width="1.1em" />
 | 
			
		||||
  {:else if toastData.type === ToastType.Error}
 | 
			
		||||
    <ErrorIcon width="1.1em" />
 | 
			
		||||
  {:else}
 | 
			
		||||
    <InfoIcon width="1.1em" />
 | 
			
		||||
  {/if}
 | 
			
		||||
 | 
			
		||||
  <div class="text">
 | 
			
		||||
    {toastData.text}
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  {#if toastData.dismissable}
 | 
			
		||||
    <button class="close" on:click={() => dispatch("dismiss")}>
 | 
			
		||||
      <CloseIcon width="0.8em" />
 | 
			
		||||
    </button>
 | 
			
		||||
  {/if}
 | 
			
		||||
</article>
 | 
			
		||||
 | 
			
		||||
<style lang="postcss">
 | 
			
		||||
  article {
 | 
			
		||||
    color: white;
 | 
			
		||||
    padding: 0.75rem 1.5rem;
 | 
			
		||||
    border-radius: 0.2rem;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    margin: 0 auto 0.5rem auto;
 | 
			
		||||
    width: 20rem;
 | 
			
		||||
    max-width: 80%;
 | 
			
		||||
  }
 | 
			
		||||
  .error {
 | 
			
		||||
    background: var(--red);
 | 
			
		||||
  }
 | 
			
		||||
  .success {
 | 
			
		||||
    background: var(--green);
 | 
			
		||||
  }
 | 
			
		||||
  .info {
 | 
			
		||||
    background: var(--blue);
 | 
			
		||||
  }
 | 
			
		||||
  .text {
 | 
			
		||||
    margin-left: 1rem;
 | 
			
		||||
  }
 | 
			
		||||
  .close {
 | 
			
		||||
    color: white;
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    border: 0 none;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    margin: 0 0 0 auto;
 | 
			
		||||
    line-height: 1;
 | 
			
		||||
    font-size: 1rem;
 | 
			
		||||
  }
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
  import Toast from "./Toast.svelte";
 | 
			
		||||
 | 
			
		||||
  import { dismissToast, toasts } from "$lib/stores";
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{#if $toasts}
 | 
			
		||||
  <section>
 | 
			
		||||
    {#each $toasts as toast (toast.id)}
 | 
			
		||||
      <Toast toastData = {toast} on:dismiss={() => dismissToast(toast.id)} />
 | 
			
		||||
    {/each}
 | 
			
		||||
  </section>
 | 
			
		||||
{/if}
 | 
			
		||||
 | 
			
		||||
<style lang="postcss">
 | 
			
		||||
  section {
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    margin-top: 1rem;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    z-index: 10;
 | 
			
		||||
  }
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	import { setContext } from 'svelte';
 | 
			
		||||
	import type { TimelinePosition, TimelineConfig } from '../types';
 | 
			
		||||
	import type { TimelinePosition, TimelineConfig } from '$lib/types';
 | 
			
		||||
	export let position: TimelinePosition = 'right';
 | 
			
		||||
	export let style: string = null;
 | 
			
		||||
	export let style: string | null = null;
 | 
			
		||||
 | 
			
		||||
	setContext<TimelineConfig>('TimelineConfig', { rootPosition: position });
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	import { getContext } from 'svelte';
 | 
			
		||||
	import type { TimelineConfig, TimelinePosition } from '../types';
 | 
			
		||||
	export let style: string = null;
 | 
			
		||||
	import type { TimelineConfig, TimelinePosition } from '$lib/types';
 | 
			
		||||
	export let style: string | null = null;
 | 
			
		||||
 | 
			
		||||
	const config = getContext<TimelineConfig>('TimelineConfig');
 | 
			
		||||
	const parentPosition = getContext<TimelinePosition>('ParentPosition');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	export let style: string = null;
 | 
			
		||||
	export let style: string | null = null;
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<span class="timeline-dot" {style}>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	import { getContext } from 'svelte';
 | 
			
		||||
	import type { TimelineConfig, TimelinePosition } from '../types';
 | 
			
		||||
	export let style: string = null;
 | 
			
		||||
	import type { TimelineConfig, TimelinePosition } from '$lib/types';
 | 
			
		||||
	export let style: string | null = null;
 | 
			
		||||
 | 
			
		||||
	const config = getContext<TimelineConfig>('TimelineConfig');
 | 
			
		||||
	const parentPosition = getContext<TimelinePosition>('ParentPosition');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	export let style: string = null;
 | 
			
		||||
	export let style: string | null = null;
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="timeline-separator" {style}>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										127
									
								
								src/main.svelte
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								src/main.svelte
									
									
									
									
									
								
							@@ -1,105 +1,48 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import { getJson } from "$lib/data";
 | 
			
		||||
	import { Toast, ToastType } from "$lib/toast";
 | 
			
		||||
    import { addToast } from "$lib/stores";
 | 
			
		||||
    import { getJson } from '$lib/data';
 | 
			
		||||
    import { toasts } from 'svelte-toasts';
 | 
			
		||||
 | 
			
		||||
    import Skills from './skills.svelte';
 | 
			
		||||
 | 
			
		||||
    import Timeline from "./timeline.svelte";
 | 
			
		||||
	import Loading from "$lib/components/Loading.svelte";
 | 
			
		||||
    import Loading from '$lib/components/Loading.svelte';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{#await getJson('/json/me.json')}
 | 
			
		||||
    <Loading />
 | 
			
		||||
{:then info}
 | 
			
		||||
    <div class="bg-secondary rounded-xl p-8 pb-12 shadow-lg mb-16">
 | 
			
		||||
        <div class="flex items-center justify-between mb-0">
 | 
			
		||||
            <h1 class="text-3xl font-bold">{info.name}</h1>
 | 
			
		||||
            <h3 class="not-required text-xl font-semibold">{info.job_title}</h3>
 | 
			
		||||
    <div style="display: none;">
 | 
			
		||||
        {toasts.add({
 | 
			
		||||
            title: 'Welcome',
 | 
			
		||||
            duration: 5000,
 | 
			
		||||
            type: 'success',
 | 
			
		||||
            placement: 'bottom-center',
 | 
			
		||||
            showProgress: true
 | 
			
		||||
        })}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="bg-slate-100/10 dark:bg-slate-100/10 p-10 m-5 rounded-2xl shadow-2xl">
 | 
			
		||||
        <div class="flex flex-row justify-between text-red-500 p-4">
 | 
			
		||||
            <p class="text-3xl md:text-4xl font-bold">
 | 
			
		||||
                {info.name}
 | 
			
		||||
            </p>
 | 
			
		||||
            <p class="max-md:hidden text-2xl md:text-3xl">{info.job_title}</p>
 | 
			
		||||
        </div>
 | 
			
		||||
        <hr class="my-4 border-accent" />
 | 
			
		||||
        <div class="flex items-center gap-8 flex-wrap md:flex-nowrap">
 | 
			
		||||
            <img class="rounded-full h-32 w-32 p-4 border-4 border-accent not-required" src={info.profile_photo} alt="{info.name}'s Profile Photo">
 | 
			
		||||
            <p class="about text-lg md:text-xl px-4 md:px-12 flex-1">{@html info.about}</p>
 | 
			
		||||
        <hr class="max-md:hidden border-3 m-5" />
 | 
			
		||||
        <div class="flex flex-row items-center gap-5 m-2">
 | 
			
		||||
            <img
 | 
			
		||||
                src={info.profile_photo}
 | 
			
		||||
                alt="Avatar"
 | 
			
		||||
                class="max-md:hidden rounded-full w-64 h-64 mt-5 mb-5 p-3 border-5"
 | 
			
		||||
            />
 | 
			
		||||
            <p>{@html info.about}</p>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    <div class="container mx-auto mb-12">
 | 
			
		||||
        <h1 class="text-2xl font-bold">Skills</h1>
 | 
			
		||||
        <hr class="my-2 border-accent" />
 | 
			
		||||
        <Skills skills={info.skills}></Skills>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="container mx-auto mb-12">
 | 
			
		||||
        <h1 class="text-2xl font-bold">Experience</h1>
 | 
			
		||||
        <hr class="my-2 border-accent" />
 | 
			
		||||
        <Timeline timelineData={info.timeline}></Timeline>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="hidden">{addToast(new Toast("Click on a skill to open a prompt", ToastType.Info, true, 8_000))}</div>
 | 
			
		||||
    <div class="hidden">{addToast(new Toast("Welcome!", ToastType.Success, true, 7_000))}</div>
 | 
			
		||||
{:catch}
 | 
			
		||||
    <div class="bg-secondary rounded-xl p-8 shadow-lg mb-8">
 | 
			
		||||
        <div class="flex items-center justify-between mb-0">
 | 
			
		||||
            <h1 class="text-3xl font-bold">Unable to load portfolio overview data</h1>
 | 
			
		||||
        </div>
 | 
			
		||||
    <div style="display: none;">
 | 
			
		||||
        {toasts.add({
 | 
			
		||||
            title: 'Error',
 | 
			
		||||
            description: 'There was an error loading static site data',
 | 
			
		||||
            duration: 0,
 | 
			
		||||
            placement: 'bottom-center',
 | 
			
		||||
            showProgress: true
 | 
			
		||||
        })}
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="hidden">{addToast(new Toast("Unable to load me.json", ToastType.Error, true, 3000))}</div>
 | 
			
		||||
{/await}
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
    .main-card {
 | 
			
		||||
        background-color: var(--bg-secondary);
 | 
			
		||||
        border-radius: 1em;
 | 
			
		||||
        padding: .2em 2em 2em 2em;
 | 
			
		||||
        box-shadow: .5em .5em .5em var(--glow);
 | 
			
		||||
        margin-bottom: 4em;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    .flex-container {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .profile {
 | 
			
		||||
        border-radius: 100%;
 | 
			
		||||
        height: 8em;
 | 
			
		||||
        width: 8em;
 | 
			
		||||
        padding: 1em 1em 1em 1em;
 | 
			
		||||
        border: .25em solid var(--accent);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    .about {
 | 
			
		||||
        padding: 0em 5% 0em 5%;
 | 
			
		||||
        font-size: 125%;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @media (max-width: 800px) {
 | 
			
		||||
        .flex-container {
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            flex-direction: column;
 | 
			
		||||
            padding: 0px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .about {
 | 
			
		||||
            font-size: 100%;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .card-header {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
        margin-bottom: 0em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .card-header h1 {
 | 
			
		||||
        font-size: 2em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .card-header h3 {
 | 
			
		||||
        font-size: 1.5em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,17 +1,23 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	import Toasts from "$lib/components/Toasts/Toasts.svelte";
 | 
			
		||||
    import ThemeSwitcher from "$lib/components/ThemeSwitcher.svelte";
 | 
			
		||||
    import "../app.css";
 | 
			
		||||
    import { ToastContainer, FlatToast } from 'svelte-toasts';
 | 
			
		||||
    import '../app.css';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<nav>
 | 
			
		||||
    <a href = "/">//Profile</a>
 | 
			
		||||
    <a href = "/repos">//Repos</a>
 | 
			
		||||
    <a href = "/contact">//Contact</a>
 | 
			
		||||
    <ThemeSwitcher />
 | 
			
		||||
</nav>
 | 
			
		||||
<div
 | 
			
		||||
    class="min-h-screen px-8 py-4 bg-white text-slate-600 dark:bg-slate-900/90 dark:text-slate-200/60 md:text-2xl sm:text-md font-mono flex flex-col gap-5 transition duration-1000 ease-in-out"
 | 
			
		||||
>
 | 
			
		||||
    <nav
 | 
			
		||||
        class="w-full px-8 py-4 flex gap-10 text-xl justify-center items-center text-green-600 font-semibold"
 | 
			
		||||
    >
 | 
			
		||||
        <a href="/" class="hover:underline">//Profile</a>
 | 
			
		||||
        <a href="/repos" class="hover:underline">//Repos</a>
 | 
			
		||||
        <a href="/contact" class="hover:underline">//Contact</a>
 | 
			
		||||
    </nav>
 | 
			
		||||
 | 
			
		||||
<div class="container mx-auto">
 | 
			
		||||
    <Toasts />
 | 
			
		||||
    <slot />
 | 
			
		||||
    <div class="container mx-auto justify-center items-center flex flex-col">
 | 
			
		||||
        <slot />
 | 
			
		||||
        <ToastContainer let:data>
 | 
			
		||||
            <FlatToast {data} />
 | 
			
		||||
        </ToastContainer>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,4 +2,6 @@
 | 
			
		||||
    import Main from '../main.svelte';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<Main></Main>
 | 
			
		||||
<div>
 | 
			
		||||
    <Main></Main>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -1,149 +1,14 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import Card from '$lib/components/Cards/Card.svelte';
 | 
			
		||||
    import { Toast, ToastType } from '$lib/toast';
 | 
			
		||||
    import { addToast } from '$lib/stores';
 | 
			
		||||
 | 
			
		||||
    import { page } from '$app/stores';
 | 
			
		||||
    const sent = $page.url.searchParams.get('sent');
 | 
			
		||||
 | 
			
		||||
    if (sent == 'true') {
 | 
			
		||||
        addToast(
 | 
			
		||||
            new Toast(
 | 
			
		||||
                'Thank you! Your E-Mail has been sent. I will reply as soon as possible!',
 | 
			
		||||
                ToastType.Success,
 | 
			
		||||
                true,
 | 
			
		||||
                5000
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    // Can't use else otherwise the warning will display on load
 | 
			
		||||
    if (sent == 'false') {
 | 
			
		||||
        addToast(
 | 
			
		||||
    new Toast(
 | 
			
		||||
        'Sorry, your E-Mail could not be sent... Please try again later!',
 | 
			
		||||
        ToastType.Error,
 | 
			
		||||
        true,
 | 
			
		||||
        5000
 | 
			
		||||
    )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    import { toasts } from 'svelte-toasts';
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<Card>
 | 
			
		||||
    <div slot="header">
 | 
			
		||||
        <h2>Contact</h2>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div slot="content">
 | 
			
		||||
        <form action="https://api.staticforms.xyz/submit" method="post" class="contact-form">
 | 
			
		||||
            <input type="hidden" name="accessKey" value="fbb5ec04-506b-448a-a445-a2e47579a966">
 | 
			
		||||
 | 
			
		||||
            <!-- Form Items-->
 | 
			
		||||
            <div class="input-group">
 | 
			
		||||
                <input type="text" id="name" name="name" required placeholder="Your Name" />
 | 
			
		||||
                <input type="email" id="email" name="email" required placeholder="Your Email" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="input-group">
 | 
			
		||||
                <input type="text" name="subject" placeholder="Subject" required>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="input-group">
 | 
			
		||||
                <textarea id="message" name="message" rows="4" required placeholder="Your Message"></textarea>
 | 
			
		||||
            </div>
 | 
			
		||||
            
 | 
			
		||||
            <!-- Hidden Attributes-->
 | 
			
		||||
            <input type="hidden" name="replyTo" value="@">
 | 
			
		||||
            <input type="text" name="honeypot" style="display: none;">
 | 
			
		||||
            <input type="hidden" name="redirectTo" value="https://luke-else.co.uk/contact?sent=true">
 | 
			
		||||
            
 | 
			
		||||
            <!-- reCAPTCHA integration -->
 | 
			
		||||
            <div class="input-group">
 | 
			
		||||
                <div class="g-recaptcha" data-sitekey="6LfjQAwrAAAAAIF57u8Wt4w5L5vBEWi5DfXXBuGy"></div>
 | 
			
		||||
                <script src="https://www.google.com/recaptcha/api.js" async defer></script>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="input-group">
 | 
			
		||||
                <button type="submit" class="submit-button">Send Message</button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div slot="footer">
 | 
			
		||||
        <a href="/Luke Else - CV.pdf" target="_blank" rel="noopener noreferrer">Curriculum Vitae</a>
 | 
			
		||||
        <a href="mailto:contact@luke-else.co.uk">E-Mail</a>
 | 
			
		||||
    </div>
 | 
			
		||||
</Card>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
 | 
			
		||||
    /* Contact form styling */
 | 
			
		||||
    .contact-form {
 | 
			
		||||
        background: none;
 | 
			
		||||
        padding: 1rem;
 | 
			
		||||
        width: 80%;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        gap: 1rem;
 | 
			
		||||
        transition: all 0.3s ease;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Input groups */
 | 
			
		||||
    .input-group {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: row;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        gap: 1rem;
 | 
			
		||||
        flex-wrap: wrap;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Input fields and textarea */
 | 
			
		||||
    .contact-form input,
 | 
			
		||||
    .contact-form textarea {
 | 
			
		||||
        padding: 0.8rem 1rem;
 | 
			
		||||
        border: 1px solid var(--fg);
 | 
			
		||||
        border-radius: 0.5rem;
 | 
			
		||||
        background: var(--input);
 | 
			
		||||
        color: var(--fg);
 | 
			
		||||
        font-size: 1rem;
 | 
			
		||||
        transition: border-color 0.3s ease, background 0.3s ease;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .contact-form button {
 | 
			
		||||
        border: 1px solid var(--fg);
 | 
			
		||||
        width: 60%;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .contact-form textarea {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        min-width: none;
 | 
			
		||||
        resize: vertical;
 | 
			
		||||
        min-height: fit-content;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .contact-form input:focus,
 | 
			
		||||
    .contact-form textarea:focus {
 | 
			
		||||
        border-color: var(--glow);
 | 
			
		||||
        outline: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Submit button */
 | 
			
		||||
    .submit-button {
 | 
			
		||||
        padding: 0.8rem 1rem;
 | 
			
		||||
        background: var(--accent);
 | 
			
		||||
        color: var(--fg);
 | 
			
		||||
        border: none;
 | 
			
		||||
        border-radius: 0.5rem;
 | 
			
		||||
        font-size: 1rem;
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        transition: background 0.3s ease;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .submit-button:hover {
 | 
			
		||||
        background: var(--link);
 | 
			
		||||
        color: var(--input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .g-recaptcha {
 | 
			
		||||
        width: fit-content;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
<div style="display: none;">
 | 
			
		||||
    {toasts.add({
 | 
			
		||||
        title: 'Warning',
 | 
			
		||||
        description: 'This page is under construction',
 | 
			
		||||
        duration: 0,
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
        placement: 'center-center',
 | 
			
		||||
        showProgress: true
 | 
			
		||||
    })}
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,64 +1,18 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import { onMount } from "svelte";
 | 
			
		||||
    import { Toast, ToastType } from "$lib/toast";
 | 
			
		||||
    import { repos, loadRepos, addToast } from "$lib/stores";
 | 
			
		||||
    import { timeSince, checkImage, IMAGE_URL_SUFFIX } from "$lib/api/git";
 | 
			
		||||
    import Card from "$lib/components/Cards/Card.svelte";
 | 
			
		||||
    import SlidingCard from "$lib/components/Cards/SlidingCard.svelte";
 | 
			
		||||
    import Loading from "$lib/components/Loading.svelte";
 | 
			
		||||
    import { loadRepos } from '$lib/stores';
 | 
			
		||||
    import { onMount } from 'svelte';
 | 
			
		||||
    import { toasts } from 'svelte-toasts';
 | 
			
		||||
 | 
			
		||||
    onMount(loadRepos);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<h1>My Projects</h1>
 | 
			
		||||
<p>This here is a list of my most recently worked on projects. Note this does not show any private repositories. For more in depth information <a href="https://git.luke-else.co.uk">Click Here</a>.</p>
 | 
			
		||||
 | 
			
		||||
<div class="container">
 | 
			
		||||
    {#if $repos.length > 0}
 | 
			
		||||
        <div style="display: none;">{addToast(new Toast("See a snapshot of my latest work.", ToastType.Info, true, 8_000))}</div>
 | 
			
		||||
        <div class="cards">
 | 
			
		||||
            {#each $repos as repo}
 | 
			
		||||
                {#await checkImage(repo)}
 | 
			
		||||
                    <Loading />
 | 
			
		||||
                {:then hasImage}
 | 
			
		||||
                    {#if hasImage}
 | 
			
		||||
                        <SlidingCard>
 | 
			
		||||
                            <div slot="header">
 | 
			
		||||
                                <h2>{repo.name}</h2>
 | 
			
		||||
                                {repo.language}
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div slot="content">
 | 
			
		||||
                                <p class="not-required">{@html repo.description}</p>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div slot="sliding-content">
 | 
			
		||||
                                <img width="100%" src="{repo.html_url}{IMAGE_URL_SUFFIX}" alt="{repo.name}" />
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div slot="footer">
 | 
			
		||||
                                <!-- svelte-ignore a11y-invalid-attribute -->
 | 
			
		||||
                                <a href="{repo.html_url}">{repo.name}</a>
 | 
			
		||||
                                {timeSince(repo.updated_at)}
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </SlidingCard>
 | 
			
		||||
                    {:else}
 | 
			
		||||
                        <Card>
 | 
			
		||||
                            <div slot="header">
 | 
			
		||||
                                <h2>{repo.name}</h2>
 | 
			
		||||
                                {repo.language}
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div slot="content">
 | 
			
		||||
                                <p class="not-required">{@html repo.description}</p>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div slot="footer">
 | 
			
		||||
                                <!-- svelte-ignore a11y-invalid-attribute -->
 | 
			
		||||
                                <a href="{repo.html_url}">{repo.name}</a>
 | 
			
		||||
                                {timeSince(repo.updated_at)}
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </Card>
 | 
			
		||||
                    {/if}
 | 
			
		||||
                {/await}
 | 
			
		||||
            {/each}
 | 
			
		||||
        </div>
 | 
			
		||||
    {:else}
 | 
			
		||||
        <Loading />
 | 
			
		||||
    {/if}
 | 
			
		||||
<div style="display: none;">
 | 
			
		||||
    {toasts.add({
 | 
			
		||||
        title: 'Warning',
 | 
			
		||||
        description: 'This page is under construction',
 | 
			
		||||
        duration: 0,
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
        placement: 'center-center',
 | 
			
		||||
        showProgress: true
 | 
			
		||||
    })}
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,63 +0,0 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    export let skills: any;
 | 
			
		||||
 | 
			
		||||
    import Card from '$lib/components/Cards/Card.svelte';
 | 
			
		||||
    import Modal from '$lib/components/Modal.svelte';
 | 
			
		||||
 | 
			
		||||
    let showModal: boolean = false;
 | 
			
		||||
    let activeModal: any = null;
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="flex flex-wrap gap-6 align-center justify-center">
 | 
			
		||||
    {#each skills as skill}
 | 
			
		||||
        <div class="w-full md:w-1/2 lg:w-1/3 bg-secondary">
 | 
			
		||||
                <Card on:click={() => {showModal = true; activeModal = skill}}>
 | 
			
		||||
                    <div slot="header">
 | 
			
		||||
                        <h2>{skill.skill}</h2>
 | 
			
		||||
                        <i class="{skill.logo} logo"></i>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div slot="content">
 | 
			
		||||
                        <p class="not-required">{@html skill.usage}</p>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div slot="footer">
 | 
			
		||||
                        <!-- svelte-ignore a11y-invalid-attribute -->
 | 
			
		||||
                        <a href="#">View More</a>
 | 
			
		||||
                        <a href="/repos">Repos</a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </Card>
 | 
			
		||||
        </div>
 | 
			
		||||
    {/each}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<!--Modal to be displayed on click-->
 | 
			
		||||
{#if activeModal != null}
 | 
			
		||||
    <Modal bind:showModal>
 | 
			
		||||
        <h2 slot="header" class="card-header">
 | 
			
		||||
            {activeModal.skill}
 | 
			
		||||
            <i class="{activeModal.logo} logo"></i>
 | 
			
		||||
        </h2>
 | 
			
		||||
 | 
			
		||||
        <p>
 | 
			
		||||
            {activeModal.about}
 | 
			
		||||
        </p>
 | 
			
		||||
 | 
			
		||||
        <div class="card-footer">
 | 
			
		||||
            <a href="{activeModal.link}" target="_blank" rel="noopener noreferrer">Learn More</a>
 | 
			
		||||
            <a href="/repos">Repos</a>
 | 
			
		||||
        </div>
 | 
			
		||||
    </Modal>
 | 
			
		||||
{/if}
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
    .card-footer {
 | 
			
		||||
        margin-bottom: 1em;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        gap: 1.5em;
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .logo {
 | 
			
		||||
        color: var(--fg);
 | 
			
		||||
        font-size: 3em;
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
:root {
 | 
			
		||||
    --bg: #f2f6f7; /* Soft blue-tinted white */
 | 
			
		||||
    --bg-secondary: #d7e1e4; /* Cool grey-blue */
 | 
			
		||||
    --accent: #92a9b0; /* Subtle blue-green */
 | 
			
		||||
 | 
			
		||||
    --header: #5d7075; /* Deep slate blue-green */
 | 
			
		||||
    --fg: #3c4649; /* Rich dark grey */
 | 
			
		||||
    
 | 
			
		||||
    --input: #e0e6e8; /* Light desaturated blue-grey */
 | 
			
		||||
    
 | 
			
		||||
    --link: #678d97; /* Muted sea blue */
 | 
			
		||||
    --glow: #b2c4c8; /* Gentle cool glow */
 | 
			
		||||
    --hover: #8fa7af; /* Soft grey-blue hover */
 | 
			
		||||
 | 
			
		||||
    --green: #78a890; /* Balanced green */
 | 
			
		||||
    --red: #e08c96; /* Soft dusty red */
 | 
			
		||||
    --blue: #729da5; /* Medium desaturated blue */
 | 
			
		||||
}
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
:root {
 | 
			
		||||
    --bg: #1e1f2a;
 | 
			
		||||
    --bg-secondary: #3a3f4b;
 | 
			
		||||
    --accent: #777f8d;
 | 
			
		||||
 | 
			
		||||
    --header: #cad1da;
 | 
			
		||||
    --fg: #e4e1db;
 | 
			
		||||
    
 | 
			
		||||
    --input: #2e3438;
 | 
			
		||||
    
 | 
			
		||||
    --link: #95add8;
 | 
			
		||||
    --glow: #bcc3ca;
 | 
			
		||||
    --hover: #cdd8e2;
 | 
			
		||||
 | 
			
		||||
    --green: #98C379;
 | 
			
		||||
    --red: #E06C75;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
:root {
 | 
			
		||||
    --bg: #2b2b2b; /* Dark but not too harsh */
 | 
			
		||||
    --bg-secondary: #3c3f41; /* Deep warm grey */
 | 
			
		||||
    --accent: #6897bb; /* Muted but clear blue */
 | 
			
		||||
 | 
			
		||||
    --header: #a9b7c6; /* Softer contrast */
 | 
			
		||||
    --fg: #bbbbbb; /* Light but not pure white */
 | 
			
		||||
    
 | 
			
		||||
    --input: #414141; /* Dark grey input */
 | 
			
		||||
    
 | 
			
		||||
    --link: #519aba; /* Soft coding blue */
 | 
			
		||||
    --glow: #4e5d68; /* Subtle bluish glow */
 | 
			
		||||
    --hover: #8c9da8; /* Brighter on hover */
 | 
			
		||||
 | 
			
		||||
    --green: #6a8759; /* Classic Darcula green */
 | 
			
		||||
    --red: #cc6666; /* Softer, warm red */
 | 
			
		||||
    --blue: #6897bb; /* Standard coding blue */
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
:root {
 | 
			
		||||
    --bg: #272822; /* Classic Monokai dark */
 | 
			
		||||
    --bg-secondary: #3e3d32; /* Darker olive grey */
 | 
			
		||||
    --accent: #f92672; /* Monokai’s signature pink-red */
 | 
			
		||||
 | 
			
		||||
    --header: #a6e22e; /* Neon green */
 | 
			
		||||
    --fg: #f8f8f2; /* Soft off-white */
 | 
			
		||||
    
 | 
			
		||||
    --input: #373831; /* Slightly lighter grey-green */
 | 
			
		||||
    
 | 
			
		||||
    --link: #66d9ef; /* Monokai cyan */
 | 
			
		||||
    --glow: #49483e; /* Muted background glow */
 | 
			
		||||
    --hover: #fd7c95; /* Lighter pink hover */
 | 
			
		||||
 | 
			
		||||
    --green: #a6e22e; /* Bright Monokai green */
 | 
			
		||||
    --red: #f92672; /* Soft pinkish-red */
 | 
			
		||||
    --blue: #66d9ef; /* Bright cyan */
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
:root {
 | 
			
		||||
    --bg: #1e1e1e; /* Dark neutral background */
 | 
			
		||||
    --bg-secondary: #252526; /* Slightly lighter for separation */
 | 
			
		||||
    --accent: #569cd6; /* Signature VS Code blue */
 | 
			
		||||
 | 
			
		||||
    --header: #9cdcfe; /* Brighter cyan for contrast */
 | 
			
		||||
    --fg: #d4d4d4; /* Light grey for readability */
 | 
			
		||||
    
 | 
			
		||||
    --input: #333; /* Dark but still visible */
 | 
			
		||||
    
 | 
			
		||||
    --link: #4fc1ff; /* Brighter blue for hyperlinks */
 | 
			
		||||
    --glow: #2a3f5f; /* Soft deep blue glow */
 | 
			
		||||
    --hover: #7bb8e8; /* Brighter accent on hover */
 | 
			
		||||
 | 
			
		||||
    --green: #4ec9b0; /* Soft green */
 | 
			
		||||
    --red: #d16969; /* Coding red */
 | 
			
		||||
    --blue: #9cdcfe; /* Soft bright cyan */
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								tailwind.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tailwind.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
  theme: {
 | 
			
		||||
    extend: {
 | 
			
		||||
      colors: {
 | 
			
		||||
        'one-bg':      '#282c34',
 | 
			
		||||
        'one-bg-light': '#3a3f4b',
 | 
			
		||||
        'one-fg':      '#abb2bf',
 | 
			
		||||
        'one-accent':  '#61afef',
 | 
			
		||||
        'one-green':   '#98c379',
 | 
			
		||||
        'one-orange':  '#d19a66',
 | 
			
		||||
        'one-red':     '#e06c75',
 | 
			
		||||
        'one-yellow':  '#e5c07b',
 | 
			
		||||
        'one-purple':  '#c678dd',
 | 
			
		||||
        'one-cyan':    '#56b6c2',
 | 
			
		||||
        'one-comment': '#5c6370',
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user