From 4ac2f33e3f5dcecb453c0a5e49c43533c1364c5f Mon Sep 17 00:00:00 2001
From: Martin Dvorak
Date: Thu, 8 Oct 2026 19:06:36 +0000
Subject: [PATCH 1/2] Fix the dead space between /create's sticky CTA and the
phone tab bar
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On phones the "Freeze my deck" strip floats one tab-bar height (4.6rem)
above the viewport bottom, but the page reserved env + 9rem of trailing
room — so at the end of the scroll the strip docked ~70px higher than where
it had been floating, leaving a visible cavity above the tab bar.
Phones now get exactly the sticky offset (env + 4.6rem) as trailing space:
the strip settles where it was floating and the bar is never double-counted.
Tablet/desktop (>=640px) keep the roomier 9rem — unchanged.
Verified at 360/390px: gap CTA-to-bar 70.3px -> 0.3px, ~70px less dead
scroll; tablet 800px and desktop 1280px measurements identical to before.
Service worker: freezmo-v7.
---
app/globals.css | 10 ++++++++++
public/sw.js | 2 +-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/app/globals.css b/app/globals.css
index 42aa009..9fe04c0 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -684,7 +684,17 @@ body {
.pt-safe { padding-top: max(env(safe-area-inset-top), 0.75rem) }
.pb-safe { padding-bottom: max(env(safe-area-inset-bottom), 0.75rem) }
.pb-tabbar { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 5.25rem) }
+/* Trailing room under the sticky "Freeze my deck" strip on /create.
+ Phones: the strip floats one tab-bar height above the viewport bottom (the
+ sticky bottom offset in UploadScreen), so the page only needs that much
+ scroll room under it — the strip settles exactly where it was already
+ floating, and the bottom bar is never double-counted. Keep 4.6rem in sync
+ with the sticky offset. Wider screens: the strip docks to the viewport
+ bottom and keeps the roomier 9rem. */
.pb-cta { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 9rem) }
+@media (max-width: 639px) {
+ .pb-cta { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 4.6rem) }
+}
@media (display-mode: standalone) {
.standalone-hide { display: none }
diff --git a/public/sw.js b/public/sw.js
index 24dc175..e0eb9b5 100644
--- a/public/sw.js
+++ b/public/sw.js
@@ -9,7 +9,7 @@
*
* Bumping CACHE_VERSION is how a new deploy invalidates old assets.
*/
-const CACHE_VERSION = "freezmo-v6";
+const CACHE_VERSION = "freezmo-v7";
const SHELL_CACHE = `${CACHE_VERSION}-shell`;
const ASSET_CACHE = `${CACHE_VERSION}-assets`;
From 22af888ec059eac53827d07f498de1edf8859abf Mon Sep 17 00:00:00 2001
From: Martin Dvorak
Date: Thu, 8 Oct 2026 19:19:20 +0000
Subject: [PATCH 2/2] Redesign the quick-action CTAs: two ways in (study deck
vs. homework)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Library empty state ("Your icebox")
- Replace the single "Make your first deck" button with two quick-action
cards: "Create interactive test" (primary, ice-gradient icon + subtle
accent border) and "Help me with my homework" (glass card, sparkles
icon). Stacked on phones, side by side from 640px up; both >=44px tall.
/create
- Replace the "Got homework instead of notes?" banner with a two-card mode
switcher above "1. Add your notes": "Study Deck & Quizzes" (the current
view — aria-current, accent tint, ice icon) and "Homework Solver" (a
shortcut to /homework). Icon-on-top tiles on phones, inline rows from
640px up; glass tokens + backdrop blur in both themes.
Strings
- New keys in both dictionaries: emptyStateCreateDeck, emptyStateHomework,
actionStudyDeck, actionHomework. Drop the now-unused homework.entry and
library.makeFirst keys.
Drive-by AA fix (light mode, /create only)
- The "New folder" dashed button and the difficulty blurbs move from
frost-500 to frost-600 (4.0:1 -> ~6:1). Dark mode is unchanged.
Service worker: freezmo-v8.
Verified: redesign suite 32/32 (stacked/side-by-side layouts, 360/390/1280,
dark+light, en+cs, >=44px targets, both cards navigate, no overflow, axe
contrast), mobile 49/49, i18n 27/27, desktop regression 73/73. Lint + build
clean.
---
components/LibraryScreen.tsx | 37 +++++++++++++++++++++---
components/UploadScreen.tsx | 54 +++++++++++++++++++++++-------------
lib/i18n-dict.ts | 16 ++++++++---
public/sw.js | 2 +-
4 files changed, 81 insertions(+), 28 deletions(-)
diff --git a/components/LibraryScreen.tsx b/components/LibraryScreen.tsx
index ec618ea..2beeea5 100644
--- a/components/LibraryScreen.tsx
+++ b/components/LibraryScreen.tsx
@@ -5,7 +5,7 @@ import { useMemo, useRef, useState, useSyncExternalStore } from "react";
import { DeckCard } from "@/components/DeckCard";
import { FolderBar } from "@/components/FolderBar";
-import { FolderIcon, UploadIcon } from "@/components/icons";
+import { FolderIcon, SnowflakeIcon, SparklesIcon, UploadIcon } from "@/components/icons";
import { Button, EmptyState } from "@/components/ui";
import { folderStore, renameFolder } from "@/lib/folders";
import { useI18n } from "@/lib/i18n";
@@ -224,9 +224,38 @@ export function LibraryScreen() {
- {t("library.makeFirst")}
-
+ /* Two ways in: build a study deck from notes, or hand over an
+ assignment. Stacked on phones, side by side from 640px up. */
+