css: consolidate stylesheets into single source of truth
All checks were successful
CI / update (push) Successful in 1m29s

Merge nordtheme.css tokens and utility classes into app.css, import
app.css once in root layout, delete redundant files (nordtheme.css,
form.css, rosenkranz.css), move domain CSS to layouts, fix broken
shake keyframe in action_button.css, and scope form styles to the
two pages that need them. 10 CSS files → 6, 41 redundant imports removed.
This commit is contained in:
2026-02-15 22:26:22 +01:00
parent a435a1142f
commit 4191012cf1
47 changed files with 209 additions and 553 deletions

View File

@@ -109,6 +109,35 @@
--color-warning: var(--nord13);
--color-error: var(--nord11);
--color-info: var(--nord10);
/* Shared transitions & shadows */
--transition-fast: 100ms;
--transition-normal: 200ms;
--shadow-sm: 0 0 0.4em 0.05em rgba(0,0,0,0.2);
--shadow-md: 0 0 0.5em 0.1em rgba(0,0,0,0.3);
--shadow-lg: 0 0 1em 0.1em rgba(0,0,0,0.4);
--shadow-hover: 0.1em 0.1em 0.5em 0.1em rgba(0,0,0,0.3);
--radius-pill: 1000px;
--radius-card: 20px;
--radius-sm: 0.3rem;
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
/* Spacing scale */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 3rem;
/* Font size scale */
--text-sm: 0.85rem;
--text-base: 1rem;
--text-lg: 1.1rem;
--text-xl: 1.5rem;
--text-2xl: 2rem;
--text-3xl: 3rem;
}
/* ============================================
@@ -208,65 +237,110 @@ a:focus-visible {
color: var(--color-link-hover);
}
/* ============================================
FORM STYLES
GLOBAL UTILITY CLASSES
============================================ */
form {
background-color: var(--color-bg-secondary);
display: flex;
flex-direction: column;
max-width: 600px;
gap: 0.5em;
margin-inline: auto;
justify-content: center;
align-items: center;
padding-block: 2rem;
margin-block: 2rem;
}
form label {
font-size: 1.2em;
}
form input {
display: block;
font-size: 1.2rem;
}
form:not(.search) button {
background-color: var(--color-accent);
color: var(--color-text-on-accent);
/* Pill-shaped element base */
.g-pill {
border-radius: var(--radius-pill);
border: none;
padding: 0.5em 1em;
font-size: 1.3em;
border-radius: 1000px;
margin-top: 1em;
transition: 100ms;
cursor: pointer;
display: inline-block;
text-decoration: none;
transition: var(--transition-fast);
}
form:not(.search) button:hover,
form:not(.search) button:focus-visible {
background-color: var(--color-accent-hover);
scale: 1.1;
/* Interactive hover/focus effects */
.g-interactive {
transition: var(--transition-fast);
}
.g-interactive:hover,
.g-interactive:focus-visible {
transform: scale(1.05);
box-shadow: var(--shadow-hover);
}
.g-interactive:focus {
scale: 0.9;
}
form:not(.search) button:active {
background-color: var(--color-accent-active);
/* Light background button (with dark mode) */
.g-btn-light {
background-color: var(--nord5);
color: var(--nord0);
box-shadow: var(--shadow-sm);
}
form p {
max-width: 400px;
margin-top: 0;
}
form h4 {
margin-bottom: 0;
}
@media screen and (max-width: 600px) {
form {
margin-top: 0;
@media (prefers-color-scheme: dark) {
.g-btn-light {
background-color: var(--nord0);
color: white;
}
}
/* Dark background button */
.g-btn-dark,
.g-btn-dark:visited,
.g-btn-dark:link {
background-color: var(--nord0);
color: var(--nord6);
box-shadow: var(--shadow-lg);
}
.g-btn-dark:hover,
.g-btn-dark:focus-visible {
background-color: var(--nord1);
color: var(--nord6);
}
/* Icon badge (circular icon container) */
.g-icon-badge {
font-family: "Noto Color Emoji", emoji, sans-serif;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
text-decoration: none;
transition: var(--transition-fast);
box-shadow: var(--shadow-lg);
}
.g-icon-badge:hover,
.g-icon-badge:focus-visible {
transform: scale(1.1);
box-shadow: var(--shadow-hover);
}
/* Tag/chip styling */
.g-tag,
.g-tag:visited,
.g-tag:link {
font-size: 1.1rem;
padding: 0.25em 1em;
border-radius: var(--radius-pill);
background-color: var(--nord5);
color: var(--nord0);
text-decoration: none;
cursor: pointer;
transition: var(--transition-fast);
box-shadow: var(--shadow-sm);
border: none;
display: inline-block;
}
.g-tag:hover,
.g-tag:focus-visible {
transform: scale(1.05);
background-color: var(--nord8);
box-shadow: var(--shadow-hover);
color: var(--nord0);
}
@media (prefers-color-scheme: dark) {
.g-tag,
.g-tag:visited,
.g-tag:link {
background-color: var(--nord0);
color: white;
}
.g-tag:hover,
.g-tag:focus-visible {
color: var(--nord0);
}
}

View File

@@ -2,7 +2,6 @@
import type { Snippet } from 'svelte';
let { href, ariaLabel = undefined, children } = $props<{ href: string, ariaLabel?: string, children?: Snippet }>();
import "$lib/css/nordtheme.css"
import "$lib/css/action_button.css"
</script>

View File

@@ -1,5 +1,4 @@
<script lang="ts">
import "$lib/css/nordtheme.css"
import { onMount } from "svelte";
import { page } from '$app/stores';
import Symbol from "./Symbol.svelte"

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
let {
value = $bindable(''),

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
</script>
<style>
:root{

View File

@@ -1,6 +1,5 @@
<script lang="ts">
let { tag, ref } = $props<{ tag: string, ref: string }>();
import '$lib/css/nordtheme.css'
</script>
<style>
a{

View File

@@ -1,5 +1,4 @@
<script lang="ts">
import "$lib/css/nordtheme.css";
import "$lib/css/shake.css";
import "$lib/css/icon.css";
import { onMount } from "svelte";

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
import TagChip from '$lib/components/recipes/TagChip.svelte';
let {

View File

@@ -5,7 +5,6 @@ import Cross from '$lib/assets/icons/Cross.svelte'
import Plus from '$lib/assets/icons/Plus.svelte'
import Check from '$lib/assets/icons/Check.svelte'
import '$lib/css/nordtheme.css'
import "$lib/css/action_button.css"
import { do_on_key } from '$lib/components/recipes/do_on_key.js'

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
import Toggle from '$lib/components/Toggle.svelte';
let {

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
import CategoryFilter from './CategoryFilter.svelte';
import TagFilter from './TagFilter.svelte';
import IconFilter from './IconFilter.svelte';

View File

@@ -1,5 +1,4 @@
<script lang="ts">
import '$lib/css/nordtheme.css';
import "$lib/css/shake.css"
let { icon, ...restProps } = $props<{ icon: string, [key: string]: any }>();
</script>

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
import TagChip from '$lib/components/recipes/TagChip.svelte';
let {

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import '$lib/css/nordtheme.css';
import Recipes from '$lib/components/recipes/Recipes.svelte';
import Search from './Search.svelte';

View File

@@ -4,8 +4,6 @@ import { onNavigate } from "$app/navigation";
import { browser } from '$app/environment';
import { page } from '$app/stores';
import HefeSwapper from './HefeSwapper.svelte';
import '$lib/css/recipe-links.css';
let { data } = $props();
// Helper function to multiply numbers in ingredient amounts

View File

@@ -1,5 +1,4 @@
<script>
import '$lib/css/recipe-links.css';
let { data } = $props();
let multiplier = $state(data.multiplier || 1);

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
let {
useAndLogic = true,

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import "$lib/css/nordtheme.css"
let { title = '', children } = $props<{ title?: string, children?: Snippet }>();
</script>
<style>

View File

@@ -1,7 +1,6 @@
<script>
import {onMount} from "svelte";
import { browser } from '$app/environment';
import "$lib/css/nordtheme.css";
import FilterPanel from './FilterPanel.svelte';
import { getCategories } from '$lib/js/categories';

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
import TagChip from '$lib/components/recipes/TagChip.svelte';
let {

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import '$lib/css/nordtheme.css';
import Recipes from '$lib/components/recipes/Recipes.svelte';
import Search from './Search.svelte';

View File

@@ -1,5 +1,4 @@
<script lang=ts>
import "$lib/css/nordtheme.css"
import { season } from '$lib/js/season_store.js'
import {onMount} from "svelte";
import {do_on_key} from "./do_on_key";

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
let {
tag = '',

View File

@@ -1,5 +1,4 @@
<script>
import "$lib/css/nordtheme.css";
import TagChip from '$lib/components/recipes/TagChip.svelte';
let {

View File

@@ -1,3 +1,5 @@
@import "./shake.css";
:root{
--angle: 15deg;
}
@@ -26,33 +28,3 @@
transition: 50ms;
scale: 0.8 0.8;
}
@keyframes shake{
0%{
transform: rotate(0)
scale(1,1);
}
25%{
box-shadow: 0em 0em 1em 0.2em rgba(0, 0, 0, 0.6);
transform: rotate(--angle)
scale(1.2,1.2)
;
}
50%{
box-shadow: 0em 0em 1em 0.2em rgba(0, 0, 0, 0.6);
transform: rotate(calc(-1 * --angle))
scale(1.2,1.2);
}
74%{
box-shadow: 0em 0em 1em 0.2em rgba(0, 0, 0, 0.6);
transform: rotate(--angle)
scale(1.2, 1.2);
}
100%{
transform: rotate(0)
scale(1.2, 1.2);
}
}

View File

@@ -1,51 +0,0 @@
form{
background-color: var(--nord5);
display: flex;
flex-direction: column;
max-width: 600px;
gap: 0.5em;
margin-inline: auto;
justify-content: center;
align-items: center;
padding-block: 2rem;
margin-block: 2rem;
}
@media (prefers-color-scheme: dark){
form{
background-color: var(--accent-dark);
}
}
form label{
font-size: 1.2em;
}
form input{
display: block;
font-size: 1.2rem;
}
form button{
background-color: var(--red);
color: white;
border: none;
padding: 0.5em 1em;
font-size: 1.3em;
border-radius: 1000px;
margin-top: 1em;
transition: 100ms;
}
form button:hover,
form button:focus-visible
{
scale: 1.1;
}
form p{
max-width: 400px;
margin-top: 0;
}
form h4{
margin-bottom:0;
}
@media screen and (max-width: 600px){
form{
margin-top: 0;
}
}

View File

@@ -1,178 +0,0 @@
:root{
--nord0: #2E3440;
--nord1: #3B4252;
--nord2: #434C5E;
--nord3: #4C566A;
--nord4: #D8DEE9;
--nord5: #E5E9F0;
--nord6: #ECEFF4;
--nord7: #8FBCBB;
--nord8: #88C0D0;
--nord9: #81A1C1;
--nord10: #5E81AC;
--nord11: #BF616A;
--nord12: #D08770;
--nord13: #EBCB8B;
--nord14: #A3BE8C;
--nord15: #B48EAD;
--lightblue: var(--nord9);
--blue: var(--nord10);
--red: var(--nord11);
--orange: var(--nord12);
--yellow: var(--nord13);
--green: var(--nord14);
--purple: var(--nord15);
--nord6-dark: #292c31;
--accent-dark: #1f1f21;
--background-dark: #21201b;
--font-default-dark: #ffffff;
/* Shared transitions & shadows */
--transition-fast: 100ms;
--transition-normal: 200ms;
--shadow-sm: 0 0 0.4em 0.05em rgba(0,0,0,0.2);
--shadow-md: 0 0 0.5em 0.1em rgba(0,0,0,0.3);
--shadow-lg: 0 0 1em 0.1em rgba(0,0,0,0.4);
--shadow-hover: 0.1em 0.1em 0.5em 0.1em rgba(0,0,0,0.3);
--radius-pill: 1000px;
--radius-card: 20px;
--radius-sm: 0.3rem;
}
a:not(:visited){
color: var(--blue);
}
a:visited{
color: var(--purple);
}
@media (prefers-color-scheme: dark) {
a:not(:visited){
color: var(--nord8);
}
}
*{
box-sizing: border-box;
font-family: Helvetica, Arial, "Noto Sans", sans-serif
}
body{
margin:0;
padding:0;
background-color: #fbf9f3;
overflow-x: hidden;
}
@media (prefers-color-scheme: dark) {
body{
color: white;
background-color: var(--background-dark);
}
}
/* ========================================
Global Utility Classes
Use these in components to avoid CSS duplication
======================================== */
/* Pill-shaped element base */
.g-pill {
border-radius: var(--radius-pill);
border: none;
cursor: pointer;
display: inline-block;
text-decoration: none;
transition: var(--transition-fast);
}
/* Interactive hover/focus effects */
.g-interactive {
transition: var(--transition-fast);
}
.g-interactive:hover,
.g-interactive:focus-visible {
transform: scale(1.05);
box-shadow: var(--shadow-hover);
}
.g-interactive:focus {
scale: 0.9;
}
/* Light background button (with dark mode) */
.g-btn-light {
background-color: var(--nord5);
color: var(--nord0);
box-shadow: var(--shadow-sm);
}
@media (prefers-color-scheme: dark) {
.g-btn-light {
background-color: var(--nord0);
color: white;
}
}
/* Dark background button */
.g-btn-dark,
.g-btn-dark:visited,
.g-btn-dark:link {
background-color: var(--nord0);
color: var(--nord6);
box-shadow: var(--shadow-lg);
}
.g-btn-dark:hover,
.g-btn-dark:focus-visible {
background-color: var(--nord1);
color: var(--nord6);
}
/* Icon badge (circular icon container) */
.g-icon-badge {
font-family: "Noto Color Emoji", emoji, sans-serif;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
text-decoration: none;
transition: var(--transition-fast);
box-shadow: var(--shadow-lg);
}
.g-icon-badge:hover,
.g-icon-badge:focus-visible {
transform: scale(1.1);
box-shadow: var(--shadow-hover);
}
/* Tag/chip styling */
.g-tag,
.g-tag:visited,
.g-tag:link {
font-size: 1.1rem;
padding: 0.25em 1em;
border-radius: var(--radius-pill);
background-color: var(--nord5);
color: var(--nord0);
text-decoration: none;
cursor: pointer;
transition: var(--transition-fast);
box-shadow: var(--shadow-sm);
border: none;
display: inline-block;
}
.g-tag:hover,
.g-tag:focus-visible {
transform: scale(1.05);
background-color: var(--nord8);
box-shadow: var(--shadow-hover);
color: var(--nord0);
}
@media (prefers-color-scheme: dark) {
.g-tag,
.g-tag:visited,
.g-tag:link {
background-color: var(--nord0);
color: white;
}
.g-tag:hover,
.g-tag:focus-visible {
color: var(--nord0);
}
}

View File

@@ -1,198 +0,0 @@
@font-face {
font-family: 'LibertineMinimal';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/fonts/LinLibertine_minimal.woff2) format('woff2'),
url(/fonts/LinLibertine_minimal.ttf) format('truetype');
}
.sbeads{
fill: var(--nord10);
}
.chain{
stroke:black;
stroke-width: 0.7;
stroke-miterlimit: 4;
stroke: gray;
fill: none;
}
.sbeads circle.hitbox{
r: 3.2px;
stroke-width:0;
}
#start1 circle{
cx:15.559271px;
cy: 20.881956px;
}
#start2 circle{
cx:21.633902px;
cy:20.367514px;
}
#start3 circle{
cx:27.96961px;
cy:21.178484px;
}
#lbead5 circle{
cx:118.50725px;
cy:59.477211px;
}
#lbead4 circle{
cx:126.81134px;
cy:15.751753px;
}
#lbead1 circle{
cx:7.6719489px;
cy:25.364584px;
}
#lbead2 circle{
cx:36.798512px;
cy:23.486462px;
}
#lbead3 circle{
cx:84.105789px;
cy:3.0456686px;
}
#lbead6 circle{
cx:72.185097px;
cy:64.006859px;
}
#start1:hover .msg,
#start2:hover .msg,
#start3:hover .msg,
#secret1:hover .msg,
#secret2:hover .msg,
#secret3:hover .msg,
#secret4:hover .msg,
#secret5:hover .msg,
#lbeads .beforedecades:hover .msg,
#lbeads .afterdecade:hover .msg,
#cross:hover .msg
{
display:block;
}
#start1:hover .sbeads circle:not(.hitbox),
#start2:hover .sbeads circle:not(.hitbox),
#start3:hover .sbeads circle:not(.hitbox),
#secret1:hover .sbeads circle,
#secret2:hover .sbeads circle,
#secret3:hover .sbeads circle,
#secret4:hover .sbeads circle,
#secret5:hover .sbeads circle
{
fill: var(--nord11);
r: 1.5px;
}
#lbead1:hover .lbead,
#lbead2:hover .lbead,
#lbead3:hover .lbead,
#lbead4:hover .lbead,
#lbead5:hover .lbead,
#lbead6:hover .lbead{
r: 2.8px;
fill: var(--nord11);
}
#cross:hover .symbol{
fill: var(--nord11);
stroke: var(--nord11);
stroke-width: 0.25;
}
#lbeads.msg{
display:block;
}
.sbeads circle{
r: 1.25px;
}
.msg .diff{
fill: var(--nord11);
}
.msg .b{
font-family: crosses;
font-weight: bold;
}
.msg .title{
fill: var(--nord10);
font-weight: bold;
font-size: 5px;
}
.msg{
font-size: 4px;
stroke: none;
fill: var(--nord4);
display:none;
}
text{
font-family: LibertineMinimal;
}
#lbeads circle.hitbox{
r:5px;
stroke:none;
stroke-width:0;
}
.lbead{
fill: var(--nord12);
r: 2.65px;
}
.hitbox{
opacity:0;
stroke-width: 2;
fill: red;
stroke: red;
}
#coin circle{
r: 2.7px;
fill:darkgray;
}
#coin text{
fill:var(--nord0);
font-size: 4.259px;
line-height:1.25;
font-family: crosses;
}
#cross .symbol{
font-family: crosses;
fill: var(--nord4);
font-size: 17.3637px;
line-height: 1.25;
stroke-width:0.434093
}
table{
width: 100%;
border-collapse: collapse;
}
td{
text-align:center;
border-left: 1px solid;
border-right: 1px solid;
border-color: var(--nord2);
padding-left: 5px;
padding-right: 5px;
}
tr :last-child{
border-right: none;
}
tr :first-child{
border-left: 0px solid;
}
thead td{
color: var(--nord4);
border-bottom-width: 3px;
border-bottom-color: var(--nord10);
border-bottom-style: dotted;
font-size: 110%;
font-weight: bold;
}
.table{
width:100%;
overflow-x: auto;
}

View File

@@ -1,5 +1,4 @@
<script lang="ts">
import "$lib/css/nordtheme.css";
import LinksGrid from "$lib/components/LinksGrid.svelte";
import { onMount } from 'svelte';
let { data } = $props();

View File

@@ -1,6 +1,40 @@
<script>
import "$lib/css/form.css"
</script>
<style>
form {
background-color: var(--color-bg-secondary);
display: flex;
flex-direction: column;
max-width: 600px;
gap: 0.5em;
margin-inline: auto;
justify-content: center;
align-items: center;
padding-block: 2rem;
margin-block: 2rem;
}
form label { font-size: 1.2em; }
form input { display: block; font-size: 1.2rem; }
form button {
background-color: var(--color-accent);
color: var(--color-text-on-accent);
border: none;
padding: 0.5em 1em;
font-size: 1.3em;
border-radius: 1000px;
margin-top: 1em;
transition: 100ms;
cursor: pointer;
}
form button:hover, form button:focus-visible {
background-color: var(--color-accent-hover);
scale: 1.1;
}
form button:active { background-color: var(--color-accent-active); }
form p { max-width: 400px; margin-top: 0; }
form h4 { margin-bottom: 0; }
@media screen and (max-width: 600px) {
form { margin-top: 0; }
}
</style>
<form action="?/register" method=POST>
<h1>Registrieren</h1>

View File

@@ -3,9 +3,44 @@
export let data
let password;
const admin = data.user?.access.includes('admin') ?? false
import "$lib/css/form.css"
</script>
<style>
form {
background-color: var(--color-bg-secondary);
display: flex;
flex-direction: column;
max-width: 600px;
gap: 0.5em;
margin-inline: auto;
justify-content: center;
align-items: center;
padding-block: 2rem;
margin-block: 2rem;
}
form label { font-size: 1.2em; }
form input { display: block; font-size: 1.2rem; }
form button {
background-color: var(--color-accent);
color: var(--color-text-on-accent);
border: none;
padding: 0.5em 1em;
font-size: 1.3em;
border-radius: 1000px;
margin-top: 1em;
transition: 100ms;
cursor: pointer;
}
form button:hover, form button:focus-visible {
background-color: var(--color-accent-hover);
scale: 1.1;
}
form button:active { background-color: var(--color-accent-active); }
form p { max-width: 400px; margin-top: 0; }
form h4 { margin-bottom: 0; }
@media screen and (max-width: 600px) {
form { margin-top: 0; }
}
input:invalid + div{
display: none;
}

View File

@@ -1,4 +1,5 @@
<script>
import '../app.css';
let { children } = $props();
</script>

View File

@@ -1,4 +1,5 @@
<script>
import '$lib/css/christ.css';
import { page } from '$app/stores';
import Header from '$lib/components/Header.svelte'
import UserHeader from '$lib/components/UserHeader.svelte';

View File

@@ -2,8 +2,6 @@
import { onMount } from 'svelte';
import { browser } from '$app/environment';
import { createLanguageContext } from "$lib/contexts/languageContext.js";
import "$lib/css/christ.css";
import "$lib/css/nordtheme.css";
import Gebet from "./Gebet.svelte";
import LanguageToggle from "$lib/components/faith/LanguageToggle.svelte";
import SearchInput from "$lib/components/SearchInput.svelte";

View File

@@ -1,8 +1,6 @@
<script>
import { onMount } from 'svelte';
import { createLanguageContext } from "$lib/contexts/languageContext.js";
import "$lib/css/christ.css";
import "$lib/css/nordtheme.css";
import LanguageToggle from "$lib/components/faith/LanguageToggle.svelte";
import Kreuzzeichen from "$lib/components/faith/prayers/Kreuzzeichen.svelte";
import GloriaPatri from "$lib/components/faith/prayers/GloriaPatri.svelte";

View File

@@ -3,7 +3,6 @@ import { onMount, tick } from "svelte";
import { createLanguageContext } from "$lib/contexts/languageContext.js";
import { createPip } from "$lib/js/pip.svelte";
import PipImage from "$lib/components/faith/PipImage.svelte";
import "$lib/css/christ.css";
import "$lib/css/action_button.css";
import Kreuzzeichen from "$lib/components/faith/prayers/Kreuzzeichen.svelte";
import Credo from "$lib/components/faith/prayers/Credo.svelte";
@@ -75,6 +74,7 @@ let currentMysteryDescriptions = $derived(data.mysteryDescriptions[selectedMyste
// Function to switch mysteries
function selectMystery(mysteryType) {
selectedMystery = mysteryType;
lastMysteryTarget = 'before';
}
// Build URLs preserving full state (for no-JS fallback)
@@ -163,6 +163,7 @@ $effect(() => {
let mysteryImageContainer;
let mysteryScrollRaf = null;
let lastMysteryTarget = 'before';
function scrollMysteryImage(targetY, duration = 1200) {
if (!mysteryImageContainer) return;
@@ -193,14 +194,17 @@ $effect(() => {
// Edge pads (before/after): scroll flush so previous image hides behind the header
const offset = isEdge ? 0 : rem * IMAGE_COL_HEADER_OFFSET;
const target = Math.max(0, targetEl.offsetTop - offset);
if (isEdge) {
// Snap instantly when jumping to top/bottom
// Smooth-scroll the last image away when naturally transitioning from decade 5 to 'after'
const isNaturalEnd = targetName === 'after' && lastMysteryTarget === 5;
if (isEdge && !isNaturalEnd) {
// Snap instantly when jumping to top/bottom (not a natural scroll)
if (mysteryScrollRaf) cancelAnimationFrame(mysteryScrollRaf);
mysteryScrollRaf = null;
mysteryImageContainer.scrollTop = target;
} else {
scrollMysteryImage(target);
}
lastMysteryTarget = targetName;
}
});

View File

@@ -1,4 +1,5 @@
<script>
import '$lib/css/recipe-links.css';
import { page } from '$app/stores';
import Header from '$lib/components/Header.svelte'
import UserHeader from '$lib/components/UserHeader.svelte';

View File

@@ -3,7 +3,6 @@
export const multiplier = writable(0);
import type { PageData } from './$types';
import "$lib/css/nordtheme.css"
import EditButton from '$lib/components/EditButton.svelte';
import InstructionsPage from '$lib/components/recipes/InstructionsPage.svelte';
import IngredientsPage from '$lib/components/recipes/IngredientsPage.svelte';

View File

@@ -10,7 +10,6 @@
import CreateStepList from '$lib/components/recipes/CreateStepList.svelte';
import Toggle from '$lib/components/Toggle.svelte';
import '$lib/css/action_button.css';
import '$lib/css/nordtheme.css';
let { data, form }: { data: PageData; form: ActionData } = $props();

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { PageData } from './$types';
import '$lib/css/nordtheme.css';
import Recipes from '$lib/components/recipes/Recipes.svelte';
import Card from '$lib/components/recipes/Card.svelte';

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { PageData } from './$types';
import '$lib/css/nordtheme.css';
let { data } = $props<{ data: PageData }>();

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { PageData } from './$types';
import "$lib/css/nordtheme.css";
let { data } = $props<{ data: PageData }>();
import TagCloud from '$lib/components/TagCloud.svelte';
import TagBall from '$lib/components/TagBall.svelte';

View File

@@ -15,7 +15,6 @@
import { season } from '$lib/js/season_store';
import { portions } from '$lib/js/portions_store';
import '$lib/css/action_button.css';
import '$lib/css/nordtheme.css';
let { data, form }: { data: PageData; form: ActionData } = $props();

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { PageData } from './$types';
import '$lib/css/nordtheme.css';
import Recipes from '$lib/components/recipes/Recipes.svelte';
import Card from '$lib/components/recipes/Card.svelte';
import Search from '$lib/components/recipes/Search.svelte';

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { PageData } from './$types';
import '$lib/css/nordtheme.css';
import Recipes from '$lib/components/recipes/Recipes.svelte';
import MediaScroller from '$lib/components/recipes/MediaScroller.svelte';
import SeasonLayout from '$lib/components/recipes/SeasonLayout.svelte'

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import type { PageData } from './$types';
import '$lib/css/nordtheme.css';
import Recipes from '$lib/components/recipes/Recipes.svelte';
import MediaScroller from '$lib/components/recipes/MediaScroller.svelte';
import SeasonLayout from '$lib/components/recipes/SeasonLayout.svelte'

View File

@@ -1,7 +1,6 @@
<script lang="ts">
import type { PageData } from './$types';
let { data } = $props<{ data: PageData }>();
import "$lib/css/nordtheme.css";
import TagCloud from '$lib/components/TagCloud.svelte';
import TagBall from '$lib/components/TagBall.svelte';