Ship LNURL mint pages, indexing UI, and reviews rewrite.
Add lnurl list/detail routes, OG fixtures, i18n strings, and the write/ index client flows so the site surfaces the new mint type end to end. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+155
-20
@@ -194,6 +194,20 @@
|
||||
--violet: #A78BFA;
|
||||
--mint: #5FD68F;
|
||||
--red: #E06450;
|
||||
/*
|
||||
* The LNURL ecosystem accent, and the only cool blue on this site.
|
||||
*
|
||||
* The palette is otherwise warm, which is exactly what makes this readable as "a
|
||||
* different ecosystem" at thumbnail size on a social card. Every other candidate was
|
||||
* already taken by a meaning the colour discipline reserves: amber is the brand,
|
||||
* mint is online/success, red is offline/critical, and violet is Nostr-protocol
|
||||
* (which the Fedimint badge borrows). A blue is the only hue left that a reader
|
||||
* cannot mistake for a status.
|
||||
*
|
||||
* Used for the LNURL card's badge and glow, and nowhere else. It is an ecosystem
|
||||
* label, not a state, and must never decorate one.
|
||||
*/
|
||||
--lnurl: #4EA8DE;
|
||||
--radius: 14px;
|
||||
|
||||
--body: 'Inter', 'Inter Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;
|
||||
@@ -523,18 +537,85 @@ main { flex: 1; }
|
||||
.kv-row .copy-btn { margin-left: auto; }
|
||||
|
||||
/* ---------- footer ---------- */
|
||||
footer { border-top: 1px solid var(--line-soft); margin-top: 70px; }
|
||||
.foot-inner {
|
||||
max-width: var(--page-max); margin: 0 auto; padding: 28px;
|
||||
display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
|
||||
font-size: 13px; color: var(--faint);
|
||||
|
||||
/*
|
||||
* Three zones: the columns, then a thin bar. `main { flex: 1 }` and the column layout
|
||||
* on `body` are what put this at the bottom of the viewport on a short page (the LNURL
|
||||
* index with one mint) rather than halfway up it, so this needs no min-height of its
|
||||
* own. `margin-top: 70px` is the gap after a long page; on a short one the flex growth
|
||||
* of `main` swallows it.
|
||||
*/
|
||||
.site-footer { border-top: 1px solid var(--line-soft); margin-top: 70px; }
|
||||
|
||||
.foot-cols {
|
||||
max-width: var(--page-max); margin: 0 auto;
|
||||
padding: 44px var(--page-pad) 36px;
|
||||
display: grid;
|
||||
/*
|
||||
* Four visible columns from three grid tracks: the middle one is the nav landmark,
|
||||
* which holds Explore and Site. One landmark over both, rather than a track each,
|
||||
* is what keeps the landmark list honest — see Footer.astro.
|
||||
*/
|
||||
grid-template-columns: minmax(0, 2.1fr) minmax(0, 2fr) minmax(0, 1.2fr);
|
||||
gap: 40px 44px;
|
||||
}
|
||||
.foot-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px 32px; }
|
||||
|
||||
/* The brand column. Narrower than its track so the sentences break at a readable
|
||||
measure instead of running the full width of a 1240px grid cell. */
|
||||
.foot-brand { max-width: 34ch; }
|
||||
.foot-mark {
|
||||
display: inline-flex; align-items: center; gap: 10px;
|
||||
font-family: var(--display); font-weight: 700; font-size: 15.5px; letter-spacing: -.01em;
|
||||
}
|
||||
.foot-desc { color: var(--muted); font-size: 13.5px; line-height: 1.55; margin-top: 12px; }
|
||||
/*
|
||||
* The custodial warning. `--muted`, not `--faint`: it is the one sentence in this
|
||||
* footer that a reader is worse off for having missed, and it used to be an orphan in
|
||||
* the bottom right corner of the last row.
|
||||
*/
|
||||
.foot-warn { color: var(--muted); font-size: 13px; line-height: 1.5; margin-top: 10px; }
|
||||
|
||||
/* The small-caps label, the same one `.side-title` and `.fb-stat .k` use. An h2 in the
|
||||
markup, so the margin is stated in full and the UA's own h2 margins cannot show. */
|
||||
.foot-head {
|
||||
font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
|
||||
color: var(--faint); margin: 0 0 14px;
|
||||
}
|
||||
.foot-col ul { list-style: none; display: flex; flex-direction: column; gap: 8px; }
|
||||
.foot-col a {
|
||||
font-size: 13.5px; color: var(--muted);
|
||||
transition: color var(--dur-quick);
|
||||
}
|
||||
.foot-col a:hover { color: var(--text); }
|
||||
|
||||
.foot-bar {
|
||||
max-width: var(--page-max); margin: 0 auto;
|
||||
padding: 16px var(--page-pad);
|
||||
border-top: 1px solid var(--line-soft);
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
gap: 8px 24px; flex-wrap: wrap;
|
||||
font-size: 12.5px; color: var(--faint);
|
||||
}
|
||||
.foot-inner .links { display: flex; gap: 18px; flex-wrap: wrap; }
|
||||
.foot-inner a:hover { color: var(--muted); }
|
||||
.foot-right { margin-left: auto; }
|
||||
/* Dotted underline like every other in-sentence link: colour alone is not enough
|
||||
to mark a link inside running text (WCAG 1.4.1). */
|
||||
.foot-right a { color: var(--amber); border-bottom: 1px dotted rgba(240, 169, 59, .4); }
|
||||
.foot-credit a { color: var(--amber); border-bottom: 1px dotted rgba(240, 169, 59, .4); }
|
||||
|
||||
/*
|
||||
* The stack.
|
||||
*
|
||||
* At 900px the three tracks become one, which puts the columns in source order —
|
||||
* Brand, then the nav's two columns side by side, then Language. Explore and Site stay
|
||||
* paired down to 460px because two short link lists next to each other read as one
|
||||
* block; below that they are two lists that would each be one word wide.
|
||||
*/
|
||||
@media (max-width: 900px) {
|
||||
.foot-cols { grid-template-columns: minmax(0, 1fr); gap: 34px; }
|
||||
.foot-brand { max-width: 46ch; }
|
||||
}
|
||||
@media (max-width: 460px) {
|
||||
.foot-nav { grid-template-columns: minmax(0, 1fr); gap: 30px; }
|
||||
}
|
||||
|
||||
/* ---------- prose (about, wallets) ---------- */
|
||||
.prose { max-width: 720px; }
|
||||
@@ -559,24 +640,29 @@ footer { border-top: 1px solid var(--line-soft); margin-top: 70px; }
|
||||
/*
|
||||
* Below this the header stops being one row.
|
||||
*
|
||||
* Five nav items, the brand, the language control and the account control do not fit
|
||||
* Six nav items, the brand, the language control and the account control do not fit
|
||||
* across anything narrower than a laptop, and a header that does not fit is a page that
|
||||
* scrolls sideways: the body inherits the overflow and every section under it drifts. So
|
||||
* the nav takes a row of its own and the two controls stay up top with the brand, which
|
||||
* is also the order they are wanted in: what page am I on, then who am I and what
|
||||
* language is this.
|
||||
*
|
||||
* 1040px, not the 620px this used to be. The old figure was already two pixels short of
|
||||
* fitting four English items at 768, and five need 400px against the 303px the first row
|
||||
* has left there — no amount of tightening the padding closes a gap that size.
|
||||
* The number is set by the widest locale, never by English. Picking the English figure
|
||||
* is how this shipped broken once already: every locale renders the same stylesheet, so
|
||||
* the breakpoint has to clear the widest of them, with room for the next language to be
|
||||
* longer still.
|
||||
*
|
||||
* The number is set by Spanish, which is the longest of the three ("Mints Cashu /
|
||||
* Fedimints / Reseñas / Monederos / Acerca de") and needs 1008px to fit on one row
|
||||
* against English's 906. Picking the English figure is how this shipped broken once
|
||||
* already: every locale renders the same stylesheet, so the breakpoint has to clear the
|
||||
* widest of them, with room for the next language to be longer still.
|
||||
* History, because the direction of travel matters here: 620px fitted four items,
|
||||
* 1040px fitted five (set by Spanish at 1008px against English's 906), and adding the
|
||||
* LNURL index made six. Measured across all shipped locales at the time it was added,
|
||||
* the widest first row needs 1123px, so this sits at 1180 — the same kind of headroom
|
||||
* the 1040 figure carried over its own 1008.
|
||||
*
|
||||
* At 1280px, the widest desktop this site targets, all six fit on one row with room to
|
||||
* spare in every locale. A seventh would not, and would need a real menu rather than
|
||||
* another bump: this row is full.
|
||||
*/
|
||||
@media (max-width: 1040px) {
|
||||
@media (max-width: 1180px) {
|
||||
.topbar-inner { flex-wrap: wrap; row-gap: 10px; }
|
||||
/* Pushes the pair to the right of the first row, where they were before it wrapped. */
|
||||
.topbar-inner > .lang-menu { margin-left: auto; }
|
||||
@@ -601,7 +687,10 @@ footer { border-top: 1px solid var(--line-soft); margin-top: 70px; }
|
||||
@media (max-width: 640px) {
|
||||
:root { --page-pad: 18px; }
|
||||
.mint-grid { grid-template-columns: minmax(0, 1fr); }
|
||||
.foot-right { margin-left: 0; }
|
||||
/* Two centred lines rather than one row pushed to both edges: at this width the
|
||||
copyright and the credit would otherwise sit in opposite corners with a gulf
|
||||
between them. */
|
||||
.foot-bar { justify-content: center; text-align: center; gap: 6px; }
|
||||
}
|
||||
@media (max-width: 420px) {
|
||||
.brand { gap: 0; }
|
||||
@@ -884,6 +973,52 @@ footer { border-top: 1px solid var(--line-soft); margin-top: 70px; }
|
||||
.fb-stats { display: flex; gap: 26px; flex-wrap: wrap; margin-top: 8px; }
|
||||
.fb-stat .k { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--faint); display: block; }
|
||||
.fb-stat .v { font-family: var(--display); font-size: 24px; font-weight: 700; }
|
||||
/* The one action a resolved-on-arrival mint offers: review it, right now. */
|
||||
.fb-actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 18px; }
|
||||
/* The reviews panel the resolver starts once it has a subject to give it. */
|
||||
.nf-reviews { margin-top: 26px; }
|
||||
|
||||
/* ---------- review by URL (the two-step dialog) ---------- */
|
||||
/*
|
||||
* Step one asks for an address. It is the same input the search boxes use, so it reads
|
||||
* as one control family across the site rather than as a form that turned up in a modal.
|
||||
*/
|
||||
.rbu-input {
|
||||
background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
|
||||
color: var(--text); font-family: var(--mono); font-size: 14px;
|
||||
padding: 12px 12px; width: 100%; display: block;
|
||||
}
|
||||
.rbu-input:focus { outline: 2px solid var(--amber); outline-offset: 1px; }
|
||||
.rbu-input:disabled { color: var(--muted); background: var(--card2); }
|
||||
.rbu-input::placeholder { color: var(--faint); font-family: var(--mono); }
|
||||
|
||||
/* "That address answered as a Cashu mint" plus the button that acts on it. */
|
||||
.rbu-switch { font-size: 13px; color: var(--muted); line-height: 1.6; }
|
||||
|
||||
/* Step two's way back, above the mint it is about to review. */
|
||||
.rbu-back {
|
||||
align-self: flex-start; display: inline-flex; align-items: center; gap: 5px;
|
||||
border: none; background: none; cursor: pointer; padding: 2px 0;
|
||||
font-family: var(--body); font-size: 12.5px; color: var(--muted);
|
||||
}
|
||||
.rbu-back:hover { color: var(--amber); }
|
||||
|
||||
/* The mint that was found: enough to recognise it by, and no more. */
|
||||
.rbu-preview {
|
||||
display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
|
||||
background: var(--card2); border: 1px solid var(--line-soft);
|
||||
border-radius: 11px; padding: 10px 12px;
|
||||
}
|
||||
.rbu-icon {
|
||||
width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
font-family: var(--display); font-size: 16px; font-weight: 700; color: #141109;
|
||||
}
|
||||
.rbu-who { display: flex; flex-direction: column; gap: 1px; min-width: 120px; flex: 1; }
|
||||
.rbu-name { font-size: 14px; font-weight: 600; overflow-wrap: anywhere; }
|
||||
.rbu-domain { font-family: var(--mono); font-size: 11.5px; color: var(--faint); overflow-wrap: anywhere; }
|
||||
.rbu-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
||||
.rbu-note { font-size: 11.5px; color: var(--faint); }
|
||||
|
||||
/* ---------- skeletons ---------- */
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user