Files
fourge-portal/kakeibo-preview/index.html
T
Krao Hasanee eee0885811 Fix file sharing load speed and move error; misc updates
- Remove recursive directory size calculations (single Seafile API call per list)
- Remove 'Used in this location' usage display
- Fix move using v2 per-type endpoints instead of broken batch endpoint
- Send entry type from frontend for correct move routing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 14:20:38 -04:00

1604 lines
45 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kakeibo — App Preview</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
/* Theme: Ink (default dark) */
--bg: #0e0e0f;
--surface: #1a1a1e;
--surface2: #252529;
--surface3: #2e2e34;
--border: rgba(255,255,255,0.08);
--text: #f0f0f2;
--text2: #9898a8;
--text3: #5a5a6a;
--accent: #c8a96e;
--accent2: #7c9e8c;
--accent3: #9b7ea8;
--accent4: #8fa3c8;
--pill: rgba(200,169,110,0.15);
--pill-text: #c8a96e;
--red: #d47070;
--green: #7ca88a;
--tab-bg: #1a1a1e;
--tab-active: #c8a96e;
--progress-bg: rgba(255,255,255,0.08);
--card-shadow: 0 2px 12px rgba(0,0,0,0.4);
--btn-primary: #c8a96e;
--btn-primary-text: #0e0e0f;
--input-bg: #252529;
--status-bar: #f0f0f2;
}
body.theme-paper {
--bg: #f5f0e8;
--surface: #faf7f2;
--surface2: #ede8df;
--surface3: #e4ddd0;
--border: rgba(0,0,0,0.08);
--text: #2a2118;
--text2: #7a6a55;
--text3: #b0a090;
--accent: #8b5e3c;
--accent2: #5a7d5e;
--accent3: #7a5a8b;
--accent4: #4a6a8b;
--pill: rgba(139,94,60,0.12);
--pill-text: #8b5e3c;
--red: #c05050;
--green: #4a7a5a;
--tab-bg: #ede8df;
--tab-active: #8b5e3c;
--progress-bg: rgba(0,0,0,0.08);
--card-shadow: 0 2px 12px rgba(0,0,0,0.08);
--btn-primary: #8b5e3c;
--btn-primary-text: #faf7f2;
--input-bg: #ede8df;
--status-bar: #2a2118;
}
body.theme-sakura {
--bg: #1a0e14;
--surface: #241520;
--surface2: #2e1d2a;
--surface3: #382535;
--border: rgba(255,180,200,0.1);
--text: #f5e8f0;
--text2: #b890a8;
--text3: #7a5570;
--accent: #e8849c;
--accent2: #a08ec8;
--accent3: #c88e58;
--accent4: #88b8a8;
--pill: rgba(232,132,156,0.15);
--pill-text: #e8849c;
--red: #e87878;
--green: #88b898;
--tab-bg: #241520;
--tab-active: #e8849c;
--progress-bg: rgba(255,180,200,0.1);
--card-shadow: 0 2px 16px rgba(0,0,0,0.5);
--btn-primary: #e8849c;
--btn-primary-text: #1a0e14;
--input-bg: #2e1d2a;
--status-bar: #f5e8f0;
}
body.theme-stone {
--bg: #f0f0ee;
--surface: #fafafa;
--surface2: #e8e8e6;
--surface3: #dcdcda;
--border: rgba(0,0,0,0.07);
--text: #1a1a1a;
--text2: #6a6a6a;
--text3: #aaaaaa;
--accent: #2a2a2a;
--accent2: #4a7a5a;
--accent3: #6a4a7a;
--accent4: #4a5a7a;
--pill: rgba(42,42,42,0.1);
--pill-text: #2a2a2a;
--red: #b05050;
--green: #4a7a5a;
--tab-bg: #e8e8e6;
--tab-active: #2a2a2a;
--progress-bg: rgba(0,0,0,0.07);
--card-shadow: 0 2px 12px rgba(0,0,0,0.06);
--btn-primary: #2a2a2a;
--btn-primary-text: #fafafa;
--input-bg: #e8e8e6;
--status-bar: #1a1a1a;
}
body {
background: #111;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Hiragino Sans', system-ui, sans-serif;
padding: 32px 20px;
gap: 28px;
}
/* Theme switcher */
.theme-bar {
display: flex;
gap: 10px;
align-items: center;
}
.theme-label {
color: #666;
font-size: 12px;
letter-spacing: 0.08em;
text-transform: uppercase;
margin-right: 4px;
}
.theme-btn {
width: 28px;
height: 28px;
border-radius: 50%;
border: 2.5px solid transparent;
cursor: pointer;
transition: transform 0.15s, border-color 0.15s;
position: relative;
}
.theme-btn:hover { transform: scale(1.15); }
.theme-btn.active { border-color: #fff; }
.theme-btn.t-ink { background: linear-gradient(135deg, #0e0e0f 50%, #c8a96e 50%); }
.theme-btn.t-paper { background: linear-gradient(135deg, #f5f0e8 50%, #8b5e3c 50%); }
.theme-btn.t-sakura { background: linear-gradient(135deg, #1a0e14 50%, #e8849c 50%); }
.theme-btn.t-stone { background: linear-gradient(135deg, #f0f0ee 50%, #2a2a2a 50%); }
/* Screen nav */
.screen-nav {
display: flex;
gap: 8px;
}
.screen-btn {
padding: 6px 14px;
border-radius: 20px;
border: 1px solid rgba(255,255,255,0.15);
background: rgba(255,255,255,0.05);
color: #999;
font-size: 12px;
cursor: pointer;
transition: all 0.15s;
letter-spacing: 0.04em;
}
.screen-btn:hover { background: rgba(255,255,255,0.1); color: #ccc; }
.screen-btn.active { background: rgba(255,255,255,0.15); color: #fff; border-color: rgba(255,255,255,0.3); }
/* Phone shell */
.phone-wrap {
position: relative;
}
.phone {
width: 390px;
height: 844px;
background: var(--bg);
border-radius: 54px;
overflow: hidden;
position: relative;
box-shadow:
0 0 0 1px rgba(255,255,255,0.12),
0 0 0 10px #1c1c1e,
0 0 0 11px rgba(255,255,255,0.08),
0 40px 80px rgba(0,0,0,0.7);
transition: background 0.3s;
}
/* Dynamic island */
.dynamic-island {
position: absolute;
top: 12px;
left: 50%;
transform: translateX(-50%);
width: 120px;
height: 36px;
background: #000;
border-radius: 20px;
z-index: 100;
}
/* Status bar */
.status-bar {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 58px;
display: flex;
align-items: flex-end;
justify-content: space-between;
padding: 0 28px 8px;
z-index: 50;
color: var(--status-bar);
font-size: 13px;
font-weight: 600;
transition: color 0.3s;
}
.status-time { font-variant-numeric: tabular-nums; }
.status-icons { display: flex; gap: 6px; align-items: center; }
.status-icon { font-size: 12px; }
/* Screen content */
.screen {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
flex-direction: column;
background: var(--bg);
transition: background 0.3s;
overflow: hidden;
}
.screen.active { display: flex; }
/* Scroll area */
.scroll-area {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding-top: 58px;
padding-bottom: 100px;
scrollbar-width: none;
}
.scroll-area::-webkit-scrollbar { display: none; }
/* Tab bar */
.tab-bar {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 88px;
background: var(--tab-bg);
border-top: 1px solid var(--border);
display: flex;
align-items: flex-start;
padding-top: 10px;
z-index: 50;
transition: background 0.3s, border-color 0.3s;
}
.tab-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
cursor: pointer;
padding-top: 2px;
}
.tab-icon {
font-size: 22px;
color: var(--text3);
transition: color 0.2s;
}
.tab-item.active .tab-icon { color: var(--tab-active); }
.tab-label {
font-size: 10px;
color: var(--text3);
letter-spacing: 0.04em;
transition: color 0.2s;
}
.tab-item.active .tab-label { color: var(--tab-active); }
/* FAB */
.fab {
position: absolute;
bottom: 96px;
right: 24px;
width: 52px;
height: 52px;
border-radius: 50%;
background: var(--btn-primary);
color: var(--btn-primary-text);
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
cursor: pointer;
z-index: 60;
transition: background 0.3s;
font-weight: 300;
line-height: 1;
}
/* Typography */
.page-title {
font-size: 28px;
font-weight: 700;
color: var(--text);
letter-spacing: -0.5px;
padding: 20px 24px 4px;
transition: color 0.3s;
}
.page-subtitle {
font-size: 13px;
color: var(--text3);
padding: 0 24px 20px;
transition: color 0.3s;
}
.section-label {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text3);
padding: 16px 24px 8px;
transition: color 0.3s;
}
/* Cards */
.card {
background: var(--surface);
border-radius: 20px;
margin: 0 16px 12px;
padding: 18px;
border: 1px solid var(--border);
box-shadow: var(--card-shadow);
transition: background 0.3s, border-color 0.3s;
}
/* Hero card */
.hero-card {
background: var(--surface);
border-radius: 24px;
margin: 0 16px 16px;
padding: 24px;
border: 1px solid var(--border);
box-shadow: var(--card-shadow);
transition: all 0.3s;
}
.hero-month {
font-size: 12px;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text3);
margin-bottom: 8px;
}
.hero-amount {
font-size: 42px;
font-weight: 700;
color: var(--text);
letter-spacing: -2px;
line-height: 1;
margin-bottom: 4px;
font-variant-numeric: tabular-nums;
}
.hero-currency {
font-size: 22px;
font-weight: 400;
color: var(--text2);
vertical-align: super;
margin-right: 4px;
letter-spacing: 0;
}
.hero-sub {
font-size: 13px;
color: var(--text2);
margin-bottom: 24px;
}
.hero-stats {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 12px;
}
.hero-stat {
display: flex;
flex-direction: column;
gap: 2px;
}
.hero-stat-label {
font-size: 10px;
color: var(--text3);
letter-spacing: 0.06em;
text-transform: uppercase;
}
.hero-stat-value {
font-size: 16px;
font-weight: 600;
color: var(--text);
font-variant-numeric: tabular-nums;
}
.hero-stat-value.positive { color: var(--green); }
.hero-stat-value.negative { color: var(--red); }
/* Pillar row */
.pillars {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin: 0 16px 16px;
}
.pillar-card {
background: var(--surface);
border-radius: 18px;
padding: 16px;
border: 1px solid var(--border);
box-shadow: var(--card-shadow);
transition: all 0.3s;
cursor: pointer;
}
.pillar-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
}
.pillar-icon {
width: 32px;
height: 32px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.pi-survival { background: rgba(143,163,200,0.2); }
.pi-optional { background: rgba(124,158,140,0.2); }
.pi-culture { background: rgba(155,126,168,0.2); }
.pi-extra { background: rgba(212,112,112,0.2); }
.pillar-name {
font-size: 12px;
font-weight: 600;
color: var(--text);
transition: color 0.3s;
}
.pillar-jp {
font-size: 10px;
color: var(--text3);
transition: color 0.3s;
}
.pillar-amounts {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 8px;
}
.pillar-spent {
font-size: 18px;
font-weight: 700;
color: var(--text);
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
.pillar-budget {
font-size: 11px;
color: var(--text3);
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
.progress-bar {
height: 4px;
background: var(--progress-bg);
border-radius: 2px;
overflow: hidden;
transition: background 0.3s;
}
.progress-fill {
height: 100%;
border-radius: 2px;
transition: width 0.6s ease, background 0.3s;
}
.pf-survival { background: var(--accent4); }
.pf-optional { background: var(--accent2); }
.pf-culture { background: var(--accent3); }
.pf-extra { background: var(--red); }
/* Recent transactions */
.tx-item {
display: flex;
align-items: center;
gap: 14px;
padding: 12px 0;
border-bottom: 1px solid var(--border);
transition: border-color 0.3s;
}
.tx-item:last-child { border-bottom: none; }
.tx-icon {
width: 40px;
height: 40px;
border-radius: 12px;
background: var(--surface2);
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
transition: background 0.3s;
}
.tx-info { flex: 1; min-width: 0; }
.tx-name {
font-size: 14px;
font-weight: 500;
color: var(--text);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: color 0.3s;
}
.tx-meta {
font-size: 11px;
color: var(--text3);
margin-top: 1px;
transition: color 0.3s;
}
.tx-amount {
font-size: 15px;
font-weight: 600;
color: var(--red);
font-variant-numeric: tabular-nums;
flex-shrink: 0;
}
.tx-amount.income { color: var(--green); }
/* Envelopes screen */
.envelope-item {
display: flex;
align-items: center;
gap: 14px;
padding: 14px 0;
border-bottom: 1px solid var(--border);
cursor: pointer;
transition: border-color 0.3s;
}
.envelope-item:last-child { border-bottom: none; }
.envelope-icon {
width: 44px;
height: 44px;
border-radius: 14px;
background: var(--surface2);
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
flex-shrink: 0;
transition: background 0.3s;
}
.envelope-info { flex: 1; min-width: 0; }
.envelope-name {
font-size: 15px;
font-weight: 500;
color: var(--text);
margin-bottom: 6px;
transition: color 0.3s;
}
.envelope-bar-wrap {
display: flex;
align-items: center;
gap: 8px;
}
.envelope-bar {
flex: 1;
height: 4px;
background: var(--progress-bg);
border-radius: 2px;
overflow: hidden;
transition: background 0.3s;
}
.envelope-bar-fill {
height: 100%;
border-radius: 2px;
transition: width 0.6s ease;
}
.envelope-pct {
font-size: 10px;
color: var(--text3);
font-variant-numeric: tabular-nums;
flex-shrink: 0;
width: 28px;
text-align: right;
transition: color 0.3s;
}
.envelope-right {
text-align: right;
flex-shrink: 0;
}
.envelope-remaining {
font-size: 15px;
font-weight: 600;
color: var(--text);
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
.envelope-remaining.low { color: var(--red); }
.envelope-budget {
font-size: 11px;
color: var(--text3);
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
/* Pillar header row */
.pillar-section-header {
display: flex;
align-items: center;
gap: 10px;
padding: 18px 24px 6px;
}
.psh-dot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
.psh-name {
font-size: 13px;
font-weight: 600;
color: var(--text2);
flex: 1;
transition: color 0.3s;
}
.psh-total {
font-size: 12px;
color: var(--text3);
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
/* Log transaction screen */
.log-header {
display: flex;
align-items: center;
gap: 12px;
padding: 68px 24px 24px;
}
.log-back {
width: 36px;
height: 36px;
border-radius: 50%;
background: var(--surface2);
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
cursor: pointer;
color: var(--accent);
transition: background 0.3s;
}
.log-title {
font-size: 20px;
font-weight: 700;
color: var(--text);
flex: 1;
transition: color 0.3s;
}
.amount-display {
text-align: center;
padding: 8px 24px 32px;
}
.amount-big {
font-size: 56px;
font-weight: 300;
color: var(--text);
letter-spacing: -3px;
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
.amount-big .currency-sym {
font-size: 28px;
font-weight: 400;
color: var(--text3);
vertical-align: super;
margin-right: 4px;
}
.amount-cursor {
display: inline-block;
width: 2px;
height: 44px;
background: var(--accent);
vertical-align: middle;
animation: blink 1s step-end infinite;
border-radius: 1px;
transition: background 0.3s;
}
@keyframes blink { 50% { opacity: 0; } }
.form-group {
margin: 0 16px 12px;
}
.form-label {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text3);
margin-bottom: 8px;
padding-left: 4px;
transition: color 0.3s;
}
.form-input {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 14px;
padding: 14px 16px;
font-size: 15px;
color: var(--text);
width: 100%;
transition: all 0.3s;
}
.form-input.placeholder { color: var(--text3); }
.pillar-chips {
display: flex;
gap: 8px;
padding: 0 16px;
overflow-x: auto;
scrollbar-width: none;
margin-bottom: 12px;
-webkit-overflow-scrolling: touch;
}
.pillar-chips::-webkit-scrollbar { display: none; }
.pillar-chip {
padding: 8px 16px;
border-radius: 20px;
background: var(--surface);
border: 1px solid var(--border);
font-size: 13px;
color: var(--text2);
white-space: nowrap;
cursor: pointer;
transition: all 0.2s;
}
.pillar-chip.selected {
background: var(--pill);
border-color: var(--accent);
color: var(--pill-text);
}
.numpad {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: var(--border);
margin: 8px 16px 0;
border-radius: 18px;
overflow: hidden;
}
.numpad-key {
background: var(--surface);
padding: 18px;
text-align: center;
font-size: 22px;
font-weight: 400;
color: var(--text);
cursor: pointer;
transition: background 0.1s, color 0.3s;
user-select: none;
}
.numpad-key:active { background: var(--surface3); }
.numpad-key.action {
font-size: 16px;
font-weight: 600;
color: var(--accent);
}
.numpad-key.delete { font-size: 18px; }
/* Journal screen */
.month-selector {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 24px;
}
.month-arrow {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--surface2);
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
color: var(--text2);
cursor: pointer;
transition: background 0.3s;
}
.month-name {
font-size: 18px;
font-weight: 600;
color: var(--text);
transition: color 0.3s;
}
.kakeibo-questions {
margin: 0 16px 16px;
display: flex;
flex-direction: column;
gap: 10px;
}
.kq-card {
background: var(--surface);
border-radius: 18px;
padding: 18px;
border: 1px solid var(--border);
box-shadow: var(--card-shadow);
transition: all 0.3s;
}
.kq-num {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.12em;
color: var(--accent);
text-transform: uppercase;
margin-bottom: 4px;
transition: color 0.3s;
}
.kq-question {
font-size: 14px;
font-weight: 600;
color: var(--text);
margin-bottom: 8px;
transition: color 0.3s;
}
.kq-answer {
font-size: 22px;
font-weight: 700;
color: var(--text);
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
.kq-answer.green { color: var(--green); }
.kq-answer.red { color: var(--red); }
.kq-reflection {
font-size: 13px;
color: var(--text2);
line-height: 1.5;
font-style: italic;
transition: color 0.3s;
}
.save-btn {
margin: 0 16px;
background: var(--btn-primary);
color: var(--btn-primary-text);
border-radius: 16px;
padding: 16px;
text-align: center;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
}
/* Pill badge */
.badge {
display: inline-block;
padding: 3px 10px;
border-radius: 20px;
background: var(--pill);
color: var(--pill-text);
font-size: 11px;
font-weight: 600;
transition: all 0.3s;
}
/* Savings ring visual */
.savings-ring-wrap {
display: flex;
justify-content: center;
padding: 16px 0 24px;
}
.savings-ring {
position: relative;
width: 140px;
height: 140px;
}
.savings-ring svg {
transform: rotate(-90deg);
}
.savings-ring-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.srt-pct {
font-size: 28px;
font-weight: 700;
color: var(--text);
display: block;
line-height: 1;
font-variant-numeric: tabular-nums;
transition: color 0.3s;
}
.srt-label {
font-size: 10px;
color: var(--text3);
letter-spacing: 0.06em;
text-transform: uppercase;
transition: color 0.3s;
}
/* Streak */
.streak-row {
display: flex;
gap: 6px;
padding: 0 24px 8px;
}
.streak-dot {
width: 28px;
height: 28px;
border-radius: 8px;
background: var(--surface2);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
transition: background 0.3s;
}
.streak-dot.logged { background: var(--accent); }
.streak-dot.today { background: var(--accent); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent); }
/* Divider */
.divider {
height: 1px;
background: var(--border);
margin: 4px 24px;
transition: background 0.3s;
}
/* Greeting */
.greeting {
padding: 68px 24px 0;
}
.greeting-ja {
font-size: 11px;
letter-spacing: 0.16em;
color: var(--text3);
margin-bottom: 4px;
transition: color 0.3s;
}
.greeting-main {
font-size: 26px;
font-weight: 700;
color: var(--text);
letter-spacing: -0.5px;
transition: color 0.3s;
}
.greeting-main span { color: var(--accent); }
/* Settings screen */
.settings-section {
margin: 0 16px 16px;
}
.setting-row {
display: flex;
align-items: center;
gap: 14px;
padding: 14px 0;
border-bottom: 1px solid var(--border);
transition: border-color 0.3s;
}
.setting-row:last-child { border-bottom: none; }
.setting-icon-wrap {
width: 36px;
height: 36px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.setting-text { flex: 1; }
.setting-name {
font-size: 15px;
color: var(--text);
transition: color 0.3s;
}
.setting-value {
font-size: 12px;
color: var(--text3);
margin-top: 1px;
transition: color 0.3s;
}
.setting-chevron {
font-size: 14px;
color: var(--text3);
transition: color 0.3s;
}
.toggle {
width: 44px;
height: 26px;
border-radius: 13px;
background: var(--green);
position: relative;
flex-shrink: 0;
}
.toggle-knob {
position: absolute;
top: 3px;
right: 3px;
width: 20px;
height: 20px;
border-radius: 50%;
background: white;
box-shadow: 0 1px 4px rgba(0,0,0,0.3);
}
.toggle.off { background: var(--surface3); }
.toggle.off .toggle-knob { right: auto; left: 3px; }
</style>
</head>
<body>
<!-- Controls -->
<div class="theme-bar">
<span class="theme-label">Theme</span>
<div class="theme-btn t-ink active" onclick="setTheme('ink', this)" title="Ink"></div>
<div class="theme-btn t-paper" onclick="setTheme('paper', this)" title="Paper"></div>
<div class="theme-btn t-sakura" onclick="setTheme('sakura', this)" title="Sakura"></div>
<div class="theme-btn t-stone" onclick="setTheme('stone', this)" title="Stone"></div>
</div>
<div class="screen-nav">
<div class="screen-btn active" onclick="showScreen('home', this)">Home</div>
<div class="screen-btn" onclick="showScreen('envelopes', this)">Envelopes</div>
<div class="screen-btn" onclick="showScreen('log', this)">Log</div>
<div class="screen-btn" onclick="showScreen('journal', this)">Journal</div>
</div>
<!-- Phone -->
<div class="phone-wrap">
<div class="phone" id="phone">
<div class="dynamic-island"></div>
<!-- STATUS BAR -->
<div class="status-bar">
<span class="status-time">9:41</span>
<div class="status-icons">
<span class="status-icon"></span>
<span class="status-icon">WiFi</span>
<span class="status-icon">■■■</span>
</div>
</div>
<!-- ═══════════ HOME SCREEN ═══════════ -->
<div class="screen active" id="screen-home">
<div class="scroll-area">
<div class="greeting">
<div class="greeting-ja">今月の予算 · May 2026</div>
<div class="greeting-main">Good morning, <span>Krao</span></div>
</div>
<!-- 7-day streak -->
<div style="padding: 16px 24px 0;">
<div style="display:flex; align-items:center; gap:8px; margin-bottom:8px;">
<span style="font-size:11px; letter-spacing:0.08em; text-transform:uppercase; color:var(--text3); transition:color 0.3s;">Logging streak</span>
<span class="badge">7 days 🔥</span>
</div>
<div class="streak-row" style="padding:0;">
<div class="streak-dot logged">M</div>
<div class="streak-dot logged">T</div>
<div class="streak-dot logged">W</div>
<div class="streak-dot logged">T</div>
<div class="streak-dot logged">F</div>
<div class="streak-dot logged">S</div>
<div class="streak-dot today">S</div>
</div>
</div>
<!-- Hero card -->
<div style="padding: 16px 0 0;">
<div class="hero-card">
<div class="hero-month">Remaining Budget</div>
<div class="hero-amount"><span class="hero-currency">฿</span>28,450</div>
<div class="hero-sub">of ฿65,000 allocated this month</div>
<div class="hero-stats">
<div class="hero-stat">
<span class="hero-stat-label">Income</span>
<span class="hero-stat-value">฿85,000</span>
</div>
<div class="hero-stat">
<span class="hero-stat-label">Spent</span>
<span class="hero-stat-value negative">฿36,550</span>
</div>
<div class="hero-stat">
<span class="hero-stat-label">Saved</span>
<span class="hero-stat-value positive">฿20,000</span>
</div>
</div>
</div>
</div>
<!-- Savings ring -->
<div class="savings-ring-wrap">
<div class="savings-ring">
<svg width="140" height="140" viewBox="0 0 140 140">
<circle cx="70" cy="70" r="58" fill="none" stroke="var(--progress-bg)" stroke-width="10"/>
<circle cx="70" cy="70" r="58" fill="none" stroke="var(--green)" stroke-width="10"
stroke-dasharray="364.4" stroke-dashoffset="291.5" stroke-linecap="round"/>
</svg>
<div class="savings-ring-text">
<span class="srt-pct">23%</span>
<span class="srt-label">saved</span>
</div>
</div>
</div>
<!-- Pillars grid -->
<div class="section-label">Spending Pillars</div>
<div class="pillars">
<div class="pillar-card">
<div class="pillar-header">
<div class="pillar-icon pi-survival">🏠</div>
<div>
<div class="pillar-name">Survival</div>
<div class="pillar-jp">生存</div>
</div>
</div>
<div class="pillar-amounts">
<span class="pillar-spent">฿18,200</span>
<span class="pillar-budget">/ ฿22,000</span>
</div>
<div class="progress-bar"><div class="progress-fill pf-survival" style="width:83%"></div></div>
</div>
<div class="pillar-card">
<div class="pillar-header">
<div class="pillar-icon pi-optional"></div>
<div>
<div class="pillar-name">Optional</div>
<div class="pillar-jp">娯楽</div>
</div>
</div>
<div class="pillar-amounts">
<span class="pillar-spent">฿8,100</span>
<span class="pillar-budget">/ ฿15,000</span>
</div>
<div class="progress-bar"><div class="progress-fill pf-optional" style="width:54%"></div></div>
</div>
<div class="pillar-card">
<div class="pillar-header">
<div class="pillar-icon pi-culture">📚</div>
<div>
<div class="pillar-name">Culture</div>
<div class="pillar-jp">教養</div>
</div>
</div>
<div class="pillar-amounts">
<span class="pillar-spent">฿4,250</span>
<span class="pillar-budget">/ ฿8,000</span>
</div>
<div class="progress-bar"><div class="progress-fill pf-culture" style="width:53%"></div></div>
</div>
<div class="pillar-card">
<div class="pillar-header">
<div class="pillar-icon pi-extra"></div>
<div>
<div class="pillar-name">Extra</div>
<div class="pillar-jp">予備</div>
</div>
</div>
<div class="pillar-amounts">
<span class="pillar-spent">฿6,000</span>
<span class="pillar-budget">/ ฿10,000</span>
</div>
<div class="progress-bar"><div class="progress-fill pf-extra" style="width:60%"></div></div>
</div>
</div>
<!-- Recent transactions -->
<div class="section-label">Recent</div>
<div class="card">
<div class="tx-item">
<div class="tx-icon">🛒</div>
<div class="tx-info">
<div class="tx-name">Tops Supermarket</div>
<div class="tx-meta">Groceries · Survival</div>
</div>
<div class="tx-amount">-฿1,240</div>
</div>
<div class="tx-item">
<div class="tx-icon"></div>
<div class="tx-info">
<div class="tx-name">Café Amazon</div>
<div class="tx-meta">Coffee · Optional</div>
</div>
<div class="tx-amount">-฿85</div>
</div>
<div class="tx-item">
<div class="tx-icon">📖</div>
<div class="tx-info">
<div class="tx-name">Kinokuniya</div>
<div class="tx-meta">Books · Culture</div>
</div>
<div class="tx-amount">-฿520</div>
</div>
<div class="tx-item">
<div class="tx-icon">💰</div>
<div class="tx-info">
<div class="tx-name">Salary</div>
<div class="tx-meta">Income · May 1</div>
</div>
<div class="tx-amount income">+฿85,000</div>
</div>
</div>
</div>
<!-- FAB -->
<div class="fab" onclick="showScreen('log', document.querySelector('.screen-btn:nth-child(3)'))">+</div>
<!-- Tab bar -->
<div class="tab-bar">
<div class="tab-item active" onclick="showScreen('home', document.querySelector('.screen-btn:nth-child(1)'))">
<div class="tab-icon"></div>
<div class="tab-label">Home</div>
</div>
<div class="tab-item" onclick="showScreen('envelopes', document.querySelector('.screen-btn:nth-child(2)'))">
<div class="tab-icon"></div>
<div class="tab-label">Envelopes</div>
</div>
<div class="tab-item" onclick="showScreen('journal', document.querySelector('.screen-btn:nth-child(4)'))">
<div class="tab-icon"></div>
<div class="tab-label">Journal</div>
</div>
<div class="tab-item">
<div class="tab-icon"></div>
<div class="tab-label">Settings</div>
</div>
</div>
</div>
<!-- ═══════════ ENVELOPES SCREEN ═══════════ -->
<div class="screen" id="screen-envelopes">
<div class="scroll-area">
<div class="page-title">Envelopes</div>
<div class="page-subtitle">May 2026 · ฿65,000 allocated</div>
<!-- Survival -->
<div class="pillar-section-header">
<div class="psh-dot" style="background:var(--accent4)"></div>
<span class="psh-name">🏠 Survival · 生存</span>
<span class="psh-total">฿18,200 / ฿22,000</span>
</div>
<div class="card" style="margin-bottom:8px; padding: 6px 18px;">
<div class="envelope-item">
<div class="envelope-icon">🏠</div>
<div class="envelope-info">
<div class="envelope-name">Rent</div>
<div class="envelope-bar-wrap">
<div class="envelope-bar"><div class="envelope-bar-fill" style="width:100%; background:var(--accent4)"></div></div>
<span class="envelope-pct">100%</span>
</div>
</div>
<div class="envelope-right">
<div class="envelope-remaining low">฿0</div>
<div class="envelope-budget">of ฿12,000</div>
</div>
</div>
<div class="envelope-item">
<div class="envelope-icon">🛒</div>
<div class="envelope-info">
<div class="envelope-name">Groceries</div>
<div class="envelope-bar-wrap">
<div class="envelope-bar"><div class="envelope-bar-fill" style="width:62%; background:var(--accent4)"></div></div>
<span class="envelope-pct">62%</span>
</div>
</div>
<div class="envelope-right">
<div class="envelope-remaining">฿3,800</div>
<div class="envelope-budget">of ฿10,000</div>
</div>
</div>
</div>
<!-- Optional -->
<div class="pillar-section-header">
<div class="psh-dot" style="background:var(--accent2)"></div>
<span class="psh-name">✨ Optional · 娯楽</span>
<span class="psh-total">฿8,100 / ฿15,000</span>
</div>
<div class="card" style="margin-bottom:8px; padding: 6px 18px;">
<div class="envelope-item">
<div class="envelope-icon">🍜</div>
<div class="envelope-info">
<div class="envelope-name">Dining Out</div>
<div class="envelope-bar-wrap">
<div class="envelope-bar"><div class="envelope-bar-fill" style="width:44%; background:var(--accent2)"></div></div>
<span class="envelope-pct">44%</span>
</div>
</div>
<div class="envelope-right">
<div class="envelope-remaining">฿5,600</div>
<div class="envelope-budget">of ฿10,000</div>
</div>
</div>
<div class="envelope-item">
<div class="envelope-icon">🛍</div>
<div class="envelope-info">
<div class="envelope-name">Shopping</div>
<div class="envelope-bar-wrap">
<div class="envelope-bar"><div class="envelope-bar-fill" style="width:76%; background:var(--accent2)"></div></div>
<span class="envelope-pct">76%</span>
</div>
</div>
<div class="envelope-right">
<div class="envelope-remaining">฿1,200</div>
<div class="envelope-budget">of ฿5,000</div>
</div>
</div>
</div>
<!-- Culture -->
<div class="pillar-section-header">
<div class="psh-dot" style="background:var(--accent3)"></div>
<span class="psh-name">📚 Culture · 教養</span>
<span class="psh-total">฿4,250 / ฿8,000</span>
</div>
<div class="card" style="margin-bottom:8px; padding: 6px 18px;">
<div class="envelope-item">
<div class="envelope-icon">📖</div>
<div class="envelope-info">
<div class="envelope-name">Books</div>
<div class="envelope-bar-wrap">
<div class="envelope-bar"><div class="envelope-bar-fill" style="width:35%; background:var(--accent3)"></div></div>
<span class="envelope-pct">35%</span>
</div>
</div>
<div class="envelope-right">
<div class="envelope-remaining">฿3,250</div>
<div class="envelope-budget">of ฿5,000</div>
</div>
</div>
<div class="envelope-item">
<div class="envelope-icon">🎬</div>
<div class="envelope-info">
<div class="envelope-name">Entertainment</div>
<div class="envelope-bar-wrap">
<div class="envelope-bar"><div class="envelope-bar-fill" style="width:67%; background:var(--accent3)"></div></div>
<span class="envelope-pct">67%</span>
</div>
</div>
<div class="envelope-right">
<div class="envelope-remaining">฿1,000</div>
<div class="envelope-budget">of ฿3,000</div>
</div>
</div>
</div>
<!-- Extra -->
<div class="pillar-section-header">
<div class="psh-dot" style="background:var(--red)"></div>
<span class="psh-name">⚡ Extra · 予備</span>
<span class="psh-total">฿6,000 / ฿10,000</span>
</div>
<div class="card" style="padding: 6px 18px;">
<div class="envelope-item">
<div class="envelope-icon">💊</div>
<div class="envelope-info">
<div class="envelope-name">Medical</div>
<div class="envelope-bar-wrap">
<div class="envelope-bar"><div class="envelope-bar-fill" style="width:60%; background:var(--red)"></div></div>
<span class="envelope-pct">60%</span>
</div>
</div>
<div class="envelope-right">
<div class="envelope-remaining">฿4,000</div>
<div class="envelope-budget">of ฿10,000</div>
</div>
</div>
</div>
</div>
<div class="fab">+</div>
<div class="tab-bar">
<div class="tab-item" onclick="showScreen('home', document.querySelector('.screen-btn:nth-child(1)'))">
<div class="tab-icon"></div>
<div class="tab-label">Home</div>
</div>
<div class="tab-item active">
<div class="tab-icon"></div>
<div class="tab-label">Envelopes</div>
</div>
<div class="tab-item" onclick="showScreen('journal', document.querySelector('.screen-btn:nth-child(4)'))">
<div class="tab-icon"></div>
<div class="tab-label">Journal</div>
</div>
<div class="tab-item">
<div class="tab-icon"></div>
<div class="tab-label">Settings</div>
</div>
</div>
</div>
<!-- ═══════════ LOG SCREEN ═══════════ -->
<div class="screen" id="screen-log">
<div class="scroll-area" style="padding-bottom: 20px;">
<div class="log-header">
<div class="log-back" onclick="showScreen('home', document.querySelector('.screen-btn:nth-child(1)'))"></div>
<div class="log-title">Log Expense</div>
<div style="font-size:13px; color:var(--text3); transition:color 0.3s;">Today</div>
</div>
<div class="amount-display">
<div class="amount-big">
<span class="currency-sym">฿</span>0<span class="amount-cursor"></span>
</div>
</div>
<!-- Description -->
<div class="form-group">
<div class="form-label">What did you spend on?</div>
<div class="form-input placeholder">e.g. Lunch at Pier 21…</div>
</div>
<!-- Pillar chips -->
<div style="padding: 0 0 4px;">
<div class="form-label" style="padding: 0 20px 8px;">Pillar</div>
<div class="pillar-chips">
<div class="pillar-chip selected">🏠 Survival</div>
<div class="pillar-chip">✨ Optional</div>
<div class="pillar-chip">📚 Culture</div>
<div class="pillar-chip">⚡ Extra</div>
</div>
</div>
<!-- Envelope -->
<div class="form-group">
<div class="form-label">Envelope</div>
<div class="form-input placeholder">Select envelope →</div>
</div>
<!-- Note -->
<div class="form-group">
<div class="form-label">Note (optional)</div>
<div class="form-input placeholder" style="min-height:60px;">How did this make you feel?</div>
</div>
<!-- Numpad -->
<div class="numpad">
<div class="numpad-key">1</div>
<div class="numpad-key">2</div>
<div class="numpad-key">3</div>
<div class="numpad-key">4</div>
<div class="numpad-key">5</div>
<div class="numpad-key">6</div>
<div class="numpad-key">7</div>
<div class="numpad-key">8</div>
<div class="numpad-key">9</div>
<div class="numpad-key action">.</div>
<div class="numpad-key">0</div>
<div class="numpad-key delete"></div>
</div>
<div style="margin: 12px 16px 0;">
<div class="save-btn">Save Transaction</div>
</div>
</div>
</div>
<!-- ═══════════ JOURNAL SCREEN ═══════════ -->
<div class="screen" id="screen-journal">
<div class="scroll-area">
<div class="page-title">Journal</div>
<div class="page-subtitle">月次記録 · Monthly reflection</div>
<div class="month-selector">
<div class="month-arrow"></div>
<div class="month-name">May 2026</div>
<div class="month-arrow"></div>
</div>
<!-- Intention -->
<div class="section-label">This month's intention</div>
<div class="card">
<div style="font-size:13px; color:var(--text2); line-height:1.6; font-style:italic; transition:color 0.3s;">
"Save more by cooking at home. Try to keep Optional spending under ฿12,000 this month."
</div>
</div>
<!-- Four questions -->
<div class="section-label">The four questions · 四つの問い</div>
<div class="kakeibo-questions">
<div class="kq-card">
<div class="kq-num">01 · いくら稼ぎましたか</div>
<div class="kq-question">How much did you earn?</div>
<div class="kq-answer">฿85,000</div>
</div>
<div class="kq-card">
<div class="kq-num">02 · いくら使いましたか</div>
<div class="kq-question">How much did you spend?</div>
<div class="kq-answer red">฿36,550 <span style="font-size:13px; font-weight:400; color:var(--text3);">so far</span></div>
</div>
<div class="kq-card">
<div class="kq-num">03 · いくら貯金できましたか</div>
<div class="kq-question">How much did you save?</div>
<div class="kq-answer green">฿20,000 <span style="font-size:13px; font-weight:400; color:var(--text3);">(23%)</span></div>
</div>
<div class="kq-card">
<div class="kq-num">04 · どうすれば改善できますか</div>
<div class="kq-question">How can you improve?</div>
<div class="kq-reflection">"Shopping envelope is 76% used with 2 weeks left. Plan before buying."</div>
</div>
</div>
<!-- Past months -->
<div class="section-label">Past reflections</div>
<div class="card" style="padding: 8px 18px;">
<div class="tx-item">
<div class="tx-icon" style="background:var(--surface3);">📓</div>
<div class="tx-info">
<div class="tx-name">April 2026</div>
<div class="tx-meta">Saved 18% · ฿15,300</div>
</div>
<div style="color:var(--text3); font-size:14px;"></div>
</div>
<div class="tx-item">
<div class="tx-icon" style="background:var(--surface3);">📓</div>
<div class="tx-info">
<div class="tx-name">March 2026</div>
<div class="tx-meta">Saved 22% · ฿18,700</div>
</div>
<div style="color:var(--text3); font-size:14px;"></div>
</div>
</div>
</div>
<div class="tab-bar">
<div class="tab-item" onclick="showScreen('home', document.querySelector('.screen-btn:nth-child(1)'))">
<div class="tab-icon"></div>
<div class="tab-label">Home</div>
</div>
<div class="tab-item" onclick="showScreen('envelopes', document.querySelector('.screen-btn:nth-child(2)'))">
<div class="tab-icon"></div>
<div class="tab-label">Envelopes</div>
</div>
<div class="tab-item active">
<div class="tab-icon"></div>
<div class="tab-label">Journal</div>
</div>
<div class="tab-item">
<div class="tab-icon"></div>
<div class="tab-label">Settings</div>
</div>
</div>
</div>
</div><!-- /phone -->
</div><!-- /phone-wrap -->
<script>
function setTheme(theme, btn) {
document.body.className = theme === 'ink' ? '' : 'theme-' + theme;
document.querySelectorAll('.theme-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
}
function showScreen(name, navBtn) {
// hide all screens
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
document.getElementById('screen-' + name).classList.add('active');
// update top nav
document.querySelectorAll('.screen-btn').forEach(b => b.classList.remove('active'));
if (navBtn) navBtn.classList.add('active');
}
</script>
</body>
</html>