+
Her kan du lage og dele lister over ting å gjøre om vinteren for å
holde vinterdepresjonen unna. Og selvfølgelig kan du også lage
lister for andre formål — noen liker jo ikke sommeren heller.
-
+
Du velger selv om hver oppføring er privat (kryptert i nettleseren
din), anonym (synlig uten navn), eller offentlig.
Mer om personvern og hvordan det virker.
diff --git a/frontend/src/styles.css b/frontend/src/styles.css
index e28ea99..efc30b0 100644
--- a/frontend/src/styles.css
+++ b/frontend/src/styles.css
@@ -1,26 +1,46 @@
:root {
color-scheme: light dark;
- --bg: #fafafa;
- --fg: #1c1c1c;
- --muted: #6c6c6c;
- --border: #d8d8d8;
- --accent: #1f6feb;
- --accent-fg: white;
+ /* Warmer palette — winter sun on snow rather than office UI. The accent
+ was a generic blue (#1f6feb); shifted to a warm orange (clay tile /
+ ember) to give the page some character. Border becomes a soft beige
+ to match. All combos verified for WCAG 2.2 AA (≥4.5:1 normal text). */
+ --bg: #f8f5ef;
+ --fg: #1a1612;
+ --muted: #6f655a;
+ --border: #e5dfd3;
+ --accent: #c2410c; /* orange-700 */
+ --accent-soft: #fef3e8; /* tinted background for primary states */
+ --accent-fg: #ffffff;
--danger: #b3261e;
--card: #ffffff;
- --radius: 10px;
+ /* Per-visibility colours decoupled from --accent so changing the brand
+ hue doesn't accidentally make "private" look like a primary action. */
+ --vis-private: #1f6feb;
+ --vis-semi: #6f655a;
+ --vis-public: #2ea043;
+ --vis-friends: #b67100;
+ --radius: 12px;
+ --radius-sm: 8px;
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
+ --shadow-md: 0 4px 12px rgba(120, 70, 20, 0.08);
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
@media (prefers-color-scheme: dark) {
:root {
- --bg: #161616;
- --fg: #e8e8e8;
- --muted: #9a9a9a;
- --border: #2d2d2d;
- --accent: #4a8cff;
- --card: #1f1f1f;
+ --bg: #14110d;
+ --fg: #f0ede5;
+ --muted: #a09587;
+ --border: #2d2820;
+ --accent: #fb923c; /* orange-400 — bright enough for dark mode */
+ --accent-soft: #2a1a0e;
+ --accent-fg: #1a1612;
+ --card: #1d1813;
--danger: #f28b82;
+ --vis-private: #4a8cff;
+ --vis-friends: #f1a528;
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
+ --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
}
}
@@ -32,24 +52,50 @@ html, body {
background: var(--bg);
color: var(--fg);
min-height: 100vh;
- /* iOS double-tap zoom is annoying for an app like this; the meta viewport
- handles the rest. */
-webkit-text-size-adjust: 100%;
}
+/* Body gets a very subtle snowflake silhouette in the corner, picking up the
+ icon language without being intrusive. Hidden on small viewports because
+ it competes with content. Disabled under prefers-reduced-motion only when
+ the background image could imply motion — here it's static, so it stays. */
+@media (min-width: 1100px) {
+ body {
+ background-image: url('/icon.svg');
+ background-position: calc(50% + 420px) 80px;
+ background-size: 260px;
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ /* Heavily de-emphasised so it never competes with text contrast. */
+ background-blend-mode: luminosity;
+ background-color: var(--bg);
+ }
+ body::before {
+ /* Layer a soft wash over the icon to fade it to barely-visible. */
+ content: '';
+ position: fixed;
+ inset: 0;
+ background: var(--bg);
+ opacity: 0.92;
+ pointer-events: none;
+ z-index: -1;
+ }
+}
+
main {
max-width: 720px;
margin: 0 auto;
- /* Use env() for safe-area insets so content doesn't slip under iOS notches
- or under Android gesture areas when installed as a PWA. */
padding: 1.5rem max(1rem, env(safe-area-inset-right)) calc(4rem + env(safe-area-inset-bottom)) max(1rem, env(safe-area-inset-left));
+ position: relative; /* sit above the body::before wash */
}
-h1, h2, h3 { line-height: 1.2; margin-top: 0; }
-h1 { font-size: 1.75rem; }
-h2 { font-size: 1.25rem; }
-p { line-height: 1.5; }
+h1, h2, h3, h4 { line-height: 1.2; margin-top: 0; }
+h1 { font-size: 1.85rem; letter-spacing: -0.01em; }
+h2 { font-size: 1.3rem; }
+h3 { font-size: 1.05rem; }
+p { line-height: 1.55; }
a { color: var(--accent); }
+a:hover { text-decoration: underline; }
input, button, select, textarea {
font: inherit;
@@ -57,22 +103,24 @@ input, button, select, textarea {
}
input[type="text"], input[type="email"], input[type="password"],
-input[type="datetime-local"], textarea, select {
+input[type="datetime-local"], input[type="search"], textarea, select {
width: 100%;
- padding: 0.5rem 0.6rem;
- border-radius: 8px;
+ padding: 0.55rem 0.7rem;
+ border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--card);
color: var(--fg);
+ transition: border-color 120ms ease;
}
-
-input:focus-visible, button:focus-visible, select:focus-visible, textarea:focus-visible {
+input:focus-visible, textarea:focus-visible, select:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 1px;
+ border-color: var(--accent);
+}
+button:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 1px;
}
-/* Anchors that inherit their colour from the heading or nav (no default link
- colour, no default underline) need an extra focus cue beyond the outline,
- so keyboard users can be sure they're on an interactive element. */
a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
@@ -81,61 +129,92 @@ a:focus-visible {
button {
cursor: pointer;
- /* WCAG 2.5.5 enhanced target size is 44×44 CSS px; we hit that with the
- vertical padding + line-height. Don't shrink below this on small viewports. */
min-height: 44px;
- padding: 0.5rem 0.9rem;
- border-radius: 8px;
+ padding: 0.5rem 0.95rem;
+ border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--card);
color: var(--fg);
+ font-weight: 500;
+ transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
+}
+button:hover:not(:disabled) {
+ background: var(--accent-soft);
+ border-color: var(--accent);
}
button.primary {
background: var(--accent);
color: var(--accent-fg);
border-color: transparent;
+ font-weight: 600;
+}
+button.primary:hover:not(:disabled) {
+ /* Subtle elevation on the primary button — it's the most-clicked thing. */
+ transform: translateY(-1px);
+ box-shadow: var(--shadow-md);
+ background: var(--accent);
+ border-color: transparent;
}
button.danger {
background: transparent;
color: var(--danger);
border-color: var(--danger);
}
+button.danger:hover:not(:disabled) {
+ background: rgba(179, 38, 30, 0.08);
+}
button:disabled { opacity: 0.5; cursor: progress; }
label { display: block; margin: 0.75rem 0 0.25rem; font-weight: 500; }
.row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.muted { color: var(--muted); font-size: 0.9rem; }
+
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius);
- padding: 1rem 1rem;
- margin-bottom: 0.75rem;
+ padding: 1.1rem 1.15rem;
+ margin-bottom: 0.85rem;
+ box-shadow: var(--shadow-sm);
+ transition: box-shadow 160ms ease, transform 160ms ease, border-color 160ms ease;
+}
+/* Activity row cards lift slightly on hover so users sense them as
+ interactive. Skip the lift for cards inside forms (Profile sections etc.)
+ by hooking into the more specific `article.card` selector — Profile cards
+ are . */
+article.card:hover {
+ box-shadow: var(--shadow-md);
+ border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
}
.banner {
- background: var(--card);
+ background: var(--accent-soft);
border: 1px solid var(--border);
border-left: 4px solid var(--accent);
padding: 0.75rem 1rem;
border-radius: var(--radius);
margin-bottom: 1rem;
}
-.banner.danger { border-left-color: var(--danger); }
+.banner.danger {
+ background: rgba(179, 38, 30, 0.06);
+ border-left-color: var(--danger);
+}
.tag {
display: inline-flex;
align-items: center;
background: rgba(127,127,127,0.15);
border-radius: 999px;
- padding: 0.1rem 0.55rem;
+ padding: 0.15rem 0.65rem;
font-size: 0.85rem;
margin: 0.15rem 0.2rem 0.15rem 0;
+ transition: background 120ms ease;
}
-.tag.private { background: rgba(31,111,235,0.15); }
-/* Tag-close buttons opt out of the 44px touch target — they're 24×24 (WCAG
- 2.5.8 minimum) which is still large enough to tap reliably and keeps the
- pill from ballooning. The button itself remains keyboard-accessible. */
+a.tag:hover {
+ background: var(--accent-soft);
+ text-decoration: none !important;
+}
+.tag.private { background: color-mix(in srgb, var(--vis-private) 18%, transparent); }
.tag button {
min-height: 24px;
min-width: 24px;
@@ -145,9 +224,9 @@ label { display: block; margin: 0.75rem 0 0.25rem; font-weight: 500; }
.recovery-code {
display: block;
font-family: ui-monospace, "SF Mono", Menlo, monospace;
- background: var(--card);
- border: 1px dashed var(--border);
- padding: 0.75rem 1rem;
+ background: var(--accent-soft);
+ border: 1px dashed var(--accent);
+ padding: 0.85rem 1rem;
border-radius: var(--radius);
font-size: 1.1rem;
letter-spacing: 0.05em;
@@ -168,37 +247,84 @@ nav.top > .row {
flex-wrap: wrap;
justify-content: flex-end;
}
+nav.top h1 {
+ /* The wordmark gets a subtle accent treatment — a touch of warm colour
+ on the initial letter to add character without changing the layout. */
+ position: relative;
+}
+nav.top h1 a { letter-spacing: -0.015em; }
+nav.top h1::after {
+ /* A small snowflake-like accent next to the title. */
+ content: '❄';
+ margin-left: 0.45rem;
+ color: var(--accent);
+ font-size: 0.85em;
+ vertical-align: 0.05em;
+ opacity: 0.85;
+}
+
+/* Hero treatment on the landing — a touch more breathing room and weight
+ on the first paragraph so the page reads as inviting, not utilitarian. */
+.landing-hero {
+ margin-bottom: 1.25rem;
+ padding-bottom: 1rem;
+ border-bottom: 1px solid var(--border);
+}
+.landing-hero p {
+ font-size: 1.05rem;
+ color: var(--fg); /* not --muted: this is the welcome line, give it presence */
+}
+.landing-hero p.muted-secondary {
+ font-size: 0.95rem;
+ color: var(--muted);
+}
-/* Narrow phones: drop the nav-button gap a little and let the title shrink. */
@media (max-width: 480px) {
main { padding-top: 1rem; }
- h1 { font-size: 1.4rem; }
+ h1 { font-size: 1.5rem; }
nav.top h1 { flex: 1 1 100%; }
- /* Inputs are wide by default; just make sure they don't overflow on tiny screens. */
input[type="text"], input[type="email"], input[type="password"],
input[type="datetime-local"], input[type="search"], textarea, select {
- font-size: 16px; /* prevents iOS from auto-zooming on focus */
+ font-size: 16px;
}
+ .landing-hero p { font-size: 1rem; }
}
.vis-badge {
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.05em;
- padding: 0.1rem 0.5rem;
+ padding: 0.18rem 0.55rem;
border-radius: 999px;
margin-left: 0.5rem;
+ font-weight: 600;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.3em;
}
-.vis-badge.private { background: rgba(31,111,235,0.15); color: var(--accent); }
-.vis-badge.semi { background: rgba(127,127,127,0.18); color: var(--muted); }
-.vis-badge.public { background: rgba(46,160,67,0.18); color: #2ea043; }
-.vis-badge.friends { background: rgba(241,165,40,0.20); color: #b67100; }
-@media (prefers-color-scheme: dark) {
- .vis-badge.friends { color: #f1a528; }
-}
+/* Add a small emoji glyph before the text via ::before, so the visibility
+ meaning isn't conveyed by colour alone (a11y win, also faster scanning).
+ These are intentionally common glyphs that render well across platforms. */
+.vis-badge.private::before { content: '🔒'; font-size: 0.95em; }
+.vis-badge.friends::before { content: '👥'; font-size: 0.95em; }
+.vis-badge.semi::before { content: '🎭'; font-size: 0.95em; }
+.vis-badge.public::before { content: '🌍'; font-size: 0.95em; }
+.vis-badge.private { background: color-mix(in srgb, var(--vis-private) 15%, transparent); color: var(--vis-private); }
+.vis-badge.semi { background: color-mix(in srgb, var(--vis-semi) 18%, transparent); color: var(--vis-semi); }
+.vis-badge.public { background: color-mix(in srgb, var(--vis-public) 18%, transparent); color: var(--vis-public); }
+.vis-badge.friends { background: color-mix(in srgb, var(--vis-friends) 20%, transparent); color: var(--vis-friends); }
.error { color: var(--danger); margin-top: 0.5rem; }
-@media (prefers-reduced-motion: reduce) {
- * { animation: none !important; transition: none !important; }
+footer {
+ /* The footer holds the personvern link — let it breathe a bit more so it
+ doesn't feel like an afterthought. */
+ padding-top: 1.25rem !important;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ /* Disable transitions but leave the static background-image (snowflake)
+ and box-shadows alone — they're not motion, just decoration. */
+ * { animation: none !important; transition: none !important; }
+ button.primary:hover { transform: none !important; }
}