eloigil6 Cursor commited on
Commit
fa2d558
·
1 Parent(s): 22a31fa

Add favicon and improve code formatting in app components

Browse files

Track logo.png with Git LFS so Hugging Face Xet accepts the push.

Co-authored-by: Cursor <cursoragent@cursor.com>

.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ frontend/app/logo.png filter=lfs diff=lfs merge=lfs -text
frontend/app/app.jsx CHANGED
@@ -2,26 +2,29 @@
2
  Mini Fam — app shell
3
  ============================================================ */
4
  const NAV = [
5
- { id: "home", label: "Family Brief", icon: "home" },
6
- { id: "chat", label: "Chat", icon: "chat" },
7
- { id: "calendar", label: "Calendar", icon: "calendar" },
8
- { id: "recipes", label: "Recipes", icon: "recipes" },
9
- { id: "meals", label: "Meal plan", icon: "meals" },
10
- { id: "notes", label: "Notes", icon: "notes" },
11
  ];
12
  const TITLES = {
13
- home: ["", ""],
14
- chat: ["Chat", "One assistant, the whole family's context — running on your device"],
 
 
 
15
  calendar: ["Calendar", "The shared family week"],
16
- recipes: ["Recipes", "Your recipe box, stored as plain Markdown"],
17
- meals: ["Meal plan", "A week of dinners, planned and shopped for"],
18
- notes: ["Notes", "A private space for each person"],
19
  settings: ["Settings", "Your family, stored locally in data/members.json"],
20
  };
21
 
22
  function App() {
23
  const [route, setRoute] = useState("home");
24
- const [active, setActive] = useState(null); // who's talking (null until roster loads)
25
  const [chatSeed, setChatSeed] = useState(null);
26
  const [recipeOpen, setRecipeOpen] = useState(null); // recipe forwarded from meal plan
27
 
@@ -29,18 +32,26 @@ function App() {
29
  // setMembers (from seed.jsx) updates the shared global every screen reads;
30
  // the local state mirror just forces a re-render so changes propagate.
31
  const [members, setMembersState] = useState([]);
32
- const applyMembers = (list) => { setMembers(list); setMembersState(list || []); };
 
 
 
33
  useEffect(() => {
34
  MFLive.members()
35
  .then((list) => {
36
  applyMembers(list);
37
- setActive((a) => (a && list.some((x) => x.id === a)) ? a : (list[0] ? list[0].id : null));
 
 
38
  })
39
  .catch((e) => console.warn("Mini Fam: member roster load failed —", e));
40
  }, []);
41
 
42
  const addMember = (name, veg) =>
43
- MFLive.addMember(name, veg).then((list) => { applyMembers(list); return list; });
 
 
 
44
  const removeMember = (id) =>
45
  MFLive.removeMember(id).then((list) => {
46
  applyMembers(list);
@@ -53,7 +64,10 @@ function App() {
53
  const [plan] = useLive(() => MFLive.mealPlan(), [], emptyPlan);
54
 
55
  const go = (r) => setRoute(r);
56
- const ask = (text) => { setChatSeed(text); setRoute("chat"); };
 
 
 
57
 
58
  const [title, sub] = TITLES[route];
59
 
@@ -63,12 +77,18 @@ function App() {
63
  <aside className="sidebar">
64
  <div className="brand">
65
  <div className="mark" />
66
- <div className="word">Mini<b>Fam</b></div>
 
 
67
  </div>
68
 
69
  <nav>
70
- {NAV.map(n => (
71
- <button key={n.id} className={`nav-item ${route === n.id ? "active" : ""}`} onClick={() => go(n.id)}>
 
 
 
 
72
  <Icon name={n.icon} size={18} />
73
  <span>{n.label}</span>
74
  {n.badge && <span className="badge">{n.badge}</span>}
@@ -78,26 +98,29 @@ function App() {
78
 
79
  <div className="nav-spacer" />
80
 
81
- <button className={`nav-item ${route === "settings" ? "active" : ""}`} onClick={() => go("settings")}><Icon name="settings" size={18} /><span>Settings</span></button>
82
- <div className="account" style={{ marginTop: 8 }}>
83
- <div className="gmail"><Icon name="mail" size={15} style={{ color: "var(--ash)" }} /></div>
 
 
 
 
 
 
 
 
84
  <div className="meta">
85
  <div className="t">The Soto Family</div>
86
  <div className="s">soto.family@gmail.com</div>
87
  </div>
88
  <div className="dot" title="Running locally" />
89
- </div>
90
  </aside>
91
 
92
  {/* ---- main ---- */}
93
  <main className="main">
94
  <header className="topbar">
95
- {route === "home" ? (
96
- <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
97
- <div className="mark" style={{ width: 26, height: 26, borderRadius: 8, background: "var(--spectrum)" }} />
98
- <span style={{ fontSize: 14, fontWeight: 600, letterSpacing: "-.01em" }}>Family Brief</span>
99
- </div>
100
- ) : (
101
  <div>
102
  <h1>{title}</h1>
103
  {sub && <div className="sub">{sub}</div>}
@@ -105,11 +128,18 @@ function App() {
105
  )}
106
 
107
  <div className="topbar-right">
108
- <button className="btn btn-icon btn-ghost" title="Notifications"><Icon name="bell" size={18} /></button>
 
 
109
  <div className="member-switch">
110
  <span className="who">Who's here?</span>
111
- {members.map(mem => (
112
- <button key={mem.id} className={`m-chip ${active === mem.id ? "on" : ""}`} onClick={() => setActive(mem.id)} title={mem.full}>
 
 
 
 
 
113
  <Avatar member={mem} size="sm" ring={active === mem.id} />
114
  <span className="name">{mem.name}</span>
115
  </button>
@@ -118,18 +148,52 @@ function App() {
118
  </div>
119
  </header>
120
 
121
- <div className={`view scroll ${route === "chat" ? "" : ""}`} style={route === "chat" ? { paddingBottom: 18, display: "flex", flexDirection: "column" } : {}}>
122
- {route === "home" && <Home activeMember={active} onNavigate={go} onAsk={ask} plan={plan} recipes={recipes} />}
123
- {route === "chat" && <Chat activeMember={active} seedInput={chatSeed} clearSeed={() => setChatSeed(null)} recipes={recipes} />}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  {route === "calendar" && <Calendar onNavigate={go} />}
125
  {route === "recipes" && <Recipes recipes={recipes} />}
126
- {route === "meals" && <Meals plan={plan} onOpenRecipe={(r) => setRecipeOpen(r)} />}
127
- {route === "notes" && <Notes activeMember={active} members={members} />}
128
- {route === "settings" && <Settings members={members} onAdd={addMember} onRemove={removeMember} />}
 
 
 
 
 
 
 
 
 
 
129
  </div>
130
  </main>
131
 
132
- {recipeOpen && <RecipeDrawer recipe={recipeOpen} onClose={() => setRecipeOpen(null)} />}
 
 
133
  </div>
134
  );
135
  }
 
2
  Mini Fam — app shell
3
  ============================================================ */
4
  const NAV = [
5
+ { id: "home", label: "Family Brief", icon: "home" },
6
+ { id: "chat", label: "Chat", icon: "chat" },
7
+ { id: "calendar", label: "Calendar", icon: "calendar" },
8
+ { id: "recipes", label: "Recipes", icon: "recipes" },
9
+ { id: "meals", label: "Meal plan", icon: "meals" },
10
+ { id: "notes", label: "Notes", icon: "notes" },
11
  ];
12
  const TITLES = {
13
+ home: ["", ""],
14
+ chat: [
15
+ "Chat",
16
+ "One assistant, the whole family's context — running on your device",
17
+ ],
18
  calendar: ["Calendar", "The shared family week"],
19
+ recipes: ["Recipes", "Your recipe box, stored as plain Markdown"],
20
+ meals: ["Meal plan", "A week of dinners, planned and shopped for"],
21
+ notes: ["Notes", "A private space for each person"],
22
  settings: ["Settings", "Your family, stored locally in data/members.json"],
23
  };
24
 
25
  function App() {
26
  const [route, setRoute] = useState("home");
27
+ const [active, setActive] = useState(null); // who's talking (null until roster loads)
28
  const [chatSeed, setChatSeed] = useState(null);
29
  const [recipeOpen, setRecipeOpen] = useState(null); // recipe forwarded from meal plan
30
 
 
32
  // setMembers (from seed.jsx) updates the shared global every screen reads;
33
  // the local state mirror just forces a re-render so changes propagate.
34
  const [members, setMembersState] = useState([]);
35
+ const applyMembers = (list) => {
36
+ setMembers(list);
37
+ setMembersState(list || []);
38
+ };
39
  useEffect(() => {
40
  MFLive.members()
41
  .then((list) => {
42
  applyMembers(list);
43
+ setActive((a) =>
44
+ a && list.some((x) => x.id === a) ? a : list[0] ? list[0].id : null,
45
+ );
46
  })
47
  .catch((e) => console.warn("Mini Fam: member roster load failed —", e));
48
  }, []);
49
 
50
  const addMember = (name, veg) =>
51
+ MFLive.addMember(name, veg).then((list) => {
52
+ applyMembers(list);
53
+ return list;
54
+ });
55
  const removeMember = (id) =>
56
  MFLive.removeMember(id).then((list) => {
57
  applyMembers(list);
 
64
  const [plan] = useLive(() => MFLive.mealPlan(), [], emptyPlan);
65
 
66
  const go = (r) => setRoute(r);
67
+ const ask = (text) => {
68
+ setChatSeed(text);
69
+ setRoute("chat");
70
+ };
71
 
72
  const [title, sub] = TITLES[route];
73
 
 
77
  <aside className="sidebar">
78
  <div className="brand">
79
  <div className="mark" />
80
+ <div className="word">
81
+ Mini<b>Fam</b>
82
+ </div>
83
  </div>
84
 
85
  <nav>
86
+ {NAV.map((n) => (
87
+ <button
88
+ key={n.id}
89
+ className={`nav-item ${route === n.id ? "active" : ""}`}
90
+ onClick={() => go(n.id)}
91
+ >
92
  <Icon name={n.icon} size={18} />
93
  <span>{n.label}</span>
94
  {n.badge && <span className="badge">{n.badge}</span>}
 
98
 
99
  <div className="nav-spacer" />
100
 
101
+ <button
102
+ className={`nav-item ${route === "settings" ? "active" : ""}`}
103
+ onClick={() => go("settings")}
104
+ >
105
+ <Icon name="settings" size={18} />
106
+ <span>Settings</span>
107
+ </button>
108
+ {/* <div className="account" style={{ marginTop: 8 }}>
109
+ <div className="gmail">
110
+ <Icon name="mail" size={15} style={{ color: "var(--ash)" }} />
111
+ </div>
112
  <div className="meta">
113
  <div className="t">The Soto Family</div>
114
  <div className="s">soto.family@gmail.com</div>
115
  </div>
116
  <div className="dot" title="Running locally" />
117
+ </div> */}
118
  </aside>
119
 
120
  {/* ---- main ---- */}
121
  <main className="main">
122
  <header className="topbar">
123
+ {route === "home" ? null : (
 
 
 
 
 
124
  <div>
125
  <h1>{title}</h1>
126
  {sub && <div className="sub">{sub}</div>}
 
128
  )}
129
 
130
  <div className="topbar-right">
131
+ <button className="btn btn-icon btn-ghost" title="Notifications">
132
+ <Icon name="bell" size={18} />
133
+ </button>
134
  <div className="member-switch">
135
  <span className="who">Who's here?</span>
136
+ {members.map((mem) => (
137
+ <button
138
+ key={mem.id}
139
+ className={`m-chip ${active === mem.id ? "on" : ""}`}
140
+ onClick={() => setActive(mem.id)}
141
+ title={mem.full}
142
+ >
143
  <Avatar member={mem} size="sm" ring={active === mem.id} />
144
  <span className="name">{mem.name}</span>
145
  </button>
 
148
  </div>
149
  </header>
150
 
151
+ <div
152
+ className={`view scroll ${route === "chat" ? "" : ""}`}
153
+ style={
154
+ route === "chat"
155
+ ? { paddingBottom: 18, display: "flex", flexDirection: "column" }
156
+ : {}
157
+ }
158
+ >
159
+ {route === "home" && (
160
+ <Home
161
+ activeMember={active}
162
+ onNavigate={go}
163
+ onAsk={ask}
164
+ plan={plan}
165
+ recipes={recipes}
166
+ />
167
+ )}
168
+ {route === "chat" && (
169
+ <Chat
170
+ activeMember={active}
171
+ seedInput={chatSeed}
172
+ clearSeed={() => setChatSeed(null)}
173
+ recipes={recipes}
174
+ />
175
+ )}
176
  {route === "calendar" && <Calendar onNavigate={go} />}
177
  {route === "recipes" && <Recipes recipes={recipes} />}
178
+ {route === "meals" && (
179
+ <Meals plan={plan} onOpenRecipe={(r) => setRecipeOpen(r)} />
180
+ )}
181
+ {route === "notes" && (
182
+ <Notes activeMember={active} members={members} />
183
+ )}
184
+ {route === "settings" && (
185
+ <Settings
186
+ members={members}
187
+ onAdd={addMember}
188
+ onRemove={removeMember}
189
+ />
190
+ )}
191
  </div>
192
  </main>
193
 
194
+ {recipeOpen && (
195
+ <RecipeDrawer recipe={recipeOpen} onClose={() => setRecipeOpen(null)} />
196
+ )}
197
  </div>
198
  );
199
  }
frontend/app/logo.png ADDED

Git LFS Details

  • SHA256: 23d22de2e498c82e9b6a72577e0d80a939a04fa988375eecf16019d86bb81ca8
  • Pointer size: 131 Bytes
  • Size of remote file: 122 kB
frontend/app/minifam.css CHANGED
@@ -7,31 +7,51 @@
7
 
8
  :root {
9
  /* ---- neutral scale (achromatic, faintly warm) ---- */
10
- --ink: #1a1a18; /* near-black text */
11
- --ink-soft: #4a4a46; /* secondary heading */
12
- --ash: #84847d; /* secondary body / captions */
13
- --ash-light: #a6a69f; /* tertiary / placeholder */
14
- --pebble: #dcdcd6; /* borders / neutral buttons */
15
- --fog: #ececE7; /* hairlines / fills */
16
- --canvas: #f4f3ef; /* app background */
17
- --snow: #ffffff; /* card base */
18
 
19
  /* ---- the spectrum (the brand's only color) ---- */
20
- --spectrum: linear-gradient(100deg,
21
- #c679c4 0%, #fa3d1d 24%, #ffb005 48%, #c9c9fe 74%, #0358f7 100%);
22
- --spectrum-soft: linear-gradient(100deg,
23
- #e6c3e5 0%, #fbb6aa 24%, #ffe2a3 48%, #e7e7ff 74%, #aac4fc 100%);
24
- --rose: #c679c4;
25
- --ember: #fa3d1d;
26
- --marigold:#ffb005;
27
- --lavender:#8f8ff0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  --signal: #0358f7;
29
 
30
  /* ---- member identity hues (used only as tints + dots) ---- */
31
- --m-elena: #c25aa6;
32
  --m-marcus: #2f6df0;
33
- --m-maya: #d98a12;
34
- --m-leo: #1aa06b;
35
 
36
  /* ---- type ---- */
37
  --font-sans: "Hanken Grotesk", system-ui, sans-serif;
@@ -43,16 +63,25 @@
43
  --r-md: 14px;
44
  --r-sm: 10px;
45
  --r-pill: 999px;
46
- --spectrum-amount: 1; /* tweakable */
47
 
48
  /* ---- shadows: soft, low, like paper lift ---- */
49
- --shadow-sm: 0 1px 2px rgba(26,26,24,.04), 0 1px 1px rgba(26,26,24,.03);
50
- --shadow-md: 0 4px 16px -6px rgba(26,26,24,.10), 0 1px 3px rgba(26,26,24,.05);
51
- --shadow-lg: 0 18px 50px -16px rgba(26,26,24,.18), 0 4px 12px -6px rgba(26,26,24,.08);
 
 
 
 
52
  }
53
 
54
- * { box-sizing: border-box; }
55
- html, body { height: 100%; }
 
 
 
 
 
56
  body {
57
  margin: 0;
58
  font-family: var(--font-sans);
@@ -61,14 +90,33 @@ body {
61
  -webkit-font-smoothing: antialiased;
62
  text-rendering: optimizeLegibility;
63
  }
64
- #root { height: 100%; }
65
- button { font-family: inherit; cursor: pointer; }
66
- ::selection { background: rgba(143,143,240,.28); }
 
 
 
 
 
 
 
67
 
68
  /* scrollbars: thin, quiet */
69
- .scroll::-webkit-scrollbar { width: 10px; height: 10px; }
70
- .scroll::-webkit-scrollbar-thumb { background: rgba(132,132,125,.28); border-radius: 999px; border: 3px solid transparent; background-clip: padding-box; }
71
- .scroll::-webkit-scrollbar-thumb:hover { background: rgba(132,132,125,.45); background-clip: padding-box; border: 3px solid transparent; }
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  /* ============================================================
74
  App shell
@@ -86,10 +134,11 @@ button { font-family: inherit; cursor: pointer; }
86
  content: "";
87
  position: absolute;
88
  inset: -20% -10% auto auto;
89
- width: 70vw; height: 60vh;
 
90
  background: var(--spectrum);
91
  filter: blur(120px);
92
- opacity: calc(.10 * var(--spectrum-amount));
93
  pointer-events: none;
94
  z-index: 0;
95
  }
@@ -106,461 +155,1641 @@ button { font-family: inherit; cursor: pointer; }
106
  flex-direction: column;
107
  gap: 4px;
108
  border-right: 1px solid var(--fog);
109
- background: rgba(255,255,255,.45);
110
  backdrop-filter: blur(18px);
111
  }
112
- .brand { display: flex; align-items: center; gap: 11px; padding: 6px 8px 20px; }
 
 
 
 
 
113
  .brand .mark {
114
- width: 30px; height: 30px; border-radius: 9px;
115
- background: var(--spectrum);
116
- box-shadow: 0 2px 8px -2px rgba(250,61,29,.35);
117
  flex: none;
118
  }
119
- .brand .word { font-size: 19px; font-weight: 500; letter-spacing: -.02em; }
120
- .brand .word b { font-weight: 700; }
 
 
 
 
 
 
121
 
122
- .nav-label { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--ash-light); padding: 14px 12px 6px; font-weight: 600; }
 
 
 
 
 
 
 
123
  .nav-item {
124
- display: flex; align-items: center; gap: 12px;
125
- padding: 9px 12px; border-radius: 11px;
126
- color: var(--ink-soft); font-size: 14.5px; font-weight: 500;
127
- border: none; background: none; width: 100%; text-align: left;
 
 
 
 
 
 
 
 
128
  white-space: nowrap;
129
- transition: background .15s, color .15s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  }
131
- .nav-item > span { white-space: nowrap; }
132
- .nav-item:hover { background: rgba(26,26,24,.045); color: var(--ink); }
133
- .nav-item.active { background: var(--snow); color: var(--ink); box-shadow: var(--shadow-sm); }
134
- .nav-item .ico { color: var(--ash); flex: none; }
135
- .nav-item.active .ico { color: var(--ink); }
136
  .nav-item .badge {
137
- margin-left: auto; font-size: 11px; font-weight: 600;
138
- min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
139
- background: var(--ink); color: #fff; display: grid; place-items: center;
 
 
 
 
 
 
 
 
 
 
 
140
  }
141
- .nav-spacer { flex: 1; }
142
 
143
  .account {
144
- display: flex; align-items: center; gap: 10px;
145
- padding: 10px; border-radius: 13px; border: 1px solid var(--fog);
146
- background: rgba(255,255,255,.6);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
- .account .gmail { width: 26px; height: 26px; border-radius: 7px; background: var(--fog); display: grid; place-items: center; flex: none; }
149
- .account .meta { min-width: 0; }
150
- .account .meta .t { font-size: 12.5px; font-weight: 600; line-height: 1.2; }
151
- .account .meta .s { font-size: 11px; color: var(--ash); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
152
- .account .dot { margin-left: auto; width: 7px; height: 7px; border-radius: 999px; background: var(--m-leo); flex: none; box-shadow: 0 0 0 3px rgba(26,160,107,.16); }
153
 
154
  /* ---- main ---- */
155
- .main { position: relative; z-index: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; height: 100vh; }
 
 
 
 
 
 
 
 
156
  .topbar {
157
- display: flex; align-items: center; gap: 16px;
 
 
158
  padding: 18px 30px 14px;
159
  flex: none;
160
  }
161
- .topbar h1 { font-size: 27px; font-weight: 300; letter-spacing: -.03em; margin: 0; }
162
- .topbar .sub { font-size: 13px; color: var(--ash); margin-top: 2px; }
163
- .topbar-right { margin-left: auto; display: flex; align-items: center; gap: 14px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
- .member-switch { display: flex; align-items: center; gap: 6px; padding: 4px; background: rgba(255,255,255,.6); border: 1px solid var(--fog); border-radius: var(--r-pill); }
166
- .member-switch .who { font-size: 11px; color: var(--ash); padding: 0 8px 0 6px; font-weight: 500; white-space: nowrap; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  .m-chip {
168
- display: flex; align-items: center; gap: 7px;
169
- padding: 4px 11px 4px 4px; border-radius: var(--r-pill);
170
- border: 1px solid transparent; background: none; transition: background .15s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  }
172
- .m-chip:hover { background: rgba(26,26,24,.04); }
173
- .m-chip.on { background: var(--snow); box-shadow: var(--shadow-sm); }
174
- .m-chip .name { font-size: 13px; font-weight: 500; display: none; }
175
- .m-chip.on .name { display: inline; }
176
 
177
- .view { flex: 1; min-height: 0; overflow-y: auto; padding: 6px 30px 36px; }
178
- .view-wide { max-width: 1180px; }
 
 
 
 
 
 
 
179
 
180
  /* ============================================================
181
  Avatars
182
  ============================================================ */
183
  .av {
184
  --c: var(--ash);
185
- border-radius: 999px; flex: none;
186
- display: grid; place-items: center;
187
- font-weight: 600; letter-spacing: -.01em;
 
 
 
188
  background: color-mix(in srgb, var(--c) 16%, white);
189
  color: color-mix(in srgb, var(--c) 62%, #20201c);
190
  border: 1px solid color-mix(in srgb, var(--c) 24%, white);
191
  }
192
- .av-xs { width: 22px; height: 22px; font-size: 10px; }
193
- .av-sm { width: 30px; height: 30px; font-size: 12px; }
194
- .av-md { width: 40px; height: 40px; font-size: 15px; }
195
- .av-lg { width: 54px; height: 54px; font-size: 19px; }
196
- .av-ring { box-shadow: 0 0 0 2px var(--snow), 0 0 0 3.5px color-mix(in srgb, var(--c) 55%, white); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
  /* the assistant's mark — the spectrum, alive */
199
- .orb { border-radius: 999px; background: var(--spectrum); flex: none; position: relative; }
200
- .orb::after { content:""; position:absolute; inset: 22%; border-radius: 999px; background: rgba(255,255,255,.55); filter: blur(2px); }
201
- .orb-xs { width: 22px; height: 22px; }
202
- .orb-sm { width: 30px; height: 30px; }
203
- .orb-md { width: 40px; height: 40px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  /* ============================================================
206
  Cards & primitives
207
  ============================================================ */
208
  .card {
209
- background: rgba(255,255,255,.78);
210
  backdrop-filter: blur(14px);
211
- border: 1px solid rgba(255,255,255,.9);
212
  box-shadow: var(--shadow-md);
213
  border-radius: var(--r-xl);
214
  }
215
- .card-flat { background: var(--snow); border: 1px solid var(--fog); box-shadow: var(--shadow-sm); border-radius: var(--r-lg); }
216
- .card-pad { padding: 22px 24px; }
 
 
 
 
 
 
 
217
 
218
- .eyebrow { font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--ash); font-weight: 600; }
219
- .muted { color: var(--ash); }
220
- .mono { font-family: var(--font-mono); }
 
 
 
 
 
 
 
 
 
 
221
 
222
  .btn {
223
- display: inline-flex; align-items: center; gap: 8px; justify-content: center;
224
- font-size: 13.5px; font-weight: 500; border: 1px solid var(--pebble);
225
- background: var(--snow); color: var(--ink);
226
- padding: 9px 16px; border-radius: var(--r-pill);
227
- transition: transform .08s, background .15s, box-shadow .15s, border-color .15s;
228
- }
229
- .btn:hover { background: #fbfbf9; box-shadow: var(--shadow-sm); }
230
- .btn:active { transform: translateY(1px); }
231
- .btn-ink { background: var(--ink); color: #fff; border-color: var(--ink); }
232
- .btn-ink:hover { background: #2a2a26; }
233
- .btn-ghost { background: transparent; border-color: transparent; color: var(--ink-soft); }
234
- .btn-ghost:hover { background: rgba(26,26,24,.05); box-shadow: none; }
235
- .btn-sm { padding: 6px 12px; font-size: 12.5px; }
236
- .btn-icon { padding: 9px; border-radius: 999px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
 
238
  .chip {
239
- display: inline-flex; align-items: center; gap: 6px;
240
- font-size: 12px; font-weight: 500; color: var(--ink-soft);
241
- background: rgba(255,255,255,.7); border: 1px solid var(--fog);
242
- padding: 4px 10px; border-radius: var(--r-pill);
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
244
- .chip .d { width: 7px; height: 7px; border-radius: 999px; background: var(--c, var(--ash)); }
245
 
246
- .tabs { display: inline-flex; gap: 2px; padding: 3px; background: rgba(26,26,24,.04); border-radius: var(--r-pill); }
247
- .tab { border: none; background: none; padding: 7px 15px; border-radius: var(--r-pill); font-size: 13px; font-weight: 500; color: var(--ash); }
248
- .tab.on { background: var(--snow); color: var(--ink); box-shadow: var(--shadow-sm); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
 
250
- .divider { height: 1px; background: var(--fog); border: none; margin: 0; }
 
 
 
 
 
251
 
252
  /* ============================================================
253
  Assistant Bar (the composer) — the brand's animated moment
254
  ============================================================ */
255
- .askbar-wrap { position: relative; }
 
 
256
  .askbar {
257
- display: flex; align-items: flex-end; gap: 10px;
 
 
258
  background: var(--snow);
259
  border: 1px solid var(--pebble);
260
  border-radius: 22px;
261
  padding: 10px 10px 10px 16px;
262
  box-shadow: var(--shadow-md);
263
- transition: box-shadow .2s, border-color .2s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  }
265
- .askbar:focus-within { border-color: transparent; box-shadow: var(--shadow-lg), 0 0 0 2px #fff, 0 0 0 4px transparent; }
266
- .askbar:focus-within { background-image: linear-gradient(#fff,#fff), var(--spectrum); background-origin: border-box; background-clip: padding-box, border-box; border-color: transparent; }
267
  .askbar textarea {
268
- flex: 1; border: none; outline: none; resize: none; background: none;
269
- font-family: inherit; font-size: 15px; color: var(--ink); line-height: 1.5;
270
- max-height: 140px; padding: 6px 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  }
272
- .askbar textarea::placeholder { color: var(--ash-light); }
273
- .ask-tools { display: flex; align-items: center; gap: 4px; padding-bottom: 2px; }
274
  .ask-send {
275
- width: 38px; height: 38px; border-radius: 999px; border: none;
276
- background: var(--spectrum); color: #fff; display: grid; place-items: center;
277
- flex: none; transition: transform .12s, filter .15s; box-shadow: 0 3px 10px -3px rgba(250,61,29,.4);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  }
279
- .ask-send:hover { transform: scale(1.05); }
280
- .ask-send:disabled { background: var(--pebble); box-shadow: none; color: var(--ash); cursor: default; transform: none; }
281
- .ask-pill { display:inline-flex; align-items:center; gap:6px; font-size:12px; color: var(--ash); border:1px solid var(--fog); background:#fff; padding:5px 10px; border-radius:999px; }
282
- .ask-pill .ico { color: var(--ash-light); }
283
 
284
- .suggestions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
 
 
 
 
 
285
  .suggestion {
286
- text-align: left; border: 1px solid var(--fog); background: rgba(255,255,255,.6);
287
- border-radius: var(--r-pill); padding: 8px 14px; font-size: 13px; color: var(--ink-soft);
288
- font-weight: 500; transition: background .15s, box-shadow .15s, transform .08s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  }
290
- .suggestion:hover { background: #fff; box-shadow: var(--shadow-sm); }
291
- .suggestion:active { transform: translateY(1px); }
292
 
293
  /* ============================================================
294
  Chat
295
  ============================================================ */
296
- .chat { display: flex; flex-direction: column; height: 100%; }
297
- .chat-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 4px 18px; }
298
- .chat-inner { max-width: 760px; margin: 0 auto; display: flex; flex-direction: column; gap: 20px; }
299
- .chat-foot { max-width: 760px; margin: 10px auto 0; width: 100%; }
300
-
301
- .msg { display: flex; gap: 12px; align-items: flex-start; }
302
- .msg.me { flex-direction: row-reverse; }
303
- .msg .bubble { max-width: 78%; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  .bubble .body {
305
- font-size: 14.5px; line-height: 1.6; color: var(--ink);
306
- background: var(--snow); border: 1px solid var(--fog);
307
- padding: 12px 16px; border-radius: 16px; box-shadow: var(--shadow-sm);
308
- }
309
- .msg.me .bubble .body { background: var(--ink); color: #fff; border-color: var(--ink); }
310
- .bubble .who { font-size: 11.5px; color: var(--ash); margin: 0 4px 5px; font-weight: 600; }
311
- .msg.me .bubble .who { text-align: right; }
312
- .bubble .body p { margin: 0 0 8px; }
313
- .bubble .body p:last-child { margin: 0; }
314
- .bubble .body .md-h { font-size: 14.5px; font-weight: 700; margin: 12px 0 6px; letter-spacing: -.01em; }
315
- .bubble .body .md-h:first-child { margin-top: 0; }
316
- .bubble .body .md-list { margin: 0 0 8px; padding-left: 20px; }
317
- .bubble .body .md-list:last-child { margin: 0; }
318
- .bubble .body .md-list li { margin: 2px 0; }
319
- .bubble .body code { font-family: var(--font-mono); font-size: 12.5px; background: rgba(26,26,24,.06); padding: 1px 5px; border-radius: 5px; }
320
- .msg.me .bubble .body code { background: rgba(255,255,255,.16); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
 
322
  /* tool-call chip inside chat — shows the agent doing something */
323
  .toolcard {
324
- margin-top: 9px; border: 1px solid var(--fog); border-radius: 14px;
325
- background: rgba(255,255,255,.7); overflow: hidden;
326
- }
327
- .toolcard .head { display: flex; align-items: center; gap: 9px; padding: 9px 13px; font-size: 12.5px; font-weight: 600; }
328
- .toolcard .head .ico { color: var(--ash); }
329
- .toolcard .head .ok { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; color: var(--m-leo); font-size: 11.5px; font-weight: 600; }
330
- .toolcard .det { padding: 0 13px 11px; font-size: 13px; }
331
- .toolcard .det .row { display: flex; gap: 10px; padding: 4px 0; }
332
- .toolcard .det .row .k { color: var(--ash); min-width: 76px; font-size: 12px; }
333
- .toolcard .det .row .v { color: var(--ink); font-weight: 500; }
334
-
335
- .typing { display: inline-flex; gap: 4px; padding: 14px 16px; }
336
- .typing i { width: 7px; height: 7px; border-radius: 999px; background: var(--ash-light); animation: bounce 1.2s infinite ease-in-out; }
337
- .typing i:nth-child(2){ animation-delay: .15s } .typing i:nth-child(3){ animation-delay: .3s }
338
- @keyframes bounce { 0%,80%,100%{ transform: translateY(0); opacity:.5 } 40%{ transform: translateY(-5px); opacity:1 } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
 
340
  /* @mention popover */
341
- .mention-pop { position: absolute; bottom: calc(100% + 8px); left: 14px; width: 280px; background: var(--snow); border: 1px solid var(--fog); border-radius: 16px; box-shadow: var(--shadow-lg); padding: 6px; z-index: 30; }
342
- .mention-pop .gl { font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--ash-light); padding: 8px 10px 4px; font-weight: 600; }
343
- .mention-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; font-size: 13.5px; }
344
- .mention-row:hover, .mention-row.hl { background: rgba(26,26,24,.05); }
345
- .token { display:inline; background: color-mix(in srgb, var(--lavender) 16%, white); color: #5a4fd0; border-radius: 5px; padding: 0 4px; font-weight: 600; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
 
347
  /* ============================================================
348
  Home — Family Brief
349
  ============================================================ */
350
- .brief-grid { display: grid; grid-template-columns: 1.55fr 1fr; gap: 20px; align-items: start; }
351
- .greet { font-size: 40px; font-weight: 300; letter-spacing: -.035em; line-height: 1.05; margin: 4px 0 2px; }
352
- .greet .accent { background: var(--spectrum); -webkit-background-clip: text; background-clip: text; color: transparent; }
353
- .greet-sub { color: var(--ash); font-size: 15px; margin-bottom: 22px; }
354
-
355
- .sect-h { display: flex; align-items: center; gap: 10px; margin: 4px 0 12px; }
356
- .sect-h h3 { font-size: 14px; font-weight: 600; margin: 0; letter-spacing: -.01em; white-space: nowrap; }
357
- .toolcard .det .row { align-items: baseline; }
358
- .sect-h .ico { color: var(--ash); }
359
- .sect-h .more { margin-left: auto; font-size: 12.5px; color: var(--ash); font-weight: 500; background:none;border:none; }
360
- .sect-h .more:hover { color: var(--ink); }
361
-
362
- .timeline { display: flex; flex-direction: column; }
363
- .tl-item { display: flex; gap: 14px; padding: 11px 4px; border-bottom: 1px solid var(--fog); }
364
- .tl-item:last-child { border-bottom: none; }
365
- .tl-time { font-size: 12.5px; color: var(--ash); width: 70px; flex: none; padding-top: 1px; font-variant-numeric: tabular-nums; }
366
- .tl-body { flex: 1; min-width: 0; }
367
- .tl-body .t { font-size: 14px; font-weight: 500; }
368
- .tl-body .s { font-size: 12.5px; color: var(--ash); margin-top: 1px; }
369
- .tl-bar { width: 3px; border-radius: 999px; background: var(--c, var(--ash)); flex: none; }
370
-
371
- .mini-list { display: flex; flex-direction: column; gap: 2px; }
372
- .mini-row { display: flex; align-items: center; gap: 11px; padding: 9px 6px; border-radius: 10px; }
373
- .mini-row:hover { background: rgba(26,26,24,.035); }
374
- .mini-row .t { font-size: 13.5px; font-weight: 500; }
375
- .mini-row .s { font-size: 12px; color: var(--ash); }
376
- .mini-row .r { margin-left: auto; font-size: 12px; color: var(--ash); }
377
-
378
- .suggest-card { display: flex; gap: 13px; align-items: flex-start; padding: 15px 16px; border-radius: 16px; border: 1px solid var(--fog); background: rgba(255,255,255,.55); margin-bottom: 10px; }
379
- .suggest-card .txt { flex: 1; }
380
- .suggest-card .txt .t { font-size: 13.5px; font-weight: 500; line-height: 1.45; }
381
- .suggest-card .acts { display: flex; gap: 7px; margin-top: 10px; }
382
-
383
- .stat-row { display: flex; gap: 12px; }
384
- .stat { flex: 1; padding: 15px 16px; border-radius: 16px; background: rgba(255,255,255,.6); border: 1px solid var(--fog); }
385
- .stat .n { font-size: 26px; font-weight: 300; letter-spacing: -.02em; }
386
- .stat .l { font-size: 12px; color: var(--ash); margin-top: 2px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
  /* ============================================================
389
  Calendar
390
  ============================================================ */
391
- .cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background: var(--fog); border: 1px solid var(--fog); border-radius: var(--r-lg); overflow: hidden; }
392
- .cal-h { background: rgba(255,255,255,.7); padding: 10px 12px; font-size: 11.5px; font-weight: 600; color: var(--ash); text-transform: uppercase; letter-spacing: .05em; }
393
- .cal-h .dn { color: var(--ink); font-size: 17px; font-weight: 300; letter-spacing: -.02em; margin-top: 3px; }
394
- .cal-h.today .dn { color: var(--ember); }
395
- .cal-col { background: var(--snow); min-height: 360px; padding: 8px 8px 14px; display: flex; flex-direction: column; gap: 6px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  .ev {
397
- border-radius: 10px; padding: 7px 9px; font-size: 12px; line-height: 1.3;
 
 
 
398
  background: color-mix(in srgb, var(--c) 13%, white);
399
  border: 1px solid color-mix(in srgb, var(--c) 24%, white);
400
  border-left: 3px solid var(--c);
401
- cursor: pointer; transition: transform .08s, box-shadow .15s;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  }
403
- .ev:hover { box-shadow: var(--shadow-sm); transform: translateY(-1px); }
404
- .ev .et { font-size: 10.5px; color: color-mix(in srgb, var(--c) 55%, #333); font-weight: 600; font-variant-numeric: tabular-nums; }
405
- .ev .en { font-weight: 500; color: #2a2a26; margin-top: 1px; }
406
 
407
  /* ============================================================
408
  Recipes
409
  ============================================================ */
410
- .recipe-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 18px; }
411
- .rcard { border-radius: var(--r-lg); overflow: hidden; background: var(--snow); border: 1px solid var(--fog); box-shadow: var(--shadow-sm); transition: transform .1s, box-shadow .18s; cursor: pointer; }
412
- .rcard:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
413
- .rcard .ph { height: 132px; position: relative; display: grid; place-items: center; overflow: hidden;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  background:
415
- repeating-linear-gradient(135deg, rgba(0,0,0,.025) 0 9px, transparent 9px 18px),
 
 
 
 
416
  color-mix(in srgb, var(--c, var(--ash)) 18%, white);
417
  }
418
- .rcard .ph .gl { font-size: 11px; color: color-mix(in srgb, var(--c) 50%, #555); font-family: var(--font-mono); letter-spacing: .04em; }
419
- .rcard .ph .tags { position: absolute; top: 10px; left: 10px; display: flex; gap: 5px; }
420
- .tag-veg { font-size: 10px; font-weight: 700; color: #1aa06b; background: rgba(26,160,107,.14); border-radius: 999px; padding: 2px 8px; letter-spacing: .03em; }
421
- .rcard .info { padding: 13px 15px 16px; }
422
- .rcard .info .t { font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
423
- .rcard .info .meta { display: flex; gap: 12px; margin-top: 7px; font-size: 12px; color: var(--ash); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
 
425
  /* recipe detail / drawer */
426
- .drawer-scrim { position: fixed; inset: 0; background: rgba(26,26,24,.28); backdrop-filter: blur(3px); z-index: 60; animation: fade .2s; }
427
- .drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(560px, 92vw); background: var(--canvas); z-index: 61; box-shadow: var(--shadow-lg); display: flex; flex-direction: column; animation: slidein .26s cubic-bezier(.2,.8,.2,1); }
428
- @keyframes slidein { from { transform: translateX(30px); opacity: 0 } to { transform: none; opacity: 1 } }
429
- @keyframes fade { from { opacity: 0 } to { opacity: 1 } }
430
- .drawer-head { padding: 18px 22px; display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--fog); flex: none; }
431
- .drawer-body { flex: 1; overflow-y: auto; padding: 22px; }
432
- .ingredient { display: flex; align-items: center; gap: 11px; padding: 8px 0; border-bottom: 1px solid var(--fog); font-size: 14px; }
433
- .ingredient .ck { width: 18px; height: 18px; border-radius: 6px; border: 1.5px solid var(--pebble); flex: none; }
434
- .step { display: flex; gap: 13px; padding: 11px 0; }
435
- .step .n { width: 24px; height: 24px; border-radius: 999px; background: var(--ink); color: #fff; font-size: 12px; font-weight: 600; display: grid; place-items: center; flex: none; }
436
- .step .x { font-size: 14px; line-height: 1.55; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
 
438
  /* the markdown peek */
439
- .md-peek { background: #1d1d1a; color: #e8e8e2; border-radius: var(--r-md); padding: 16px 18px; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.7; overflow-x: auto; }
440
- .md-peek .fm { color: #84847d; }
441
- .md-peek .key { color: #ffb005; }
442
- .md-peek .str { color: #c9c9fe; }
443
- .md-peek .h { color: #fff; font-weight: 700; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
 
445
  /* ============================================================
446
  Meals — planner + shopping list
447
  ============================================================ */
448
- .meal-layout { display: grid; grid-template-columns: 1fr 320px; gap: 20px; align-items: start; }
449
- .week { display: flex; flex-direction: column; gap: 10px; }
450
- .day-row { display: flex; align-items: center; gap: 16px; padding: 14px 18px; background: var(--snow); border: 1px solid var(--fog); border-radius: var(--r-md); box-shadow: var(--shadow-sm); }
451
- .day-row .dow { width: 44px; flex: none; }
452
- .day-row .dow .d3 { font-size: 13px; font-weight: 600; }
453
- .day-row .dow .num { font-size: 12px; color: var(--ash); }
454
- .day-row .dish { flex: 1; display: flex; align-items: center; gap: 12px; min-width: 0; }
455
- .day-row .dish .sw { width: 34px; height: 34px; border-radius: 9px; flex: none;
456
- background: repeating-linear-gradient(135deg, rgba(0,0,0,.03) 0 6px, transparent 6px 12px), color-mix(in srgb, var(--c, var(--ash)) 20%, white); }
457
- .day-row .dish .t { font-size: 14px; font-weight: 500; }
458
- .day-row .dish .s { font-size: 12px; color: var(--ash); }
459
- .day-row .swap { opacity: 0; transition: opacity .15s; }
460
- .day-row:hover .swap { opacity: 1; }
461
-
462
- .shop { position: sticky; top: 6px; }
463
- .shop .grp { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--ash-light); font-weight: 600; margin: 14px 0 4px; }
464
- .shop-item { display: flex; align-items: center; gap: 10px; padding: 7px 0; font-size: 13.5px; border-bottom: 1px solid var(--fog); }
465
- .shop-item .ck { width: 16px; height: 16px; border-radius: 5px; border: 1.5px solid var(--pebble); flex: none; }
466
- .shop-item.done { color: var(--ash-light); text-decoration: line-through; }
467
- .shop-item .q { margin-left: auto; font-size: 12px; color: var(--ash); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
 
469
  /* ============================================================
470
  Notes
471
  ============================================================ */
472
- .notes-layout { display: grid; grid-template-columns: 200px 1fr; gap: 22px; align-items: start; }
473
- .note-members { display: flex; flex-direction: column; gap: 3px; }
474
- .note-mtab { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border-radius: 11px; border: none; background: none; width: 100%; text-align: left; font-size: 13.5px; font-weight: 500; color: var(--ink-soft); }
475
- .note-mtab:hover { background: rgba(26,26,24,.04); }
476
- .note-mtab.on { background: var(--snow); box-shadow: var(--shadow-sm); color: var(--ink); }
477
- .note-mtab .ct { margin-left: auto; font-size: 11px; color: var(--ash); }
478
- .note-cols { columns: 2; column-gap: 16px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  .note {
480
- break-inside: avoid; margin-bottom: 16px; padding: 16px 17px;
481
- border-radius: var(--r-md); border: 1px solid var(--fog);
482
- background: var(--snow); box-shadow: var(--shadow-sm);
 
 
 
 
483
  border-top: 3px solid var(--c, var(--ash));
484
  }
485
- .note .t { font-size: 14px; font-weight: 600; margin-bottom: 7px; }
486
- .note .body { font-size: 13px; line-height: 1.6; color: var(--ink-soft); white-space: pre-wrap; }
487
- .note .check { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; padding: 3px 0; }
488
- .note .check .b { width: 15px; height: 15px; border-radius: 4px; border: 1.5px solid var(--pebble); flex: none; margin-top: 2px; }
489
- .note .check.done { color: var(--ash-light); }
490
- .note .check.done .b { background: var(--m-leo); border-color: var(--m-leo); }
491
- .note .foot { font-size: 11px; color: var(--ash-light); margin-top: 11px; font-family: var(--font-mono); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
 
493
  /* ============================================================
494
  Settings — family roster
495
  ============================================================ */
496
  .set-input {
497
- width: 100%; padding: 10px 12px; font-size: 14px; font-family: inherit;
498
- border: 1px solid var(--pebble); border-radius: var(--r-md);
499
- background: var(--snow); color: var(--ink); outline: none;
500
- }
501
- .set-input:focus { border-color: var(--ash); }
502
- .set-veg { display: flex; align-items: center; gap: 9px; font-size: 13.5px; color: var(--ink-soft); margin-top: 12px; cursor: pointer; user-select: none; }
503
- .set-veg .b { width: 16px; height: 16px; border-radius: 5px; border: 1.5px solid var(--pebble); flex: none; }
504
- .member-list { display: flex; flex-direction: column; gap: 10px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  .member-row {
506
- display: flex; align-items: center; gap: 13px; padding: 13px 15px;
507
- border-radius: var(--r-md); border: 1px solid var(--fog);
508
- background: var(--snow); box-shadow: var(--shadow-sm);
 
 
 
 
 
509
  }
510
 
511
  /* ============================================================
512
  Inbox — email → event
513
  ============================================================ */
514
- .inbox-layout { display: grid; grid-template-columns: 1fr; gap: 14px; max-width: 760px; }
 
 
 
 
 
515
  .mail {
516
- display: flex; gap: 14px; padding: 17px 19px; border-radius: var(--r-lg);
517
- background: var(--snow); border: 1px solid var(--fog); box-shadow: var(--shadow-sm);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  }
519
- .mail .from-av { flex: none; }
520
- .mail .m-main { flex: 1; min-width: 0; }
521
- .mail .m-top { display: flex; align-items: baseline; gap: 10px; }
522
- .mail .m-from { font-size: 14px; font-weight: 600; }
523
- .mail .m-date { margin-left: auto; font-size: 12px; color: var(--ash); flex: none; }
524
- .mail .m-subj { font-size: 13.5px; font-weight: 500; margin-top: 3px; }
525
- .mail .m-prev { font-size: 13px; color: var(--ash); margin-top: 3px; line-height: 1.5; }
526
 
527
  .proposal {
528
- margin-top: 13px; border-radius: 14px; padding: 14px 16px;
529
- background: rgba(255,255,255,.7);
 
 
530
  border: 1px solid transparent;
531
- background-image: linear-gradient(rgba(255,255,255,.85),rgba(255,255,255,.85)), var(--spectrum-soft);
532
- background-origin: border-box; background-clip: padding-box, border-box;
533
- }
534
- .proposal .ph { display: flex; align-items: center; gap: 9px; font-size: 12px; font-weight: 600; color: var(--ink-soft); margin-bottom: 10px; }
535
- .proposal .ph .orb { width: 18px; height: 18px; }
536
- .proposal .pe { display: flex; align-items: center; gap: 12px; padding: 10px 12px; background: var(--snow); border: 1px solid var(--fog); border-radius: 11px; }
537
- .proposal .pe .when { text-align: center; flex: none; padding-right: 12px; border-right: 1px solid var(--fog); }
538
- .proposal .pe .when .mo { font-size: 10px; text-transform: uppercase; color: var(--ember); font-weight: 700; letter-spacing: .05em; }
539
- .proposal .pe .when .dd { font-size: 20px; font-weight: 300; line-height: 1; }
540
- .proposal .pe .det .t { font-size: 13.5px; font-weight: 600; }
541
- .proposal .pe .det .s { font-size: 12px; color: var(--ash); margin-top: 2px; }
542
- .proposal .acts { display: flex; gap: 8px; margin-top: 12px; }
543
- .mail.handled { opacity: .62; }
544
- .confirmed-tag { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--m-leo); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
 
546
  /* ============================================================
547
  misc
548
  ============================================================ */
549
- .empty { text-align: center; padding: 60px 20px; color: var(--ash); }
550
- .fade-in { animation: fade .3s ease both; }
551
- .rise { animation: rise .35s cubic-bezier(.2,.8,.2,1) both; }
552
- @keyframes rise { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
553
 
554
  @media (prefers-reduced-motion: reduce) {
555
- * { animation-duration: .001ms !important; transition-duration: .05ms !important; }
 
 
 
556
  }
557
 
558
  /* ---- tweak-driven states ---- */
559
- html.surf-solid .card { background: var(--snow); backdrop-filter: none; border-color: var(--fog); }
560
- html.surf-solid .sidebar { background: rgba(255,255,255,.92); backdrop-filter: none; }
 
 
 
 
 
 
 
561
  html.surf-solid .chip,
562
  html.surf-solid .suggestion,
563
  html.surf-solid .member-switch,
564
- html.surf-solid .proposal { background-color: var(--snow); }
565
- html.names-on .m-chip .name { display: inline; }
566
- html.names-on .m-chip { padding-right: 11px; }
 
 
 
 
 
 
 
7
 
8
  :root {
9
  /* ---- neutral scale (achromatic, faintly warm) ---- */
10
+ --ink: #1a1a18; /* near-black text */
11
+ --ink-soft: #4a4a46; /* secondary heading */
12
+ --ash: #84847d; /* secondary body / captions */
13
+ --ash-light: #a6a69f; /* tertiary / placeholder */
14
+ --pebble: #dcdcd6; /* borders / neutral buttons */
15
+ --fog: #ecece7; /* hairlines / fills */
16
+ --canvas: #f4f3ef; /* app background */
17
+ --snow: #ffffff; /* card base */
18
 
19
  /* ---- the spectrum (the brand's only color) ---- */
20
+ --spectrum: linear-gradient(
21
+ 100deg,
22
+ #c679c4 0%,
23
+ #fa3d1d 24%,
24
+ #ffb005 48%,
25
+ #c9c9fe 74%,
26
+ #0358f7 100%
27
+ );
28
+ --spectrum-soft: linear-gradient(
29
+ 100deg,
30
+ #e6c3e5 0%,
31
+ #fbb6aa 24%,
32
+ #ffe2a3 48%,
33
+ #e7e7ff 74%,
34
+ #aac4fc 100%
35
+ );
36
+ --spectrum-accent: linear-gradient(
37
+ 100deg,
38
+ #b898b6 0%,
39
+ #c89888 24%,
40
+ #c8b888 48%,
41
+ #b0b0c8 74%,
42
+ #7890b8 100%
43
+ );
44
+ --rose: #c679c4;
45
+ --ember: #fa3d1d;
46
+ --marigold: #ffb005;
47
+ --lavender: #8f8ff0;
48
  --signal: #0358f7;
49
 
50
  /* ---- member identity hues (used only as tints + dots) ---- */
51
+ --m-elena: #c25aa6;
52
  --m-marcus: #2f6df0;
53
+ --m-maya: #d98a12;
54
+ --m-leo: #1aa06b;
55
 
56
  /* ---- type ---- */
57
  --font-sans: "Hanken Grotesk", system-ui, sans-serif;
 
63
  --r-md: 14px;
64
  --r-sm: 10px;
65
  --r-pill: 999px;
66
+ --spectrum-amount: 1; /* tweakable */
67
 
68
  /* ---- shadows: soft, low, like paper lift ---- */
69
+ --shadow-sm:
70
+ 0 1px 2px rgba(26, 26, 24, 0.04), 0 1px 1px rgba(26, 26, 24, 0.03);
71
+ --shadow-md:
72
+ 0 4px 16px -6px rgba(26, 26, 24, 0.1), 0 1px 3px rgba(26, 26, 24, 0.05);
73
+ --shadow-lg:
74
+ 0 18px 50px -16px rgba(26, 26, 24, 0.18),
75
+ 0 4px 12px -6px rgba(26, 26, 24, 0.08);
76
  }
77
 
78
+ * {
79
+ box-sizing: border-box;
80
+ }
81
+ html,
82
+ body {
83
+ height: 100%;
84
+ }
85
  body {
86
  margin: 0;
87
  font-family: var(--font-sans);
 
90
  -webkit-font-smoothing: antialiased;
91
  text-rendering: optimizeLegibility;
92
  }
93
+ #root {
94
+ height: 100%;
95
+ }
96
+ button {
97
+ font-family: inherit;
98
+ cursor: pointer;
99
+ }
100
+ ::selection {
101
+ background: rgba(143, 143, 240, 0.28);
102
+ }
103
 
104
  /* scrollbars: thin, quiet */
105
+ .scroll::-webkit-scrollbar {
106
+ width: 10px;
107
+ height: 10px;
108
+ }
109
+ .scroll::-webkit-scrollbar-thumb {
110
+ background: rgba(132, 132, 125, 0.28);
111
+ border-radius: 999px;
112
+ border: 3px solid transparent;
113
+ background-clip: padding-box;
114
+ }
115
+ .scroll::-webkit-scrollbar-thumb:hover {
116
+ background: rgba(132, 132, 125, 0.45);
117
+ background-clip: padding-box;
118
+ border: 3px solid transparent;
119
+ }
120
 
121
  /* ============================================================
122
  App shell
 
134
  content: "";
135
  position: absolute;
136
  inset: -20% -10% auto auto;
137
+ width: 70vw;
138
+ height: 60vh;
139
  background: var(--spectrum);
140
  filter: blur(120px);
141
+ opacity: calc(0.1 * var(--spectrum-amount));
142
  pointer-events: none;
143
  z-index: 0;
144
  }
 
155
  flex-direction: column;
156
  gap: 4px;
157
  border-right: 1px solid var(--fog);
158
+ background: rgba(255, 255, 255, 0.45);
159
  backdrop-filter: blur(18px);
160
  }
161
+ .brand {
162
+ display: flex;
163
+ align-items: center;
164
+ gap: 11px;
165
+ padding: 6px 8px 20px;
166
+ }
167
  .brand .mark {
168
+ width: 42px;
169
+ height: 42px;
170
+ background: url("logo.png?v=3") center/contain no-repeat;
171
  flex: none;
172
  }
173
+ .brand .word {
174
+ font-size: 22px;
175
+ font-weight: 500;
176
+ letter-spacing: -0.02em;
177
+ }
178
+ .brand .word b {
179
+ font-weight: 700;
180
+ }
181
 
182
+ .nav-label {
183
+ font-size: 11px;
184
+ letter-spacing: 0.08em;
185
+ text-transform: uppercase;
186
+ color: var(--ash-light);
187
+ padding: 14px 12px 6px;
188
+ font-weight: 600;
189
+ }
190
  .nav-item {
191
+ display: flex;
192
+ align-items: center;
193
+ gap: 12px;
194
+ padding: 9px 12px;
195
+ border-radius: 11px;
196
+ color: var(--ink-soft);
197
+ font-size: 14.5px;
198
+ font-weight: 500;
199
+ border: none;
200
+ background: none;
201
+ width: 100%;
202
+ text-align: left;
203
  white-space: nowrap;
204
+ transition:
205
+ background 0.15s,
206
+ color 0.15s;
207
+ }
208
+ .nav-item > span {
209
+ white-space: nowrap;
210
+ }
211
+ .nav-item:hover {
212
+ background: rgba(26, 26, 24, 0.045);
213
+ color: var(--ink);
214
+ }
215
+ .nav-item.active {
216
+ background: var(--snow);
217
+ color: var(--ink);
218
+ box-shadow: var(--shadow-sm);
219
+ }
220
+ .nav-item .ico {
221
+ color: var(--ash);
222
+ flex: none;
223
+ }
224
+ .nav-item.active .ico {
225
+ color: var(--ink);
226
  }
 
 
 
 
 
227
  .nav-item .badge {
228
+ margin-left: auto;
229
+ font-size: 11px;
230
+ font-weight: 600;
231
+ min-width: 18px;
232
+ height: 18px;
233
+ padding: 0 5px;
234
+ border-radius: 999px;
235
+ background: var(--ink);
236
+ color: #fff;
237
+ display: grid;
238
+ place-items: center;
239
+ }
240
+ .nav-spacer {
241
+ flex: 1;
242
  }
 
243
 
244
  .account {
245
+ display: flex;
246
+ align-items: center;
247
+ gap: 10px;
248
+ padding: 10px;
249
+ border-radius: 13px;
250
+ border: 1px solid var(--fog);
251
+ background: rgba(255, 255, 255, 0.6);
252
+ }
253
+ .account .gmail {
254
+ width: 26px;
255
+ height: 26px;
256
+ border-radius: 7px;
257
+ background: var(--fog);
258
+ display: grid;
259
+ place-items: center;
260
+ flex: none;
261
+ }
262
+ .account .meta {
263
+ min-width: 0;
264
+ }
265
+ .account .meta .t {
266
+ font-size: 12.5px;
267
+ font-weight: 600;
268
+ line-height: 1.2;
269
+ }
270
+ .account .meta .s {
271
+ font-size: 11px;
272
+ color: var(--ash);
273
+ white-space: nowrap;
274
+ overflow: hidden;
275
+ text-overflow: ellipsis;
276
+ }
277
+ .account .dot {
278
+ margin-left: auto;
279
+ width: 7px;
280
+ height: 7px;
281
+ border-radius: 999px;
282
+ background: var(--m-leo);
283
+ flex: none;
284
+ box-shadow: 0 0 0 3px rgba(26, 160, 107, 0.16);
285
  }
 
 
 
 
 
286
 
287
  /* ---- main ---- */
288
+ .main {
289
+ position: relative;
290
+ z-index: 1;
291
+ display: flex;
292
+ flex-direction: column;
293
+ min-width: 0;
294
+ min-height: 0;
295
+ height: 100vh;
296
+ }
297
  .topbar {
298
+ display: flex;
299
+ align-items: center;
300
+ gap: 16px;
301
  padding: 18px 30px 14px;
302
  flex: none;
303
  }
304
+ .topbar h1 {
305
+ font-size: 27px;
306
+ font-weight: 300;
307
+ letter-spacing: -0.03em;
308
+ margin: 0;
309
+ }
310
+ .topbar .sub {
311
+ font-size: 13px;
312
+ color: var(--ash);
313
+ margin-top: 2px;
314
+ }
315
+ .topbar-right {
316
+ margin-left: auto;
317
+ display: flex;
318
+ align-items: center;
319
+ gap: 14px;
320
+ }
321
 
322
+ .member-switch {
323
+ display: flex;
324
+ align-items: center;
325
+ gap: 6px;
326
+ padding: 4px;
327
+ background: rgba(255, 255, 255, 0.6);
328
+ border: 1px solid var(--fog);
329
+ border-radius: var(--r-pill);
330
+ }
331
+ .member-switch .who {
332
+ font-size: 11px;
333
+ color: var(--ash);
334
+ padding: 0 8px 0 6px;
335
+ font-weight: 500;
336
+ white-space: nowrap;
337
+ }
338
  .m-chip {
339
+ display: flex;
340
+ align-items: center;
341
+ gap: 7px;
342
+ padding: 4px 11px 4px 4px;
343
+ border-radius: var(--r-pill);
344
+ border: 1px solid transparent;
345
+ background: none;
346
+ transition: background 0.15s;
347
+ }
348
+ .m-chip:hover {
349
+ background: rgba(26, 26, 24, 0.04);
350
+ }
351
+ .m-chip.on {
352
+ background: var(--snow);
353
+ box-shadow: var(--shadow-sm);
354
+ }
355
+ .m-chip .name {
356
+ font-size: 13px;
357
+ font-weight: 500;
358
+ display: none;
359
+ }
360
+ .m-chip.on .name {
361
+ display: inline;
362
  }
 
 
 
 
363
 
364
+ .view {
365
+ flex: 1;
366
+ min-height: 0;
367
+ overflow-y: auto;
368
+ padding: 6px 30px 36px;
369
+ }
370
+ .view-wide {
371
+ max-width: 1180px;
372
+ }
373
 
374
  /* ============================================================
375
  Avatars
376
  ============================================================ */
377
  .av {
378
  --c: var(--ash);
379
+ border-radius: 999px;
380
+ flex: none;
381
+ display: grid;
382
+ place-items: center;
383
+ font-weight: 600;
384
+ letter-spacing: -0.01em;
385
  background: color-mix(in srgb, var(--c) 16%, white);
386
  color: color-mix(in srgb, var(--c) 62%, #20201c);
387
  border: 1px solid color-mix(in srgb, var(--c) 24%, white);
388
  }
389
+ .av-xs {
390
+ width: 22px;
391
+ height: 22px;
392
+ font-size: 10px;
393
+ }
394
+ .av-sm {
395
+ width: 30px;
396
+ height: 30px;
397
+ font-size: 12px;
398
+ }
399
+ .av-md {
400
+ width: 40px;
401
+ height: 40px;
402
+ font-size: 15px;
403
+ }
404
+ .av-lg {
405
+ width: 54px;
406
+ height: 54px;
407
+ font-size: 19px;
408
+ }
409
+ .av-ring {
410
+ box-shadow:
411
+ 0 0 0 2px var(--snow),
412
+ 0 0 0 3.5px color-mix(in srgb, var(--c) 55%, white);
413
+ }
414
 
415
  /* the assistant's mark — the spectrum, alive */
416
+ .orb {
417
+ border-radius: 999px;
418
+ background: var(--spectrum);
419
+ flex: none;
420
+ position: relative;
421
+ }
422
+ .orb::after {
423
+ content: "";
424
+ position: absolute;
425
+ inset: 22%;
426
+ border-radius: 999px;
427
+ background: rgba(255, 255, 255, 0.55);
428
+ filter: blur(2px);
429
+ }
430
+ .orb-xs {
431
+ width: 22px;
432
+ height: 22px;
433
+ }
434
+ .orb-sm {
435
+ width: 30px;
436
+ height: 30px;
437
+ }
438
+ .orb-md {
439
+ width: 40px;
440
+ height: 40px;
441
+ }
442
 
443
  /* ============================================================
444
  Cards & primitives
445
  ============================================================ */
446
  .card {
447
+ background: rgba(255, 255, 255, 0.78);
448
  backdrop-filter: blur(14px);
449
+ border: 1px solid rgba(255, 255, 255, 0.9);
450
  box-shadow: var(--shadow-md);
451
  border-radius: var(--r-xl);
452
  }
453
+ .card-flat {
454
+ background: var(--snow);
455
+ border: 1px solid var(--fog);
456
+ box-shadow: var(--shadow-sm);
457
+ border-radius: var(--r-lg);
458
+ }
459
+ .card-pad {
460
+ padding: 22px 24px;
461
+ }
462
 
463
+ .eyebrow {
464
+ font-size: 11.5px;
465
+ letter-spacing: 0.07em;
466
+ text-transform: uppercase;
467
+ color: var(--ash);
468
+ font-weight: 600;
469
+ }
470
+ .muted {
471
+ color: var(--ash);
472
+ }
473
+ .mono {
474
+ font-family: var(--font-mono);
475
+ }
476
 
477
  .btn {
478
+ display: inline-flex;
479
+ align-items: center;
480
+ gap: 8px;
481
+ justify-content: center;
482
+ font-size: 13.5px;
483
+ font-weight: 500;
484
+ border: 1px solid var(--pebble);
485
+ background: var(--snow);
486
+ color: var(--ink);
487
+ padding: 9px 16px;
488
+ border-radius: var(--r-pill);
489
+ transition:
490
+ transform 0.08s,
491
+ background 0.15s,
492
+ box-shadow 0.15s,
493
+ border-color 0.15s;
494
+ }
495
+ .btn:hover {
496
+ background: #fbfbf9;
497
+ box-shadow: var(--shadow-sm);
498
+ }
499
+ .btn:active {
500
+ transform: translateY(1px);
501
+ }
502
+ .btn-ink {
503
+ background: var(--ink);
504
+ color: #fff;
505
+ border-color: var(--ink);
506
+ }
507
+ .btn-ink:hover {
508
+ background: #2a2a26;
509
+ }
510
+ .btn-ghost {
511
+ background: transparent;
512
+ border-color: transparent;
513
+ color: var(--ink-soft);
514
+ }
515
+ .btn-ghost:hover {
516
+ background: rgba(26, 26, 24, 0.05);
517
+ box-shadow: none;
518
+ }
519
+ .btn-sm {
520
+ padding: 6px 12px;
521
+ font-size: 12.5px;
522
+ }
523
+ .btn-icon {
524
+ padding: 9px;
525
+ border-radius: 999px;
526
+ }
527
 
528
  .chip {
529
+ display: inline-flex;
530
+ align-items: center;
531
+ gap: 6px;
532
+ font-size: 12px;
533
+ font-weight: 500;
534
+ color: var(--ink-soft);
535
+ background: rgba(255, 255, 255, 0.7);
536
+ border: 1px solid var(--fog);
537
+ padding: 4px 10px;
538
+ border-radius: var(--r-pill);
539
+ }
540
+ .chip .d {
541
+ width: 7px;
542
+ height: 7px;
543
+ border-radius: 999px;
544
+ background: var(--c, var(--ash));
545
  }
 
546
 
547
+ .tabs {
548
+ display: inline-flex;
549
+ gap: 2px;
550
+ padding: 3px;
551
+ background: rgba(26, 26, 24, 0.04);
552
+ border-radius: var(--r-pill);
553
+ }
554
+ .tab {
555
+ border: none;
556
+ background: none;
557
+ padding: 7px 15px;
558
+ border-radius: var(--r-pill);
559
+ font-size: 13px;
560
+ font-weight: 500;
561
+ color: var(--ash);
562
+ }
563
+ .tab.on {
564
+ background: var(--snow);
565
+ color: var(--ink);
566
+ box-shadow: var(--shadow-sm);
567
+ }
568
 
569
+ .divider {
570
+ height: 1px;
571
+ background: var(--fog);
572
+ border: none;
573
+ margin: 0;
574
+ }
575
 
576
  /* ============================================================
577
  Assistant Bar (the composer) — the brand's animated moment
578
  ============================================================ */
579
+ .askbar-wrap {
580
+ position: relative;
581
+ }
582
  .askbar {
583
+ display: flex;
584
+ align-items: flex-end;
585
+ gap: 10px;
586
  background: var(--snow);
587
  border: 1px solid var(--pebble);
588
  border-radius: 22px;
589
  padding: 10px 10px 10px 16px;
590
  box-shadow: var(--shadow-md);
591
+ transition:
592
+ box-shadow 0.2s,
593
+ border-color 0.2s;
594
+ }
595
+ .askbar:focus-within {
596
+ border-color: transparent;
597
+ box-shadow:
598
+ var(--shadow-lg),
599
+ 0 0 0 2px #fff,
600
+ 0 0 0 4px transparent;
601
+ }
602
+ .askbar:focus-within {
603
+ background-image: linear-gradient(#fff, #fff), var(--spectrum);
604
+ background-origin: border-box;
605
+ background-clip: padding-box, border-box;
606
+ border-color: transparent;
607
  }
 
 
608
  .askbar textarea {
609
+ flex: 1;
610
+ border: none;
611
+ outline: none;
612
+ resize: none;
613
+ background: none;
614
+ font-family: inherit;
615
+ font-size: 15px;
616
+ color: var(--ink);
617
+ line-height: 1.5;
618
+ max-height: 140px;
619
+ overflow-y: hidden;
620
+ scrollbar-width: none;
621
+ padding: 6px 0;
622
+ transition: height 0.15s ease;
623
+ }
624
+ .askbar textarea::-webkit-scrollbar {
625
+ display: none;
626
+ }
627
+ .askbar textarea::placeholder {
628
+ color: var(--ash-light);
629
+ }
630
+ .askbar > .av {
631
+ margin-bottom: 4px;
632
+ }
633
+ .ask-tools {
634
+ display: flex;
635
+ align-items: center;
636
+ gap: 4px;
637
+ padding-bottom: 2px;
638
  }
 
 
639
  .ask-send {
640
+ width: 38px;
641
+ height: 38px;
642
+ border-radius: 999px;
643
+ border: none;
644
+ background: var(--spectrum);
645
+ color: #fff;
646
+ display: grid;
647
+ place-items: center;
648
+ flex: none;
649
+ transition:
650
+ transform 0.12s,
651
+ filter 0.15s;
652
+ box-shadow: 0 3px 10px -3px rgba(250, 61, 29, 0.4);
653
+ }
654
+ .ask-send:hover {
655
+ transform: scale(1.05);
656
+ }
657
+ .ask-send:disabled {
658
+ background: var(--pebble);
659
+ box-shadow: none;
660
+ color: var(--ash);
661
+ cursor: default;
662
+ transform: none;
663
+ }
664
+ .ask-pill {
665
+ display: inline-flex;
666
+ align-items: center;
667
+ gap: 6px;
668
+ font-size: 12px;
669
+ color: var(--ash);
670
+ border: 1px solid var(--fog);
671
+ background: #fff;
672
+ padding: 5px 10px;
673
+ border-radius: 999px;
674
+ }
675
+ .ask-pill .ico {
676
+ color: var(--ash-light);
677
  }
 
 
 
 
678
 
679
+ .suggestions {
680
+ display: flex;
681
+ flex-wrap: wrap;
682
+ gap: 8px;
683
+ margin-top: 12px;
684
+ }
685
  .suggestion {
686
+ text-align: left;
687
+ border: 1px solid var(--fog);
688
+ background: rgba(255, 255, 255, 0.6);
689
+ border-radius: var(--r-pill);
690
+ padding: 8px 14px;
691
+ font-size: 13px;
692
+ color: var(--ink-soft);
693
+ font-weight: 500;
694
+ transition:
695
+ background 0.15s,
696
+ box-shadow 0.15s,
697
+ transform 0.08s;
698
+ }
699
+ .suggestion:hover {
700
+ background: #fff;
701
+ box-shadow: var(--shadow-sm);
702
+ }
703
+ .suggestion:active {
704
+ transform: translateY(1px);
705
  }
 
 
706
 
707
  /* ============================================================
708
  Chat
709
  ============================================================ */
710
+ .chat {
711
+ display: flex;
712
+ flex-direction: column;
713
+ height: 100%;
714
+ }
715
+ .chat-scroll {
716
+ flex: 1;
717
+ min-height: 0;
718
+ overflow-y: auto;
719
+ padding: 12px 4px 18px;
720
+ }
721
+ .chat-inner {
722
+ max-width: 760px;
723
+ margin: 0 auto;
724
+ display: flex;
725
+ flex-direction: column;
726
+ gap: 20px;
727
+ }
728
+ .chat-foot {
729
+ max-width: 760px;
730
+ margin: 10px auto 0;
731
+ width: 100%;
732
+ }
733
+
734
+ .msg {
735
+ display: flex;
736
+ gap: 12px;
737
+ align-items: flex-start;
738
+ }
739
+ .msg.me {
740
+ flex-direction: row-reverse;
741
+ }
742
+ .msg .bubble {
743
+ max-width: 78%;
744
+ }
745
  .bubble .body {
746
+ font-size: 14.5px;
747
+ line-height: 1.6;
748
+ color: var(--ink);
749
+ background: var(--snow);
750
+ border: 1px solid var(--fog);
751
+ padding: 12px 16px;
752
+ border-radius: 16px;
753
+ box-shadow: var(--shadow-sm);
754
+ }
755
+ .msg.me .bubble .body {
756
+ background: var(--ink);
757
+ color: #fff;
758
+ border-color: var(--ink);
759
+ }
760
+ .bubble .who {
761
+ font-size: 11.5px;
762
+ color: var(--ash);
763
+ margin: 0 4px 5px;
764
+ font-weight: 600;
765
+ }
766
+ .msg.me .bubble .who {
767
+ text-align: right;
768
+ }
769
+ .bubble .body p {
770
+ margin: 0 0 8px;
771
+ }
772
+ .bubble .body p:last-child {
773
+ margin: 0;
774
+ }
775
+ .bubble .body .md-h {
776
+ font-size: 14.5px;
777
+ font-weight: 700;
778
+ margin: 12px 0 6px;
779
+ letter-spacing: -0.01em;
780
+ }
781
+ .bubble .body .md-h:first-child {
782
+ margin-top: 0;
783
+ }
784
+ .bubble .body .md-list {
785
+ margin: 0 0 8px;
786
+ padding-left: 20px;
787
+ }
788
+ .bubble .body .md-list:last-child {
789
+ margin: 0;
790
+ }
791
+ .bubble .body .md-list li {
792
+ margin: 2px 0;
793
+ }
794
+ .bubble .body code {
795
+ font-family: var(--font-mono);
796
+ font-size: 12.5px;
797
+ background: rgba(26, 26, 24, 0.06);
798
+ padding: 1px 5px;
799
+ border-radius: 5px;
800
+ }
801
+ .msg.me .bubble .body code {
802
+ background: rgba(255, 255, 255, 0.16);
803
+ }
804
 
805
  /* tool-call chip inside chat — shows the agent doing something */
806
  .toolcard {
807
+ margin-top: 9px;
808
+ border: 1px solid var(--fog);
809
+ border-radius: 14px;
810
+ background: rgba(255, 255, 255, 0.7);
811
+ overflow: hidden;
812
+ }
813
+ .toolcard .head {
814
+ display: flex;
815
+ align-items: center;
816
+ gap: 9px;
817
+ padding: 9px 13px;
818
+ font-size: 12.5px;
819
+ font-weight: 600;
820
+ }
821
+ .toolcard .head .ico {
822
+ color: var(--ash);
823
+ }
824
+ .toolcard .head .ok {
825
+ margin-left: auto;
826
+ display: inline-flex;
827
+ align-items: center;
828
+ gap: 5px;
829
+ color: var(--m-leo);
830
+ font-size: 11.5px;
831
+ font-weight: 600;
832
+ }
833
+ .toolcard .det {
834
+ padding: 0 13px 11px;
835
+ font-size: 13px;
836
+ }
837
+ .toolcard .det .row {
838
+ display: flex;
839
+ gap: 10px;
840
+ padding: 4px 0;
841
+ }
842
+ .toolcard .det .row .k {
843
+ color: var(--ash);
844
+ min-width: 76px;
845
+ font-size: 12px;
846
+ }
847
+ .toolcard .det .row .v {
848
+ color: var(--ink);
849
+ font-weight: 500;
850
+ }
851
+
852
+ .typing {
853
+ display: inline-flex;
854
+ gap: 4px;
855
+ padding: 14px 16px;
856
+ }
857
+ .typing i {
858
+ width: 7px;
859
+ height: 7px;
860
+ border-radius: 999px;
861
+ background: var(--ash-light);
862
+ animation: bounce 1.2s infinite ease-in-out;
863
+ }
864
+ .typing i:nth-child(2) {
865
+ animation-delay: 0.15s;
866
+ }
867
+ .typing i:nth-child(3) {
868
+ animation-delay: 0.3s;
869
+ }
870
+ @keyframes bounce {
871
+ 0%,
872
+ 80%,
873
+ 100% {
874
+ transform: translateY(0);
875
+ opacity: 0.5;
876
+ }
877
+ 40% {
878
+ transform: translateY(-5px);
879
+ opacity: 1;
880
+ }
881
+ }
882
 
883
  /* @mention popover */
884
+ .mention-pop {
885
+ position: absolute;
886
+ bottom: calc(100% + 8px);
887
+ left: 14px;
888
+ width: 280px;
889
+ background: var(--snow);
890
+ border: 1px solid var(--fog);
891
+ border-radius: 16px;
892
+ box-shadow: var(--shadow-lg);
893
+ padding: 6px;
894
+ z-index: 30;
895
+ }
896
+ .mention-pop .gl {
897
+ font-size: 10.5px;
898
+ letter-spacing: 0.07em;
899
+ text-transform: uppercase;
900
+ color: var(--ash-light);
901
+ padding: 8px 10px 4px;
902
+ font-weight: 600;
903
+ }
904
+ .mention-row {
905
+ display: flex;
906
+ align-items: center;
907
+ gap: 10px;
908
+ padding: 8px 10px;
909
+ border-radius: 10px;
910
+ font-size: 13.5px;
911
+ }
912
+ .mention-row:hover,
913
+ .mention-row.hl {
914
+ background: rgba(26, 26, 24, 0.05);
915
+ }
916
+ .token {
917
+ display: inline;
918
+ background: color-mix(in srgb, var(--lavender) 16%, white);
919
+ color: #5a4fd0;
920
+ border-radius: 5px;
921
+ padding: 0 4px;
922
+ font-weight: 600;
923
+ }
924
 
925
  /* ============================================================
926
  Home — Family Brief
927
  ============================================================ */
928
+ .brief-grid {
929
+ display: grid;
930
+ grid-template-columns: 1.55fr 1fr;
931
+ gap: 20px;
932
+ align-items: start;
933
+ }
934
+ .greet {
935
+ font-size: 40px;
936
+ font-weight: 300;
937
+ letter-spacing: -0.035em;
938
+ line-height: 1.05;
939
+ margin: 4px 0 2px;
940
+ }
941
+ .greet .accent {
942
+ background: var(--spectrum);
943
+ -webkit-background-clip: text;
944
+ background-clip: text;
945
+ color: transparent;
946
+ }
947
+ .greet-sub {
948
+ color: var(--ash);
949
+ font-size: 15px;
950
+ margin-bottom: 22px;
951
+ }
952
+
953
+ .sect-h {
954
+ display: flex;
955
+ align-items: center;
956
+ gap: 10px;
957
+ margin: 4px 0 12px;
958
+ }
959
+ .sect-h h3 {
960
+ font-size: 14px;
961
+ font-weight: 600;
962
+ margin: 0;
963
+ letter-spacing: -0.01em;
964
+ white-space: nowrap;
965
+ }
966
+ .toolcard .det .row {
967
+ align-items: baseline;
968
+ }
969
+ .sect-h .ico {
970
+ color: var(--ash);
971
+ }
972
+ .sect-h .more {
973
+ margin-left: auto;
974
+ font-size: 12.5px;
975
+ color: var(--ash);
976
+ font-weight: 500;
977
+ background: none;
978
+ border: none;
979
+ }
980
+ .sect-h .more:hover {
981
+ color: var(--ink);
982
+ }
983
+
984
+ .timeline {
985
+ display: flex;
986
+ flex-direction: column;
987
+ }
988
+ .tl-item {
989
+ display: flex;
990
+ gap: 14px;
991
+ padding: 11px 4px;
992
+ border-bottom: 1px solid var(--fog);
993
+ }
994
+ .tl-item:last-child {
995
+ border-bottom: none;
996
+ }
997
+ .tl-time {
998
+ font-size: 12.5px;
999
+ color: var(--ash);
1000
+ width: 70px;
1001
+ flex: none;
1002
+ padding-top: 1px;
1003
+ font-variant-numeric: tabular-nums;
1004
+ }
1005
+ .tl-body {
1006
+ flex: 1;
1007
+ min-width: 0;
1008
+ }
1009
+ .tl-body .t {
1010
+ font-size: 14px;
1011
+ font-weight: 500;
1012
+ }
1013
+ .tl-body .s {
1014
+ font-size: 12.5px;
1015
+ color: var(--ash);
1016
+ margin-top: 1px;
1017
+ }
1018
+ .tl-bar {
1019
+ width: 3px;
1020
+ border-radius: 999px;
1021
+ background: var(--c, var(--ash));
1022
+ flex: none;
1023
+ }
1024
+
1025
+ .mini-list {
1026
+ display: flex;
1027
+ flex-direction: column;
1028
+ gap: 2px;
1029
+ }
1030
+ .mini-row {
1031
+ display: flex;
1032
+ align-items: center;
1033
+ gap: 11px;
1034
+ padding: 9px 6px;
1035
+ border-radius: 10px;
1036
+ }
1037
+ .mini-row:hover {
1038
+ background: rgba(26, 26, 24, 0.035);
1039
+ }
1040
+ .mini-row .t {
1041
+ font-size: 13.5px;
1042
+ font-weight: 500;
1043
+ }
1044
+ .mini-row .s {
1045
+ font-size: 12px;
1046
+ color: var(--ash);
1047
+ }
1048
+ .mini-row .r {
1049
+ margin-left: auto;
1050
+ font-size: 12px;
1051
+ color: var(--ash);
1052
+ }
1053
+
1054
+ .suggest-card {
1055
+ display: flex;
1056
+ gap: 13px;
1057
+ align-items: flex-start;
1058
+ padding: 15px 16px;
1059
+ border-radius: 16px;
1060
+ border: 1px solid var(--fog);
1061
+ background: rgba(255, 255, 255, 0.55);
1062
+ margin-bottom: 10px;
1063
+ }
1064
+ .suggest-card .txt {
1065
+ flex: 1;
1066
+ }
1067
+ .suggest-card .txt .t {
1068
+ font-size: 13.5px;
1069
+ font-weight: 500;
1070
+ line-height: 1.45;
1071
+ }
1072
+ .suggest-card .acts {
1073
+ display: flex;
1074
+ gap: 7px;
1075
+ margin-top: 10px;
1076
+ }
1077
+
1078
+ .stat-row {
1079
+ display: flex;
1080
+ gap: 12px;
1081
+ }
1082
+ .stat {
1083
+ flex: 1;
1084
+ padding: 15px 16px;
1085
+ border-radius: 16px;
1086
+ background: rgba(255, 255, 255, 0.6);
1087
+ border: 1px solid var(--fog);
1088
+ }
1089
+ .stat .n {
1090
+ font-size: 26px;
1091
+ font-weight: 300;
1092
+ letter-spacing: -0.02em;
1093
+ }
1094
+ .stat .l {
1095
+ font-size: 12px;
1096
+ color: var(--ash);
1097
+ margin-top: 2px;
1098
+ }
1099
 
1100
  /* ============================================================
1101
  Calendar
1102
  ============================================================ */
1103
+ .cal {
1104
+ display: grid;
1105
+ grid-template-columns: repeat(7, 1fr);
1106
+ gap: 1px;
1107
+ background: var(--fog);
1108
+ border: 1px solid var(--fog);
1109
+ border-radius: var(--r-lg);
1110
+ overflow: hidden;
1111
+ }
1112
+ .cal-h {
1113
+ background: rgba(255, 255, 255, 0.7);
1114
+ padding: 10px 12px;
1115
+ font-size: 11.5px;
1116
+ font-weight: 600;
1117
+ color: var(--ash);
1118
+ text-transform: uppercase;
1119
+ letter-spacing: 0.05em;
1120
+ }
1121
+ .cal-h .dn {
1122
+ color: var(--ink);
1123
+ font-size: 17px;
1124
+ font-weight: 300;
1125
+ letter-spacing: -0.02em;
1126
+ margin-top: 3px;
1127
+ }
1128
+ .cal-h.today .dn {
1129
+ color: var(--ember);
1130
+ }
1131
+ .cal-col {
1132
+ background: var(--snow);
1133
+ min-height: 360px;
1134
+ padding: 8px 8px 14px;
1135
+ display: flex;
1136
+ flex-direction: column;
1137
+ gap: 6px;
1138
+ }
1139
  .ev {
1140
+ border-radius: 10px;
1141
+ padding: 7px 9px;
1142
+ font-size: 12px;
1143
+ line-height: 1.3;
1144
  background: color-mix(in srgb, var(--c) 13%, white);
1145
  border: 1px solid color-mix(in srgb, var(--c) 24%, white);
1146
  border-left: 3px solid var(--c);
1147
+ cursor: pointer;
1148
+ transition:
1149
+ transform 0.08s,
1150
+ box-shadow 0.15s;
1151
+ }
1152
+ .ev:hover {
1153
+ box-shadow: var(--shadow-sm);
1154
+ transform: translateY(-1px);
1155
+ }
1156
+ .ev .et {
1157
+ font-size: 10.5px;
1158
+ color: color-mix(in srgb, var(--c) 55%, #333);
1159
+ font-weight: 600;
1160
+ font-variant-numeric: tabular-nums;
1161
+ }
1162
+ .ev .en {
1163
+ font-weight: 500;
1164
+ color: #2a2a26;
1165
+ margin-top: 1px;
1166
  }
 
 
 
1167
 
1168
  /* ============================================================
1169
  Recipes
1170
  ============================================================ */
1171
+ .recipe-grid {
1172
+ display: grid;
1173
+ grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
1174
+ gap: 18px;
1175
+ }
1176
+ .rcard {
1177
+ border-radius: var(--r-lg);
1178
+ overflow: hidden;
1179
+ background: var(--snow);
1180
+ border: 1px solid var(--fog);
1181
+ box-shadow: var(--shadow-sm);
1182
+ transition:
1183
+ transform 0.1s,
1184
+ box-shadow 0.18s;
1185
+ cursor: pointer;
1186
+ }
1187
+ .rcard:hover {
1188
+ transform: translateY(-3px);
1189
+ box-shadow: var(--shadow-md);
1190
+ }
1191
+ .rcard .ph {
1192
+ height: 132px;
1193
+ position: relative;
1194
+ display: grid;
1195
+ place-items: center;
1196
+ overflow: hidden;
1197
  background:
1198
+ repeating-linear-gradient(
1199
+ 135deg,
1200
+ rgba(0, 0, 0, 0.025) 0 9px,
1201
+ transparent 9px 18px
1202
+ ),
1203
  color-mix(in srgb, var(--c, var(--ash)) 18%, white);
1204
  }
1205
+ .rcard .ph .gl {
1206
+ font-size: 11px;
1207
+ color: color-mix(in srgb, var(--c) 50%, #555);
1208
+ font-family: var(--font-mono);
1209
+ letter-spacing: 0.04em;
1210
+ }
1211
+ .rcard .ph .tags {
1212
+ position: absolute;
1213
+ top: 10px;
1214
+ left: 10px;
1215
+ display: flex;
1216
+ gap: 5px;
1217
+ }
1218
+ .tag-veg {
1219
+ font-size: 10px;
1220
+ font-weight: 700;
1221
+ color: #1aa06b;
1222
+ background: rgba(26, 160, 107, 0.14);
1223
+ border-radius: 999px;
1224
+ padding: 2px 8px;
1225
+ letter-spacing: 0.03em;
1226
+ }
1227
+ .rcard .info {
1228
+ padding: 13px 15px 16px;
1229
+ }
1230
+ .rcard .info .t {
1231
+ font-size: 15px;
1232
+ font-weight: 600;
1233
+ letter-spacing: -0.01em;
1234
+ }
1235
+ .rcard .info .meta {
1236
+ display: flex;
1237
+ gap: 12px;
1238
+ margin-top: 7px;
1239
+ font-size: 12px;
1240
+ color: var(--ash);
1241
+ }
1242
 
1243
  /* recipe detail / drawer */
1244
+ .drawer-scrim {
1245
+ position: fixed;
1246
+ inset: 0;
1247
+ background: rgba(26, 26, 24, 0.28);
1248
+ backdrop-filter: blur(3px);
1249
+ z-index: 60;
1250
+ animation: fade 0.2s;
1251
+ }
1252
+ .drawer {
1253
+ position: fixed;
1254
+ top: 0;
1255
+ right: 0;
1256
+ bottom: 0;
1257
+ width: min(560px, 92vw);
1258
+ background: var(--canvas);
1259
+ z-index: 61;
1260
+ box-shadow: var(--shadow-lg);
1261
+ display: flex;
1262
+ flex-direction: column;
1263
+ animation: slidein 0.26s cubic-bezier(0.2, 0.8, 0.2, 1);
1264
+ }
1265
+ @keyframes slidein {
1266
+ from {
1267
+ transform: translateX(30px);
1268
+ opacity: 0;
1269
+ }
1270
+ to {
1271
+ transform: none;
1272
+ opacity: 1;
1273
+ }
1274
+ }
1275
+ @keyframes fade {
1276
+ from {
1277
+ opacity: 0;
1278
+ }
1279
+ to {
1280
+ opacity: 1;
1281
+ }
1282
+ }
1283
+ .drawer-head {
1284
+ padding: 18px 22px;
1285
+ display: flex;
1286
+ align-items: center;
1287
+ gap: 12px;
1288
+ border-bottom: 1px solid var(--fog);
1289
+ flex: none;
1290
+ }
1291
+ .drawer-body {
1292
+ flex: 1;
1293
+ overflow-y: auto;
1294
+ padding: 22px;
1295
+ }
1296
+ .ingredient {
1297
+ display: flex;
1298
+ align-items: center;
1299
+ gap: 11px;
1300
+ padding: 8px 0;
1301
+ border-bottom: 1px solid var(--fog);
1302
+ font-size: 14px;
1303
+ }
1304
+ .ingredient .ck {
1305
+ width: 18px;
1306
+ height: 18px;
1307
+ border-radius: 6px;
1308
+ border: 1.5px solid var(--pebble);
1309
+ flex: none;
1310
+ }
1311
+ .step {
1312
+ display: flex;
1313
+ gap: 13px;
1314
+ padding: 11px 0;
1315
+ }
1316
+ .step .n {
1317
+ width: 24px;
1318
+ height: 24px;
1319
+ border-radius: 999px;
1320
+ background: var(--ink);
1321
+ color: #fff;
1322
+ font-size: 12px;
1323
+ font-weight: 600;
1324
+ display: grid;
1325
+ place-items: center;
1326
+ flex: none;
1327
+ }
1328
+ .step .x {
1329
+ font-size: 14px;
1330
+ line-height: 1.55;
1331
+ }
1332
 
1333
  /* the markdown peek */
1334
+ .md-peek {
1335
+ background: #1d1d1a;
1336
+ color: #e8e8e2;
1337
+ border-radius: var(--r-md);
1338
+ padding: 16px 18px;
1339
+ font-family: var(--font-mono);
1340
+ font-size: 12.5px;
1341
+ line-height: 1.7;
1342
+ overflow-x: auto;
1343
+ }
1344
+ .md-peek .fm {
1345
+ color: #84847d;
1346
+ }
1347
+ .md-peek .key {
1348
+ color: #ffb005;
1349
+ }
1350
+ .md-peek .str {
1351
+ color: #c9c9fe;
1352
+ }
1353
+ .md-peek .h {
1354
+ color: #fff;
1355
+ font-weight: 700;
1356
+ }
1357
 
1358
  /* ============================================================
1359
  Meals — planner + shopping list
1360
  ============================================================ */
1361
+ .meal-layout {
1362
+ display: grid;
1363
+ grid-template-columns: 1fr 320px;
1364
+ gap: 20px;
1365
+ align-items: start;
1366
+ }
1367
+ .week {
1368
+ display: flex;
1369
+ flex-direction: column;
1370
+ gap: 10px;
1371
+ }
1372
+ .day-row {
1373
+ display: flex;
1374
+ align-items: center;
1375
+ gap: 16px;
1376
+ padding: 14px 18px;
1377
+ background: var(--snow);
1378
+ border: 1px solid var(--fog);
1379
+ border-radius: var(--r-md);
1380
+ box-shadow: var(--shadow-sm);
1381
+ }
1382
+ .day-row .dow {
1383
+ width: 44px;
1384
+ flex: none;
1385
+ }
1386
+ .day-row .dow .d3 {
1387
+ font-size: 13px;
1388
+ font-weight: 600;
1389
+ }
1390
+ .day-row .dow .num {
1391
+ font-size: 12px;
1392
+ color: var(--ash);
1393
+ }
1394
+ .day-row .dish {
1395
+ flex: 1;
1396
+ display: flex;
1397
+ align-items: center;
1398
+ gap: 12px;
1399
+ min-width: 0;
1400
+ }
1401
+ .day-row .dish .sw {
1402
+ width: 34px;
1403
+ height: 34px;
1404
+ border-radius: 9px;
1405
+ flex: none;
1406
+ background:
1407
+ repeating-linear-gradient(
1408
+ 135deg,
1409
+ rgba(0, 0, 0, 0.03) 0 6px,
1410
+ transparent 6px 12px
1411
+ ),
1412
+ color-mix(in srgb, var(--c, var(--ash)) 20%, white);
1413
+ }
1414
+ .day-row .dish .t {
1415
+ font-size: 14px;
1416
+ font-weight: 500;
1417
+ }
1418
+ .day-row .dish .s {
1419
+ font-size: 12px;
1420
+ color: var(--ash);
1421
+ }
1422
+ .day-row .swap {
1423
+ opacity: 0;
1424
+ transition: opacity 0.15s;
1425
+ }
1426
+ .day-row:hover .swap {
1427
+ opacity: 1;
1428
+ }
1429
+
1430
+ .shop {
1431
+ position: sticky;
1432
+ top: 6px;
1433
+ }
1434
+ .shop .grp {
1435
+ font-size: 11px;
1436
+ letter-spacing: 0.06em;
1437
+ text-transform: uppercase;
1438
+ color: var(--ash-light);
1439
+ font-weight: 600;
1440
+ margin: 14px 0 4px;
1441
+ }
1442
+ .shop-item {
1443
+ display: flex;
1444
+ align-items: center;
1445
+ gap: 10px;
1446
+ padding: 7px 0;
1447
+ font-size: 13.5px;
1448
+ border-bottom: 1px solid var(--fog);
1449
+ }
1450
+ .shop-item .ck {
1451
+ width: 16px;
1452
+ height: 16px;
1453
+ border-radius: 5px;
1454
+ border: 1.5px solid var(--pebble);
1455
+ flex: none;
1456
+ }
1457
+ .shop-item.done {
1458
+ color: var(--ash-light);
1459
+ text-decoration: line-through;
1460
+ }
1461
+ .shop-item .q {
1462
+ margin-left: auto;
1463
+ font-size: 12px;
1464
+ color: var(--ash);
1465
+ }
1466
 
1467
  /* ============================================================
1468
  Notes
1469
  ============================================================ */
1470
+ .notes-layout {
1471
+ display: grid;
1472
+ grid-template-columns: 200px 1fr;
1473
+ gap: 22px;
1474
+ align-items: start;
1475
+ }
1476
+ .note-members {
1477
+ display: flex;
1478
+ flex-direction: column;
1479
+ gap: 3px;
1480
+ }
1481
+ .note-mtab {
1482
+ display: flex;
1483
+ align-items: center;
1484
+ gap: 10px;
1485
+ padding: 9px 11px;
1486
+ border-radius: 11px;
1487
+ border: none;
1488
+ background: none;
1489
+ width: 100%;
1490
+ text-align: left;
1491
+ font-size: 13.5px;
1492
+ font-weight: 500;
1493
+ color: var(--ink-soft);
1494
+ }
1495
+ .note-mtab:hover {
1496
+ background: rgba(26, 26, 24, 0.04);
1497
+ }
1498
+ .note-mtab.on {
1499
+ background: var(--snow);
1500
+ box-shadow: var(--shadow-sm);
1501
+ color: var(--ink);
1502
+ }
1503
+ .note-mtab .ct {
1504
+ margin-left: auto;
1505
+ font-size: 11px;
1506
+ color: var(--ash);
1507
+ }
1508
+ .note-cols {
1509
+ columns: 2;
1510
+ column-gap: 16px;
1511
+ }
1512
  .note {
1513
+ break-inside: avoid;
1514
+ margin-bottom: 16px;
1515
+ padding: 16px 17px;
1516
+ border-radius: var(--r-md);
1517
+ border: 1px solid var(--fog);
1518
+ background: var(--snow);
1519
+ box-shadow: var(--shadow-sm);
1520
  border-top: 3px solid var(--c, var(--ash));
1521
  }
1522
+ .note .t {
1523
+ font-size: 14px;
1524
+ font-weight: 600;
1525
+ margin-bottom: 7px;
1526
+ }
1527
+ .note .body {
1528
+ font-size: 13px;
1529
+ line-height: 1.6;
1530
+ color: var(--ink-soft);
1531
+ white-space: pre-wrap;
1532
+ }
1533
+ .note .check {
1534
+ display: flex;
1535
+ gap: 8px;
1536
+ align-items: flex-start;
1537
+ font-size: 13px;
1538
+ padding: 3px 0;
1539
+ }
1540
+ .note .check .b {
1541
+ width: 15px;
1542
+ height: 15px;
1543
+ border-radius: 4px;
1544
+ border: 1.5px solid var(--pebble);
1545
+ flex: none;
1546
+ margin-top: 2px;
1547
+ }
1548
+ .note .check.done {
1549
+ color: var(--ash-light);
1550
+ }
1551
+ .note .check.done .b {
1552
+ background: var(--m-leo);
1553
+ border-color: var(--m-leo);
1554
+ }
1555
+ .note .foot {
1556
+ font-size: 11px;
1557
+ color: var(--ash-light);
1558
+ margin-top: 11px;
1559
+ font-family: var(--font-mono);
1560
+ }
1561
 
1562
  /* ============================================================
1563
  Settings — family roster
1564
  ============================================================ */
1565
  .set-input {
1566
+ width: 100%;
1567
+ padding: 10px 12px;
1568
+ font-size: 14px;
1569
+ font-family: inherit;
1570
+ border: 1px solid var(--pebble);
1571
+ border-radius: var(--r-md);
1572
+ background: var(--snow);
1573
+ color: var(--ink);
1574
+ outline: none;
1575
+ }
1576
+ .set-input:focus {
1577
+ border-color: var(--ash);
1578
+ }
1579
+ .set-veg {
1580
+ display: flex;
1581
+ align-items: center;
1582
+ gap: 9px;
1583
+ font-size: 13.5px;
1584
+ color: var(--ink-soft);
1585
+ margin-top: 12px;
1586
+ cursor: pointer;
1587
+ user-select: none;
1588
+ }
1589
+ .set-veg .b {
1590
+ width: 16px;
1591
+ height: 16px;
1592
+ border-radius: 5px;
1593
+ border: 1.5px solid var(--pebble);
1594
+ flex: none;
1595
+ }
1596
+ .member-list {
1597
+ display: flex;
1598
+ flex-direction: column;
1599
+ gap: 10px;
1600
+ }
1601
  .member-row {
1602
+ display: flex;
1603
+ align-items: center;
1604
+ gap: 13px;
1605
+ padding: 13px 15px;
1606
+ border-radius: var(--r-md);
1607
+ border: 1px solid var(--fog);
1608
+ background: var(--snow);
1609
+ box-shadow: var(--shadow-sm);
1610
  }
1611
 
1612
  /* ============================================================
1613
  Inbox — email → event
1614
  ============================================================ */
1615
+ .inbox-layout {
1616
+ display: grid;
1617
+ grid-template-columns: 1fr;
1618
+ gap: 14px;
1619
+ max-width: 760px;
1620
+ }
1621
  .mail {
1622
+ display: flex;
1623
+ gap: 14px;
1624
+ padding: 17px 19px;
1625
+ border-radius: var(--r-lg);
1626
+ background: var(--snow);
1627
+ border: 1px solid var(--fog);
1628
+ box-shadow: var(--shadow-sm);
1629
+ }
1630
+ .mail .from-av {
1631
+ flex: none;
1632
+ }
1633
+ .mail .m-main {
1634
+ flex: 1;
1635
+ min-width: 0;
1636
+ }
1637
+ .mail .m-top {
1638
+ display: flex;
1639
+ align-items: baseline;
1640
+ gap: 10px;
1641
+ }
1642
+ .mail .m-from {
1643
+ font-size: 14px;
1644
+ font-weight: 600;
1645
+ }
1646
+ .mail .m-date {
1647
+ margin-left: auto;
1648
+ font-size: 12px;
1649
+ color: var(--ash);
1650
+ flex: none;
1651
+ }
1652
+ .mail .m-subj {
1653
+ font-size: 13.5px;
1654
+ font-weight: 500;
1655
+ margin-top: 3px;
1656
+ }
1657
+ .mail .m-prev {
1658
+ font-size: 13px;
1659
+ color: var(--ash);
1660
+ margin-top: 3px;
1661
+ line-height: 1.5;
1662
  }
 
 
 
 
 
 
 
1663
 
1664
  .proposal {
1665
+ margin-top: 13px;
1666
+ border-radius: 14px;
1667
+ padding: 14px 16px;
1668
+ background: rgba(255, 255, 255, 0.7);
1669
  border: 1px solid transparent;
1670
+ background-image:
1671
+ linear-gradient(rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.85)),
1672
+ var(--spectrum-soft);
1673
+ background-origin: border-box;
1674
+ background-clip: padding-box, border-box;
1675
+ }
1676
+ .proposal .ph {
1677
+ display: flex;
1678
+ align-items: center;
1679
+ gap: 9px;
1680
+ font-size: 12px;
1681
+ font-weight: 600;
1682
+ color: var(--ink-soft);
1683
+ margin-bottom: 10px;
1684
+ }
1685
+ .proposal .ph .orb {
1686
+ width: 18px;
1687
+ height: 18px;
1688
+ }
1689
+ .proposal .pe {
1690
+ display: flex;
1691
+ align-items: center;
1692
+ gap: 12px;
1693
+ padding: 10px 12px;
1694
+ background: var(--snow);
1695
+ border: 1px solid var(--fog);
1696
+ border-radius: 11px;
1697
+ }
1698
+ .proposal .pe .when {
1699
+ text-align: center;
1700
+ flex: none;
1701
+ padding-right: 12px;
1702
+ border-right: 1px solid var(--fog);
1703
+ }
1704
+ .proposal .pe .when .mo {
1705
+ font-size: 10px;
1706
+ text-transform: uppercase;
1707
+ color: var(--ember);
1708
+ font-weight: 700;
1709
+ letter-spacing: 0.05em;
1710
+ }
1711
+ .proposal .pe .when .dd {
1712
+ font-size: 20px;
1713
+ font-weight: 300;
1714
+ line-height: 1;
1715
+ }
1716
+ .proposal .pe .det .t {
1717
+ font-size: 13.5px;
1718
+ font-weight: 600;
1719
+ }
1720
+ .proposal .pe .det .s {
1721
+ font-size: 12px;
1722
+ color: var(--ash);
1723
+ margin-top: 2px;
1724
+ }
1725
+ .proposal .acts {
1726
+ display: flex;
1727
+ gap: 8px;
1728
+ margin-top: 12px;
1729
+ }
1730
+ .mail.handled {
1731
+ opacity: 0.62;
1732
+ }
1733
+ .confirmed-tag {
1734
+ display: inline-flex;
1735
+ align-items: center;
1736
+ gap: 6px;
1737
+ font-size: 12px;
1738
+ font-weight: 600;
1739
+ color: var(--m-leo);
1740
+ }
1741
 
1742
  /* ============================================================
1743
  misc
1744
  ============================================================ */
1745
+ .empty {
1746
+ text-align: center;
1747
+ padding: 60px 20px;
1748
+ color: var(--ash);
1749
+ }
1750
+ .fade-in {
1751
+ animation: fade 0.3s ease both;
1752
+ }
1753
+ .rise {
1754
+ animation: rise 0.35s cubic-bezier(0.2, 0.8, 0.2, 1) both;
1755
+ }
1756
+ @keyframes rise {
1757
+ from {
1758
+ opacity: 0;
1759
+ transform: translateY(8px);
1760
+ }
1761
+ to {
1762
+ opacity: 1;
1763
+ transform: none;
1764
+ }
1765
+ }
1766
 
1767
  @media (prefers-reduced-motion: reduce) {
1768
+ * {
1769
+ animation-duration: 0.001ms !important;
1770
+ transition-duration: 0.05ms !important;
1771
+ }
1772
  }
1773
 
1774
  /* ---- tweak-driven states ---- */
1775
+ html.surf-solid .card {
1776
+ background: var(--snow);
1777
+ backdrop-filter: none;
1778
+ border-color: var(--fog);
1779
+ }
1780
+ html.surf-solid .sidebar {
1781
+ background: rgba(255, 255, 255, 0.92);
1782
+ backdrop-filter: none;
1783
+ }
1784
  html.surf-solid .chip,
1785
  html.surf-solid .suggestion,
1786
  html.surf-solid .member-switch,
1787
+ html.surf-solid .proposal {
1788
+ background-color: var(--snow);
1789
+ }
1790
+ html.names-on .m-chip .name {
1791
+ display: inline;
1792
+ }
1793
+ html.names-on .m-chip {
1794
+ padding-right: 11px;
1795
+ }
frontend/app/screens1.jsx CHANGED
@@ -20,8 +20,17 @@ function AskBar({
20
  const grow = () => {
21
  const t = taRef.current;
22
  if (!t) return;
23
- t.style.height = "auto";
24
- t.style.height = Math.min(t.scrollHeight, 140) + "px";
 
 
 
 
 
 
 
 
 
25
  };
26
  useEffect(grow, [value]);
27
  useEffect(() => {
 
20
  const grow = () => {
21
  const t = taRef.current;
22
  if (!t) return;
23
+ const prev = t.offsetHeight;
24
+ t.style.transition = "none";
25
+ t.style.height = "0px";
26
+ const next = Math.min(t.scrollHeight, 140);
27
+ t.style.height = `${prev}px`;
28
+ void t.offsetHeight;
29
+ requestAnimationFrame(() => {
30
+ if (!taRef.current) return;
31
+ taRef.current.style.transition = "";
32
+ taRef.current.style.height = `${next}px`;
33
+ });
34
  };
35
  useEffect(grow, [value]);
36
  useEffect(() => {
frontend/index.html CHANGED
@@ -4,6 +4,7 @@
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>Mini Fam — the family assistant that stays home</title>
 
7
  <link rel="preconnect" href="https://fonts.googleapis.com" />
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
  <link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
 
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>Mini Fam — the family assistant that stays home</title>
7
+ <link rel="icon" type="image/png" href="app/logo.png?v=3" />
8
  <link rel="preconnect" href="https://fonts.googleapis.com" />
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
  <link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />