feat: saved-names wishlist (#1); style the shared feedback chat-pop with Tailwind (#2)

- ☆ on every card saves it to a browser-only shortlist (localStorage
  names.wishlist, cap 60) shown as a Saved panel with snapshotted
  statuses, Re-check and Copy list.
- SuggestionLightbulb from @otm/account-panel is Tailwind-styled and
  names had no Tailwind, so it rendered as a bare button. Added Tailwind
  (preflight off, dark class pinned), scoped element CSS to .wrap and
  mounted the widget outside it.
- v0.2.0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XStQKxPfEjrTvWo83KFCxG
This commit is contained in:
2026-08-16 18:14:40 -05:00
parent 9489ce5708
commit c7d6812466
11 changed files with 1591 additions and 33 deletions

View File

@@ -1,3 +1,6 @@
@tailwind components;
@tailwind utilities;
:root {
--bg: #0b0d10;
--panel: #14181d;
@@ -88,10 +91,13 @@ h2 {
margin-bottom: 7px;
}
input[type="text"],
input[type="password"],
textarea,
select {
/* Element rules are scoped to .wrap so they can't bleed into the shared
OTM widgets (SuggestionLightbulb) mounted outside it, which style
themselves with Tailwind utilities. */
.wrap input[type="text"],
.wrap input[type="password"],
.wrap textarea,
.wrap select {
width: 100%;
background: var(--panel);
color: var(--text);
@@ -103,9 +109,9 @@ select {
line-height: 1.4;
}
input:focus,
textarea:focus,
select:focus {
.wrap input:focus,
.wrap textarea:focus,
.wrap select:focus {
outline: none;
border-color: var(--accent-dim);
}
@@ -117,7 +123,7 @@ select:focus {
line-height: 1.5;
}
button {
.wrap button {
font-family: inherit;
font-size: 15px;
cursor: pointer;
@@ -128,23 +134,23 @@ button {
padding: 11px 18px;
}
button:hover:not(:disabled) {
.wrap button:hover:not(:disabled) {
border-color: var(--accent-dim);
}
button:disabled {
.wrap button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
button.primary {
.wrap button.primary {
background: var(--accent-dim);
border-color: var(--accent-dim);
color: #fff;
font-weight: 600;
}
button.primary:hover:not(:disabled) {
.wrap button.primary:hover:not(:disabled) {
background: var(--accent);
border-color: var(--accent);
}
@@ -254,6 +260,89 @@ button.primary:hover:not(:disabled) {
opacity: 0.55;
}
.card-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 8px;
}
/* Save star: bare glyph, no chrome. Filled + accent when saved. */
.wrap button.save {
background: none;
border: none;
padding: 0 2px;
line-height: 1;
font-size: 20px;
color: var(--faint);
border-radius: 6px;
flex: none;
}
.wrap button.save:hover:not(:disabled) {
color: var(--warn);
border-color: transparent;
}
.wrap button.save[aria-pressed="true"] {
color: var(--warn);
}
.card.is-saved {
border-color: #4a3f1c;
}
/* ---------- wishlist ---------- */
.wishlist {
margin-top: 22px;
padding: 14px 16px 16px;
border: 1px solid #4a3f1c;
border-radius: 14px;
background: linear-gradient(180deg, #17150f, var(--bg));
}
.wishlist-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
flex-wrap: wrap;
}
.wishlist h2 {
margin: 0;
font-size: 16px;
font-weight: 600;
}
.wishlist h2 .count {
display: inline-block;
min-width: 22px;
padding: 1px 7px;
margin-left: 6px;
border-radius: 999px;
background: var(--warn-bg);
color: var(--warn);
font-size: 12px;
text-align: center;
}
.wishlist-actions {
display: flex;
gap: 8px;
}
.wrap button.mini {
font-size: 13px;
padding: 6px 12px;
border-radius: 8px;
}
.wishlist .results {
margin-top: 10px;
}
.strategy {
font-size: 11px;
text-transform: uppercase;

View File

@@ -14,14 +14,13 @@ export const metadata: Metadata = {
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<html lang="en" className="dark">
<body>
<div className="wrap">
<div className="topbar">
<Link href="/" className="brand" style={{ textDecoration: "none" }}>
Powered by OTM
</Link>
<SuggestionLightbulb />
</div>
{children}
<footer className="footer">
@@ -41,6 +40,9 @@ export default function RootLayout({ children }: { children: ReactNode }) {
</span>
</footer>
</div>
{/* Shared OTM feedback chat-pop (bottom-right). Mounted outside .wrap
so the app's scoped element CSS can't restyle it. */}
<SuggestionLightbulb />
</body>
</html>
);